[RFC PATCH v5 4/4] target/riscv: smstateen check for AIA/IMSIC

Mayuresh Chitale posted 4 patches 2 years, 3 months ago
Maintainers: Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Bin Meng <bin.meng@windriver.com>
There is a newer version of this series
[RFC PATCH v5 4/4] target/riscv: smstateen check for AIA/IMSIC
Posted by Mayuresh Chitale 2 years, 3 months ago
If smstateen is implemented then accesses to AIA
registers CSRS, IMSIC CSRs and other IMSIC registers
is controlled by setting of corresponding bits in
mstateen/hstateen registers. Otherwise an illegal
instruction trap or virtual instruction trap is
generated.

Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
---
 target/riscv/csr.c | 253 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 248 insertions(+), 5 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 8bbbed38ff..213b3c17ff 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -39,6 +39,7 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops)
 }
 
 /* Predicates */
+#if !defined(CONFIG_USER_ONLY)
 static RISCVException smstateen_acc_ok(CPURISCVState *env, int mode, int bit)
 {
     CPUState *cs = env_cpu(env);
@@ -49,7 +50,6 @@ static RISCVException smstateen_acc_ok(CPURISCVState *env, int mode, int bit)
         return RISCV_EXCP_NONE;
     }
 
-#if !defined(CONFIG_USER_ONLY)
     if (!(env->mstateen[0] & 1UL << bit)) {
         return RISCV_EXCP_ILLEGAL_INST;
     }
@@ -65,11 +65,57 @@ static RISCVException smstateen_acc_ok(CPURISCVState *env, int mode, int bit)
             return RISCV_EXCP_ILLEGAL_INST;
         }
     }
-#endif
-
     return RISCV_EXCP_NONE;
 }
 
+static RISCVException smstateen_aia_acc_ok(CPURISCVState *env, int csrno)
+{
+    int bit, mode;
+
+    switch (csrno) {
+    case CSR_SSETEIPNUM:
+    case CSR_SCLREIPNUM:
+    case CSR_SSETEIENUM:
+    case CSR_SCLREIENUM:
+    case CSR_STOPEI:
+    case CSR_VSSETEIPNUM:
+    case CSR_VSCLREIPNUM:
+    case CSR_VSSETEIENUM:
+    case CSR_VSCLREIENUM:
+    case CSR_VSTOPEI:
+    case CSR_HSTATUS:
+        mode = PRV_S;
+        bit = SMSTATEEN0_IMSIC;
+        break;
+
+    case CSR_SIEH:
+    case CSR_SIPH:
+    case CSR_HVIPH:
+    case CSR_HVICTL:
+    case CSR_HVIPRIO1:
+    case CSR_HVIPRIO2:
+    case CSR_HVIPRIO1H:
+    case CSR_HVIPRIO2H:
+    case CSR_VSIEH:
+    case CSR_VSIPH:
+        mode = PRV_S;
+        bit = SMSTATEEN0_AIA;
+        break;
+
+    case CSR_SISELECT:
+    case CSR_VSISELECT:
+        mode = PRV_S;
+        bit = SMSTATEEN0_SVSLCT;
+        break;
+
+    default:
+        return RISCV_EXCP_NONE;
+    }
+
+    return smstateen_acc_ok(env, mode, bit);
+}
+#endif
+
 static RISCVException fs(CPURISCVState *env, int csrno)
 {
 #if !defined(CONFIG_USER_ONLY)
@@ -1130,6 +1176,13 @@ static int rmw_xiselect(CPURISCVState *env, int csrno, target_ulong *val,
                         target_ulong new_val, target_ulong wr_mask)
 {
     target_ulong *iselect;
+    RISCVException ret;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
 
     /* Translate CSR number for VS-mode */
     csrno = aia_xlate_vs_csrno(env, csrno);
@@ -1212,7 +1265,9 @@ static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val,
     bool virt;
     uint8_t *iprio;
     int ret = -EINVAL;
-    target_ulong priv, isel, vgein;
+    target_ulong priv, isel, vgein = 0;
+    CPUState *cs = env_cpu(env);
+    RISCVCPU *cpu = RISCV_CPU(cs);
 
     /* Translate CSR number for VS-mode */
     csrno = aia_xlate_vs_csrno(env, csrno);
@@ -1241,11 +1296,20 @@ static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val,
     };
 
     /* Find the selected guest interrupt file */
-    vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
+    if (virt) {
+        if (!cpu->cfg.ext_smstateen ||
+                (env->hstateen[0] & 1UL << SMSTATEEN0_IMSIC)) {
+            vgein = get_field(env->hstatus, HSTATUS_VGEIN);
+        }
+    }
 
     if (ISELECT_IPRIO0 <= isel && isel <= ISELECT_IPRIO15) {
         /* Local interrupt priority registers not available for VS-mode */
         if (!virt) {
+            if (priv == PRV_S && cpu->cfg.ext_smstateen &&
+                !(env->hstateen[0] & 1UL << SMSTATEEN0_AIA)) {
+                goto done;
+            }
             ret = rmw_iprio(riscv_cpu_mxl_bits(env),
                             isel, iprio, val, new_val, wr_mask,
                             (priv == PRV_M) ? IRQ_M_EXT : IRQ_S_EXT);
@@ -1279,6 +1343,13 @@ static int rmw_xsetclreinum(CPURISCVState *env, int csrno, target_ulong *val,
     int ret = -EINVAL;
     bool set, pend, virt;
     target_ulong priv, isel, vgein, xlen, nval, wmask;
+    RISCVException excp;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    excp = smstateen_aia_acc_ok(env, csrno);
+    if (excp != RISCV_EXCP_NONE) {
+        return excp;
+    }
 
     /* Translate CSR number for VS-mode */
     csrno = aia_xlate_vs_csrno(env, csrno);
@@ -1397,6 +1468,13 @@ static int rmw_xtopei(CPURISCVState *env, int csrno, target_ulong *val,
     bool virt;
     int ret = -EINVAL;
     target_ulong priv, vgein;
+    RISCVException excp;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    excp = smstateen_aia_acc_ok(env, csrno);
+    if (excp != RISCV_EXCP_NONE) {
+        return excp;
+    }
 
     /* Translate CSR number for VS-mode */
     csrno = aia_xlate_vs_csrno(env, csrno);
@@ -1708,6 +1786,12 @@ static RISCVException write_mstateen(CPURISCVState *env, int csrno,
         wr_mask |= 1UL << SMSTATEEN0_FCSR;
     }
 
+    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
+        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
+                | (1UL << SMSTATEEN0_AIA)
+                | (1UL << SMSTATEEN0_SVSLCT);
+    }
+
     write_smstateen(env, reg, wr_mask, new_val);
 
     return RISCV_EXCP_NONE;
@@ -1736,6 +1820,12 @@ static RISCVException write_mstateenh(CPURISCVState *env, int csrno,
         wr_mask |= 1UL << SMSTATEEN0_FCSR;
     }
 
+    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
+        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
+                | (1UL << SMSTATEEN0_AIA)
+                | (1UL << SMSTATEEN0_SVSLCT);
+    }
+
     write_smstateen(env, reg, wr_mask, val);
 
     return RISCV_EXCP_NONE;
@@ -1761,6 +1851,12 @@ static RISCVException write_hstateen(CPURISCVState *env, int csrno,
         wr_mask |= 1UL << SMSTATEEN0_FCSR;
     }
 
+    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
+        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
+                | (1UL << SMSTATEEN0_AIA)
+                | (1UL << SMSTATEEN0_SVSLCT);
+    }
+
     reg = &env->hstateen[index];
     wr_mask &= env->mstateen[index];
     write_smstateen(env, reg, wr_mask, new_val);
@@ -1789,6 +1885,12 @@ static RISCVException write_hstateenh(CPURISCVState *env, int csrno,
         wr_mask |= 1UL << SMSTATEEN0_FCSR;
     }
 
+    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
+        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
+                | (1UL << SMSTATEEN0_AIA)
+                | (1UL << SMSTATEEN0_SVSLCT);
+    }
+
     reg = &env->hstateen[index];
     val = (uint64_t)new_val << 32;
     val |= *reg & 0xFFFFFFFF;
@@ -1979,6 +2081,12 @@ static RISCVException rmw_vsieh(CPURISCVState *env, int csrno,
     uint64_t rval;
     RISCVException ret;
 
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     ret = rmw_vsie64(env, csrno, &rval,
         ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
     if (ret_val) {
@@ -2033,6 +2141,12 @@ static RISCVException rmw_sieh(CPURISCVState *env, int csrno,
     uint64_t rval;
     RISCVException ret;
 
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     ret = rmw_sie64(env, csrno, &rval,
         ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
     if (ret_val) {
@@ -2195,6 +2309,12 @@ static RISCVException rmw_vsiph(CPURISCVState *env, int csrno,
     uint64_t rval;
     RISCVException ret;
 
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     ret = rmw_vsip64(env, csrno, &rval,
         ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
     if (ret_val) {
@@ -2249,6 +2369,12 @@ static RISCVException rmw_siph(CPURISCVState *env, int csrno,
     uint64_t rval;
     RISCVException ret;
 
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     ret = rmw_sip64(env, csrno, &rval,
         ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
     if (ret_val) {
@@ -2441,6 +2567,10 @@ static RISCVException read_hstatus(CPURISCVState *env, int csrno,
 static RISCVException write_hstatus(CPURISCVState *env, int csrno,
                                     target_ulong val)
 {
+    if (smstateen_aia_acc_ok(env, csrno) != RISCV_EXCP_NONE) {
+        val &= ~HSTATUS_VGEIN;
+    }
+
     env->hstatus = val;
     if (riscv_cpu_mxl(env) != MXL_RV32 && get_field(val, HSTATUS_VSXL) != 2) {
         qemu_log_mask(LOG_UNIMP, "QEMU does not support mixed HSXLEN options.");
@@ -2501,6 +2631,12 @@ static RISCVException rmw_hidelegh(CPURISCVState *env, int csrno,
     uint64_t rval;
     RISCVException ret;
 
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     ret = rmw_hideleg64(env, csrno, &rval,
         ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
     if (ret_val) {
@@ -2547,6 +2683,12 @@ static RISCVException rmw_hviph(CPURISCVState *env, int csrno,
     uint64_t rval;
     RISCVException ret;
 
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     ret = rmw_hvip64(env, csrno, &rval,
         ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
     if (ret_val) {
@@ -2601,6 +2743,13 @@ static RISCVException write_hcounteren(CPURISCVState *env, int csrno,
 static RISCVException read_hgeie(CPURISCVState *env, int csrno,
                                  target_ulong *val)
 {
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, PRV_S, SMSTATEEN0_IMSIC);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     if (val) {
         *val = env->hgeie;
     }
@@ -2610,6 +2759,13 @@ static RISCVException read_hgeie(CPURISCVState *env, int csrno,
 static RISCVException write_hgeie(CPURISCVState *env, int csrno,
                                   target_ulong val)
 {
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, PRV_S, SMSTATEEN0_IMSIC);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     /* Only GEILEN:1 bits implemented and BIT0 is never implemented */
     val &= ((((target_ulong)1) << env->geilen) - 1) << 1;
     env->hgeie = val;
@@ -2649,6 +2805,13 @@ static RISCVException write_htinst(CPURISCVState *env, int csrno,
 static RISCVException read_hgeip(CPURISCVState *env, int csrno,
                                  target_ulong *val)
 {
+    RISCVException ret;
+
+    ret = smstateen_acc_ok(env, PRV_S, SMSTATEEN0_IMSIC);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     if (val) {
         *val = env->hgeip;
     }
@@ -2719,12 +2882,28 @@ static RISCVException write_htimedeltah(CPURISCVState *env, int csrno,
 
 static int read_hvictl(CPURISCVState *env, int csrno, target_ulong *val)
 {
+    RISCVException ret;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     *val = env->hvictl;
     return RISCV_EXCP_NONE;
 }
 
 static int write_hvictl(CPURISCVState *env, int csrno, target_ulong val)
 {
+    RISCVException ret = RISCV_EXCP_NONE;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     env->hvictl = val & HVICTL_VALID_MASK;
     return RISCV_EXCP_NONE;
 }
@@ -2783,41 +2962,105 @@ static int write_hvipriox(CPURISCVState *env, int first_index,
 
 static int read_hviprio1(CPURISCVState *env, int csrno, target_ulong *val)
 {
+    RISCVException ret;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     return read_hvipriox(env, 0, env->hviprio, val);
 }
 
 static int write_hviprio1(CPURISCVState *env, int csrno, target_ulong val)
 {
+    RISCVException ret;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     return write_hvipriox(env, 0, env->hviprio, val);
 }
 
 static int read_hviprio1h(CPURISCVState *env, int csrno, target_ulong *val)
 {
+    RISCVException ret;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     return read_hvipriox(env, 4, env->hviprio, val);
 }
 
 static int write_hviprio1h(CPURISCVState *env, int csrno, target_ulong val)
 {
+    RISCVException ret;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     return write_hvipriox(env, 4, env->hviprio, val);
 }
 
 static int read_hviprio2(CPURISCVState *env, int csrno, target_ulong *val)
 {
+    RISCVException ret;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     return read_hvipriox(env, 8, env->hviprio, val);
 }
 
 static int write_hviprio2(CPURISCVState *env, int csrno, target_ulong val)
 {
+    RISCVException ret;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     return write_hvipriox(env, 8, env->hviprio, val);
 }
 
 static int read_hviprio2h(CPURISCVState *env, int csrno, target_ulong *val)
 {
+    RISCVException ret;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     return read_hvipriox(env, 12, env->hviprio, val);
 }
 
 static int write_hviprio2h(CPURISCVState *env, int csrno, target_ulong val)
 {
+    RISCVException ret;
+
+    /* Check if smstateen is enabled and this access is allowed */
+    ret = smstateen_aia_acc_ok(env, csrno);
+    if (ret != RISCV_EXCP_NONE) {
+        return ret;
+    }
+
     return write_hvipriox(env, 12, env->hviprio, val);
 }
 
-- 
2.25.1
Re: [RFC PATCH v5 4/4] target/riscv: smstateen check for AIA/IMSIC
Posted by Alistair Francis 2 years, 2 months ago
On Sat, Jun 4, 2022 at 2:15 AM Mayuresh Chitale
<mchitale@ventanamicro.com> wrote:
>
> If smstateen is implemented then accesses to AIA
> registers CSRS, IMSIC CSRs and other IMSIC registers
> is controlled by setting of corresponding bits in
> mstateen/hstateen registers. Otherwise an illegal
> instruction trap or virtual instruction trap is
> generated.
>
> Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
> ---
>  target/riscv/csr.c | 253 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 248 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 8bbbed38ff..213b3c17ff 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -39,6 +39,7 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops)
>  }
>
>  /* Predicates */
> +#if !defined(CONFIG_USER_ONLY)

This should just be in the original patch.

>  static RISCVException smstateen_acc_ok(CPURISCVState *env, int mode, int bit)
>  {
>      CPUState *cs = env_cpu(env);
> @@ -49,7 +50,6 @@ static RISCVException smstateen_acc_ok(CPURISCVState *env, int mode, int bit)
>          return RISCV_EXCP_NONE;
>      }
>
> -#if !defined(CONFIG_USER_ONLY)
>      if (!(env->mstateen[0] & 1UL << bit)) {
>          return RISCV_EXCP_ILLEGAL_INST;
>      }
> @@ -65,11 +65,57 @@ static RISCVException smstateen_acc_ok(CPURISCVState *env, int mode, int bit)
>              return RISCV_EXCP_ILLEGAL_INST;
>          }
>      }
> -#endif
> -
>      return RISCV_EXCP_NONE;
>  }
>
> +static RISCVException smstateen_aia_acc_ok(CPURISCVState *env, int csrno)

The spec doesn't mention the effects on AIA, it just says that some
bits are reserved. How do you know what should happen here?

Alistair

> +{
> +    int bit, mode;
> +
> +    switch (csrno) {
> +    case CSR_SSETEIPNUM:
> +    case CSR_SCLREIPNUM:
> +    case CSR_SSETEIENUM:
> +    case CSR_SCLREIENUM:
> +    case CSR_STOPEI:
> +    case CSR_VSSETEIPNUM:
> +    case CSR_VSCLREIPNUM:
> +    case CSR_VSSETEIENUM:
> +    case CSR_VSCLREIENUM:
> +    case CSR_VSTOPEI:
> +    case CSR_HSTATUS:
> +        mode = PRV_S;
> +        bit = SMSTATEEN0_IMSIC;
> +        break;
> +
> +    case CSR_SIEH:
> +    case CSR_SIPH:
> +    case CSR_HVIPH:
> +    case CSR_HVICTL:
> +    case CSR_HVIPRIO1:
> +    case CSR_HVIPRIO2:
> +    case CSR_HVIPRIO1H:
> +    case CSR_HVIPRIO2H:
> +    case CSR_VSIEH:
> +    case CSR_VSIPH:
> +        mode = PRV_S;
> +        bit = SMSTATEEN0_AIA;
> +        break;
> +
> +    case CSR_SISELECT:
> +    case CSR_VSISELECT:
> +        mode = PRV_S;
> +        bit = SMSTATEEN0_SVSLCT;
> +        break;
> +
> +    default:
> +        return RISCV_EXCP_NONE;
> +    }
> +
> +    return smstateen_acc_ok(env, mode, bit);
> +}
> +#endif
> +
>  static RISCVException fs(CPURISCVState *env, int csrno)
>  {
>  #if !defined(CONFIG_USER_ONLY)
> @@ -1130,6 +1176,13 @@ static int rmw_xiselect(CPURISCVState *env, int csrno, target_ulong *val,
>                          target_ulong new_val, target_ulong wr_mask)
>  {
>      target_ulong *iselect;
> +    RISCVException ret;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
>
>      /* Translate CSR number for VS-mode */
>      csrno = aia_xlate_vs_csrno(env, csrno);
> @@ -1212,7 +1265,9 @@ static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val,
>      bool virt;
>      uint8_t *iprio;
>      int ret = -EINVAL;
> -    target_ulong priv, isel, vgein;
> +    target_ulong priv, isel, vgein = 0;
> +    CPUState *cs = env_cpu(env);
> +    RISCVCPU *cpu = RISCV_CPU(cs);
>
>      /* Translate CSR number for VS-mode */
>      csrno = aia_xlate_vs_csrno(env, csrno);
> @@ -1241,11 +1296,20 @@ static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val,
>      };
>
>      /* Find the selected guest interrupt file */
> -    vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
> +    if (virt) {
> +        if (!cpu->cfg.ext_smstateen ||
> +                (env->hstateen[0] & 1UL << SMSTATEEN0_IMSIC)) {
> +            vgein = get_field(env->hstatus, HSTATUS_VGEIN);
> +        }
> +    }
>
>      if (ISELECT_IPRIO0 <= isel && isel <= ISELECT_IPRIO15) {
>          /* Local interrupt priority registers not available for VS-mode */
>          if (!virt) {
> +            if (priv == PRV_S && cpu->cfg.ext_smstateen &&
> +                !(env->hstateen[0] & 1UL << SMSTATEEN0_AIA)) {
> +                goto done;
> +            }
>              ret = rmw_iprio(riscv_cpu_mxl_bits(env),
>                              isel, iprio, val, new_val, wr_mask,
>                              (priv == PRV_M) ? IRQ_M_EXT : IRQ_S_EXT);
> @@ -1279,6 +1343,13 @@ static int rmw_xsetclreinum(CPURISCVState *env, int csrno, target_ulong *val,
>      int ret = -EINVAL;
>      bool set, pend, virt;
>      target_ulong priv, isel, vgein, xlen, nval, wmask;
> +    RISCVException excp;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    excp = smstateen_aia_acc_ok(env, csrno);
> +    if (excp != RISCV_EXCP_NONE) {
> +        return excp;
> +    }
>
>      /* Translate CSR number for VS-mode */
>      csrno = aia_xlate_vs_csrno(env, csrno);
> @@ -1397,6 +1468,13 @@ static int rmw_xtopei(CPURISCVState *env, int csrno, target_ulong *val,
>      bool virt;
>      int ret = -EINVAL;
>      target_ulong priv, vgein;
> +    RISCVException excp;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    excp = smstateen_aia_acc_ok(env, csrno);
> +    if (excp != RISCV_EXCP_NONE) {
> +        return excp;
> +    }
>
>      /* Translate CSR number for VS-mode */
>      csrno = aia_xlate_vs_csrno(env, csrno);
> @@ -1708,6 +1786,12 @@ static RISCVException write_mstateen(CPURISCVState *env, int csrno,
>          wr_mask |= 1UL << SMSTATEEN0_FCSR;
>      }
>
> +    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
> +        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
> +                | (1UL << SMSTATEEN0_AIA)
> +                | (1UL << SMSTATEEN0_SVSLCT);
> +    }
> +
>      write_smstateen(env, reg, wr_mask, new_val);
>
>      return RISCV_EXCP_NONE;
> @@ -1736,6 +1820,12 @@ static RISCVException write_mstateenh(CPURISCVState *env, int csrno,
>          wr_mask |= 1UL << SMSTATEEN0_FCSR;
>      }
>
> +    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
> +        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
> +                | (1UL << SMSTATEEN0_AIA)
> +                | (1UL << SMSTATEEN0_SVSLCT);
> +    }
> +
>      write_smstateen(env, reg, wr_mask, val);
>
>      return RISCV_EXCP_NONE;
> @@ -1761,6 +1851,12 @@ static RISCVException write_hstateen(CPURISCVState *env, int csrno,
>          wr_mask |= 1UL << SMSTATEEN0_FCSR;
>      }
>
> +    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
> +        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
> +                | (1UL << SMSTATEEN0_AIA)
> +                | (1UL << SMSTATEEN0_SVSLCT);
> +    }
> +
>      reg = &env->hstateen[index];
>      wr_mask &= env->mstateen[index];
>      write_smstateen(env, reg, wr_mask, new_val);
> @@ -1789,6 +1885,12 @@ static RISCVException write_hstateenh(CPURISCVState *env, int csrno,
>          wr_mask |= 1UL << SMSTATEEN0_FCSR;
>      }
>
> +    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
> +        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
> +                | (1UL << SMSTATEEN0_AIA)
> +                | (1UL << SMSTATEEN0_SVSLCT);
> +    }
> +
>      reg = &env->hstateen[index];
>      val = (uint64_t)new_val << 32;
>      val |= *reg & 0xFFFFFFFF;
> @@ -1979,6 +2081,12 @@ static RISCVException rmw_vsieh(CPURISCVState *env, int csrno,
>      uint64_t rval;
>      RISCVException ret;
>
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      ret = rmw_vsie64(env, csrno, &rval,
>          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
>      if (ret_val) {
> @@ -2033,6 +2141,12 @@ static RISCVException rmw_sieh(CPURISCVState *env, int csrno,
>      uint64_t rval;
>      RISCVException ret;
>
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      ret = rmw_sie64(env, csrno, &rval,
>          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
>      if (ret_val) {
> @@ -2195,6 +2309,12 @@ static RISCVException rmw_vsiph(CPURISCVState *env, int csrno,
>      uint64_t rval;
>      RISCVException ret;
>
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      ret = rmw_vsip64(env, csrno, &rval,
>          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
>      if (ret_val) {
> @@ -2249,6 +2369,12 @@ static RISCVException rmw_siph(CPURISCVState *env, int csrno,
>      uint64_t rval;
>      RISCVException ret;
>
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      ret = rmw_sip64(env, csrno, &rval,
>          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
>      if (ret_val) {
> @@ -2441,6 +2567,10 @@ static RISCVException read_hstatus(CPURISCVState *env, int csrno,
>  static RISCVException write_hstatus(CPURISCVState *env, int csrno,
>                                      target_ulong val)
>  {
> +    if (smstateen_aia_acc_ok(env, csrno) != RISCV_EXCP_NONE) {
> +        val &= ~HSTATUS_VGEIN;
> +    }
> +
>      env->hstatus = val;
>      if (riscv_cpu_mxl(env) != MXL_RV32 && get_field(val, HSTATUS_VSXL) != 2) {
>          qemu_log_mask(LOG_UNIMP, "QEMU does not support mixed HSXLEN options.");
> @@ -2501,6 +2631,12 @@ static RISCVException rmw_hidelegh(CPURISCVState *env, int csrno,
>      uint64_t rval;
>      RISCVException ret;
>
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      ret = rmw_hideleg64(env, csrno, &rval,
>          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
>      if (ret_val) {
> @@ -2547,6 +2683,12 @@ static RISCVException rmw_hviph(CPURISCVState *env, int csrno,
>      uint64_t rval;
>      RISCVException ret;
>
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      ret = rmw_hvip64(env, csrno, &rval,
>          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
>      if (ret_val) {
> @@ -2601,6 +2743,13 @@ static RISCVException write_hcounteren(CPURISCVState *env, int csrno,
>  static RISCVException read_hgeie(CPURISCVState *env, int csrno,
>                                   target_ulong *val)
>  {
> +    RISCVException ret;
> +
> +    ret = smstateen_acc_ok(env, PRV_S, SMSTATEEN0_IMSIC);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      if (val) {
>          *val = env->hgeie;
>      }
> @@ -2610,6 +2759,13 @@ static RISCVException read_hgeie(CPURISCVState *env, int csrno,
>  static RISCVException write_hgeie(CPURISCVState *env, int csrno,
>                                    target_ulong val)
>  {
> +    RISCVException ret;
> +
> +    ret = smstateen_acc_ok(env, PRV_S, SMSTATEEN0_IMSIC);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      /* Only GEILEN:1 bits implemented and BIT0 is never implemented */
>      val &= ((((target_ulong)1) << env->geilen) - 1) << 1;
>      env->hgeie = val;
> @@ -2649,6 +2805,13 @@ static RISCVException write_htinst(CPURISCVState *env, int csrno,
>  static RISCVException read_hgeip(CPURISCVState *env, int csrno,
>                                   target_ulong *val)
>  {
> +    RISCVException ret;
> +
> +    ret = smstateen_acc_ok(env, PRV_S, SMSTATEEN0_IMSIC);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      if (val) {
>          *val = env->hgeip;
>      }
> @@ -2719,12 +2882,28 @@ static RISCVException write_htimedeltah(CPURISCVState *env, int csrno,
>
>  static int read_hvictl(CPURISCVState *env, int csrno, target_ulong *val)
>  {
> +    RISCVException ret;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      *val = env->hvictl;
>      return RISCV_EXCP_NONE;
>  }
>
>  static int write_hvictl(CPURISCVState *env, int csrno, target_ulong val)
>  {
> +    RISCVException ret = RISCV_EXCP_NONE;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      env->hvictl = val & HVICTL_VALID_MASK;
>      return RISCV_EXCP_NONE;
>  }
> @@ -2783,41 +2962,105 @@ static int write_hvipriox(CPURISCVState *env, int first_index,
>
>  static int read_hviprio1(CPURISCVState *env, int csrno, target_ulong *val)
>  {
> +    RISCVException ret;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      return read_hvipriox(env, 0, env->hviprio, val);
>  }
>
>  static int write_hviprio1(CPURISCVState *env, int csrno, target_ulong val)
>  {
> +    RISCVException ret;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      return write_hvipriox(env, 0, env->hviprio, val);
>  }
>
>  static int read_hviprio1h(CPURISCVState *env, int csrno, target_ulong *val)
>  {
> +    RISCVException ret;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      return read_hvipriox(env, 4, env->hviprio, val);
>  }
>
>  static int write_hviprio1h(CPURISCVState *env, int csrno, target_ulong val)
>  {
> +    RISCVException ret;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      return write_hvipriox(env, 4, env->hviprio, val);
>  }
>
>  static int read_hviprio2(CPURISCVState *env, int csrno, target_ulong *val)
>  {
> +    RISCVException ret;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      return read_hvipriox(env, 8, env->hviprio, val);
>  }
>
>  static int write_hviprio2(CPURISCVState *env, int csrno, target_ulong val)
>  {
> +    RISCVException ret;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      return write_hvipriox(env, 8, env->hviprio, val);
>  }
>
>  static int read_hviprio2h(CPURISCVState *env, int csrno, target_ulong *val)
>  {
> +    RISCVException ret;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      return read_hvipriox(env, 12, env->hviprio, val);
>  }
>
>  static int write_hviprio2h(CPURISCVState *env, int csrno, target_ulong val)
>  {
> +    RISCVException ret;
> +
> +    /* Check if smstateen is enabled and this access is allowed */
> +    ret = smstateen_aia_acc_ok(env, csrno);
> +    if (ret != RISCV_EXCP_NONE) {
> +        return ret;
> +    }
> +
>      return write_hvipriox(env, 12, env->hviprio, val);
>  }
>
> --
> 2.25.1
>
>
Re: [RFC PATCH v5 4/4] target/riscv: smstateen check for AIA/IMSIC
Posted by Mayuresh Chitale 2 years, 2 months ago
On Thu, 2022-06-16 at 17:18 +1000, Alistair Francis wrote:
> On Sat, Jun 4, 2022 at 2:15 AM Mayuresh Chitale
> <mchitale@ventanamicro.com> wrote:
> > If smstateen is implemented then accesses to AIA
> > registers CSRS, IMSIC CSRs and other IMSIC registers
> > is controlled by setting of corresponding bits in
> > mstateen/hstateen registers. Otherwise an illegal
> > instruction trap or virtual instruction trap is
> > generated.
> > 
> > Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
> > ---
> >  target/riscv/csr.c | 253
> > ++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 248 insertions(+), 5 deletions(-)
> > 
> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > index 8bbbed38ff..213b3c17ff 100644
> > --- a/target/riscv/csr.c
> > +++ b/target/riscv/csr.c
> > @@ -39,6 +39,7 @@ void riscv_set_csr_ops(int csrno,
> > riscv_csr_operations *ops)
> >  }
> > 
> >  /* Predicates */
> > +#if !defined(CONFIG_USER_ONLY)
> 
> This should just be in the original patch.

I will modify the second patch. 
> 
> >  static RISCVException smstateen_acc_ok(CPURISCVState *env, int
> > mode, int bit)
> >  {
> >      CPUState *cs = env_cpu(env);
> > @@ -49,7 +50,6 @@ static RISCVException
> > smstateen_acc_ok(CPURISCVState *env, int mode, int bit)
> >          return RISCV_EXCP_NONE;
> >      }
> > 
> > -#if !defined(CONFIG_USER_ONLY)
> >      if (!(env->mstateen[0] & 1UL << bit)) {
> >          return RISCV_EXCP_ILLEGAL_INST;
> >      }
> > @@ -65,11 +65,57 @@ static RISCVException
> > smstateen_acc_ok(CPURISCVState *env, int mode, int bit)
> >              return RISCV_EXCP_ILLEGAL_INST;
> >          }
> >      }
> > -#endif
> > -
> >      return RISCV_EXCP_NONE;
> >  }
> > 
> > +static RISCVException smstateen_aia_acc_ok(CPURISCVState *env, int
> > csrno)
> 
> The spec doesn't mention the effects on AIA, it just says that some
> bits are reserved. How do you know what should happen here?
Actually these bits were defined in an earlier version of the spec but
I can drop this patch for now and resend once those bits get defined
again.
> 
> Alistair
> 
> > +{
> > +    int bit, mode;
> > +
> > +    switch (csrno) {
> > +    case CSR_SSETEIPNUM:
> > +    case CSR_SCLREIPNUM:
> > +    case CSR_SSETEIENUM:
> > +    case CSR_SCLREIENUM:
> > +    case CSR_STOPEI:
> > +    case CSR_VSSETEIPNUM:
> > +    case CSR_VSCLREIPNUM:
> > +    case CSR_VSSETEIENUM:
> > +    case CSR_VSCLREIENUM:
> > +    case CSR_VSTOPEI:
> > +    case CSR_HSTATUS:
> > +        mode = PRV_S;
> > +        bit = SMSTATEEN0_IMSIC;
> > +        break;
> > +
> > +    case CSR_SIEH:
> > +    case CSR_SIPH:
> > +    case CSR_HVIPH:
> > +    case CSR_HVICTL:
> > +    case CSR_HVIPRIO1:
> > +    case CSR_HVIPRIO2:
> > +    case CSR_HVIPRIO1H:
> > +    case CSR_HVIPRIO2H:
> > +    case CSR_VSIEH:
> > +    case CSR_VSIPH:
> > +        mode = PRV_S;
> > +        bit = SMSTATEEN0_AIA;
> > +        break;
> > +
> > +    case CSR_SISELECT:
> > +    case CSR_VSISELECT:
> > +        mode = PRV_S;
> > +        bit = SMSTATEEN0_SVSLCT;
> > +        break;
> > +
> > +    default:
> > +        return RISCV_EXCP_NONE;
> > +    }
> > +
> > +    return smstateen_acc_ok(env, mode, bit);
> > +}
> > +#endif
> > +
> >  static RISCVException fs(CPURISCVState *env, int csrno)
> >  {
> >  #if !defined(CONFIG_USER_ONLY)
> > @@ -1130,6 +1176,13 @@ static int rmw_xiselect(CPURISCVState *env,
> > int csrno, target_ulong *val,
> >                          target_ulong new_val, target_ulong
> > wr_mask)
> >  {
> >      target_ulong *iselect;
> > +    RISCVException ret;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > 
> >      /* Translate CSR number for VS-mode */
> >      csrno = aia_xlate_vs_csrno(env, csrno);
> > @@ -1212,7 +1265,9 @@ static int rmw_xireg(CPURISCVState *env, int
> > csrno, target_ulong *val,
> >      bool virt;
> >      uint8_t *iprio;
> >      int ret = -EINVAL;
> > -    target_ulong priv, isel, vgein;
> > +    target_ulong priv, isel, vgein = 0;
> > +    CPUState *cs = env_cpu(env);
> > +    RISCVCPU *cpu = RISCV_CPU(cs);
> > 
> >      /* Translate CSR number for VS-mode */
> >      csrno = aia_xlate_vs_csrno(env, csrno);
> > @@ -1241,11 +1296,20 @@ static int rmw_xireg(CPURISCVState *env,
> > int csrno, target_ulong *val,
> >      };
> > 
> >      /* Find the selected guest interrupt file */
> > -    vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
> > +    if (virt) {
> > +        if (!cpu->cfg.ext_smstateen ||
> > +                (env->hstateen[0] & 1UL << SMSTATEEN0_IMSIC)) {
> > +            vgein = get_field(env->hstatus, HSTATUS_VGEIN);
> > +        }
> > +    }
> > 
> >      if (ISELECT_IPRIO0 <= isel && isel <= ISELECT_IPRIO15) {
> >          /* Local interrupt priority registers not available for
> > VS-mode */
> >          if (!virt) {
> > +            if (priv == PRV_S && cpu->cfg.ext_smstateen &&
> > +                !(env->hstateen[0] & 1UL << SMSTATEEN0_AIA)) {
> > +                goto done;
> > +            }
> >              ret = rmw_iprio(riscv_cpu_mxl_bits(env),
> >                              isel, iprio, val, new_val, wr_mask,
> >                              (priv == PRV_M) ? IRQ_M_EXT :
> > IRQ_S_EXT);
> > @@ -1279,6 +1343,13 @@ static int rmw_xsetclreinum(CPURISCVState
> > *env, int csrno, target_ulong *val,
> >      int ret = -EINVAL;
> >      bool set, pend, virt;
> >      target_ulong priv, isel, vgein, xlen, nval, wmask;
> > +    RISCVException excp;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    excp = smstateen_aia_acc_ok(env, csrno);
> > +    if (excp != RISCV_EXCP_NONE) {
> > +        return excp;
> > +    }
> > 
> >      /* Translate CSR number for VS-mode */
> >      csrno = aia_xlate_vs_csrno(env, csrno);
> > @@ -1397,6 +1468,13 @@ static int rmw_xtopei(CPURISCVState *env,
> > int csrno, target_ulong *val,
> >      bool virt;
> >      int ret = -EINVAL;
> >      target_ulong priv, vgein;
> > +    RISCVException excp;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    excp = smstateen_aia_acc_ok(env, csrno);
> > +    if (excp != RISCV_EXCP_NONE) {
> > +        return excp;
> > +    }
> > 
> >      /* Translate CSR number for VS-mode */
> >      csrno = aia_xlate_vs_csrno(env, csrno);
> > @@ -1708,6 +1786,12 @@ static RISCVException
> > write_mstateen(CPURISCVState *env, int csrno,
> >          wr_mask |= 1UL << SMSTATEEN0_FCSR;
> >      }
> > 
> > +    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
> > +                | (1UL << SMSTATEEN0_AIA)
> > +                | (1UL << SMSTATEEN0_SVSLCT);
> > +    }
> > +
> >      write_smstateen(env, reg, wr_mask, new_val);
> > 
> >      return RISCV_EXCP_NONE;
> > @@ -1736,6 +1820,12 @@ static RISCVException
> > write_mstateenh(CPURISCVState *env, int csrno,
> >          wr_mask |= 1UL << SMSTATEEN0_FCSR;
> >      }
> > 
> > +    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
> > +                | (1UL << SMSTATEEN0_AIA)
> > +                | (1UL << SMSTATEEN0_SVSLCT);
> > +    }
> > +
> >      write_smstateen(env, reg, wr_mask, val);
> > 
> >      return RISCV_EXCP_NONE;
> > @@ -1761,6 +1851,12 @@ static RISCVException
> > write_hstateen(CPURISCVState *env, int csrno,
> >          wr_mask |= 1UL << SMSTATEEN0_FCSR;
> >      }
> > 
> > +    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
> > +                | (1UL << SMSTATEEN0_AIA)
> > +                | (1UL << SMSTATEEN0_SVSLCT);
> > +    }
> > +
> >      reg = &env->hstateen[index];
> >      wr_mask &= env->mstateen[index];
> >      write_smstateen(env, reg, wr_mask, new_val);
> > @@ -1789,6 +1885,12 @@ static RISCVException
> > write_hstateenh(CPURISCVState *env, int csrno,
> >          wr_mask |= 1UL << SMSTATEEN0_FCSR;
> >      }
> > 
> > +    if (riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +        wr_mask |= (1UL << SMSTATEEN0_IMSIC)
> > +                | (1UL << SMSTATEEN0_AIA)
> > +                | (1UL << SMSTATEEN0_SVSLCT);
> > +    }
> > +
> >      reg = &env->hstateen[index];
> >      val = (uint64_t)new_val << 32;
> >      val |= *reg & 0xFFFFFFFF;
> > @@ -1979,6 +2081,12 @@ static RISCVException
> > rmw_vsieh(CPURISCVState *env, int csrno,
> >      uint64_t rval;
> >      RISCVException ret;
> > 
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      ret = rmw_vsie64(env, csrno, &rval,
> >          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
> >      if (ret_val) {
> > @@ -2033,6 +2141,12 @@ static RISCVException rmw_sieh(CPURISCVState
> > *env, int csrno,
> >      uint64_t rval;
> >      RISCVException ret;
> > 
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      ret = rmw_sie64(env, csrno, &rval,
> >          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
> >      if (ret_val) {
> > @@ -2195,6 +2309,12 @@ static RISCVException
> > rmw_vsiph(CPURISCVState *env, int csrno,
> >      uint64_t rval;
> >      RISCVException ret;
> > 
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      ret = rmw_vsip64(env, csrno, &rval,
> >          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
> >      if (ret_val) {
> > @@ -2249,6 +2369,12 @@ static RISCVException rmw_siph(CPURISCVState
> > *env, int csrno,
> >      uint64_t rval;
> >      RISCVException ret;
> > 
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      ret = rmw_sip64(env, csrno, &rval,
> >          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
> >      if (ret_val) {
> > @@ -2441,6 +2567,10 @@ static RISCVException
> > read_hstatus(CPURISCVState *env, int csrno,
> >  static RISCVException write_hstatus(CPURISCVState *env, int csrno,
> >                                      target_ulong val)
> >  {
> > +    if (smstateen_aia_acc_ok(env, csrno) != RISCV_EXCP_NONE) {
> > +        val &= ~HSTATUS_VGEIN;
> > +    }
> > +
> >      env->hstatus = val;
> >      if (riscv_cpu_mxl(env) != MXL_RV32 && get_field(val,
> > HSTATUS_VSXL) != 2) {
> >          qemu_log_mask(LOG_UNIMP, "QEMU does not support mixed
> > HSXLEN options.");
> > @@ -2501,6 +2631,12 @@ static RISCVException
> > rmw_hidelegh(CPURISCVState *env, int csrno,
> >      uint64_t rval;
> >      RISCVException ret;
> > 
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      ret = rmw_hideleg64(env, csrno, &rval,
> >          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
> >      if (ret_val) {
> > @@ -2547,6 +2683,12 @@ static RISCVException
> > rmw_hviph(CPURISCVState *env, int csrno,
> >      uint64_t rval;
> >      RISCVException ret;
> > 
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      ret = rmw_hvip64(env, csrno, &rval,
> >          ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32);
> >      if (ret_val) {
> > @@ -2601,6 +2743,13 @@ static RISCVException
> > write_hcounteren(CPURISCVState *env, int csrno,
> >  static RISCVException read_hgeie(CPURISCVState *env, int csrno,
> >                                   target_ulong *val)
> >  {
> > +    RISCVException ret;
> > +
> > +    ret = smstateen_acc_ok(env, PRV_S, SMSTATEEN0_IMSIC);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      if (val) {
> >          *val = env->hgeie;
> >      }
> > @@ -2610,6 +2759,13 @@ static RISCVException
> > read_hgeie(CPURISCVState *env, int csrno,
> >  static RISCVException write_hgeie(CPURISCVState *env, int csrno,
> >                                    target_ulong val)
> >  {
> > +    RISCVException ret;
> > +
> > +    ret = smstateen_acc_ok(env, PRV_S, SMSTATEEN0_IMSIC);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      /* Only GEILEN:1 bits implemented and BIT0 is never
> > implemented */
> >      val &= ((((target_ulong)1) << env->geilen) - 1) << 1;
> >      env->hgeie = val;
> > @@ -2649,6 +2805,13 @@ static RISCVException
> > write_htinst(CPURISCVState *env, int csrno,
> >  static RISCVException read_hgeip(CPURISCVState *env, int csrno,
> >                                   target_ulong *val)
> >  {
> > +    RISCVException ret;
> > +
> > +    ret = smstateen_acc_ok(env, PRV_S, SMSTATEEN0_IMSIC);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      if (val) {
> >          *val = env->hgeip;
> >      }
> > @@ -2719,12 +2882,28 @@ static RISCVException
> > write_htimedeltah(CPURISCVState *env, int csrno,
> > 
> >  static int read_hvictl(CPURISCVState *env, int csrno, target_ulong
> > *val)
> >  {
> > +    RISCVException ret;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      *val = env->hvictl;
> >      return RISCV_EXCP_NONE;
> >  }
> > 
> >  static int write_hvictl(CPURISCVState *env, int csrno,
> > target_ulong val)
> >  {
> > +    RISCVException ret = RISCV_EXCP_NONE;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      env->hvictl = val & HVICTL_VALID_MASK;
> >      return RISCV_EXCP_NONE;
> >  }
> > @@ -2783,41 +2962,105 @@ static int write_hvipriox(CPURISCVState
> > *env, int first_index,
> > 
> >  static int read_hviprio1(CPURISCVState *env, int csrno,
> > target_ulong *val)
> >  {
> > +    RISCVException ret;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      return read_hvipriox(env, 0, env->hviprio, val);
> >  }
> > 
> >  static int write_hviprio1(CPURISCVState *env, int csrno,
> > target_ulong val)
> >  {
> > +    RISCVException ret;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      return write_hvipriox(env, 0, env->hviprio, val);
> >  }
> > 
> >  static int read_hviprio1h(CPURISCVState *env, int csrno,
> > target_ulong *val)
> >  {
> > +    RISCVException ret;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      return read_hvipriox(env, 4, env->hviprio, val);
> >  }
> > 
> >  static int write_hviprio1h(CPURISCVState *env, int csrno,
> > target_ulong val)
> >  {
> > +    RISCVException ret;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      return write_hvipriox(env, 4, env->hviprio, val);
> >  }
> > 
> >  static int read_hviprio2(CPURISCVState *env, int csrno,
> > target_ulong *val)
> >  {
> > +    RISCVException ret;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      return read_hvipriox(env, 8, env->hviprio, val);
> >  }
> > 
> >  static int write_hviprio2(CPURISCVState *env, int csrno,
> > target_ulong val)
> >  {
> > +    RISCVException ret;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      return write_hvipriox(env, 8, env->hviprio, val);
> >  }
> > 
> >  static int read_hviprio2h(CPURISCVState *env, int csrno,
> > target_ulong *val)
> >  {
> > +    RISCVException ret;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      return read_hvipriox(env, 12, env->hviprio, val);
> >  }
> > 
> >  static int write_hviprio2h(CPURISCVState *env, int csrno,
> > target_ulong val)
> >  {
> > +    RISCVException ret;
> > +
> > +    /* Check if smstateen is enabled and this access is allowed */
> > +    ret = smstateen_aia_acc_ok(env, csrno);
> > +    if (ret != RISCV_EXCP_NONE) {
> > +        return ret;
> > +    }
> > +
> >      return write_hvipriox(env, 12, env->hviprio, val);
> >  }
> > 
> > --
> > 2.25.1
> > 
> >