From 6d7370457ffeb60183444bdb4737c9a6988473b9 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 12 Feb 2018 23:08:46 -0500 Subject: [PATCH] target-arm: Don't halt on WFI unless we don't have any work Just NOP the WFI instruction if we have work to do. This doesn't make much difference currently (though it does avoid jumping out to the top level loop and immediately restarting), but the distinction between "halt" and "don't halt" will become more important when the decision to halt requires us to trap to a higher exception level instead. Backport commit 84549b6dcf9147559ec08b066de673587be6b763 from qemu --- qemu/target-arm/op_helper.c | 7 +++++++ qemu/target-arm/translate-a64.c | 4 ++++ qemu/target-arm/translate.c | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/qemu/target-arm/op_helper.c b/qemu/target-arm/op_helper.c index 6e2d760e..0e5f2a8c 100644 --- a/qemu/target-arm/op_helper.c +++ b/qemu/target-arm/op_helper.c @@ -252,6 +252,13 @@ void HELPER(wfi)(CPUARMState *env) { CPUState *cs = CPU(arm_env_get_cpu(env)); + if (cpu_has_work(cs)) { + /* Don't bother to go into our "low power state" if + * we would just wake up immediately. + */ + return; + } + cs->exception_index = EXCP_HLT; cs->halted = 1; cpu_loop_exit(cs); diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index f835491f..79cd761c 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -11406,6 +11406,10 @@ tb_end: */ gen_a64_set_pc_im(dc, dc->pc); gen_helper_wfi(tcg_ctx, tcg_ctx->cpu_env); + /* The helper doesn't necessarily throw an exception, but we + * must go back to the main loop to check for interrupts anyway. + */ + tcg_gen_exit_tb(tcg_ctx, 0); break; } } diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index 0971698c..21c64ea8 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -11691,6 +11691,10 @@ tb_end: break; case DISAS_WFI: gen_helper_wfi(tcg_ctx, tcg_ctx->cpu_env); + /* The helper doesn't necessarily throw an exception, but we + * must go back to the main loop to check for interrupts anyway. + */ + tcg_gen_exit_tb(tcg_ctx, 0); break; case DISAS_WFE: gen_helper_wfe(tcg_ctx, tcg_ctx->cpu_env);