riscv: vector: adjust minimum Vector requirement to ZVE32X
Make has_vector() to check for ZVE32X. Every in-kernel usage of V that requires a more complicate version of V must then call out explicitly. Also, change riscv_v_first_use_handler(), and boot code that calls riscv_v_setup_vsize() to accept ZVE32X. Most kernel/user interfaces requires minimum of ZVE32X. Thus, programs compiled and run with ZVE32X should be supported by the kernel on most aspects. This includes context-switch, signal, ptrace, prctl, and hwprobe. One exception is that ELF_HWCAP returns 'V' only if full V is supported on the platform. This means that the system without a full V must not rely on ELF_HWCAP to tell whether it is allowable to execute Vector without first invoking a prctl() check. Signed-off-by: Andy Chiu <andy.chiu@sifive.com> Acked-by: Joel Granados <j.granados@samsung.com> Link: https://lore.kernel.org/r/20240510-zve-detection-v5-7-0711bdd26c12@sifive.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
parent
de8f8282a9
commit
ac295b6742
@ -37,7 +37,7 @@ static inline u32 riscv_v_flags(void)
|
|||||||
|
|
||||||
static __always_inline bool has_vector(void)
|
static __always_inline bool has_vector(void)
|
||||||
{
|
{
|
||||||
return riscv_has_extension_unlikely(RISCV_ISA_EXT_v);
|
return riscv_has_extension_unlikely(RISCV_ISA_EXT_ZVE32X);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __riscv_v_vstate_clean(struct pt_regs *regs)
|
static inline void __riscv_v_vstate_clean(struct pt_regs *regs)
|
||||||
@ -91,7 +91,7 @@ static __always_inline void __vstate_csr_restore(struct __riscv_v_ext_state *src
|
|||||||
{
|
{
|
||||||
asm volatile (
|
asm volatile (
|
||||||
".option push\n\t"
|
".option push\n\t"
|
||||||
".option arch, +v\n\t"
|
".option arch, +zve32x\n\t"
|
||||||
"vsetvl x0, %2, %1\n\t"
|
"vsetvl x0, %2, %1\n\t"
|
||||||
".option pop\n\t"
|
".option pop\n\t"
|
||||||
"csrw " __stringify(CSR_VSTART) ", %0\n\t"
|
"csrw " __stringify(CSR_VSTART) ", %0\n\t"
|
||||||
@ -109,7 +109,7 @@ static inline void __riscv_v_vstate_save(struct __riscv_v_ext_state *save_to,
|
|||||||
__vstate_csr_save(save_to);
|
__vstate_csr_save(save_to);
|
||||||
asm volatile (
|
asm volatile (
|
||||||
".option push\n\t"
|
".option push\n\t"
|
||||||
".option arch, +v\n\t"
|
".option arch, +zve32x\n\t"
|
||||||
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
||||||
"vse8.v v0, (%1)\n\t"
|
"vse8.v v0, (%1)\n\t"
|
||||||
"add %1, %1, %0\n\t"
|
"add %1, %1, %0\n\t"
|
||||||
@ -131,7 +131,7 @@ static inline void __riscv_v_vstate_restore(struct __riscv_v_ext_state *restore_
|
|||||||
riscv_v_enable();
|
riscv_v_enable();
|
||||||
asm volatile (
|
asm volatile (
|
||||||
".option push\n\t"
|
".option push\n\t"
|
||||||
".option arch, +v\n\t"
|
".option arch, +zve32x\n\t"
|
||||||
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
||||||
"vle8.v v0, (%1)\n\t"
|
"vle8.v v0, (%1)\n\t"
|
||||||
"add %1, %1, %0\n\t"
|
"add %1, %1, %0\n\t"
|
||||||
@ -153,7 +153,7 @@ static inline void __riscv_v_vstate_discard(void)
|
|||||||
riscv_v_enable();
|
riscv_v_enable();
|
||||||
asm volatile (
|
asm volatile (
|
||||||
".option push\n\t"
|
".option push\n\t"
|
||||||
".option arch, +v\n\t"
|
".option arch, +zve32x\n\t"
|
||||||
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
|
||||||
"vmv.v.i v0, -1\n\t"
|
"vmv.v.i v0, -1\n\t"
|
||||||
"vmv.v.i v8, -1\n\t"
|
"vmv.v.i v8, -1\n\t"
|
||||||
|
@ -724,11 +724,14 @@ void __init riscv_fill_hwcap(void)
|
|||||||
elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
|
elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elf_hwcap & COMPAT_HWCAP_ISA_V) {
|
if (__riscv_isa_extension_available(NULL, RISCV_ISA_EXT_ZVE32X)) {
|
||||||
/*
|
/*
|
||||||
* This cannot fail when called on the boot hart
|
* This cannot fail when called on the boot hart
|
||||||
*/
|
*/
|
||||||
riscv_v_setup_vsize();
|
riscv_v_setup_vsize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elf_hwcap & COMPAT_HWCAP_ISA_V) {
|
||||||
/*
|
/*
|
||||||
* ISA string in device tree might have 'v' flag, but
|
* ISA string in device tree might have 'v' flag, but
|
||||||
* CONFIG_RISCV_ISA_V is disabled in kernel.
|
* CONFIG_RISCV_ISA_V is disabled in kernel.
|
||||||
|
@ -69,7 +69,7 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
|
|||||||
if (riscv_isa_extension_available(NULL, c))
|
if (riscv_isa_extension_available(NULL, c))
|
||||||
pair->value |= RISCV_HWPROBE_IMA_C;
|
pair->value |= RISCV_HWPROBE_IMA_C;
|
||||||
|
|
||||||
if (has_vector())
|
if (has_vector() && riscv_isa_extension_available(NULL, v))
|
||||||
pair->value |= RISCV_HWPROBE_IMA_V;
|
pair->value |= RISCV_HWPROBE_IMA_V;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -113,6 +113,10 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
|
|||||||
EXT_KEY(ZICOND);
|
EXT_KEY(ZICOND);
|
||||||
EXT_KEY(ZIHINTPAUSE);
|
EXT_KEY(ZIHINTPAUSE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All the following extensions must depend on the kernel
|
||||||
|
* support of V.
|
||||||
|
*/
|
||||||
if (has_vector()) {
|
if (has_vector()) {
|
||||||
EXT_KEY(ZVE32X);
|
EXT_KEY(ZVE32X);
|
||||||
EXT_KEY(ZVE32F);
|
EXT_KEY(ZVE32F);
|
||||||
|
@ -173,8 +173,11 @@ bool riscv_v_first_use_handler(struct pt_regs *regs)
|
|||||||
u32 __user *epc = (u32 __user *)regs->epc;
|
u32 __user *epc = (u32 __user *)regs->epc;
|
||||||
u32 insn = (u32)regs->badaddr;
|
u32 insn = (u32)regs->badaddr;
|
||||||
|
|
||||||
|
if (!has_vector())
|
||||||
|
return false;
|
||||||
|
|
||||||
/* Do not handle if V is not supported, or disabled */
|
/* Do not handle if V is not supported, or disabled */
|
||||||
if (!(ELF_HWCAP & COMPAT_HWCAP_ISA_V))
|
if (!riscv_v_vstate_ctrl_user_allowed())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* If V has been enabled then it is not the first-use trap */
|
/* If V has been enabled then it is not the first-use trap */
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
SYM_FUNC_START(__asm_copy_to_user)
|
SYM_FUNC_START(__asm_copy_to_user)
|
||||||
#ifdef CONFIG_RISCV_ISA_V
|
#ifdef CONFIG_RISCV_ISA_V
|
||||||
ALTERNATIVE("j fallback_scalar_usercopy", "nop", 0, RISCV_ISA_EXT_v, CONFIG_RISCV_ISA_V)
|
ALTERNATIVE("j fallback_scalar_usercopy", "nop", 0, RISCV_ISA_EXT_ZVE32X, CONFIG_RISCV_ISA_V)
|
||||||
REG_L t0, riscv_v_usercopy_threshold
|
REG_L t0, riscv_v_usercopy_threshold
|
||||||
bltu a2, t0, fallback_scalar_usercopy
|
bltu a2, t0, fallback_scalar_usercopy
|
||||||
tail enter_vector_usercopy
|
tail enter_vector_usercopy
|
||||||
|
Loading…
Reference in New Issue
Block a user