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
);
24 static struct kmem_cache
*riscv_v_user_cachep
;
25 #ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
26 static struct kmem_cache
*riscv_v_kernel_cachep
;
29 unsigned long riscv_v_vsize __read_mostly
;
30 EXPORT_SYMBOL_GPL(riscv_v_vsize
);
32 int riscv_v_setup_vsize(void)
34 unsigned long this_vsize
;
36 /* There are 32 vector registers with vlenb length. */
38 this_vsize
= csr_read(CSR_VLENB
) * 32;
42 riscv_v_vsize
= this_vsize
;
46 if (riscv_v_vsize
!= this_vsize
) {
47 WARN(1, "RISCV_ISA_V only supports one vlenb on SMP systems");
54 void __init
riscv_v_setup_ctx_cache(void)
59 riscv_v_user_cachep
= kmem_cache_create_usercopy("riscv_vector_ctx",
60 riscv_v_vsize
, 16, SLAB_PANIC
,
61 0, riscv_v_vsize
, NULL
);
62 #ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
63 riscv_v_kernel_cachep
= kmem_cache_create("riscv_vector_kctx",
69 static bool insn_is_vector(u32 insn_buf
)
71 u32 opcode
= insn_buf
& __INSN_OPCODE_MASK
;
75 * All V-related instructions, including CSR operations are 4-Byte. So,
76 * do not handle if the instruction length is not 4-Byte.
78 if (unlikely(GET_INSN_LENGTH(insn_buf
) != 4))
82 case RVV_OPCODE_VECTOR
:
86 width
= RVV_EXRACT_VL_VS_WIDTH(insn_buf
);
87 if (width
== RVV_VL_VS_WIDTH_8
|| width
== RVV_VL_VS_WIDTH_16
||
88 width
== RVV_VL_VS_WIDTH_32
|| width
== RVV_VL_VS_WIDTH_64
)
92 case RVG_OPCODE_SYSTEM
:
93 csr
= RVG_EXTRACT_SYSTEM_CSR(insn_buf
);
94 if ((csr
>= CSR_VSTART
&& csr
<= CSR_VCSR
) ||
95 (csr
>= CSR_VL
&& csr
<= CSR_VLENB
))
102 static int riscv_v_thread_zalloc(struct kmem_cache
*cache
,
103 struct __riscv_v_ext_state
*ctx
)
107 datap
= kmem_cache_zalloc(cache
, GFP_KERNEL
);
112 memset(ctx
, 0, offsetof(struct __riscv_v_ext_state
, datap
));
116 void riscv_v_thread_alloc(struct task_struct
*tsk
)
118 #ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
119 riscv_v_thread_zalloc(riscv_v_kernel_cachep
, &tsk
->thread
.kernel_vstate
);
123 void riscv_v_thread_free(struct task_struct
*tsk
)
125 if (tsk
->thread
.vstate
.datap
)
126 kmem_cache_free(riscv_v_user_cachep
, tsk
->thread
.vstate
.datap
);
127 #ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
128 if (tsk
->thread
.kernel_vstate
.datap
)
129 kmem_cache_free(riscv_v_kernel_cachep
, tsk
->thread
.kernel_vstate
.datap
);
133 #define VSTATE_CTRL_GET_CUR(x) ((x) & PR_RISCV_V_VSTATE_CTRL_CUR_MASK)
134 #define VSTATE_CTRL_GET_NEXT(x) (((x) & PR_RISCV_V_VSTATE_CTRL_NEXT_MASK) >> 2)
135 #define VSTATE_CTRL_MAKE_NEXT(x) (((x) << 2) & PR_RISCV_V_VSTATE_CTRL_NEXT_MASK)
136 #define VSTATE_CTRL_GET_INHERIT(x) (!!((x) & PR_RISCV_V_VSTATE_CTRL_INHERIT))
137 static inline int riscv_v_ctrl_get_cur(struct task_struct
*tsk
)
139 return VSTATE_CTRL_GET_CUR(tsk
->thread
.vstate_ctrl
);
142 static inline int riscv_v_ctrl_get_next(struct task_struct
*tsk
)
144 return VSTATE_CTRL_GET_NEXT(tsk
->thread
.vstate_ctrl
);
147 static inline bool riscv_v_ctrl_test_inherit(struct task_struct
*tsk
)
149 return VSTATE_CTRL_GET_INHERIT(tsk
->thread
.vstate_ctrl
);
152 static inline void riscv_v_ctrl_set(struct task_struct
*tsk
, int cur
, int nxt
,
157 ctrl
= cur
& PR_RISCV_V_VSTATE_CTRL_CUR_MASK
;
158 ctrl
|= VSTATE_CTRL_MAKE_NEXT(nxt
);
160 ctrl
|= PR_RISCV_V_VSTATE_CTRL_INHERIT
;
161 tsk
->thread
.vstate_ctrl
&= ~PR_RISCV_V_VSTATE_CTRL_MASK
;
162 tsk
->thread
.vstate_ctrl
|= ctrl
;
165 bool riscv_v_vstate_ctrl_user_allowed(void)
167 return riscv_v_ctrl_get_cur(current
) == PR_RISCV_V_VSTATE_CTRL_ON
;
169 EXPORT_SYMBOL_GPL(riscv_v_vstate_ctrl_user_allowed
);
171 bool riscv_v_first_use_handler(struct pt_regs
*regs
)
173 u32 __user
*epc
= (u32 __user
*)regs
->epc
;
174 u32 insn
= (u32
)regs
->badaddr
;
179 /* Do not handle if V is not supported, or disabled */
180 if (!riscv_v_vstate_ctrl_user_allowed())
183 /* If V has been enabled then it is not the first-use trap */
184 if (riscv_v_vstate_query(regs
))
187 /* Get the instruction */
189 if (__get_user(insn
, epc
))
193 /* Filter out non-V instructions */
194 if (!insn_is_vector(insn
))
197 /* Sanity check. datap should be null by the time of the first-use trap */
198 WARN_ON(current
->thread
.vstate
.datap
);
201 * Now we sure that this is a V instruction. And it executes in the
202 * context where VS has been off. So, try to allocate the user's V
203 * context and resume execution.
205 if (riscv_v_thread_zalloc(riscv_v_user_cachep
, ¤t
->thread
.vstate
)) {
209 riscv_v_vstate_on(regs
);
210 riscv_v_vstate_set_restore(current
, regs
);
214 void riscv_v_vstate_ctrl_init(struct task_struct
*tsk
)
222 next
= riscv_v_ctrl_get_next(tsk
);
224 if (READ_ONCE(riscv_v_implicit_uacc
))
225 cur
= PR_RISCV_V_VSTATE_CTRL_ON
;
227 cur
= PR_RISCV_V_VSTATE_CTRL_OFF
;
231 /* Clear next mask if inherit-bit is not set */
232 inherit
= riscv_v_ctrl_test_inherit(tsk
);
234 next
= PR_RISCV_V_VSTATE_CTRL_DEFAULT
;
236 riscv_v_ctrl_set(tsk
, cur
, next
, inherit
);
239 long riscv_v_vstate_ctrl_get_current(void)
244 return current
->thread
.vstate_ctrl
& PR_RISCV_V_VSTATE_CTRL_MASK
;
247 long riscv_v_vstate_ctrl_set_current(unsigned long arg
)
255 if (arg
& ~PR_RISCV_V_VSTATE_CTRL_MASK
)
258 cur
= VSTATE_CTRL_GET_CUR(arg
);
260 case PR_RISCV_V_VSTATE_CTRL_OFF
:
261 /* Do not allow user to turn off V if current is not off */
262 if (riscv_v_ctrl_get_cur(current
) != PR_RISCV_V_VSTATE_CTRL_OFF
)
266 case PR_RISCV_V_VSTATE_CTRL_ON
:
268 case PR_RISCV_V_VSTATE_CTRL_DEFAULT
:
269 cur
= riscv_v_ctrl_get_cur(current
);
275 next
= VSTATE_CTRL_GET_NEXT(arg
);
276 inherit
= VSTATE_CTRL_GET_INHERIT(arg
);
278 case PR_RISCV_V_VSTATE_CTRL_DEFAULT
:
279 case PR_RISCV_V_VSTATE_CTRL_OFF
:
280 case PR_RISCV_V_VSTATE_CTRL_ON
:
281 riscv_v_ctrl_set(current
, cur
, next
, inherit
);
290 static struct ctl_table riscv_v_default_vstate_table
[] = {
292 .procname
= "riscv_v_default_allow",
293 .data
= &riscv_v_implicit_uacc
,
294 .maxlen
= sizeof(riscv_v_implicit_uacc
),
296 .proc_handler
= proc_dobool
,
300 static int __init
riscv_v_sysctl_init(void)
303 if (!register_sysctl("abi", riscv_v_default_vstate_table
))
308 #else /* ! CONFIG_SYSCTL */
309 static int __init
riscv_v_sysctl_init(void) { return 0; }
310 #endif /* ! CONFIG_SYSCTL */
312 static int riscv_v_init(void)
314 return riscv_v_sysctl_init();
316 core_initcall(riscv_v_init
);