Skip to content

Commit 748462b

Browse files
Merge patch series "riscv: allow case-insensitive ISA string parsing"
Yangyu Chen <[email protected]> says: This patchset allows case-insensitive ISA string parsing, which is needed in the ACPI environment. As the RISC-V Hart Capabilities Table (RHCT) description in UEFI Forum ECR[1] shows the format of the ISA string is defined in the RISC-V unprivileged specification[2]. However, the RISC-V unprivileged specification defines the ISA naming strings are case-insensitive while the current ISA string parser in the kernel only accepts lowercase letters. In this case, the kernel should allow case-insensitive ISA string parsing. Moreover, this reason has been discussed in Conor's patch[3]. And I have also checked the current ISA string parsing in the recent ACPI support patch[4] will also call `riscv_fill_hwcap` function as DT we use now. The original motivation for my patch v1[5] is that some SoC generators will provide generated DT with illegal ISA string in dt-binding such as rocket-chip, which will even cause kernel panic in some cases as I mentioned in v1[5]. Now, the rocket-chip has been fixed in PR #3333[6]. However, when using some specific version of rocket-chip with illegal ISA string in DT, this patchset will also work for parsing uppercase letters correctly in DT, thus will have better compatibility. In summary, this patch not only works for case-insensitive ISA string parsing to meet the requirements in ECR[1] but also can be a workaround for some specific versions of rocket-chip. * b4-shazam-merge: dt-bindings: riscv: drop invalid comment about riscv,isa lower-case reasoning riscv: allow case-insensitive ISA string parsing Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
2 parents 90502d5 + 9e320d7 commit 748462b

File tree

3 files changed

+20
-20
lines changed

3 files changed

+20
-20
lines changed

Documentation/devicetree/bindings/riscv/cpus.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ properties:
9494

9595
While the isa strings in ISA specification are case
9696
insensitive, letters in the riscv,isa string must be all
97-
lowercase to simplify parsing.
97+
lowercase.
9898
$ref: "/schemas/types.yaml#/definitions/string"
9999
pattern: ^rv(?:64|32)imaf?d?q?c?b?k?j?p?v?h?(?:[hsxz](?:[a-z])+)?(?:_[hsxz](?:[a-z])+)*$
100100

arch/riscv/kernel/cpu.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <linux/acpi.h>
77
#include <linux/cpu.h>
8+
#include <linux/ctype.h>
89
#include <linux/init.h>
910
#include <linux/seq_file.h>
1011
#include <linux/of.h>
@@ -44,7 +45,7 @@ int riscv_of_processor_hartid(struct device_node *node, unsigned long *hart)
4445
pr_warn("CPU with hartid=%lu has no \"riscv,isa\" property\n", *hart);
4546
return -ENODEV;
4647
}
47-
if (isa[0] != 'r' || isa[1] != 'v') {
48+
if (tolower(isa[0]) != 'r' || tolower(isa[1]) != 'v') {
4849
pr_warn("CPU with hartid=%lu has an invalid ISA of \"%s\"\n", *hart, isa);
4950
return -ENODEV;
5051
}

arch/riscv/kernel/cpufeature.c

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,10 @@ void __init riscv_fill_hwcap(void)
150150
}
151151

152152
temp = isa;
153-
#if IS_ENABLED(CONFIG_32BIT)
154-
if (!strncmp(isa, "rv32", 4))
153+
if (IS_ENABLED(CONFIG_32BIT) && !strncasecmp(isa, "rv32", 4))
155154
isa += 4;
156-
#elif IS_ENABLED(CONFIG_64BIT)
157-
if (!strncmp(isa, "rv64", 4))
155+
else if (IS_ENABLED(CONFIG_64BIT) && !strncasecmp(isa, "rv64", 4))
158156
isa += 4;
159-
#endif
160157
/* The riscv,isa DT property must start with rv64 or rv32 */
161158
if (temp == isa)
162159
continue;
@@ -180,13 +177,15 @@ void __init riscv_fill_hwcap(void)
180177
break;
181178
}
182179
fallthrough;
180+
case 'S':
183181
case 'x':
182+
case 'X':
184183
case 'z':
184+
case 'Z':
185185
ext_long = true;
186186
/* Multi-letter extension must be delimited */
187187
for (; *isa && *isa != '_'; ++isa)
188-
if (unlikely(!islower(*isa)
189-
&& !isdigit(*isa)))
188+
if (unlikely(!isalnum(*isa)))
190189
ext_err = true;
191190
/* Parse backwards */
192191
ext_end = isa;
@@ -197,7 +196,7 @@ void __init riscv_fill_hwcap(void)
197196
/* Skip the minor version */
198197
while (isdigit(*--ext_end))
199198
;
200-
if (ext_end[0] != 'p'
199+
if (tolower(ext_end[0]) != 'p'
201200
|| !isdigit(ext_end[-1])) {
202201
/* Advance it to offset the pre-decrement */
203202
++ext_end;
@@ -209,7 +208,7 @@ void __init riscv_fill_hwcap(void)
209208
++ext_end;
210209
break;
211210
default:
212-
if (unlikely(!islower(*ext))) {
211+
if (unlikely(!isalpha(*ext))) {
213212
ext_err = true;
214213
break;
215214
}
@@ -219,7 +218,7 @@ void __init riscv_fill_hwcap(void)
219218
/* Skip the minor version */
220219
while (isdigit(*++isa))
221220
;
222-
if (*isa != 'p')
221+
if (tolower(*isa) != 'p')
223222
break;
224223
if (!isdigit(*++isa)) {
225224
--isa;
@@ -233,18 +232,18 @@ void __init riscv_fill_hwcap(void)
233232
if (*isa != '_')
234233
--isa;
235234

236-
#define SET_ISA_EXT_MAP(name, bit) \
237-
do { \
238-
if ((ext_end - ext == sizeof(name) - 1) && \
239-
!memcmp(ext, name, sizeof(name) - 1) && \
240-
riscv_isa_extension_check(bit)) \
241-
set_bit(bit, this_isa); \
242-
} while (false) \
235+
#define SET_ISA_EXT_MAP(name, bit) \
236+
do { \
237+
if ((ext_end - ext == sizeof(name) - 1) && \
238+
!strncasecmp(ext, name, sizeof(name) - 1) && \
239+
riscv_isa_extension_check(bit)) \
240+
set_bit(bit, this_isa); \
241+
} while (false) \
243242

244243
if (unlikely(ext_err))
245244
continue;
246245
if (!ext_long) {
247-
int nr = *ext - 'a';
246+
int nr = tolower(*ext) - 'a';
248247

249248
if (riscv_isa_extension_check(nr)) {
250249
this_hwcap |= isa2hwcap[nr];

0 commit comments

Comments
 (0)