Message ID | 20220721153136.377578-5-mchitale@ventanamicro.com |
---|---|
State | New |
Headers | show |
Series | RISC-V Smstateen support | expand |
在 2022/7/21 下午11:31, Mayuresh Chitale 写道: > 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. Is there any spec for this? I found only two sentences for this in smstateen spec: " bits 60:58 - Reserved for the RISC-V Advanced Interrupt Architecture" " Setting hstateen0 bit 58 to zero prevents a virtual machine from accessing the hart’s IMSIC the same as setting hstatus.VGEIN = 0" > Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com> > --- > target/riscv/csr.c | 222 ++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 220 insertions(+), 2 deletions(-) > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index a597b6cbc7..e40dd35d85 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -87,6 +87,42 @@ static RISCVException smstateen_acc_ok(CPURISCVState *env, int index, > > return RISCV_EXCP_NONE; > } > + > +static RISCVException smstateen_aia_acc_ok(CPURISCVState *env, int csrno) > +{ > + uint64_t bit; > + > + switch (csrno) { > + case CSR_STOPEI: > + case CSR_VSTOPEI: > + case CSR_HSTATUS: > + 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: > + bit = SMSTATEEN0_AIA; > + break; > + > + case CSR_SISELECT: > + case CSR_VSISELECT: > + bit = SMSTATEEN0_SVSLCT; > + break; > + > + default: > + return RISCV_EXCP_NONE; > + } > + > + return smstateen_acc_ok(env, 0, bit); > +} > #endif > > static RISCVException fs(CPURISCVState *env, int csrno) > @@ -1383,6 +1419,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); > @@ -1465,7 +1508,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); > @@ -1494,11 +1539,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] & 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] & 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); > @@ -1532,6 +1586,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); > @@ -1884,6 +1945,10 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno, > wr_mask |= SMSTATEEN0_FCSR; > } > > + if (riscv_feature(env, RISCV_FEATURE_AIA)) { > + wr_mask |= (SMSTATEEN0_IMSIC | SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT); > + } > + > return write_mstateen(env, csrno, wr_mask, new_val); > } > > @@ -1935,6 +2000,10 @@ static RISCVException write_mstateen0h(CPURISCVState *env, int csrno, > wr_mask |= SMSTATEEN0_FCSR; > } > > + if (riscv_feature(env, RISCV_FEATURE_AIA)) { > + wr_mask |= (SMSTATEEN0_IMSIC | SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT); > + } > + > return write_mstateenh(env, csrno, wr_mask, new_val); > } > > @@ -1988,6 +2057,10 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno, > wr_mask |= SMSTATEEN0_FCSR; > } > > + if (riscv_feature(env, RISCV_FEATURE_AIA)) { > + wr_mask |= (SMSTATEEN0_IMSIC | SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT); > + } > + > return write_hstateen(env, csrno, wr_mask, new_val); > } > > @@ -2043,6 +2116,10 @@ static RISCVException write_hstateen0h(CPURISCVState *env, int csrno, > wr_mask |= SMSTATEEN0_FCSR; > } > > + if (riscv_feature(env, RISCV_FEATURE_AIA)) { > + wr_mask |= SMSTATEEN0_IMSIC | SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT; > + } > + > return write_hstateenh(env, csrno, wr_mask, new_val); > } > > @@ -2277,6 +2354,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) { > @@ -2331,6 +2414,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) { > @@ -2493,6 +2582,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) { > @@ -2547,6 +2642,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) { > @@ -2739,6 +2840,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; > + } > + Why this? For the statement "Setting hstateen0 bit 58 to zero prevents a virtual machine from accessing the hart’s IMSIC the same as setting hstatus.VGEIN = 0" I think it means "setting hstateen0 bit 58 to zero" and "setting hstatus.VGEIN = 0" have the same function: " prevents a virtual machine from accessing the hart’s IMSIC", not "setting hstateen0 bit 58 to zero" is to "setting hstatus.VGEIN = 0". Or any other statement about this ? Regards, Weiwei Li > 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."); > @@ -2799,6 +2904,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) { > @@ -2845,6 +2956,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) { > @@ -2899,6 +3016,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, 0, SMSTATEEN0_IMSIC); > + if (ret != RISCV_EXCP_NONE) { > + return ret; > + } > + > if (val) { > *val = env->hgeie; > } > @@ -2908,6 +3032,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, 0, 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; > @@ -2947,6 +3078,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, 0, SMSTATEEN0_IMSIC); > + if (ret != RISCV_EXCP_NONE) { > + return ret; > + } > + > if (val) { > *val = env->hgeip; > } > @@ -3017,12 +3155,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; > } > @@ -3081,41 +3235,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); > } >
diff --git a/target/riscv/csr.c b/target/riscv/csr.c index a597b6cbc7..e40dd35d85 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -87,6 +87,42 @@ static RISCVException smstateen_acc_ok(CPURISCVState *env, int index, return RISCV_EXCP_NONE; } + +static RISCVException smstateen_aia_acc_ok(CPURISCVState *env, int csrno) +{ + uint64_t bit; + + switch (csrno) { + case CSR_STOPEI: + case CSR_VSTOPEI: + case CSR_HSTATUS: + 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: + bit = SMSTATEEN0_AIA; + break; + + case CSR_SISELECT: + case CSR_VSISELECT: + bit = SMSTATEEN0_SVSLCT; + break; + + default: + return RISCV_EXCP_NONE; + } + + return smstateen_acc_ok(env, 0, bit); +} #endif static RISCVException fs(CPURISCVState *env, int csrno) @@ -1383,6 +1419,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); @@ -1465,7 +1508,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); @@ -1494,11 +1539,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] & 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] & 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); @@ -1532,6 +1586,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); @@ -1884,6 +1945,10 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno, wr_mask |= SMSTATEEN0_FCSR; } + if (riscv_feature(env, RISCV_FEATURE_AIA)) { + wr_mask |= (SMSTATEEN0_IMSIC | SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT); + } + return write_mstateen(env, csrno, wr_mask, new_val); } @@ -1935,6 +2000,10 @@ static RISCVException write_mstateen0h(CPURISCVState *env, int csrno, wr_mask |= SMSTATEEN0_FCSR; } + if (riscv_feature(env, RISCV_FEATURE_AIA)) { + wr_mask |= (SMSTATEEN0_IMSIC | SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT); + } + return write_mstateenh(env, csrno, wr_mask, new_val); } @@ -1988,6 +2057,10 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno, wr_mask |= SMSTATEEN0_FCSR; } + if (riscv_feature(env, RISCV_FEATURE_AIA)) { + wr_mask |= (SMSTATEEN0_IMSIC | SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT); + } + return write_hstateen(env, csrno, wr_mask, new_val); } @@ -2043,6 +2116,10 @@ static RISCVException write_hstateen0h(CPURISCVState *env, int csrno, wr_mask |= SMSTATEEN0_FCSR; } + if (riscv_feature(env, RISCV_FEATURE_AIA)) { + wr_mask |= SMSTATEEN0_IMSIC | SMSTATEEN0_AIA | SMSTATEEN0_SVSLCT; + } + return write_hstateenh(env, csrno, wr_mask, new_val); } @@ -2277,6 +2354,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) { @@ -2331,6 +2414,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) { @@ -2493,6 +2582,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) { @@ -2547,6 +2642,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) { @@ -2739,6 +2840,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."); @@ -2799,6 +2904,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) { @@ -2845,6 +2956,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) { @@ -2899,6 +3016,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, 0, SMSTATEEN0_IMSIC); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + if (val) { *val = env->hgeie; } @@ -2908,6 +3032,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, 0, 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; @@ -2947,6 +3078,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, 0, SMSTATEEN0_IMSIC); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + if (val) { *val = env->hgeip; } @@ -3017,12 +3155,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; } @@ -3081,41 +3235,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); }
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 | 222 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 220 insertions(+), 2 deletions(-)