summaryrefslogtreecommitdiffstats
path: root/arch/riscv/kernel/cpufeature.c
diff options
context:
space:
mode:
authorAtish Patra <atishp@rivosinc.com>2022-03-14 21:38:43 +0100
committerPalmer Dabbelt <palmer@rivosinc.com>2022-03-17 20:18:00 +0100
commit02d52fbd940af7d7fe0a523e99938113b2addd35 (patch)
treeb31a40200efc8cc7468c87d119cca05e389a6661 /arch/riscv/kernel/cpufeature.c
parentRISC-V: Extract multi-letter extension names from "riscv, isa" (diff)
downloadlinux-02d52fbd940af7d7fe0a523e99938113b2addd35.tar.xz
linux-02d52fbd940af7d7fe0a523e99938113b2addd35.zip
RISC-V: Implement multi-letter ISA extension probing framework
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. Tested-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Atish Patra <atishp@rivosinc.com> Reviewed-by: Anup Patel <anup@brainfault.org> Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Diffstat (limited to 'arch/riscv/kernel/cpufeature.c')
-rw-r--r--arch/riscv/kernel/cpufeature.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index b0df7eff47f7..3455fdfd680e 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -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;
@@ -172,12 +173,20 @@ 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); \
+ } 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
}
/*
@@ -190,10 +199,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
@@ -207,7 +217,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++)