riscv: cpufeature: Fix thead vector hwcap removal
authorCharlie Jenkins <charlie@rivosinc.com>
Fri, 3 May 2024 04:50:50 +0000 (21:50 -0700)
committerPalmer Dabbelt <palmer@rivosinc.com>
Wed, 22 May 2024 16:41:02 +0000 (09:41 -0700)
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 mvendorid/marchid from the boot hart to determine if the DT
contains an invalid V.

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>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Guo Ren <guoren@kernel.org>
Link: https://lore.kernel.org/r/20240502-cpufeature_fixes-v4-1-b3d1a088722d@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/include/asm/sbi.h
arch/riscv/kernel/cpu.c
arch/riscv/kernel/cpufeature.c

index 6e68f8dff76bc6d09f7a5e555e54474587021ed9..0fab508a65b3c9a68daf9cafd75ff658855e0f63 100644 (file)
@@ -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);
index d11d6320fb0d2db489f221ab2527297a247fd304..c1f3655238fd2b906db466295d5c3274c67d916c 100644 (file)
@@ -139,6 +139,34 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid)
        return -1;
 }
 
+unsigned long __init riscv_get_marchid(void)
+{
+       struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo);
+
+#if IS_ENABLED(CONFIG_RISCV_SBI)
+       ci->marchid = sbi_spec_is_0_1() ? 0 : sbi_get_marchid();
+#elif IS_ENABLED(CONFIG_RISCV_M_MODE)
+       ci->marchid = csr_read(CSR_MARCHID);
+#else
+       ci->marchid = 0;
+#endif
+       return ci->marchid;
+}
+
+unsigned long __init riscv_get_mvendorid(void)
+{
+       struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo);
+
+#if IS_ENABLED(CONFIG_RISCV_SBI)
+       ci->mvendorid = sbi_spec_is_0_1() ? 0 : sbi_get_mvendorid();
+#elif IS_ENABLED(CONFIG_RISCV_M_MODE)
+       ci->mvendorid = csr_read(CSR_MVENDORID);
+#else
+       ci->mvendorid = 0;
+#endif
+       return ci->mvendorid;
+}
+
 DEFINE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
 
 unsigned long riscv_cached_mvendorid(unsigned int cpu_id)
@@ -170,12 +198,16 @@ static int riscv_cpuinfo_starting(unsigned int cpu)
        struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo);
 
 #if IS_ENABLED(CONFIG_RISCV_SBI)
-       ci->mvendorid = sbi_spec_is_0_1() ? 0 : sbi_get_mvendorid();
-       ci->marchid = sbi_spec_is_0_1() ? 0 : sbi_get_marchid();
+       if (!ci->mvendorid)
+               ci->mvendorid = sbi_spec_is_0_1() ? 0 : sbi_get_mvendorid();
+       if (!ci->marchid)
+               ci->marchid = sbi_spec_is_0_1() ? 0 : sbi_get_marchid();
        ci->mimpid = sbi_spec_is_0_1() ? 0 : sbi_get_mimpid();
 #elif IS_ENABLED(CONFIG_RISCV_M_MODE)
-       ci->mvendorid = csr_read(CSR_MVENDORID);
-       ci->marchid = csr_read(CSR_MARCHID);
+       if (!ci->mvendorid)
+               ci->mvendorid = csr_read(CSR_MVENDORID);
+       if (!ci->marchid)
+               ci->marchid = csr_read(CSR_MARCHID);
        ci->mimpid = csr_read(CSR_MIMPID);
 #else
        ci->mvendorid = 0;
index 3ed2359eae353f863561c02983e4e5e5bf27603d..13d4fc0d1817ec048951a09d14eaf17cd5da2f9f 100644 (file)
@@ -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,6 +499,9 @@ 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;
@@ -544,8 +549,7 @@ 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 && boot_vendorid == THEAD_VENDOR_ID && boot_archid == 0x0) {
                        this_hwcap &= ~isa2hwcap[RISCV_ISA_EXT_v];
                        clear_bit(RISCV_ISA_EXT_v, isainfo->isa);
                }