1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2023 SiFive
4 * Author: Andy Chiu <andy.chiu@sifive.com>
6 #include <linux/export.h>
7 #include <linux/sched/signal.h>
8 #include <linux/types.h>
9 #include <linux/slab.h>
10 #include <linux/sched.h>
11 #include <linux/uaccess.h>
12 #include <linux/prctl.h>
14 #include <asm/thread_info.h>
15 #include <asm/processor.h>
17 #include <asm/vector.h>
20 #include <asm/ptrace.h>
23 static bool riscv_v_implicit_uacc = IS_ENABLED(CONFIG_RISCV_ISA_V_DEFAULT_ENABLE);
25 unsigned long riscv_v_vsize __read_mostly;
26 EXPORT_SYMBOL_GPL(riscv_v_vsize);
28 int riscv_v_setup_vsize(void)
30 unsigned long this_vsize;
32 /* There are 32 vector registers with vlenb length. */
34 this_vsize = csr_read(CSR_VLENB) * 32;
38 riscv_v_vsize = this_vsize;
42 if (riscv_v_vsize != this_vsize) {
43 WARN(1, "RISCV_ISA_V only supports one vlenb on SMP systems");
50 static bool insn_is_vector(u32 insn_buf)
52 u32 opcode = insn_buf & __INSN_OPCODE_MASK;
56 * All V-related instructions, including CSR operations are 4-Byte. So,
57 * do not handle if the instruction length is not 4-Byte.
59 if (unlikely(GET_INSN_LENGTH(insn_buf) != 4))
63 case RVV_OPCODE_VECTOR:
67 width = RVV_EXRACT_VL_VS_WIDTH(insn_buf);
68 if (width == RVV_VL_VS_WIDTH_8 || width == RVV_VL_VS_WIDTH_16 ||
69 width == RVV_VL_VS_WIDTH_32 || width == RVV_VL_VS_WIDTH_64)
73 case RVG_OPCODE_SYSTEM:
74 csr = RVG_EXTRACT_SYSTEM_CSR(insn_buf);
75 if ((csr >= CSR_VSTART && csr <= CSR_VCSR) ||
76 (csr >= CSR_VL && csr <= CSR_VLENB))
83 static int riscv_v_thread_zalloc(void)
87 datap = kzalloc(riscv_v_vsize, GFP_KERNEL);
91 current->thread.vstate.datap = datap;
92 memset(¤t->thread.vstate, 0, offsetof(struct __riscv_v_ext_state,
97 #define VSTATE_CTRL_GET_CUR(x) ((x) & PR_RISCV_V_VSTATE_CTRL_CUR_MASK)
98 #define VSTATE_CTRL_GET_NEXT(x) (((x) & PR_RISCV_V_VSTATE_CTRL_NEXT_MASK) >> 2)
99 #define VSTATE_CTRL_MAKE_NEXT(x) (((x) << 2) & PR_RISCV_V_VSTATE_CTRL_NEXT_MASK)
100 #define VSTATE_CTRL_GET_INHERIT(x) (!!((x) & PR_RISCV_V_VSTATE_CTRL_INHERIT))
101 static inline int riscv_v_ctrl_get_cur(struct task_struct *tsk)
103 return VSTATE_CTRL_GET_CUR(tsk->thread.vstate_ctrl);
106 static inline int riscv_v_ctrl_get_next(struct task_struct *tsk)
108 return VSTATE_CTRL_GET_NEXT(tsk->thread.vstate_ctrl);
111 static inline bool riscv_v_ctrl_test_inherit(struct task_struct *tsk)
113 return VSTATE_CTRL_GET_INHERIT(tsk->thread.vstate_ctrl);
116 static inline void riscv_v_ctrl_set(struct task_struct *tsk, int cur, int nxt,
121 ctrl = cur & PR_RISCV_V_VSTATE_CTRL_CUR_MASK;
122 ctrl |= VSTATE_CTRL_MAKE_NEXT(nxt);
124 ctrl |= PR_RISCV_V_VSTATE_CTRL_INHERIT;
125 tsk->thread.vstate_ctrl = ctrl;
128 bool riscv_v_vstate_ctrl_user_allowed(void)
130 return riscv_v_ctrl_get_cur(current) == PR_RISCV_V_VSTATE_CTRL_ON;
132 EXPORT_SYMBOL_GPL(riscv_v_vstate_ctrl_user_allowed);
134 bool riscv_v_first_use_handler(struct pt_regs *regs)
136 u32 __user *epc = (u32 __user *)regs->epc;
137 u32 insn = (u32)regs->badaddr;
139 /* Do not handle if V is not supported, or disabled */
140 if (!(ELF_HWCAP & COMPAT_HWCAP_ISA_V))
143 /* If V has been enabled then it is not the first-use trap */
144 if (riscv_v_vstate_query(regs))
147 /* Get the instruction */
149 if (__get_user(insn, epc))
153 /* Filter out non-V instructions */
154 if (!insn_is_vector(insn))
157 /* Sanity check. datap should be null by the time of the first-use trap */
158 WARN_ON(current->thread.vstate.datap);
161 * Now we sure that this is a V instruction. And it executes in the
162 * context where VS has been off. So, try to allocate the user's V
163 * context and resume execution.
165 if (riscv_v_thread_zalloc()) {
169 riscv_v_vstate_on(regs);
170 riscv_v_vstate_restore(current, regs);
174 void riscv_v_vstate_ctrl_init(struct task_struct *tsk)
182 next = riscv_v_ctrl_get_next(tsk);
184 if (READ_ONCE(riscv_v_implicit_uacc))
185 cur = PR_RISCV_V_VSTATE_CTRL_ON;
187 cur = PR_RISCV_V_VSTATE_CTRL_OFF;
191 /* Clear next mask if inherit-bit is not set */
192 inherit = riscv_v_ctrl_test_inherit(tsk);
194 next = PR_RISCV_V_VSTATE_CTRL_DEFAULT;
196 riscv_v_ctrl_set(tsk, cur, next, inherit);
199 long riscv_v_vstate_ctrl_get_current(void)
204 return current->thread.vstate_ctrl & PR_RISCV_V_VSTATE_CTRL_MASK;
207 long riscv_v_vstate_ctrl_set_current(unsigned long arg)
215 if (arg & ~PR_RISCV_V_VSTATE_CTRL_MASK)
218 cur = VSTATE_CTRL_GET_CUR(arg);
220 case PR_RISCV_V_VSTATE_CTRL_OFF:
221 /* Do not allow user to turn off V if current is not off */
222 if (riscv_v_ctrl_get_cur(current) != PR_RISCV_V_VSTATE_CTRL_OFF)
226 case PR_RISCV_V_VSTATE_CTRL_ON:
228 case PR_RISCV_V_VSTATE_CTRL_DEFAULT:
229 cur = riscv_v_ctrl_get_cur(current);
235 next = VSTATE_CTRL_GET_NEXT(arg);
236 inherit = VSTATE_CTRL_GET_INHERIT(arg);
238 case PR_RISCV_V_VSTATE_CTRL_DEFAULT:
239 case PR_RISCV_V_VSTATE_CTRL_OFF:
240 case PR_RISCV_V_VSTATE_CTRL_ON:
241 riscv_v_ctrl_set(current, cur, next, inherit);
250 static struct ctl_table riscv_v_default_vstate_table[] = {
252 .procname = "riscv_v_default_allow",
253 .data = &riscv_v_implicit_uacc,
254 .maxlen = sizeof(riscv_v_implicit_uacc),
256 .proc_handler = proc_dobool,
260 static int __init riscv_v_sysctl_init(void)
263 if (!register_sysctl("abi", riscv_v_default_vstate_table))
268 #else /* ! CONFIG_SYSCTL */
269 static int __init riscv_v_sysctl_init(void) { return 0; }
270 #endif /* ! CONFIG_SYSCTL */
272 static int riscv_v_init(void)
274 return riscv_v_sysctl_init();
276 core_initcall(riscv_v_init);