[PATCH 2/5] RISC-V: KVM: Add a hstateen lazy enabler helper function
Atish Patra
atishp at rivosinc.com
Mon May 5 14:39:27 PDT 2025
Hstateen has different bits that can be enabled lazily at runtime.
Most of them have similar functionality where the hstateen bit must
be enabled if not enabled already. The correpsonding config bit in
vcpu must be enabled as well so that hstateen CSR is updated correctly
during the next vcpu load. In absesnce of Smstateen extension, exit
to the userspace in the trap because CSR access control exists
architecturally only if Smstateen extension is available.
Add a common helper function to achieve the above said objective.
Signed-off-by: Atish Patra <atishp at rivosinc.com>
---
arch/riscv/include/asm/kvm_vcpu_insn.h | 4 ++++
arch/riscv/kvm/vcpu_insn.c | 21 +++++++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/arch/riscv/include/asm/kvm_vcpu_insn.h b/arch/riscv/include/asm/kvm_vcpu_insn.h
index 350011c83581..1125f3f1c8c4 100644
--- a/arch/riscv/include/asm/kvm_vcpu_insn.h
+++ b/arch/riscv/include/asm/kvm_vcpu_insn.h
@@ -6,6 +6,8 @@
#ifndef __KVM_VCPU_RISCV_INSN_H
#define __KVM_VCPU_RISCV_INSN_H
+#include <linux/kvm_types.h>
+
struct kvm_vcpu;
struct kvm_run;
struct kvm_cpu_trap;
@@ -44,5 +46,7 @@ int kvm_riscv_vcpu_mmio_store(struct kvm_vcpu *vcpu, struct kvm_run *run,
unsigned long fault_addr,
unsigned long htinst);
int kvm_riscv_vcpu_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_riscv_vcpu_hstateen_lazy_enable(struct kvm_vcpu *vcpu, unsigned int csr_num,
+ uint64_t hstateen_feature_bit_mask);
#endif
diff --git a/arch/riscv/kvm/vcpu_insn.c b/arch/riscv/kvm/vcpu_insn.c
index 97dec18e6989..3bc39572b79d 100644
--- a/arch/riscv/kvm/vcpu_insn.c
+++ b/arch/riscv/kvm/vcpu_insn.c
@@ -235,6 +235,27 @@ static int seed_csr_rmw(struct kvm_vcpu *vcpu, unsigned int csr_num,
return KVM_INSN_EXIT_TO_USER_SPACE;
}
+int kvm_riscv_vcpu_hstateen_lazy_enable(struct kvm_vcpu *vcpu, unsigned int csr_num,
+ uint64_t hstateen_feature_bit_mask)
+{
+ /* Access from VS shouldn't trap if smstaeen is not present */
+ if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN))
+ return KVM_INSN_EXIT_TO_USER_SPACE;
+
+ /* Enable the bit in hstateen0 lazily upon first access */
+ if (!(vcpu->arch.cfg.hstateen0 & hstateen_feature_bit_mask)) {
+ vcpu->arch.cfg.hstateen0 |= hstateen_feature_bit_mask;
+ csr_set(CSR_HSTATEEN0, hstateen_feature_bit_mask);
+ if (IS_ENABLED(CONFIG_32BIT))
+ csr_set(CSR_HSTATEEN0H, hstateen_feature_bit_mask >> 32);
+ } else {
+ return KVM_INSN_EXIT_TO_USER_SPACE;
+ }
+
+ /* Let the guest retry the instruction read after hstateen0 is modified */
+ return KVM_INSN_CONTINUE_SAME_SEPC;
+}
+
static const struct csr_func csr_funcs[] = {
KVM_RISCV_VCPU_AIA_CSR_FUNCS
KVM_RISCV_VCPU_HPMCOUNTER_CSR_FUNCS
--
2.43.0
More information about the kvm-riscv
mailing list