Unverified Commit e482eab4 authored by Charlie Jenkins's avatar Charlie Jenkins Committed by Palmer Dabbelt
Browse files

riscv: cpufeature: Fix thead vector hwcap removal



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: d82f3220 ("RISC-V: Ignore V from the riscv,isa DT property on older T-Head CPUs")
Signed-off-by: default avatarCharlie Jenkins <charlie@rivosinc.com>
Reviewed-by: default avatarConor Dooley <conor.dooley@microchip.com>
Reviewed-by: default avatarGuo Ren <guoren@kernel.org>
Link: https://lore.kernel.org/r/20240502-cpufeature_fixes-v4-1-b3d1a088722d@rivosinc.com


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 4cece764
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+36 −4
Original line number Diff line number Diff line
@@ -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,11 +198,15 @@ static int riscv_cpuinfo_starting(unsigned int cpu)
	struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo);

#if IS_ENABLED(CONFIG_RISCV_SBI)
	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)
	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
+6 −2
Original line number Diff line number Diff line
@@ -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);
		}