[PATCH] RISC-V: KVM: Do not touch the envcfg CSRs on the SiFive P550
Davidlohr Bueso
dave at stgolabs.net
Thu Oct 15 13:09:34 PDT 2026
The SiFive P550 (ESWIN EIC7700X) implements the hypervisor extension
on a privileged spec 1.11 base, so it has neither henvcfg nor senvcfg.
KVM swaps senvcfg on every guest entry and writes henvcfg on vCPU load
regardless, and the host dies on the first guest entry:
Oops - illegal instruction [#1]
Modules linked in: kvm
CPU: 2 UID: 0 PID: 127 Comm: qemu-system-ris Not tainted 7.2.0-kvm73bug+ #4 PREEMPTLAZY
Hardware name: Unknown Unknown Product/Unknown Product, BIOS 2024.01 01/01/2024
epc : kvm_riscv_vcpu_enter_exit+0x26/0xcf8 [kvm]
ra : kvm_arch_vcpu_ioctl_run+0x4ce/0x5a6 [kvm]
status: 0000000200000100 badaddr: 0000000010a797f3 cause: 0000000000000002
[<ffffffff01df432e>] kvm_riscv_vcpu_enter_exit+0x26/0xcf8 [kvm]
[<ffffffff01deb3b0>] kvm_arch_vcpu_ioctl_run+0x4ce/0x5a6 [kvm]
[<ffffffff01dd7914>] kvm_vcpu_ioctl+0x180/0x5e4 [kvm]
[<ffffffff8025702e>] __riscv_sys_ioctl+0x84/0x9a
[<ffffffff80dfdc72>] do_trap_ecall_u+0x1d8/0x38a
[<ffffffff80e08644>] handle_exception+0x168/0x174
Code: 84aa 892e b703 8887 1773 1067 3023 16e5 b783 8907 (97f3) 10a7
Introduce a hardware quirk for this core, similar to the Andes AX66 TLB one,
and skip both CSRs when it is set.
Fixes: db3c01c7a308 ("RISCV: KVM: Add senvcfg context save/restore")
Suggested-by: Anup Patel <anup at brainfault.org>
Signed-off-by: Davidlohr Bueso <dave at stgolabs.net>
---
arch/riscv/include/asm/kvm_host.h | 1 +
arch/riscv/kvm/main.c | 9 +++++++++
arch/riscv/kvm/vcpu.c | 6 ++++--
arch/riscv/kvm/vcpu_config.c | 16 ++++++++++------
4 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
index a30600579231..51b6d1f76626 100644
--- a/arch/riscv/include/asm/kvm_host.h
+++ b/arch/riscv/include/asm/kvm_host.h
@@ -331,5 +331,6 @@ void kvm_riscv_vcpu_record_steal_time(struct kvm_vcpu *vcpu);
/* Flags representing implementation specific details */
DECLARE_STATIC_KEY_FALSE(kvm_riscv_vsstage_tlb_no_gpa);
+DECLARE_STATIC_KEY_FALSE(kvm_riscv_no_xenvcfg);
#endif /* __RISCV_KVM_HOST_H__ */
diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c
index 89568ccce01d..0725c8e03c6a 100644
--- a/arch/riscv/kvm/main.c
+++ b/arch/riscv/kvm/main.c
@@ -15,11 +15,13 @@
#include <asm/kvm_mmu.h>
#include <asm/kvm_nacl.h>
#include <asm/sbi.h>
+#include <asm/vendorid_list.h>
#include <asm/kvm_vcpu_vector.h>
static DEFINE_PER_CPU(bool, kvm_riscv_virtualization_enabled);
DEFINE_STATIC_KEY_FALSE(kvm_riscv_vsstage_tlb_no_gpa);
+DEFINE_STATIC_KEY_FALSE(kvm_riscv_no_xenvcfg);
static void kvm_riscv_setup_vendor_features(void)
{
@@ -29,6 +31,13 @@ static void kvm_riscv_setup_vendor_features(void)
static_branch_enable(&kvm_riscv_vsstage_tlb_no_gpa);
kvm_info("VS-stage TLB does not cache guest physical address and VMID\n");
}
+
+ /* SiFive P550 (ESWIN EIC7700X): H on a 1.11 base, no henvcfg/senvcfg */
+ if (riscv_cached_mvendorid(0) == SIFIVE_VENDOR_ID &&
+ riscv_cached_marchid(0) == 0x8000000000000008ULL) {
+ static_branch_enable(&kvm_riscv_no_xenvcfg);
+ kvm_info("henvcfg and senvcfg CSRs not implemented\n");
+ }
}
long kvm_arch_dev_ioctl(struct file *filp,
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index 7f1636c44d41..e5f877284026 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -772,7 +772,8 @@ static __always_inline void kvm_riscv_vcpu_swap_in_guest_state(struct kvm_vcpu *
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
vcpu->arch.host_scounteren = csr_swap(CSR_SCOUNTEREN, csr->scounteren);
- vcpu->arch.host_senvcfg = csr_swap(CSR_SENVCFG, csr->senvcfg);
+ if (!static_branch_unlikely(&kvm_riscv_no_xenvcfg))
+ vcpu->arch.host_senvcfg = csr_swap(CSR_SENVCFG, csr->senvcfg);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN))
vcpu->arch.host_sstateen0 = csr_swap(CSR_SSTATEEN0, smcsr->sstateen0);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICFISS))
@@ -786,7 +787,8 @@ static __always_inline void kvm_riscv_vcpu_swap_in_host_state(struct kvm_vcpu *v
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
csr->scounteren = csr_swap(CSR_SCOUNTEREN, vcpu->arch.host_scounteren);
- csr->senvcfg = csr_swap(CSR_SENVCFG, vcpu->arch.host_senvcfg);
+ if (!static_branch_unlikely(&kvm_riscv_no_xenvcfg))
+ csr->senvcfg = csr_swap(CSR_SENVCFG, vcpu->arch.host_senvcfg);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN))
smcsr->sstateen0 = csr_swap(CSR_SSTATEEN0, vcpu->arch.host_sstateen0);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICFISS))
diff --git a/arch/riscv/kvm/vcpu_config.c b/arch/riscv/kvm/vcpu_config.c
index b68aa830aaf5..9b8e4f1f12f4 100644
--- a/arch/riscv/kvm/vcpu_config.c
+++ b/arch/riscv/kvm/vcpu_config.c
@@ -82,9 +82,11 @@ void kvm_riscv_vcpu_config_load(struct kvm_vcpu *vcpu)
nsh = nacl_shmem();
nacl_csr_write(nsh, CSR_HEDELEG, cfg->hedeleg);
nacl_csr_write(nsh, CSR_HIDELEG, cfg->hideleg);
- nacl_csr_write(nsh, CSR_HENVCFG, cfg->henvcfg);
- if (IS_ENABLED(CONFIG_32BIT))
- nacl_csr_write(nsh, CSR_HENVCFGH, cfg->henvcfg >> 32);
+ if (!static_branch_unlikely(&kvm_riscv_no_xenvcfg)) {
+ nacl_csr_write(nsh, CSR_HENVCFG, cfg->henvcfg);
+ if (IS_ENABLED(CONFIG_32BIT))
+ nacl_csr_write(nsh, CSR_HENVCFGH, cfg->henvcfg >> 32);
+ }
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
nacl_csr_write(nsh, CSR_HSTATEEN0, cfg->hstateen0);
if (IS_ENABLED(CONFIG_32BIT))
@@ -93,9 +95,11 @@ void kvm_riscv_vcpu_config_load(struct kvm_vcpu *vcpu)
} else {
csr_write(CSR_HEDELEG, cfg->hedeleg);
csr_write(CSR_HIDELEG, cfg->hideleg);
- csr_write(CSR_HENVCFG, cfg->henvcfg);
- if (IS_ENABLED(CONFIG_32BIT))
- csr_write(CSR_HENVCFGH, cfg->henvcfg >> 32);
+ if (!static_branch_unlikely(&kvm_riscv_no_xenvcfg)) {
+ csr_write(CSR_HENVCFG, cfg->henvcfg);
+ if (IS_ENABLED(CONFIG_32BIT))
+ csr_write(CSR_HENVCFGH, cfg->henvcfg >> 32);
+ }
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
csr_write(CSR_HSTATEEN0, cfg->hstateen0);
if (IS_ENABLED(CONFIG_32BIT))
--
2.39.5
More information about the linux-riscv
mailing list