target/riscv: smstateen check for h/s/envcfg

Accesses to henvcfg, henvcfgh and senvcfg are allowed only if the corresponding
bit in mstateen0/hstateen0 is enabled. Otherwise an illegal instruction trap is
generated.

Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
Reviewed-by: Weiwei Li<liweiwei@iscas.ac.cn>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20221016124726.102129-3-mchitale@ventanamicro.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Mayuresh Chitale 2022-10-16 18:17:23 +05:30 committed by Alistair Francis
parent 3bee0e4010
commit 252b06f638

View File

@ -41,6 +41,42 @@ 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 index,
uint64_t bit)
{
bool virt = riscv_cpu_virt_enabled(env);
CPUState *cs = env_cpu(env);
RISCVCPU *cpu = RISCV_CPU(cs);
if (env->priv == PRV_M || !cpu->cfg.ext_smstateen) {
return RISCV_EXCP_NONE;
}
if (!(env->mstateen[index] & bit)) {
return RISCV_EXCP_ILLEGAL_INST;
}
if (virt) {
if (!(env->hstateen[index] & bit)) {
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
}
if (env->priv == PRV_U && !(env->sstateen[index] & bit)) {
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
}
}
if (env->priv == PRV_U && riscv_has_ext(env, RVS)) {
if (!(env->sstateen[index] & bit)) {
return RISCV_EXCP_ILLEGAL_INST;
}
}
return RISCV_EXCP_NONE;
}
#endif
static RISCVException fs(CPURISCVState *env, int csrno)
{
#if !defined(CONFIG_USER_ONLY)
@ -1874,6 +1910,13 @@ static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
static RISCVException read_senvcfg(CPURISCVState *env, int csrno,
target_ulong *val)
{
RISCVException ret;
ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
*val = env->senvcfg;
return RISCV_EXCP_NONE;
}
@ -1882,15 +1925,27 @@ static RISCVException write_senvcfg(CPURISCVState *env, int csrno,
target_ulong val)
{
uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | SENVCFG_CBZE;
RISCVException ret;
ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
env->senvcfg = (env->senvcfg & ~mask) | (val & mask);
return RISCV_EXCP_NONE;
}
static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
target_ulong *val)
{
RISCVException ret;
ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
*val = env->henvcfg;
return RISCV_EXCP_NONE;
}
@ -1899,6 +1954,12 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
target_ulong val)
{
uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE | HENVCFG_CBZE;
RISCVException ret;
ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
if (riscv_cpu_mxl(env) == MXL_RV64) {
mask |= HENVCFG_PBMTE | HENVCFG_STCE;
@ -1912,6 +1973,13 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
target_ulong *val)
{
RISCVException ret;
ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
*val = env->henvcfg >> 32;
return RISCV_EXCP_NONE;
}
@ -1921,9 +1989,14 @@ static RISCVException write_henvcfgh(CPURISCVState *env, int csrno,
{
uint64_t mask = HENVCFG_PBMTE | HENVCFG_STCE;
uint64_t valh = (uint64_t)val << 32;
RISCVException ret;
ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
env->henvcfg = (env->henvcfg & ~mask) | (valh & mask);
return RISCV_EXCP_NONE;
}
@ -1949,7 +2022,7 @@ static RISCVException write_mstateen(CPURISCVState *env, int csrno,
static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
target_ulong new_val)
{
uint64_t wr_mask = SMSTATEEN_STATEEN;
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
return write_mstateen(env, csrno, wr_mask, new_val);
}
@ -1984,7 +2057,7 @@ static RISCVException write_mstateenh(CPURISCVState *env, int csrno,
static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,
target_ulong new_val)
{
uint64_t wr_mask = SMSTATEEN_STATEEN;
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
return write_mstateenh(env, csrno, wr_mask, new_val);
}
@ -2021,7 +2094,7 @@ static RISCVException write_hstateen(CPURISCVState *env, int csrno,
static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
target_ulong new_val)
{
uint64_t wr_mask = SMSTATEEN_STATEEN;
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
return write_hstateen(env, csrno, wr_mask, new_val);
}
@ -2060,7 +2133,7 @@ static RISCVException write_hstateenh(CPURISCVState *env, int csrno,
static RISCVException write_hstateen0h(CPURISCVState *env, int csrno,
target_ulong new_val)
{
uint64_t wr_mask = SMSTATEEN_STATEEN;
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
return write_hstateenh(env, csrno, wr_mask, new_val);
}
@ -2107,7 +2180,7 @@ static RISCVException write_sstateen(CPURISCVState *env, int csrno,
static RISCVException write_sstateen0(CPURISCVState *env, int csrno,
target_ulong new_val)
{
uint64_t wr_mask = SMSTATEEN_STATEEN;
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
return write_sstateen(env, csrno, wr_mask, new_val);
}