Commit 6d8e604c authored by Palmer Dabbelt's avatar Palmer Dabbelt

Merge patch series "Support Zve32[xf] and Zve64[xfd] Vector subextensions"

Andy Chiu <andy.chiu@sifive.com> says:

The series composes of two parts. The first part Specifically,
patch 1 adds a comment at a callsite of riscv_setup_vsize to clarify how
vlenb is observed by the system. Patch 2 fixes the issue by failing the
boot process of a secondary core if vlenb mismatches.

Here is the organization of the series:
 - Patch 1, 2 provide a fix for mismatching vlen problem [1]. The
   solution is to fail secondary cores if their vlenb is not the same as
   the boot core.
 - Patch 3 is a cleanup for introducing ZVE* Vector subextensions. It
   gives the obsolete ISA parser the ability to expand ISA extensions for
   sigle letter extensions.
 - Patch 4, 5, 6 introduce Zve32x, Zve32f, Zve64x, Zve64f, Zve64d for isa
   parsing and hwprobe, and document about it.
 - Patch 7 makes has_vector() check against ZVE32X instead of V, so most
   userspace Vector supports will be available for bare ZVE32X.
 - Patch 8 updates the prctl test so that it runs on ZVE32X.

The series is tested on a QEMU and verified that booting, Vector
programs context-switch, signal, ptrace, prctl interfaces works when we
only report partial V from the ISA.

* b4-shazam-lts:
  selftest: run vector prctl test for ZVE32X
  riscv: vector: adjust minimum Vector requirement to ZVE32X
  riscv: hwprobe: add zve Vector subextensions into hwprobe interface
  riscv: cpufeature: add zve32[xf] and zve64[xfd] isa detection
  dt-bindings: riscv: add Zve32[xf] Zve64[xfd] ISA extension description
  riscv: cpufeature: call match_isa_ext() for single-letter extensions
  riscv: vector: add a comment when calling riscv_setup_vsize()
  riscv: smp: fail booting up smp if inconsistent vlen is detected

[Palmer: reorder the first two patches so I can merge the fix, and
rebase this on v6.10-rc1 so it's a little easier to manage.]

Link: https://lore.kernel.org/r/20240510-zve-detection-v5-0-0711bdd26c12@sifive.comSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parents 1613e604 edc96a2b
......@@ -192,6 +192,21 @@ The following keys are defined:
supported as defined in the RISC-V ISA manual starting from commit
d8ab5c78c207 ("Zihintpause is ratified").
* :c:macro:`RISCV_HWPROBE_EXT_ZVE32X`: The Vector sub-extension Zve32x is
supported, as defined by version 1.0 of the RISC-V Vector extension manual.
* :c:macro:`RISCV_HWPROBE_EXT_ZVE32F`: The Vector sub-extension Zve32f is
supported, as defined by version 1.0 of the RISC-V Vector extension manual.
* :c:macro:`RISCV_HWPROBE_EXT_ZVE64X`: The Vector sub-extension Zve64x is
supported, as defined by version 1.0 of the RISC-V Vector extension manual.
* :c:macro:`RISCV_HWPROBE_EXT_ZVE64F`: The Vector sub-extension Zve64f is
supported, as defined by version 1.0 of the RISC-V Vector extension manual.
* :c:macro:`RISCV_HWPROBE_EXT_ZVE64D`: The Vector sub-extension Zve64d is
supported, as defined by version 1.0 of the RISC-V Vector extension manual.
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: A bitmask that contains performance
information about the selected set of processors.
......
......@@ -381,6 +381,36 @@ properties:
instructions, as ratified in commit 56ed795 ("Update
riscv-crypto-spec-vector.adoc") of riscv-crypto.
- const: zve32f
description:
The standard Zve32f extension for embedded processors, as ratified
in commit 6f702a2 ("Vector extensions are now ratified") of
riscv-v-spec.
- const: zve32x
description:
The standard Zve32x extension for embedded processors, as ratified
in commit 6f702a2 ("Vector extensions are now ratified") of
riscv-v-spec.
- const: zve64d
description:
The standard Zve64d extension for embedded processors, as ratified
in commit 6f702a2 ("Vector extensions are now ratified") of
riscv-v-spec.
- const: zve64f
description:
The standard Zve64f extension for embedded processors, as ratified
in commit 6f702a2 ("Vector extensions are now ratified") of
riscv-v-spec.
- const: zve64x
description:
The standard Zve64x extension for embedded processors, as ratified
in commit 6f702a2 ("Vector extensions are now ratified") of
riscv-v-spec.
- const: zvfh
description:
The standard Zvfh extension for vectored half-precision
......
......@@ -81,6 +81,11 @@
#define RISCV_ISA_EXT_ZTSO 72
#define RISCV_ISA_EXT_ZACAS 73
#define RISCV_ISA_EXT_XANDESPMU 74
#define RISCV_ISA_EXT_ZVE32X 75
#define RISCV_ISA_EXT_ZVE32F 76
#define RISCV_ISA_EXT_ZVE64X 77
#define RISCV_ISA_EXT_ZVE64F 78
#define RISCV_ISA_EXT_ZVE64D 79
#define RISCV_ISA_EXT_XLINUXENVCFG 127
......
......@@ -37,7 +37,7 @@ static inline u32 riscv_v_flags(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)
......@@ -91,7 +91,7 @@ static __always_inline void __vstate_csr_restore(struct __riscv_v_ext_state *src
{
asm volatile (
".option push\n\t"
".option arch, +v\n\t"
".option arch, +zve32x\n\t"
"vsetvl x0, %2, %1\n\t"
".option pop\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);
asm volatile (
".option push\n\t"
".option arch, +v\n\t"
".option arch, +zve32x\n\t"
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
"vse8.v v0, (%1)\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();
asm volatile (
".option push\n\t"
".option arch, +v\n\t"
".option arch, +zve32x\n\t"
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
"vle8.v v0, (%1)\n\t"
"add %1, %1, %0\n\t"
......@@ -153,7 +153,7 @@ static inline void __riscv_v_vstate_discard(void)
riscv_v_enable();
asm volatile (
".option push\n\t"
".option arch, +v\n\t"
".option arch, +zve32x\n\t"
"vsetvli %0, x0, e8, m8, ta, ma\n\t"
"vmv.v.i v0, -1\n\t"
"vmv.v.i v8, -1\n\t"
......
......@@ -60,6 +60,11 @@ struct riscv_hwprobe {
#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34)
#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35)
#define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36)
#define RISCV_HWPROBE_EXT_ZVE32X (1ULL << 37)
#define RISCV_HWPROBE_EXT_ZVE32F (1ULL << 38)
#define RISCV_HWPROBE_EXT_ZVE64X (1ULL << 39)
#define RISCV_HWPROBE_EXT_ZVE64F (1ULL << 40)
#define RISCV_HWPROBE_EXT_ZVE64D (1ULL << 41)
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
......
......@@ -188,6 +188,40 @@ static const unsigned int riscv_zvbb_exts[] = {
RISCV_ISA_EXT_ZVKB
};
#define RISCV_ISA_EXT_ZVE64F_IMPLY_LIST \
RISCV_ISA_EXT_ZVE64X, \
RISCV_ISA_EXT_ZVE32F, \
RISCV_ISA_EXT_ZVE32X
#define RISCV_ISA_EXT_ZVE64D_IMPLY_LIST \
RISCV_ISA_EXT_ZVE64F, \
RISCV_ISA_EXT_ZVE64F_IMPLY_LIST
#define RISCV_ISA_EXT_V_IMPLY_LIST \
RISCV_ISA_EXT_ZVE64D, \
RISCV_ISA_EXT_ZVE64D_IMPLY_LIST
static const unsigned int riscv_zve32f_exts[] = {
RISCV_ISA_EXT_ZVE32X
};
static const unsigned int riscv_zve64f_exts[] = {
RISCV_ISA_EXT_ZVE64F_IMPLY_LIST
};
static const unsigned int riscv_zve64d_exts[] = {
RISCV_ISA_EXT_ZVE64D_IMPLY_LIST
};
static const unsigned int riscv_v_exts[] = {
RISCV_ISA_EXT_V_IMPLY_LIST
};
static const unsigned int riscv_zve64x_exts[] = {
RISCV_ISA_EXT_ZVE32X,
RISCV_ISA_EXT_ZVE64X
};
/*
* While the [ms]envcfg CSRs were not defined until version 1.12 of the RISC-V
* privileged ISA, the existence of the CSRs is implied by any extension which
......@@ -245,7 +279,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(d, RISCV_ISA_EXT_d),
__RISCV_ISA_EXT_DATA(q, RISCV_ISA_EXT_q),
__RISCV_ISA_EXT_DATA(c, RISCV_ISA_EXT_c),
__RISCV_ISA_EXT_DATA(v, RISCV_ISA_EXT_v),
__RISCV_ISA_EXT_SUPERSET(v, RISCV_ISA_EXT_v, riscv_v_exts),
__RISCV_ISA_EXT_DATA(h, RISCV_ISA_EXT_h),
__RISCV_ISA_EXT_SUPERSET(zicbom, RISCV_ISA_EXT_ZICBOM, riscv_xlinuxenvcfg_exts),
__RISCV_ISA_EXT_SUPERSET(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts),
......@@ -280,6 +314,11 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(ztso, RISCV_ISA_EXT_ZTSO),
__RISCV_ISA_EXT_SUPERSET(zvbb, RISCV_ISA_EXT_ZVBB, riscv_zvbb_exts),
__RISCV_ISA_EXT_DATA(zvbc, RISCV_ISA_EXT_ZVBC),
__RISCV_ISA_EXT_SUPERSET(zve32f, RISCV_ISA_EXT_ZVE32F, riscv_zve32f_exts),
__RISCV_ISA_EXT_DATA(zve32x, RISCV_ISA_EXT_ZVE32X),
__RISCV_ISA_EXT_SUPERSET(zve64d, RISCV_ISA_EXT_ZVE64D, riscv_zve64d_exts),
__RISCV_ISA_EXT_SUPERSET(zve64f, RISCV_ISA_EXT_ZVE64F, riscv_zve64f_exts),
__RISCV_ISA_EXT_SUPERSET(zve64x, RISCV_ISA_EXT_ZVE64X, riscv_zve64x_exts),
__RISCV_ISA_EXT_DATA(zvfh, RISCV_ISA_EXT_ZVFH),
__RISCV_ISA_EXT_DATA(zvfhmin, RISCV_ISA_EXT_ZVFHMIN),
__RISCV_ISA_EXT_DATA(zvkb, RISCV_ISA_EXT_ZVKB),
......@@ -468,16 +507,15 @@ static void __init riscv_parse_isa_string(unsigned long *this_hwcap, struct risc
if (unlikely(ext_err))
continue;
for (int i = 0; i < riscv_isa_ext_count; i++)
match_isa_ext(&riscv_isa_ext[i], ext, ext_end, isainfo);
if (!ext_long) {
int nr = tolower(*ext) - 'a';
if (riscv_isa_extension_check(nr)) {
if (riscv_isa_extension_check(nr))
*this_hwcap |= isa2hwcap[nr];
set_bit(nr, isainfo->isa);
}
} else {
for (int i = 0; i < riscv_isa_ext_count; i++)
match_isa_ext(&riscv_isa_ext[i], ext, ext_end, isainfo);
}
}
}
......@@ -686,8 +724,14 @@ void __init riscv_fill_hwcap(void)
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
*/
riscv_v_setup_vsize();
}
if (elf_hwcap & COMPAT_HWCAP_ISA_V) {
/*
* ISA string in device tree might have 'v' flag, but
* CONFIG_RISCV_ISA_V is disabled in kernel.
......
......@@ -165,9 +165,20 @@ secondary_start_sbi:
#endif
call .Lsetup_trap_vector
scs_load_current
tail smp_callin
call smp_callin
#endif /* CONFIG_SMP */
.align 2
.Lsecondary_park:
/*
* Park this hart if we:
* - have too many harts on CONFIG_RISCV_BOOT_SPINWAIT
* - receive an early trap, before setup_trap_vector finished
* - fail in smp_callin(), as a successful one wouldn't return
*/
wfi
j .Lsecondary_park
.align 2
.Lsetup_trap_vector:
/* Set trap vector to exception handler */
......@@ -181,12 +192,6 @@ secondary_start_sbi:
csrw CSR_SCRATCH, zero
ret
.align 2
.Lsecondary_park:
/* We lack SMP support or have too many harts, so park this hart */
wfi
j .Lsecondary_park
SYM_CODE_END(_start)
SYM_CODE_START(_start_kernel)
......
......@@ -214,6 +214,15 @@ asmlinkage __visible void smp_callin(void)
struct mm_struct *mm = &init_mm;
unsigned int curr_cpuid = smp_processor_id();
if (has_vector()) {
/*
* Return as early as possible so the hart with a mismatching
* vlen won't boot.
*/
if (riscv_v_setup_vsize())
return;
}
/* All kernel threads share the same mm context. */
mmgrab(mm);
current->active_mm = mm;
......@@ -226,11 +235,6 @@ asmlinkage __visible void smp_callin(void)
numa_add_cpu(curr_cpuid);
set_cpu_online(curr_cpuid, true);
if (has_vector()) {
if (riscv_v_setup_vsize())
elf_hwcap &= ~COMPAT_HWCAP_ISA_V;
}
riscv_user_isa_enable();
/*
......
......@@ -69,7 +69,7 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
if (riscv_isa_extension_available(NULL, 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;
/*
......@@ -113,7 +113,16 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
EXT_KEY(ZICOND);
EXT_KEY(ZIHINTPAUSE);
/*
* All the following extensions must depend on the kernel
* support of V.
*/
if (has_vector()) {
EXT_KEY(ZVE32X);
EXT_KEY(ZVE32F);
EXT_KEY(ZVE64X);
EXT_KEY(ZVE64F);
EXT_KEY(ZVE64D);
EXT_KEY(ZVBB);
EXT_KEY(ZVBC);
EXT_KEY(ZVKB);
......
......@@ -173,8 +173,11 @@ bool riscv_v_first_use_handler(struct pt_regs *regs)
u32 __user *epc = (u32 __user *)regs->epc;
u32 insn = (u32)regs->badaddr;
if (!has_vector())
return false;
/* 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;
/* If V has been enabled then it is not the first-use trap */
......
......@@ -14,7 +14,7 @@
SYM_FUNC_START(__asm_copy_to_user)
#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
bltu a2, t0, fallback_scalar_usercopy
tail enter_vector_usercopy
......
......@@ -88,16 +88,16 @@ int main(void)
return -2;
}
if (!(pair.value & RISCV_HWPROBE_IMA_V)) {
if (!(pair.value & RISCV_HWPROBE_EXT_ZVE32X)) {
rc = prctl(PR_RISCV_V_GET_CONTROL);
if (rc != -1 || errno != EINVAL) {
ksft_test_result_fail("GET_CONTROL should fail on kernel/hw without V\n");
ksft_test_result_fail("GET_CONTROL should fail on kernel/hw without ZVE32X\n");
return -3;
}
rc = prctl(PR_RISCV_V_SET_CONTROL, PR_RISCV_V_VSTATE_CTRL_ON);
if (rc != -1 || errno != EINVAL) {
ksft_test_result_fail("GET_CONTROL should fail on kernel/hw without V\n");
ksft_test_result_fail("SET_CONTROL should fail on kernel/hw without ZVE32X\n");
return -4;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment