diff --git a/qemu/target/riscv/cpu_bits.h b/qemu/target/riscv/cpu_bits.h index f40ea261..ffa73864 100644 --- a/qemu/target/riscv/cpu_bits.h +++ b/qemu/target/riscv/cpu_bits.h @@ -427,6 +427,7 @@ #define HSTATUS_SP2P 0x00000100 #define HSTATUS_SP2V 0x00000200 #define HSTATUS_VTVM 0x00100000 +#define HSTATUS_VTW 0x00200000 #define HSTATUS_VTSR 0x00400000 #define HSTATUS32_WPRI 0xFF8FF87E diff --git a/qemu/target/riscv/op_helper.c b/qemu/target/riscv/op_helper.c index 05dd67ae..5afb2ce8 100644 --- a/qemu/target/riscv/op_helper.c +++ b/qemu/target/riscv/op_helper.c @@ -172,11 +172,15 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) void helper_wfi(CPURISCVState *env) { CPUState *cs = env_cpu(env); + bool rvs = riscv_has_ext(env, RVS); + bool prv_u = env->priv == PRV_U; + bool prv_s = env->priv == PRV_S; - if ((env->priv == PRV_S && - env->priv_ver >= PRIV_VERSION_1_10_0 && - get_field(env->mstatus, MSTATUS_TW)) || - riscv_cpu_virt_enabled(env)) { + if (((prv_s || (!rvs && prv_u)) && get_field(env->mstatus, MSTATUS_TW)) || + (rvs && prv_u && !riscv_cpu_virt_enabled(env))) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } else if (riscv_cpu_virt_enabled(env) && (prv_u || + (prv_s && get_field(env->hstatus, HSTATUS_VTW)))) { riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); } else { cs->halted = 1;