diff options
author | Yangyu Chen <cyy@cyyself.name> | 2023-05-01 19:17:38 +0300 |
---|---|---|
committer | Palmer Dabbelt <palmer@rivosinc.com> | 2023-06-07 01:19:30 +0300 |
commit | 255b34d799ddaaef5e8672b96c47a3b94fe85da9 (patch) | |
tree | ac66d9bce362846718cd1a625c56967bab03e474 /arch/riscv/kernel/cpufeature.c | |
parent | ac9a78681b921877518763ba0e89202254349d1b (diff) | |
download | linux-255b34d799ddaaef5e8672b96c47a3b94fe85da9.tar.xz |
riscv: allow case-insensitive ISA string parsing
According to RISC-V Hart Capabilities Table (RHCT) description in UEFI
Forum ECR, the format of the ISA string is defined in the RISC-V
unprivileged specification which is case-insensitive. However, the
current ISA string parser in the kernel does not support ISA strings
with uppercase letters.
This patch modifies the ISA string parser in the kernel to support
case-insensitive ISA string parsing.
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Yangyu Chen <cyy@cyyself.name>
Link: https://lore.kernel.org/r/tencent_B30EED51C7235CA1988890E5C658BE35C107@qq.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Diffstat (limited to 'arch/riscv/kernel/cpufeature.c')
-rw-r--r-- | arch/riscv/kernel/cpufeature.c | 35 |
1 files changed, 17 insertions, 18 deletions
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index b1d6b7e4b829..157687965ce5 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -127,13 +127,10 @@ void __init riscv_fill_hwcap(void) } temp = isa; -#if IS_ENABLED(CONFIG_32BIT) - if (!strncmp(isa, "rv32", 4)) + if (IS_ENABLED(CONFIG_32BIT) && !strncasecmp(isa, "rv32", 4)) isa += 4; -#elif IS_ENABLED(CONFIG_64BIT) - if (!strncmp(isa, "rv64", 4)) + else if (IS_ENABLED(CONFIG_64BIT) && !strncasecmp(isa, "rv64", 4)) isa += 4; -#endif /* The riscv,isa DT property must start with rv64 or rv32 */ if (temp == isa) continue; @@ -157,13 +154,15 @@ void __init riscv_fill_hwcap(void) break; } fallthrough; + case 'S': case 'x': + case 'X': case 'z': + case 'Z': ext_long = true; /* Multi-letter extension must be delimited */ for (; *isa && *isa != '_'; ++isa) - if (unlikely(!islower(*isa) - && !isdigit(*isa))) + if (unlikely(!isalnum(*isa))) ext_err = true; /* Parse backwards */ ext_end = isa; @@ -174,7 +173,7 @@ void __init riscv_fill_hwcap(void) /* Skip the minor version */ while (isdigit(*--ext_end)) ; - if (ext_end[0] != 'p' + if (tolower(ext_end[0]) != 'p' || !isdigit(ext_end[-1])) { /* Advance it to offset the pre-decrement */ ++ext_end; @@ -186,7 +185,7 @@ void __init riscv_fill_hwcap(void) ++ext_end; break; default: - if (unlikely(!islower(*ext))) { + if (unlikely(!isalpha(*ext))) { ext_err = true; break; } @@ -196,7 +195,7 @@ void __init riscv_fill_hwcap(void) /* Skip the minor version */ while (isdigit(*++isa)) ; - if (*isa != 'p') + if (tolower(*isa) != 'p') break; if (!isdigit(*++isa)) { --isa; @@ -210,18 +209,18 @@ 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) && \ - riscv_isa_extension_check(bit)) \ - set_bit(bit, this_isa); \ - } while (false) \ +#define SET_ISA_EXT_MAP(name, bit) \ + do { \ + if ((ext_end - ext == sizeof(name) - 1) && \ + !strncasecmp(ext, name, sizeof(name) - 1) && \ + riscv_isa_extension_check(bit)) \ + set_bit(bit, this_isa); \ + } while (false) \ if (unlikely(ext_err)) continue; if (!ext_long) { - int nr = *ext - 'a'; + int nr = tolower(*ext) - 'a'; if (riscv_isa_extension_check(nr)) { this_hwcap |= isa2hwcap[nr]; |