mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-07 08:03:00 -04:00
Merge patch series "riscv: Per-thread envcfg CSR support"
Samuel Holland <samuel.holland@sifive.com> says: This series (or equivalent) is a prerequisite for both user-mode pointer masking and CFI support, as both of those are per-thread features and are controlled by fields in the envcfg CSR. These patches are based on v1 of the pointer masking series[1], with significant input from both Deepak and Andrew. [1]: https://lore.kernel.org/linux-riscv/20240319215915.832127-6-samuel.holland@sifive.com/ * b4-shazam-merge: riscv: Call riscv_user_isa_enable() only on the boot hart riscv: Add support for per-thread envcfg CSR values riscv: Enable cbo.zero only when all harts support Zicboz ink: https://lore.kernel.org/r/20240814081126.956287-1-samuel.holland@sifive.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
@@ -31,7 +31,7 @@ DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
|
||||
/* Per-cpu ISA extensions. */
|
||||
extern struct riscv_isainfo hart_isa[NR_CPUS];
|
||||
|
||||
void riscv_user_isa_enable(void);
|
||||
void __init riscv_user_isa_enable(void);
|
||||
|
||||
#define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \
|
||||
.name = #_name, \
|
||||
|
||||
@@ -102,6 +102,7 @@ struct thread_struct {
|
||||
unsigned long s[12]; /* s[0]: frame pointer */
|
||||
struct __riscv_d_ext_state fstate;
|
||||
unsigned long bad_cause;
|
||||
unsigned long envcfg;
|
||||
u32 riscv_v_flags;
|
||||
u32 vstate_ctrl;
|
||||
struct __riscv_v_ext_state vstate;
|
||||
|
||||
@@ -70,6 +70,13 @@ static __always_inline bool has_fpu(void) { return false; }
|
||||
#define __switch_to_fpu(__prev, __next) do { } while (0)
|
||||
#endif
|
||||
|
||||
static inline void __switch_to_envcfg(struct task_struct *next)
|
||||
{
|
||||
asm volatile (ALTERNATIVE("nop", "csrw " __stringify(CSR_ENVCFG) ", %0",
|
||||
0, RISCV_ISA_EXT_XLINUXENVCFG, 1)
|
||||
:: "r" (next->thread.envcfg) : "memory");
|
||||
}
|
||||
|
||||
extern struct task_struct *__switch_to(struct task_struct *,
|
||||
struct task_struct *);
|
||||
|
||||
@@ -103,6 +110,7 @@ do { \
|
||||
__switch_to_vector(__prev, __next); \
|
||||
if (switch_to_should_flush_icache(__next)) \
|
||||
local_flush_icache_all(); \
|
||||
__switch_to_envcfg(__next); \
|
||||
((last) = __switch_to(__prev, __next)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#define NUM_ALPHA_EXTS ('z' - 'a' + 1)
|
||||
|
||||
static bool any_cpu_has_zicboz;
|
||||
|
||||
unsigned long elf_hwcap __read_mostly;
|
||||
|
||||
/* Host ISA bitmap */
|
||||
@@ -98,6 +100,7 @@ static int riscv_ext_zicboz_validate(const struct riscv_isa_ext_data *data,
|
||||
pr_err("Zicboz disabled as cboz-block-size present, but is not a power-of-2\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
any_cpu_has_zicboz = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -917,10 +920,12 @@ unsigned long riscv_get_elf_hwcap(void)
|
||||
return hwcap;
|
||||
}
|
||||
|
||||
void riscv_user_isa_enable(void)
|
||||
void __init riscv_user_isa_enable(void)
|
||||
{
|
||||
if (riscv_cpu_has_extension_unlikely(smp_processor_id(), RISCV_ISA_EXT_ZICBOZ))
|
||||
csr_set(CSR_ENVCFG, ENVCFG_CBZE);
|
||||
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICBOZ))
|
||||
current->thread.envcfg |= ENVCFG_CBZE;
|
||||
else if (any_cpu_has_zicboz)
|
||||
pr_warn("Zicboz disabled as it is unavailable on some harts\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RISCV_ALTERNATIVE
|
||||
|
||||
@@ -233,8 +233,6 @@ asmlinkage __visible void smp_callin(void)
|
||||
numa_add_cpu(curr_cpuid);
|
||||
set_cpu_online(curr_cpuid, true);
|
||||
|
||||
riscv_user_isa_enable();
|
||||
|
||||
/*
|
||||
* Remote cache and TLB flushes are ignored while the CPU is offline,
|
||||
* so flush them both right now just in case.
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
void suspend_save_csrs(struct suspend_context *context)
|
||||
{
|
||||
if (riscv_cpu_has_extension_unlikely(smp_processor_id(), RISCV_ISA_EXT_XLINUXENVCFG))
|
||||
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_XLINUXENVCFG))
|
||||
context->envcfg = csr_read(CSR_ENVCFG);
|
||||
context->tvec = csr_read(CSR_TVEC);
|
||||
context->ie = csr_read(CSR_IE);
|
||||
@@ -37,7 +37,7 @@ void suspend_save_csrs(struct suspend_context *context)
|
||||
void suspend_restore_csrs(struct suspend_context *context)
|
||||
{
|
||||
csr_write(CSR_SCRATCH, 0);
|
||||
if (riscv_cpu_has_extension_unlikely(smp_processor_id(), RISCV_ISA_EXT_XLINUXENVCFG))
|
||||
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_XLINUXENVCFG))
|
||||
csr_write(CSR_ENVCFG, context->envcfg);
|
||||
csr_write(CSR_TVEC, context->tvec);
|
||||
csr_write(CSR_IE, context->ie);
|
||||
|
||||
Reference in New Issue
Block a user