在 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 <mchit...@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);
}