Skip to content

Commit b8d1394

Browse files
guoren83avpatel
authored andcommitted
RISC-V: KVM: Prevent HGATP_MODE_BARE passed
Current kvm_riscv_gstage_mode_detect() assumes H-extension must have HGATP_MODE_SV39X4/SV32X4 at least, but the spec allows H-extension with HGATP_MODE_BARE alone. The KVM depends on !HGATP_MODE_BARE at least, so enhance the gstage-mode-detect to block HGATP_MODE_BARE. Move gstage-mode-check closer to gstage-mode-detect to prevent unnecessary init. Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Signed-off-by: Guo Ren (Alibaba DAMO Academy) <guoren@kernel.org> Reviewed-by: Fangyu Yu <fangyu.yu@linux.alibaba.com> Link: https://lore.kernel.org/r/20250821142542.2472079-4-guoren@kernel.org Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent 9eac374 commit b8d1394

2 files changed

Lines changed: 41 additions & 19 deletions

File tree

arch/riscv/kvm/gstage.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,18 +321,39 @@ void __init kvm_riscv_gstage_mode_detect(void)
321321
if ((csr_read(CSR_HGATP) >> HGATP_MODE_SHIFT) == HGATP_MODE_SV57X4) {
322322
kvm_riscv_gstage_mode = HGATP_MODE_SV57X4;
323323
kvm_riscv_gstage_pgd_levels = 5;
324-
goto skip_sv48x4_test;
324+
goto done;
325325
}
326326

327327
/* Try Sv48x4 G-stage mode */
328328
csr_write(CSR_HGATP, HGATP_MODE_SV48X4 << HGATP_MODE_SHIFT);
329329
if ((csr_read(CSR_HGATP) >> HGATP_MODE_SHIFT) == HGATP_MODE_SV48X4) {
330330
kvm_riscv_gstage_mode = HGATP_MODE_SV48X4;
331331
kvm_riscv_gstage_pgd_levels = 4;
332+
goto done;
332333
}
333-
skip_sv48x4_test:
334334

335+
/* Try Sv39x4 G-stage mode */
336+
csr_write(CSR_HGATP, HGATP_MODE_SV39X4 << HGATP_MODE_SHIFT);
337+
if ((csr_read(CSR_HGATP) >> HGATP_MODE_SHIFT) == HGATP_MODE_SV39X4) {
338+
kvm_riscv_gstage_mode = HGATP_MODE_SV39X4;
339+
kvm_riscv_gstage_pgd_levels = 3;
340+
goto done;
341+
}
342+
#else /* CONFIG_32BIT */
343+
/* Try Sv32x4 G-stage mode */
344+
csr_write(CSR_HGATP, HGATP_MODE_SV32X4 << HGATP_MODE_SHIFT);
345+
if ((csr_read(CSR_HGATP) >> HGATP_MODE_SHIFT) == HGATP_MODE_SV32X4) {
346+
kvm_riscv_gstage_mode = HGATP_MODE_SV32X4;
347+
kvm_riscv_gstage_pgd_levels = 2;
348+
goto done;
349+
}
350+
#endif
351+
352+
/* KVM depends on !HGATP_MODE_OFF */
353+
kvm_riscv_gstage_mode = HGATP_MODE_OFF;
354+
kvm_riscv_gstage_pgd_levels = 0;
355+
356+
done:
335357
csr_write(CSR_HGATP, 0);
336358
kvm_riscv_local_hfence_gvma_all();
337-
#endif
338359
}

arch/riscv/kvm/main.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,23 @@ static int __init riscv_kvm_init(void)
9393
return rc;
9494

9595
kvm_riscv_gstage_mode_detect();
96+
switch (kvm_riscv_gstage_mode) {
97+
case HGATP_MODE_SV32X4:
98+
str = "Sv32x4";
99+
break;
100+
case HGATP_MODE_SV39X4:
101+
str = "Sv39x4";
102+
break;
103+
case HGATP_MODE_SV48X4:
104+
str = "Sv48x4";
105+
break;
106+
case HGATP_MODE_SV57X4:
107+
str = "Sv57x4";
108+
break;
109+
default:
110+
kvm_riscv_nacl_exit();
111+
return -ENODEV;
112+
}
96113

97114
kvm_riscv_gstage_vmid_detect();
98115

@@ -135,22 +152,6 @@ static int __init riscv_kvm_init(void)
135152
(rc) ? slist : "no features");
136153
}
137154

138-
switch (kvm_riscv_gstage_mode) {
139-
case HGATP_MODE_SV32X4:
140-
str = "Sv32x4";
141-
break;
142-
case HGATP_MODE_SV39X4:
143-
str = "Sv39x4";
144-
break;
145-
case HGATP_MODE_SV48X4:
146-
str = "Sv48x4";
147-
break;
148-
case HGATP_MODE_SV57X4:
149-
str = "Sv57x4";
150-
break;
151-
default:
152-
return -ENODEV;
153-
}
154155
kvm_info("using %s G-stage page table format\n", str);
155156

156157
kvm_info("VMID %ld bits available\n", kvm_riscv_gstage_vmid_bits());

0 commit comments

Comments
 (0)