diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 1ab91f915e..5e1625a1c8 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -370,6 +370,9 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp, */ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) { + int debug_el = arm_debug_target_el(env); + int cur_el = arm_current_el(env); + /* FSR will only be used if the debug target EL is AArch32. */ env->exception.fsr = arm_debug_exception_fsr(env); /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing @@ -377,7 +380,18 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) * exception/security level. */ env->exception.vaddress = 0; - raise_exception(env, EXCP_BKPT, syndrome, arm_debug_target_el(env)); + /* + * Other kinds of architectural debug exception are ignored if + * they target an exception level below the current one (in QEMU + * this is checked by arm_generate_debug_exceptions()). Breakpoint + * instructions are special because they always generate an exception + * to somewhere: if they can't go to the configured debug exception + * level they are taken to the current exception level. + */ + if (debug_el < cur_el) { + debug_el = cur_el; + } + raise_exception(env, EXCP_BKPT, syndrome, debug_el); } uint32_t HELPER(cpsr_read)(CPUARMState *env)