Add will_return_to_guest() function, and handle process of return to guest at end of helper_ertn().
Signed-off-by: SignKirigami <[email protected]> Signed-off-by: Hengyu Yu <[email protected]> --- target/loongarch/cpu.h | 8 ++++++++ target/loongarch/tcg/op_helper.c | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index ba28d80272..891eea47bd 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -573,6 +573,14 @@ static inline void trigger_vm_exit(CPULoongArchState *env) env->vm_exit = true; } +static inline bool will_return_to_guest(CPULoongArchState *env) +{ + if (!cpu_has_lvz(env) || env_vm_level(env) == VM_LEVEL1) { + return false; + } + return FIELD_EX64(get_sys(env, VM_LEVEL0)->CSR_GSTAT, CSR_GSTAT, PVM); +} + static inline CPUTimerState *env_timer(CPULoongArchState *env) { return &env->sys_states[0].timer_state; diff --git a/target/loongarch/tcg/op_helper.c b/target/loongarch/tcg/op_helper.c index f98fe4d4a1..3035dfa08d 100644 --- a/target/loongarch/tcg/op_helper.c +++ b/target/loongarch/tcg/op_helper.c @@ -12,6 +12,7 @@ #include "exec/helper-proto.h" #include "accel/tcg/cpu-ldst.h" #include "internals.h" +#include "qemu/main-loop.h" #include "qemu/crc32c.h" #include <zlib.h> /* for crc32 */ #include "cpu-csr.h" @@ -90,6 +91,8 @@ void helper_ertn(CPULoongArchState *env) { uint64_t csr_pplv, csr_pie; CPUSysState *sys = env_sys(env); + CPUSysState *host = get_sys(env, VM_LEVEL0); + CPUSysState *guest = get_sys(env, VM_LEVEL1); if (FIELD_EX64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) { csr_pplv = FIELD_EX64(sys->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV); @@ -113,6 +116,17 @@ void helper_ertn(CPULoongArchState *env) sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, IE, csr_pie); env->lladdr = 1; + if (will_return_to_guest(env)) { + host->CSR_GSTAT = FIELD_DP64(host->CSR_GSTAT, CSR_GSTAT, VM, 1); + set_sys(env, VM_LEVEL1); + bql_lock(); + if (FIELD_EX64(guest->CSR_ESTAT, CSR_ESTAT, IS)) { + cpu_interrupt(env_cpu(env), CPU_INTERRUPT_GUEST); + } else { + cpu_reset_interrupt(env_cpu(env), CPU_INTERRUPT_GUEST); + } + bql_unlock(); + } } void helper_idle(CPULoongArchState *env) -- 2.55.0
