diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 43617e7c1f..fb6a3e9092 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -445,6 +445,7 @@ #define HSTATUS_VTSR 0x00400000 #define HSTATUS_HU 0x00000200 #define HSTATUS_GVA 0x00000040 +#define HSTATUS_SPVP 0x00000100 #define HSTATUS32_WPRI 0xFF8FF87E #define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 661e790fdc..dc7ae3e7b1 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -929,9 +929,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) } else if (riscv_cpu_virt_enabled(env)) { /* Trap into HS mode, from virt */ riscv_cpu_swap_hypervisor_regs(env); - env->hstatus = set_field(env->hstatus, HSTATUS_SP2V, - get_field(env->hstatus, HSTATUS_SPV)); - env->hstatus = set_field(env->hstatus, HSTATUS_SP2P, + env->hstatus = set_field(env->hstatus, HSTATUS_SPVP, get_field(env->mstatus, SSTATUS_SPP)); env->hstatus = set_field(env->hstatus, HSTATUS_SPV, riscv_cpu_virt_enabled(env)); @@ -942,13 +940,11 @@ void riscv_cpu_do_interrupt(CPUState *cs) riscv_cpu_set_force_hs_excep(env, 0); } else { /* Trap into HS mode */ - env->hstatus = set_field(env->hstatus, HSTATUS_SP2V, - get_field(env->hstatus, HSTATUS_SPV)); - env->hstatus = set_field(env->hstatus, HSTATUS_SP2P, - get_field(env->mstatus, SSTATUS_SPP)); - env->hstatus = set_field(env->hstatus, HSTATUS_SPV, - riscv_cpu_virt_enabled(env)); - + if (!riscv_cpu_two_stage_lookup(env)) { + env->hstatus = set_field(env->hstatus, HSTATUS_SPV, + riscv_cpu_virt_enabled(env)); + } + riscv_cpu_set_two_stage_lookup(env, false); htval = env->guest_phys_fault_addr; } } diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 3d306c343c..4b64bfe7d2 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -97,12 +97,8 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) prev_priv = get_field(mstatus, MSTATUS_SPP); prev_virt = get_field(hstatus, HSTATUS_SPV); - hstatus = set_field(hstatus, HSTATUS_SPV, - get_field(hstatus, HSTATUS_SP2V)); - mstatus = set_field(mstatus, MSTATUS_SPP, - get_field(hstatus, HSTATUS_SP2P)); - hstatus = set_field(hstatus, HSTATUS_SP2V, 0); - hstatus = set_field(hstatus, HSTATUS_SP2P, 0); + hstatus = set_field(hstatus, HSTATUS_SPV, 0); + mstatus = set_field(mstatus, MSTATUS_SPP, 0); mstatus = set_field(mstatus, SSTATUS_SIE, get_field(mstatus, SSTATUS_SPIE)); mstatus = set_field(mstatus, SSTATUS_SPIE, 1); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 3919f570f7..79dca2291b 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -797,16 +797,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) #if !defined(CONFIG_USER_ONLY) if (riscv_has_ext(env, RVH)) { ctx->virt_enabled = riscv_cpu_virt_enabled(env); - if (env->priv_ver == PRV_M && - get_field(env->mstatus, MSTATUS_MPRV) && - MSTATUS_MPV_ISSET(env)) { - ctx->virt_enabled = true; - } else if (env->priv == PRV_S && - !riscv_cpu_virt_enabled(env) && - get_field(env->hstatus, HSTATUS_SPRV) && - get_field(env->hstatus, HSTATUS_SPV)) { - ctx->virt_enabled = true; - } } else { ctx->virt_enabled = false; }