Skip to content

Commit 5fc7355

Browse files
SiFiveHollandpalmer-dabbelt
authored andcommitted
riscv: Add support for per-thread envcfg CSR values
Some bits in the [ms]envcfg CSR, such as the CFI state and pointer masking mode, need to be controlled on a per-thread basis. Support this by keeping a copy of the CSR value in struct thread_struct and writing it during context switches. It is safe to discard the old CSR value during the context switch because the CSR is modified only by software, so the CSR will remain in sync with the copy in thread_struct. Use ALTERNATIVE directly instead of riscv_has_extension_unlikely() to minimize branchiness in the context switching code. Since thread_struct is copied during fork(), setting the value for the init task sets the default value for all other threads. Reviewed-by: Andrew Jones <[email protected]> Reviewed-by: Deepak Gupta <[email protected]> Signed-off-by: Samuel Holland <[email protected]> Reviewed-by: Charlie Jenkins <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 1b57747 commit 5fc7355

File tree

3 files changed

+10
-1
lines changed

3 files changed

+10
-1
lines changed

arch/riscv/include/asm/processor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ struct thread_struct {
102102
unsigned long s[12]; /* s[0]: frame pointer */
103103
struct __riscv_d_ext_state fstate;
104104
unsigned long bad_cause;
105+
unsigned long envcfg;
105106
u32 riscv_v_flags;
106107
u32 vstate_ctrl;
107108
struct __riscv_v_ext_state vstate;

arch/riscv/include/asm/switch_to.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ static __always_inline bool has_fpu(void) { return false; }
7070
#define __switch_to_fpu(__prev, __next) do { } while (0)
7171
#endif
7272

73+
static inline void __switch_to_envcfg(struct task_struct *next)
74+
{
75+
asm volatile (ALTERNATIVE("nop", "csrw " __stringify(CSR_ENVCFG) ", %0",
76+
0, RISCV_ISA_EXT_XLINUXENVCFG, 1)
77+
:: "r" (next->thread.envcfg) : "memory");
78+
}
79+
7380
extern struct task_struct *__switch_to(struct task_struct *,
7481
struct task_struct *);
7582

@@ -103,6 +110,7 @@ do { \
103110
__switch_to_vector(__prev, __next); \
104111
if (switch_to_should_flush_icache(__next)) \
105112
local_flush_icache_all(); \
113+
__switch_to_envcfg(__next); \
106114
((last) = __switch_to(__prev, __next)); \
107115
} while (0)
108116

arch/riscv/kernel/cpufeature.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,7 @@ unsigned long riscv_get_elf_hwcap(void)
923923
void riscv_user_isa_enable(void)
924924
{
925925
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICBOZ))
926-
csr_set(CSR_ENVCFG, ENVCFG_CBZE);
926+
current->thread.envcfg |= ENVCFG_CBZE;
927927
else if (any_cpu_has_zicboz)
928928
pr_warn_once("Zicboz disabled as it is unavailable on some harts\n");
929929
}

0 commit comments

Comments
 (0)