Smstateen extension must be configure for Guest whenever it is
available otherwise Guest will not access to HENVCFG CSR.
arch/riscv/cpu/generic/cpu_vcpu_helper.c | 31 +++++++++++++++++++
arch/riscv/cpu/generic/cpu_vcpu_nested.c | 3 ++
arch/riscv/cpu/generic/include/arch_regs.h | 3 ++
.../cpu/generic/include/cpu_vcpu_helper.h | 3 ++
4 files changed, 40 insertions(+)
diff --git a/arch/riscv/cpu/generic/cpu_vcpu_helper.c b/arch/riscv/cpu/generic/cpu_vcpu_helper.c
index eecda785..c3141dba 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_helper.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_helper.c
@@ -326,6 +326,16 @@ int arch_vcpu_init(struct vmm_vcpu *vcpu)
/* By default, make CY, TM, and IR counters accessible in VU mode */
riscv_priv(vcpu)->scounteren = 7;
+ /* Initialize stateen configuration */
+ riscv_priv(vcpu)->hstateen0 = SMSTATEEN0_HSENVCFG;
+ if (riscv_isa_extension_available(riscv_priv(vcpu)->isa, SMSTATEEN))
+ riscv_priv(vcpu)->hstateen0 |= SMSTATEEN0_SSTATEEN0;
+ if (riscv_isa_extension_available(riscv_priv(vcpu)->isa, SSAIA)) {
+ riscv_priv(vcpu)->hstateen0 |= SMSTATEEN0_CSRIND;
+ riscv_priv(vcpu)->hstateen0 |= SMSTATEEN0_AIA;
+ riscv_priv(vcpu)->hstateen0 |= SMSTATEEN0_AIA_IMSIC;
+ }
+
/* Reset nested state */
cpu_vcpu_nested_reset(vcpu);
@@ -413,6 +423,8 @@ void arch_vcpu_switch(struct vmm_vcpu *tvcpu,
priv->vstval = csr_read(CSR_VSTVAL);
priv->vsatp = csr_read(CSR_VSATP);
priv->scounteren = csr_read(CSR_SCOUNTEREN);
+ if (riscv_isa_extension_available(priv->isa, SMSTATEEN))
+ priv->sstateen0 = csr_read(CSR_SSTATEEN0);
cpu_vcpu_fp_save(tvcpu, regs);
cpu_vcpu_timer_save(tvcpu);
}
@@ -432,6 +444,9 @@ void arch_vcpu_switch(struct vmm_vcpu *tvcpu,
csr_write(CSR_VSTVAL, priv->vstval);
csr_write(CSR_VSATP, priv->vsatp);
csr_write(CSR_SCOUNTEREN, priv->scounteren);
+ if (riscv_isa_extension_available(priv->isa, SMSTATEEN))
+ csr_write(CSR_SSTATEEN0, priv->sstateen0);
+ cpu_vcpu_stateen_update(vcpu, riscv_nested_virt(vcpu));
cpu_vcpu_envcfg_update(vcpu, riscv_nested_virt(vcpu));
cpu_vcpu_timer_restore(vcpu);
cpu_vcpu_fp_restore(vcpu, regs);
@@ -448,6 +463,22 @@ void arch_vcpu_post_switch(struct vmm_vcpu *vcpu,
/* For now nothing to do here. */
}
+void cpu_vcpu_stateen_update(struct vmm_vcpu *vcpu, bool nested_virt)
+{
+ u64 hstateen0;
+
+ if (!riscv_isa_extension_available(NULL, SMSTATEEN))
+ return;
+
+ hstateen0 = (nested_virt) ? 0 : riscv_priv(vcpu)->hstateen0;
+#ifdef CONFIG_32BIT
+ csr_write(CSR_HSTATEEN0, (u32)hstateen0);
+ csr_write(CSR_HSTATEEN0H, (u32)(hstateen0 >> 32));
+#else
+ csr_write(CSR_HSTATEEN0, hstateen0);
+#endif
+}
+
void cpu_vcpu_envcfg_update(struct vmm_vcpu *vcpu, bool nested_virt)
{
u64 henvcfg = (nested_virt) ? 0 : riscv_priv(vcpu)->henvcfg;
diff --git a/arch/riscv/cpu/generic/cpu_vcpu_nested.c b/arch/riscv/cpu/generic/cpu_vcpu_nested.c
index 12db30b1..6c08fd25 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_nested.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_nested.c
@@ -1980,6 +1980,9 @@ void cpu_vcpu_nested_set_virt(struct vmm_vcpu *vcpu, struct arch_regs *regs,
npriv->hcounteren = csr_swap(CSR_HCOUNTEREN, npriv->hcounteren);
npriv->hedeleg = csr_swap(CSR_HEDELEG, npriv->hedeleg);
+ /* Update stateen configuration */
+ cpu_vcpu_stateen_update(vcpu, virt);
+
/* Update environment configuration */
cpu_vcpu_envcfg_update(vcpu, virt);
diff --git a/arch/riscv/cpu/generic/include/arch_regs.h b/arch/riscv/cpu/generic/include/arch_regs.h
index 3e0d8ceb..a4046225 100644
--- a/arch/riscv/cpu/generic/include/arch_regs.h
+++ b/arch/riscv/cpu/generic/include/arch_regs.h
@@ -229,6 +229,9 @@ struct riscv_priv {
unsigned long vstval;
unsigned long vsatp;
unsigned long scounteren;
+ /* Sstateen state */
+ u64 hstateen0;
+ unsigned long sstateen0;
/* Nested state */
struct riscv_priv_nested nested;
/* FP state */
diff --git a/arch/riscv/cpu/generic/include/cpu_vcpu_helper.h b/arch/riscv/cpu/generic/include/cpu_vcpu_helper.h
index 1c2f49d1..76cd02c1 100644
--- a/arch/riscv/cpu/generic/include/cpu_vcpu_helper.h
+++ b/arch/riscv/cpu/generic/include/cpu_vcpu_helper.h
@@ -26,6 +26,9 @@
#include <vmm_types.h>
#include <vmm_manager.h>
+/** Function to update stateen configuration */
+void cpu_vcpu_stateen_update(struct vmm_vcpu *vcpu, bool nested_virt);
+
/** Function to update environment configuration */
void cpu_vcpu_envcfg_update(struct vmm_vcpu *vcpu, bool nested_virt);
--
2.43.0