Unverified Commit 4bf88607 authored by Jisheng Zhang's avatar Jisheng Zhang Committed by Palmer Dabbelt
Browse files

riscv: cpufeature: extend riscv_cpufeature_patch_func to all ISA extensions



riscv_cpufeature_patch_func() currently only scans a limited set of
cpufeatures, explicitly defined with macros. Extend it to probe for all
ISA extensions.

Signed-off-by: default avatarJisheng Zhang <jszhang@kernel.org>
Reviewed-by: default avatarAndrew Jones <ajones@ventanamicro.com>
Reviewed-by: default avatarConor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20230128172856.3814-5-jszhang@kernel.org


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent d8a3d8a7
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@

#include <asm/alternative.h>
#include <asm/csr.h>
#include <asm/hwcap.h>
#include <asm/vendorid_list.h>

#ifdef CONFIG_ERRATA_SIFIVE
@@ -22,10 +23,6 @@
#define	ERRATA_THEAD_NUMBER 3
#endif

#define	CPUFEATURE_SVPBMT 0
#define	CPUFEATURE_ZICBOM 1
#define	CPUFEATURE_NUMBER 2

#ifdef __ASSEMBLY__

#define ALT_INSN_FAULT(x)						\
@@ -55,7 +52,7 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \
#define ALT_SVPBMT(_val, prot)						\
asm(ALTERNATIVE_2("li %0, 0\t\nnop",					\
		  "li %0, %1\t\nslli %0,%0,%3", 0,			\
			CPUFEATURE_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,	\
			RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,	\
		  "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID,	\
			ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)	\
		: "=r"(_val)						\
@@ -129,7 +126,7 @@ asm volatile(ALTERNATIVE_2( \
	"add a0, a0, %0\n\t"						\
	"2:\n\t"							\
	"bltu a0, %2, 3b\n\t"						\
	"nop", 0, CPUFEATURE_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,		\
	"nop", 0, RISCV_ISA_EXT_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,	\
	"mv a0, %1\n\t"							\
	"j 2f\n\t"							\
	"3:\n\t"							\
+8 −56
Original line number Diff line number Diff line
@@ -276,59 +276,11 @@ void __init riscv_fill_hwcap(void)
}

#ifdef CONFIG_RISCV_ALTERNATIVE
static bool __init_or_module cpufeature_probe_svpbmt(unsigned int stage)
{
	if (!IS_ENABLED(CONFIG_RISCV_ISA_SVPBMT))
		return false;

	if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
		return false;

	return riscv_isa_extension_available(NULL, SVPBMT);
}

static bool __init_or_module cpufeature_probe_zicbom(unsigned int stage)
{
	if (!IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM))
		return false;

	if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
		return false;

	if (!riscv_isa_extension_available(NULL, ZICBOM))
		return false;

	return true;
}

/*
 * Probe presence of individual extensions.
 *
 * This code may also be executed before kernel relocation, so we cannot use
 * addresses generated by the address-of operator as they won't be valid in
 * this context.
 * Tests, unless otherwise required, are to be added in alphabetical order.
 */
static u32 __init_or_module cpufeature_probe(unsigned int stage)
{
	u32 cpu_req_feature = 0;

	if (cpufeature_probe_svpbmt(stage))
		cpu_req_feature |= BIT(CPUFEATURE_SVPBMT);

	if (cpufeature_probe_zicbom(stage))
		cpu_req_feature |= BIT(CPUFEATURE_ZICBOM);

	return cpu_req_feature;
}

void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
						  struct alt_entry *end,
						  unsigned int stage)
{
	u32 cpu_req_feature = cpufeature_probe(stage);
	struct alt_entry *alt;
	u32 tmp;

	if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
		return;
@@ -336,18 +288,18 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
	for (alt = begin; alt < end; alt++) {
		if (alt->vendor_id != 0)
			continue;
		if (alt->errata_id >= CPUFEATURE_NUMBER) {
			WARN(1, "This feature id:%d is not in kernel cpufeature list",
		if (alt->errata_id >= RISCV_ISA_EXT_MAX) {
			WARN(1, "This extension id:%d is not in ISA extension list",
				alt->errata_id);
			continue;
		}

		tmp = (1U << alt->errata_id);
		if (cpu_req_feature & tmp) {
		if (!__riscv_isa_extension_available(NULL, alt->errata_id))
			continue;

		patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
		riscv_alternative_fix_offsets(alt->old_ptr, alt->alt_len,
					      alt->old_ptr - alt->alt_ptr);
	}
}
}
#endif