[PATCH] riscv/kvm: Only context-switch senvcfg where it exists

Davidlohr Bueso dave at stgolabs.net
Thu Oct 15 11:06:56 PDT 2026


On Sat, 10 Oct 2026, Anup Patel wrote:

>I think having static-key kvm_riscv_no_xenvcfg is much cleaner
>because we already have kvm_riscv_vsstage_tlb_no_gpa which
>is another work-around. The kvm_riscv_no_xenvcfg will be diabled
>by default and will be enabled only for P500 (ESWIN EIC7700X).

Thanks for the suggestion, I agree it looks cleaner.
How about the below (fixes things for me)?

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..dec338319cb7 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) & 0xFFFF) == 0x8) {
+		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