RISC-V: Implement multi-letter ISA extension probing framework
authorAtish Patra <atishp@rivosinc.com>
Tue, 8 Feb 2022 22:58:38 +0000 (14:58 -0800)
committerminda.chen <minda.chen@starfivetech.com>
Tue, 3 Jan 2023 06:26:17 +0000 (14:26 +0800)
Multi-letter extensions can be probed using exising
riscv_isa_extension_available API now. It doesn't support versioning
right now as there is no use case for it.
Individual extension specific implementation will be added during
each extension support.

Signed-off-by: Atish Patra <atishp@rivosinc.com>
arch/riscv/include/asm/hwcap.h
arch/riscv/kernel/cpufeature.c

index 5ce5046..170bd80 100644 (file)
@@ -34,7 +34,25 @@ extern unsigned long elf_hwcap;
 #define RISCV_ISA_EXT_s                ('s' - 'a')
 #define RISCV_ISA_EXT_u                ('u' - 'a')
 
+/*
+ * Increse this to higher value as kernel support more ISA extensions.
+ */
 #define RISCV_ISA_EXT_MAX      64
+#define RISCV_ISA_EXT_NAME_LEN_MAX 32
+
+/* The base ID for multi-letter ISA extensions */
+#define RISCV_ISA_EXT_BASE 26
+
+/*
+ * This enum represent the logical ID for each multi-letter RISC-V ISA extension.
+ * The logical ID should start from RISCV_ISA_EXT_BASE and must not exceed
+ * RISCV_ISA_EXT_MAX. 0-25 range is reserved for single letter
+ * extensions while all the multi-letter extensions should define the next
+ * available logical extension id.
+ */
+enum riscv_isa_ext_id {
+       RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
+};
 
 unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
 
index cd9eb34..59c70c1 100644 (file)
@@ -83,7 +83,7 @@ void __init riscv_fill_hwcap(void)
 
        for_each_of_cpu_node(node) {
                unsigned long this_hwcap = 0;
-               unsigned long this_isa = 0;
+               DECLARE_BITMAP(this_isa, RISCV_ISA_EXT_MAX);
 
                if (riscv_of_processor_hartid(node) < 0)
                        continue;
@@ -100,6 +100,7 @@ void __init riscv_fill_hwcap(void)
                if (!strncmp(isa, "rv64", 4))
                        isa += 4;
 #endif
+               bitmap_zero(this_isa, RISCV_ISA_EXT_MAX);
                for (; *isa; ++isa) {
                        const char *ext = isa++;
                        const char *ext_end = isa;
@@ -167,12 +168,22 @@ void __init riscv_fill_hwcap(void)
                        if (*isa != '_')
                                --isa;
 
+#define SET_ISA_EXT_MAP(name, bit)                                             \
+                       do {                                                    \
+                               if ((ext_end - ext == sizeof(name) - 1) &&      \
+                                    !memcmp(ext, name, sizeof(name) - 1)) {    \
+                                       set_bit(bit, this_isa);                 \
+                                       pr_info("Found ISA extension %s", name);\
+                               }                                               \
+                       } while (false)                                         \
+
                        if (unlikely(ext_err))
                                continue;
                        if (!ext_long) {
                                this_hwcap |= isa2hwcap[(unsigned char)(*ext)];
-                               this_isa |= (1UL << (*ext - 'a'));
+                               set_bit(*ext - 'a', this_isa);
                        }
+#undef SET_ISA_EXT_MAP
                }
 
                /*
@@ -185,10 +196,11 @@ void __init riscv_fill_hwcap(void)
                else
                        elf_hwcap = this_hwcap;
 
-               if (riscv_isa[0])
-                       riscv_isa[0] &= this_isa;
+               if (bitmap_weight(riscv_isa, RISCV_ISA_EXT_MAX))
+                       bitmap_and(riscv_isa, riscv_isa, this_isa, RISCV_ISA_EXT_MAX);
                else
-                       riscv_isa[0] = this_isa;
+                       bitmap_copy(riscv_isa, this_isa, RISCV_ISA_EXT_MAX);
+
        }
 
        /* We don't support systems with F but without D, so mask those out
@@ -202,7 +214,7 @@ void __init riscv_fill_hwcap(void)
        for (i = 0, j = 0; i < NUM_ALPHA_EXTS; i++)
                if (riscv_isa[0] & BIT_MASK(i))
                        print_str[j++] = (char)('a' + i);
-       pr_info("riscv: ISA extensions %s\n", print_str);
+       pr_info("riscv: base ISA extensions %s\n", print_str);
 
        memset(print_str, 0, sizeof(print_str));
        for (i = 0, j = 0; i < NUM_ALPHA_EXTS; i++)