RISC-V: Implement mstatus.TSR/TW/TVM
This adds the necessary minimum to support S-mode virtualization for priv ISA >= v1.10 Signed-off-by: Michael Clark <mjc@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Co-authored-by: Matthew Suozzo <msuozzo@google.com> Co-authored-by: Michael Clark <mjc@sifive.com> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
This commit is contained in:
parent
533b8f8877
commit
7f2b5ff125
|
@ -305,7 +305,8 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
|
|||
}
|
||||
mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
|
||||
MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
|
||||
MSTATUS_MPP | MSTATUS_MXR;
|
||||
MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
|
||||
MSTATUS_TW;
|
||||
}
|
||||
|
||||
/* silenty discard mstatus.mpp writes for unsupported modes */
|
||||
|
@ -642,7 +643,11 @@ static int read_satp(CPURISCVState *env, int csrno, target_ulong *val)
|
|||
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
|
||||
*val = 0;
|
||||
} else if (env->priv_ver >= PRIV_VERSION_1_10_0) {
|
||||
*val = env->satp;
|
||||
if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
|
||||
return -1;
|
||||
} else {
|
||||
*val = env->satp;
|
||||
}
|
||||
} else {
|
||||
*val = env->sptbr;
|
||||
}
|
||||
|
@ -663,8 +668,12 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
|
|||
validate_vm(env, get_field(val, SATP_MODE)) &&
|
||||
((val ^ env->satp) & (SATP_MODE | SATP_ASID | SATP_PPN)))
|
||||
{
|
||||
tlb_flush(CPU(riscv_env_get_cpu(env)));
|
||||
env->satp = val;
|
||||
if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
|
||||
return -1;
|
||||
} else {
|
||||
tlb_flush(CPU(riscv_env_get_cpu(env)));
|
||||
env->satp = val;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -82,6 +82,11 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
|
|||
do_raise_exception_err(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
|
||||
}
|
||||
|
||||
if (env->priv_ver >= PRIV_VERSION_1_10_0 &&
|
||||
get_field(env->mstatus, MSTATUS_TSR)) {
|
||||
do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
||||
}
|
||||
|
||||
target_ulong mstatus = env->mstatus;
|
||||
target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
|
||||
mstatus = set_field(mstatus,
|
||||
|
@ -125,16 +130,28 @@ void helper_wfi(CPURISCVState *env)
|
|||
{
|
||||
CPUState *cs = CPU(riscv_env_get_cpu(env));
|
||||
|
||||
cs->halted = 1;
|
||||
cs->exception_index = EXCP_HLT;
|
||||
cpu_loop_exit(cs);
|
||||
if (env->priv == PRV_S &&
|
||||
env->priv_ver >= PRIV_VERSION_1_10_0 &&
|
||||
get_field(env->mstatus, MSTATUS_TW)) {
|
||||
do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
||||
} else {
|
||||
cs->halted = 1;
|
||||
cs->exception_index = EXCP_HLT;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
}
|
||||
|
||||
void helper_tlb_flush(CPURISCVState *env)
|
||||
{
|
||||
RISCVCPU *cpu = riscv_env_get_cpu(env);
|
||||
CPUState *cs = CPU(cpu);
|
||||
tlb_flush(cs);
|
||||
if (env->priv == PRV_S &&
|
||||
env->priv_ver >= PRIV_VERSION_1_10_0 &&
|
||||
get_field(env->mstatus, MSTATUS_TVM)) {
|
||||
do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
||||
} else {
|
||||
tlb_flush(cs);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
|
Loading…
Reference in a new issue