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

riscv: Introduce vendor variants of extension helpers



Vendor extensions are maintained in per-vendor structs (separate from
standard extensions which live in riscv_isa). Create vendor variants for
the existing extension helpers to interface with the riscv_isa_vendor
bitmaps.

Signed-off-by: default avatarCharlie Jenkins <charlie@rivosinc.com>
Reviewed-by: default avatarConor Dooley <conor.dooley@microchip.com>
Reviewed-by: default avatarAndy Chiu <andy.chiu@sifive.com>
Link: https://lore.kernel.org/r/20240719-support_vendor_extensions-v3-3-0af7587bbec0@rivosinc.com


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 9448d9ac
Loading
Loading
Loading
Loading
+83 −0
Original line number Diff line number Diff line
@@ -42,8 +42,91 @@ extern const size_t riscv_isa_vendor_ext_list_size;
#define VENDOR_EXT_ALL_CPUS			-1

bool __riscv_isa_vendor_extension_available(int cpu, unsigned long vendor, unsigned int bit);
#define riscv_cpu_isa_vendor_extension_available(cpu, vendor, ext)	\
	__riscv_isa_vendor_extension_available(cpu, vendor, RISCV_ISA_VENDOR_EXT_##ext)
#define riscv_isa_vendor_extension_available(vendor, ext)	\
	__riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, \
					       RISCV_ISA_VENDOR_EXT_##ext)

static __always_inline bool __riscv_has_extension_likely(const unsigned long vendor,
							 const unsigned long ext)
{
	asm goto(ALTERNATIVE("j	%l[l_no]", "nop", %[vendor], %[ext], 1)
	:
	: [vendor] "i" (vendor), [ext] "i" (ext)
	:
	: l_no);

	return true;
l_no:
	return false;
}

static __always_inline bool __riscv_has_extension_unlikely(const unsigned long vendor,
							   const unsigned long ext)
{
	asm goto(ALTERNATIVE("nop", "j	%l[l_yes]", %[vendor], %[ext], 1)
	:
	: [vendor] "i" (vendor), [ext] "i" (ext)
	:
	: l_yes);

	return false;
l_yes:
	return true;
}

static __always_inline bool riscv_has_vendor_extension_likely(const unsigned long vendor,
							      const unsigned long ext)
{
	if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
		return false;

	if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
		return __riscv_has_extension_likely(vendor,
						    ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE);

	return __riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, ext);
}

static __always_inline bool riscv_has_vendor_extension_unlikely(const unsigned long vendor,
								const unsigned long ext)
{
	if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
		return false;

	if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE))
		return __riscv_has_extension_unlikely(vendor,
						      ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE);

	return __riscv_isa_vendor_extension_available(VENDOR_EXT_ALL_CPUS, vendor, ext);
}

static __always_inline bool riscv_cpu_has_vendor_extension_likely(const unsigned long vendor,
								  int cpu, const unsigned long ext)
{
	if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
		return false;

	if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
	    __riscv_has_extension_likely(vendor, ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE))
		return true;

	return __riscv_isa_vendor_extension_available(cpu, vendor, ext);
}

static __always_inline bool riscv_cpu_has_vendor_extension_unlikely(const unsigned long vendor,
								    int cpu,
								    const unsigned long ext)
{
	if (!IS_ENABLED(CONFIG_RISCV_ISA_VENDOR_EXT))
		return false;

	if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
	    __riscv_has_extension_unlikely(vendor, ext + RISCV_VENDOR_EXT_ALTERNATIVES_BASE))
		return true;

	return __riscv_isa_vendor_extension_available(cpu, vendor, ext);
}

#endif /* _ASM_VENDOR_EXTENSIONS_H */
+2 −1
Original line number Diff line number Diff line
@@ -1064,7 +1064,8 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde
		   riscv_cached_mimpid(0) == 0) {
		riscv_pmu_irq_num = THEAD_C9XX_RV_IRQ_PMU;
		riscv_pmu_use_irq = true;
	} else if (riscv_isa_vendor_extension_available(ANDES_VENDOR_ID, XANDESPMU) &&
	} else if (riscv_has_vendor_extension_unlikely(ANDES_VENDOR_ID,
						       RISCV_ISA_VENDOR_EXT_XANDESPMU) &&
		   IS_ENABLED(CONFIG_ANDES_CUSTOM_PMU)) {
		riscv_pmu_irq_num = ANDES_SLI_CAUSE_BASE + ANDES_RV_IRQ_PMOVI;
		riscv_pmu_use_irq = true;