mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
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.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
commit
6d8e604c95
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user