The riscv_cpuinfo struct that contains mvendorid and marchid is not populated until all harts are booted which happens after the DT parsing. Use the vendorid/archid values from the DT if available or assume all harts have the same values as the boot hart as a fallback.
Fixes: d82f32202e0d ("RISC-V: Ignore V from the riscv,isa DT property on older T-Head CPUs") Signed-off-by: Charlie Jenkins charlie@rivosinc.com --- arch/riscv/include/asm/sbi.h | 2 ++ arch/riscv/kernel/cpu.c | 20 ++++++++++++++++++++ arch/riscv/kernel/cpufeature.c | 22 ++++++++++++++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index 6e68f8dff76b..0fab508a65b3 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -370,6 +370,8 @@ static inline int sbi_remote_fence_i(const struct cpumask *cpu_mask) { return -1 static inline void sbi_init(void) {} #endif /* CONFIG_RISCV_SBI */
+unsigned long riscv_get_mvendorid(void); +unsigned long riscv_get_marchid(void); unsigned long riscv_cached_mvendorid(unsigned int cpu_id); unsigned long riscv_cached_marchid(unsigned int cpu_id); unsigned long riscv_cached_mimpid(unsigned int cpu_id); diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c index d11d6320fb0d..08319a819f32 100644 --- a/arch/riscv/kernel/cpu.c +++ b/arch/riscv/kernel/cpu.c @@ -139,6 +139,26 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid) return -1; }
+unsigned long __init riscv_get_marchid(void) +{ +#if IS_ENABLED(CONFIG_RISCV_SBI) + return sbi_spec_is_0_1() ? 0 : sbi_get_marchid(); +#elif IS_ENABLED(CONFIG_RISCV_M_MODE) + return csr_read(CSR_MARCHID); +#endif + return 0; +} + +unsigned long __init riscv_get_mvendorid(void) +{ +#if IS_ENABLED(CONFIG_RISCV_SBI) + return sbi_spec_is_0_1() ? 0 : sbi_get_mvendorid(); +#elif IS_ENABLED(CONFIG_RISCV_M_MODE) + return csr_read(CSR_MVENDORID); +#endif + return 0; +} + DEFINE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
unsigned long riscv_cached_mvendorid(unsigned int cpu_id) diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 3ed2359eae35..cd156adbeb66 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -490,6 +490,8 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap) struct acpi_table_header *rhct; acpi_status status; unsigned int cpu; + u64 boot_vendorid; + u64 boot_archid;
if (!acpi_disabled) { status = acpi_get_table(ACPI_SIG_RHCT, 0, &rhct); @@ -497,9 +499,14 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap) return; }
+ boot_vendorid = riscv_get_mvendorid(); + boot_archid = riscv_get_marchid(); + for_each_possible_cpu(cpu) { struct riscv_isainfo *isainfo = &hart_isa[cpu]; unsigned long this_hwcap = 0; + u64 this_vendorid; + u64 this_archid;
if (acpi_disabled) { node = of_cpu_device_node_get(cpu); @@ -514,12 +521,23 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap) pr_warn("Unable to find "riscv,isa" devicetree entry\n"); continue; } + if (of_property_read_u64(node, "riscv,vendorid", &this_vendorid) < 0) { + pr_warn("Unable to find "riscv,vendorid" devicetree entry, using boot hart mvendorid instead\n"); + this_vendorid = boot_vendorid; + } + + if (of_property_read_u64(node, "riscv,archid", &this_archid) < 0) { + pr_warn("Unable to find "riscv,vendorid" devicetree entry, using boot hart marchid instead\n"); + this_archid = boot_archid; + } } else { rc = acpi_get_riscv_isa(rhct, cpu, &isa); if (rc < 0) { pr_warn("Unable to get ISA for the hart - %d\n", cpu); continue; } + this_vendorid = boot_vendorid; + this_archid = boot_archid; }
riscv_parse_isa_string(&this_hwcap, isainfo, isa2hwcap, isa); @@ -544,8 +562,8 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap) * CPU cores with the ratified spec will contain non-zero * marchid. */ - if (acpi_disabled && riscv_cached_mvendorid(cpu) == THEAD_VENDOR_ID && - riscv_cached_marchid(cpu) == 0x0) { + if (acpi_disabled && this_vendorid == THEAD_VENDOR_ID && + this_archid == 0x0) { this_hwcap &= ~isa2hwcap[RISCV_ISA_EXT_v]; clear_bit(RISCV_ISA_EXT_v, isainfo->isa); }