target/arm: Create helper_exception_swstep

Move the computation from gen_swstep_exception into a helper.

This fixes a bug when:
  - MDSCR_EL1.KDE == 1 to enable debug exceptions within EL_D itself
  - we singlestep an ERET from EL_D to some lower EL

Previously we were computing 'same el' based on the EL which
executed the ERET instruction, whereas it ought to be computed
based on the EL to which ERET returned.  This happens naturally
with the new helper, which runs after EL has been changed.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20220609202901.1177572-14-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2022-06-10 14:32:32 +01:00 committed by Peter Maydell
parent 486d6c9699
commit f0d7c2054a
3 changed files with 20 additions and 9 deletions

View File

@ -487,6 +487,22 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
raise_exception(env, EXCP_BKPT, syndrome, debug_el); raise_exception(env, EXCP_BKPT, syndrome, debug_el);
} }
void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)
{
int debug_el = arm_debug_target_el(env);
int cur_el = arm_current_el(env);
/*
* If singlestep is targeting a lower EL than the current one, then
* DisasContext.ss_active must be false and we can never get here.
*/
assert(debug_el >= cur_el);
if (debug_el == cur_el) {
syndrome |= 1 << ARM_EL_EC_SHIFT;
}
raise_exception(env, EXCP_UDEF, syndrome, debug_el);
}
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)

View File

@ -47,6 +47,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
DEF_HELPER_2(exception_internal, noreturn, env, i32) DEF_HELPER_2(exception_internal, noreturn, env, i32)
DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32) DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32) DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
DEF_HELPER_2(exception_swstep, noreturn, env, i32)
DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl) DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
DEF_HELPER_1(setend, void, env) DEF_HELPER_1(setend, void, env)
DEF_HELPER_2(wfi, void, env, i32) DEF_HELPER_2(wfi, void, env, i32)

View File

@ -341,15 +341,9 @@ static inline void gen_exception(int excp, uint32_t syndrome,
/* Generate an architectural singlestep exception */ /* Generate an architectural singlestep exception */
static inline void gen_swstep_exception(DisasContext *s, int isv, int ex) static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
{ {
bool same_el = (s->debug_target_el == s->current_el); /* Fill in the same_el field of the syndrome in the helper. */
uint32_t syn = syn_swstep(false, isv, ex);
/* gen_helper_exception_swstep(cpu_env, tcg_constant_i32(syn));
* If singlestep is targeting a lower EL than the current one,
* then s->ss_active must be false and we can never get here.
*/
assert(s->debug_target_el >= s->current_el);
gen_exception(EXCP_UDEF, syn_swstep(same_el, isv, ex), s->debug_target_el);
} }
/* /*