]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
riscv: Introduce vendor variants of extension helpers
authorCharlie Jenkins <charlie@rivosinc.com>
Fri, 19 Jul 2024 16:15:20 +0000 (09:15 -0700)
committerPalmer Dabbelt <palmer@rivosinc.com>
Mon, 22 Jul 2024 22:36:56 +0000 (15:36 -0700)
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: Charlie Jenkins <charlie@rivosinc.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Andy Chiu <andy.chiu@sifive.com>
Link: https://lore.kernel.org/r/20240719-support_vendor_extensions-v3-3-0af7587bbec0@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/include/asm/vendor_extensions.h
drivers/perf/riscv_pmu_sbi.c

index 5fca550fc1f6136b7417dd34165e08247e95ff60..04d72b02ae6b934e75b09117a0e6d4be843a0462 100644 (file)
@@ -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 */
index 02719e0c636875d2eb0a767a93ae0a28be83a1dd..e1f0edfb7dcc35ea1275e5e5c787506faaa9e816 100644 (file)
@@ -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;