Skip to content

Commit 19ccf29

Browse files
RISC-V: Filter ISA and MMU values in cpuinfo
We shouldn't be directly passing device tree values to userspace, both because there could be mistakes in device trees and because the kernel doesn't support arbitrary ISAs. Signed-off-by: Palmer Dabbelt <palmer@sifive.com> [Atish: checkpatch fix and code comment formatting update] Signed-off-by: Atish Patra <atish.patra@wdc.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
1 parent 566d6c4 commit 19ccf29

File tree

1 file changed

+61
-7
lines changed

1 file changed

+61
-7
lines changed

arch/riscv/kernel/cpu.c

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,63 @@ int riscv_of_processor_hart(struct device_node *node)
5858

5959
#ifdef CONFIG_PROC_FS
6060

61+
static void print_isa(struct seq_file *f, const char *orig_isa)
62+
{
63+
static const char *ext = "mafdc";
64+
const char *isa = orig_isa;
65+
const char *e;
66+
67+
/*
68+
* Linux doesn't support rv32e or rv128i, and we only support booting
69+
* kernels on harts with the same ISA that the kernel is compiled for.
70+
*/
71+
#if defined(CONFIG_32BIT)
72+
if (strncmp(isa, "rv32i", 5) != 0)
73+
return;
74+
#elif defined(CONFIG_64BIT)
75+
if (strncmp(isa, "rv64i", 5) != 0)
76+
return;
77+
#endif
78+
79+
/* Print the base ISA, as we already know it's legal. */
80+
seq_puts(f, "isa\t: ");
81+
seq_write(f, isa, 5);
82+
isa += 5;
83+
84+
/*
85+
* Check the rest of the ISA string for valid extensions, printing those
86+
* we find. RISC-V ISA strings define an order, so we only print the
87+
* extension bits when they're in order.
88+
*/
89+
for (e = ext; *e != '\0'; ++e) {
90+
if (isa[0] == e[0]) {
91+
seq_write(f, isa, 1);
92+
isa++;
93+
}
94+
}
95+
96+
/*
97+
* If we were given an unsupported ISA in the device tree then print
98+
* a bit of info describing what went wrong.
99+
*/
100+
if (isa[0] != '\0')
101+
pr_info("unsupported ISA \"%s\" in device tree", orig_isa);
102+
}
103+
104+
static void print_mmu(struct seq_file *f, const char *mmu_type)
105+
{
106+
#if defined(CONFIG_32BIT)
107+
if (strcmp(mmu_type, "riscv,sv32") != 0)
108+
return;
109+
#elif defined(CONFIG_64BIT)
110+
if (strcmp(mmu_type, "riscv,sv39") != 0 &&
111+
strcmp(mmu_type, "riscv,sv48") != 0)
112+
return;
113+
#endif
114+
115+
seq_printf(f, "mmu\t: %s\n", mmu_type+6);
116+
}
117+
61118
static void *c_start(struct seq_file *m, loff_t *pos)
62119
{
63120
*pos = cpumask_next(*pos - 1, cpu_online_mask);
@@ -83,13 +140,10 @@ static int c_show(struct seq_file *m, void *v)
83140
const char *compat, *isa, *mmu;
84141

85142
seq_printf(m, "hart\t: %lu\n", hart_id);
86-
if (!of_property_read_string(node, "riscv,isa", &isa)
87-
&& isa[0] == 'r'
88-
&& isa[1] == 'v')
89-
seq_printf(m, "isa\t: %s\n", isa);
90-
if (!of_property_read_string(node, "mmu-type", &mmu)
91-
&& !strncmp(mmu, "riscv,", 6))
92-
seq_printf(m, "mmu\t: %s\n", mmu+6);
143+
if (!of_property_read_string(node, "riscv,isa", &isa))
144+
print_isa(m, isa);
145+
if (!of_property_read_string(node, "mmu-type", &mmu))
146+
print_mmu(m, mmu);
93147
if (!of_property_read_string(node, "compatible", &compat)
94148
&& strcmp(compat, "riscv"))
95149
seq_printf(m, "uarch\t: %s\n", compat);

0 commit comments

Comments
 (0)