Unverified Commit 1540def1 authored by Palmer Dabbelt's avatar Palmer Dabbelt
Browse files

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: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parents 9852d85e 368546eb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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,									\
+1 −0
Original line number Diff line number Diff line
@@ -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;
+8 −0
Original line number Diff line number Diff line
@@ -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)

+8 −3
Original line number Diff line number Diff line
@@ -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
+0 −2
Original line number Diff line number Diff line
@@ -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.
Loading