Now WFE can actually suspend on A-profile we also need to handle when its trapped. To do this we need to pass the instruction size so we can deal with the is_16bit syndrome encoding. Reviewed-by: Richard Henderson Signed-off-by: Alex Bennée --- v6 - defer calculating target_el until after the early return --- target/arm/tcg/helper-defs.h | 2 +- target/arm/tcg/op_helper.c | 16 +++++++++++++++- target/arm/tcg/translate-a64.c | 2 +- target/arm/tcg/translate.c | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/target/arm/tcg/helper-defs.h b/target/arm/tcg/helper-defs.h index a05f2258f29..ebdf09be38a 100644 --- a/target/arm/tcg/helper-defs.h +++ b/target/arm/tcg/helper-defs.h @@ -54,7 +54,7 @@ DEF_HELPER_2(exception_swstep, noreturn, env, i32) DEF_HELPER_2(exception_pc_alignment, noreturn, env, vaddr) DEF_HELPER_1(setend, void, env) DEF_HELPER_2(wfi, void, env, i32) -DEF_HELPER_1(wfe, void, env) +DEF_HELPER_2(wfe, void, env, i32) DEF_HELPER_2(wfit, void, env, i32) DEF_HELPER_1(yield, void, env) DEF_HELPER_1(pre_hvc, void, env) diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c index b803c9bf162..060b155d559 100644 --- a/target/arm/tcg/op_helper.c +++ b/target/arm/tcg/op_helper.c @@ -574,7 +574,7 @@ static int64_t gt_calc_next_event_stream(CPUARMState *env) } #endif -void HELPER(wfe)(CPUARMState *env) +void HELPER(wfe)(CPUARMState *env, uint32_t insn_len) { #ifdef CONFIG_USER_ONLY /* @@ -592,11 +592,25 @@ void HELPER(wfe)(CPUARMState *env) */ CPUState *cs = env_cpu(env); ARMCPU *cpu = env_archcpu(env); + uint32_t excp; + int target_el; if (qatomic_xchg(&env->event_register, false)) { return; } + /* We might sleep, so now we check to see if we should trap */ + target_el = check_wfx_trap(env, true, &excp); + if (target_el) { + if (env->aarch64) { + env->pc -= insn_len; + } else { + env->regs[15] -= insn_len; + } + raise_exception(env, excp, syn_wfx(1, 0xe, 0, false, WFE, insn_len == 2), + target_el); + } + /* * If the CPU has entered the exclusive region we could sleep * until the global monitor moves from Exclusive to Open Access. diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index ec03eaa3bbd..a4603e1a5c7 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -10961,7 +10961,7 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) */ case DISAS_WFE: gen_a64_update_pc(dc, 4); - gen_helper_wfe(tcg_env); + gen_helper_wfe(tcg_env, tcg_constant_i32(4)); tcg_gen_exit_tb(NULL, 0); break; case DISAS_WFI: diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c index c10cc382d15..1f554f6c271 100644 --- a/target/arm/tcg/translate.c +++ b/target/arm/tcg/translate.c @@ -6836,7 +6836,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) tcg_gen_exit_tb(NULL, 0); break; case DISAS_WFE: - gen_helper_wfe(tcg_env); + gen_helper_wfe(tcg_env, tcg_constant_i32(curr_insn_len(dc))); /* * The helper can return if the event register is set, so we * must go back to the main loop to check for events. -- 2.47.3