Implement function to initialize VCPU's CSR registers to delegate handling
of some traps to VS-mode ( guest ), enable vstimecmp for VS-mode, and
allow some AIA-related register (thier vs* copies ) for VS-mode.

Add detection of Smstateen extension to properly initialize hstateen0 to
allow guest to access AIA-added state.

Add call of vcpu_csr_init() in arch_vcpu_create().

Signed-off-by: Oleksii Kurochko <[email protected]>
---
 xen/arch/riscv/cpufeature.c                 |  1 +
 xen/arch/riscv/domain.c                     | 63 +++++++++++++++++++++
 xen/arch/riscv/include/asm/cpufeature.h     |  1 +
 xen/arch/riscv/include/asm/riscv_encoding.h |  2 +
 4 files changed, 67 insertions(+)

diff --git a/xen/arch/riscv/cpufeature.c b/xen/arch/riscv/cpufeature.c
index 02b68aeaa49f..03e27b037be0 100644
--- a/xen/arch/riscv/cpufeature.c
+++ b/xen/arch/riscv/cpufeature.c
@@ -137,6 +137,7 @@ const struct riscv_isa_ext_data __initconst riscv_isa_ext[] 
= {
     RISCV_ISA_EXT_DATA(zbb),
     RISCV_ISA_EXT_DATA(zbs),
     RISCV_ISA_EXT_DATA(smaia),
+    RISCV_ISA_EXT_DATA(smstateen),
     RISCV_ISA_EXT_DATA(ssaia),
     RISCV_ISA_EXT_DATA(svade),
     RISCV_ISA_EXT_DATA(svpbmt),
diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c
index e5fda1af4ee9..44387d056546 100644
--- a/xen/arch/riscv/domain.c
+++ b/xen/arch/riscv/domain.c
@@ -3,6 +3,67 @@
 #include <xen/mm.h>
 #include <xen/sched.h>
 
+#include <asm/cpufeature.h>
+#include <asm/csr.h>
+#include <asm/riscv_encoding.h>
+
+static void vcpu_csr_init(struct vcpu *v)
+{
+    unsigned long hedeleg, hideleg, hstatus;
+
+    hedeleg = 0;
+    hedeleg |= (1U << CAUSE_MISALIGNED_FETCH);
+    hedeleg |= (1U << CAUSE_FETCH_ACCESS);
+    hedeleg |= (1U << CAUSE_ILLEGAL_INSTRUCTION);
+    hedeleg |= (1U << CAUSE_MISALIGNED_LOAD);
+    hedeleg |= (1U << CAUSE_LOAD_ACCESS);
+    hedeleg |= (1U << CAUSE_MISALIGNED_STORE);
+    hedeleg |= (1U << CAUSE_STORE_ACCESS);
+    hedeleg |= (1U << CAUSE_BREAKPOINT);
+    hedeleg |= (1U << CAUSE_USER_ECALL);
+    hedeleg |= (1U << CAUSE_FETCH_PAGE_FAULT);
+    hedeleg |= (1U << CAUSE_LOAD_PAGE_FAULT);
+    hedeleg |= (1U << CAUSE_STORE_PAGE_FAULT);
+    v->arch.hedeleg = hedeleg;
+
+    hstatus = HSTATUS_SPV | HSTATUS_SPVP;
+    v->arch.hstatus = hstatus;
+
+    hideleg = MIP_VSTIP |  MIP_VSEIP | MIP_VSSIP;
+    v->arch.hideleg = hideleg;
+
+    /*
+     * VS should access only the time counter directly.
+     * Everything else should trap.
+     */
+    v->arch.hcounteren |= HCOUNTEREN_TM;
+
+    if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_svpbmt) )
+        v->arch.henvcfg |= ENVCFG_PBMTE;
+
+    if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_smstateen) )
+    {
+        /*
+         * If the hypervisor extension is implemented, the same three bitsare
+         * defined also in hypervisor CSR hstateen0 but concern only the state
+         * potentially accessible to a virtual machine executing in privilege
+         * modes VS and VU:
+         *      bit 60 CSRs siselect and sireg (really vsiselect and vsireg)
+         *      bit 59 CSRs siph and sieh (RV32 only) and stopi (really vsiph,
+         *             vsieh, and vstopi)
+         *      bit 58 all state of IMSIC guest interrupt files, including CSR
+         *             stopei (really vstopei)
+         * If one of these bits is zero in hstateen0, and the same bit is one
+         * in mstateen0, then an attempt to access the corresponding state from
+         * VS or VU-mode raises a virtual instruction exception.
+        */
+        v->arch.hstateen0 = SMSTATEEN0_AIA | SMSTATEEN0_IMSIC | 
SMSTATEEN0_SVSLCT;
+
+        /* Allow guest to access CSR_ENVCFG */
+        v->arch.hstateen0 |= SMSTATEEN0_HSENVCFG;
+    }
+}
+
 static void continue_new_vcpu(struct vcpu *prev)
 {
     BUG_ON("unimplemented\n");
@@ -30,6 +91,8 @@ int arch_vcpu_create(struct vcpu *v)
            v->arch.xen_saved_context.sp, v->arch.xen_saved_context.ra,
            (unsigned long)v->arch.cpu_info);
 
+    vcpu_csr_init(v);
+
     /* Idle VCPUs don't need the rest of this setup */
     if ( is_idle_vcpu(v) )
         return rc;
diff --git a/xen/arch/riscv/include/asm/cpufeature.h 
b/xen/arch/riscv/include/asm/cpufeature.h
index b69616038888..ef02a3e26d2c 100644
--- a/xen/arch/riscv/include/asm/cpufeature.h
+++ b/xen/arch/riscv/include/asm/cpufeature.h
@@ -36,6 +36,7 @@ enum riscv_isa_ext_id {
     RISCV_ISA_EXT_zbb,
     RISCV_ISA_EXT_zbs,
     RISCV_ISA_EXT_smaia,
+    RISCV_ISA_EXT_smstateen,
     RISCV_ISA_EXT_ssaia,
     RISCV_ISA_EXT_svade,
     RISCV_ISA_EXT_svpbmt,
diff --git a/xen/arch/riscv/include/asm/riscv_encoding.h 
b/xen/arch/riscv/include/asm/riscv_encoding.h
index 1f7e612366f8..dd15731a86fa 100644
--- a/xen/arch/riscv/include/asm/riscv_encoding.h
+++ b/xen/arch/riscv/include/asm/riscv_encoding.h
@@ -228,6 +228,8 @@
 #define ENVCFG_CBIE_INV                        _UL(0x3)
 #define ENVCFG_FIOM                    _UL(0x1)
 
+#define HCOUNTEREN_TM BIT(1, U)
+
 /* ===== User-level CSRs ===== */
 
 /* User Trap Setup (N-extension) */
-- 
2.52.0


Reply via email to