target/arm: Create raise_exception_debug

Handle the debug vs current el exception test in one place.
Leave EXCP_BKPT alone, since that treats debug < current differently.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20220609202901.1177572-22-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:34 +01:00 committed by Peter Maydell
parent 82303761c6
commit 04eacf6e79
1 changed files with 24 additions and 20 deletions

View File

@ -12,6 +12,26 @@
#include "exec/helper-proto.h"
/*
* Raise an exception to the debug target el.
* Modify syndrome to indicate when origin and target EL are the same.
*/
G_NORETURN static void
raise_exception_debug(CPUARMState *env, uint32_t excp, 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.
* Similarly for watchpoint and breakpoint matches.
*/
assert(debug_el >= cur_el);
syndrome |= (debug_el == cur_el) << ARM_EL_EC_SHIFT;
raise_exception(env, excp, syndrome, debug_el);
}
/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
static bool aa64_generate_debug_exceptions(CPUARMState *env)
{
@ -418,19 +438,16 @@ void arm_debug_excp_handler(CPUState *cs)
if (wp_hit) {
if (wp_hit->flags & BP_CPU) {
bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
bool same_el = arm_debug_target_el(env) == arm_current_el(env);
cs->watchpoint_hit = NULL;
env->exception.fsr = arm_debug_exception_fsr(env);
env->exception.vaddress = wp_hit->hitaddr;
raise_exception(env, EXCP_DATA_ABORT,
syn_watchpoint(same_el, 0, wnr),
arm_debug_target_el(env));
raise_exception_debug(env, EXCP_DATA_ABORT,
syn_watchpoint(0, 0, wnr));
}
} else {
uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
/*
* (1) GDB breakpoints should be handled first.
@ -450,9 +467,7 @@ void arm_debug_excp_handler(CPUState *cs)
* exception/security level.
*/
env->exception.vaddress = 0;
raise_exception(env, EXCP_PREFETCH_ABORT,
syn_breakpoint(same_el),
arm_debug_target_el(env));
raise_exception_debug(env, EXCP_PREFETCH_ABORT, syn_breakpoint(0));
}
}
@ -489,18 +504,7 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
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);
raise_exception_debug(env, EXCP_UDEF, syndrome);
}
#if !defined(CONFIG_USER_ONLY)