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:
parent
82303761c6
commit
04eacf6e79
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user