mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 00:05:36 +00:00
target-arm: Fix CPU breakpoint handling
A QEMU breakpoint match is not definitely an architectural breakpoint match. If an exception is generated unconditionally during translation, it is hardly possible to ignore it in the debug exception handler. Generate a call to a helper to check CPU breakpoints and raise an exception only if any breakpoint matches architecturally. Backports commit 5d98bf8f38c17a348ab6e8af196088cd4953acd0 from qemu
This commit is contained in:
parent
4706e10887
commit
e4e0c75f0f
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_aarch64
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_aarch64
|
||||
#define gen_helper_add_setq gen_helper_add_setq_aarch64
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_aarch64
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_aarch64
|
||||
#define gen_helper_clz32 gen_helper_clz32_aarch64
|
||||
#define gen_helper_clz64 gen_helper_clz64_aarch64
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_aarch64eb
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_aarch64eb
|
||||
#define gen_helper_add_setq gen_helper_add_setq_aarch64eb
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_aarch64eb
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_aarch64eb
|
||||
#define gen_helper_clz32 gen_helper_clz32_aarch64eb
|
||||
#define gen_helper_clz64 gen_helper_clz64_aarch64eb
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_arm
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_arm
|
||||
#define gen_helper_add_setq gen_helper_add_setq_arm
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_arm
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_arm
|
||||
#define gen_helper_clz32 gen_helper_clz32_arm
|
||||
#define gen_helper_clz64 gen_helper_clz64_arm
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_armeb
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_armeb
|
||||
#define gen_helper_add_setq gen_helper_add_setq_armeb
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_armeb
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_armeb
|
||||
#define gen_helper_clz32 gen_helper_clz32_armeb
|
||||
#define gen_helper_clz64 gen_helper_clz64_armeb
|
||||
|
|
|
@ -673,6 +673,7 @@ symbols = (
|
|||
'gen_helper_access_check_cp_reg',
|
||||
'gen_helper_add_saturate',
|
||||
'gen_helper_add_setq',
|
||||
'gen_helper_check_breakpoints',
|
||||
'gen_helper_clear_pstate_ss',
|
||||
'gen_helper_clz32',
|
||||
'gen_helper_clz64',
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_m68k
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_m68k
|
||||
#define gen_helper_add_setq gen_helper_add_setq_m68k
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_m68k
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_m68k
|
||||
#define gen_helper_clz32 gen_helper_clz32_m68k
|
||||
#define gen_helper_clz64 gen_helper_clz64_m68k
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_mips
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_mips
|
||||
#define gen_helper_add_setq gen_helper_add_setq_mips
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_mips
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_mips
|
||||
#define gen_helper_clz32 gen_helper_clz32_mips
|
||||
#define gen_helper_clz64 gen_helper_clz64_mips
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_mips64
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_mips64
|
||||
#define gen_helper_add_setq gen_helper_add_setq_mips64
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_mips64
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_mips64
|
||||
#define gen_helper_clz32 gen_helper_clz32_mips64
|
||||
#define gen_helper_clz64 gen_helper_clz64_mips64
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_mips64el
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_mips64el
|
||||
#define gen_helper_add_setq gen_helper_add_setq_mips64el
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_mips64el
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_mips64el
|
||||
#define gen_helper_clz32 gen_helper_clz32_mips64el
|
||||
#define gen_helper_clz64 gen_helper_clz64_mips64el
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_mipsel
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_mipsel
|
||||
#define gen_helper_add_setq gen_helper_add_setq_mipsel
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_mipsel
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_mipsel
|
||||
#define gen_helper_clz32 gen_helper_clz32_mipsel
|
||||
#define gen_helper_clz64 gen_helper_clz64_mipsel
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_powerpc
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_powerpc
|
||||
#define gen_helper_add_setq gen_helper_add_setq_powerpc
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_powerpc
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_powerpc
|
||||
#define gen_helper_clz32 gen_helper_clz32_powerpc
|
||||
#define gen_helper_clz64 gen_helper_clz64_powerpc
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_sparc
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_sparc
|
||||
#define gen_helper_add_setq gen_helper_add_setq_sparc
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_sparc
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_sparc
|
||||
#define gen_helper_clz32 gen_helper_clz32_sparc
|
||||
#define gen_helper_clz64 gen_helper_clz64_sparc
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_sparc64
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_sparc64
|
||||
#define gen_helper_add_setq gen_helper_add_setq_sparc64
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_sparc64
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_sparc64
|
||||
#define gen_helper_clz32 gen_helper_clz32_sparc64
|
||||
#define gen_helper_clz64 gen_helper_clz64_sparc64
|
||||
|
|
|
@ -57,6 +57,8 @@ DEF_HELPER_1(yield, void, env)
|
|||
DEF_HELPER_1(pre_hvc, void, env)
|
||||
DEF_HELPER_2(pre_smc, void, env, i32)
|
||||
|
||||
DEF_HELPER_1(check_breakpoints, void, env)
|
||||
|
||||
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
|
||||
DEF_HELPER_1(cpsr_read, i32, env)
|
||||
|
||||
|
|
|
@ -864,6 +864,15 @@ static bool check_breakpoints(ARMCPU *cpu)
|
|||
return false;
|
||||
}
|
||||
|
||||
void HELPER(check_breakpoints)(CPUARMState *env)
|
||||
{
|
||||
ARMCPU *cpu = arm_env_get_cpu(env);
|
||||
|
||||
if (check_breakpoints(cpu)) {
|
||||
HELPER(exception_internal(env, EXCP_DEBUG));
|
||||
}
|
||||
}
|
||||
|
||||
void arm_debug_excp_handler(CPUState *cs)
|
||||
{
|
||||
/* Called by core code when a watchpoint or breakpoint fires;
|
||||
|
@ -894,25 +903,24 @@ void arm_debug_excp_handler(CPUState *cs)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
/* Unicorn: commented out
|
||||
uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
|
||||
// Unicorn: commented out
|
||||
//uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
|
||||
bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
|
||||
|
||||
if (cpu_breakpoint_test(cs, pc, BP_GDB)) {
|
||||
return;
|
||||
}*/
|
||||
// Unicorn: commented out
|
||||
//if (cpu_breakpoint_test(cs, pc, BP_GDB)) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
if (check_breakpoints(cpu)) {
|
||||
bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
|
||||
if (extended_addresses_enabled(env)) {
|
||||
env->exception.fsr = (1 << 9) | 0x22;
|
||||
} else {
|
||||
env->exception.fsr = 0x2;
|
||||
}
|
||||
/* FAR is UNKNOWN, so doesn't need setting */
|
||||
raise_exception(env, EXCP_PREFETCH_ABORT,
|
||||
syn_breakpoint(same_el),
|
||||
arm_debug_target_el(env));
|
||||
if (extended_addresses_enabled(env)) {
|
||||
env->exception.fsr = (1 << 9) | 0x22;
|
||||
} else {
|
||||
env->exception.fsr = 0x2;
|
||||
}
|
||||
/* FAR is UNKNOWN, so doesn't need setting */
|
||||
raise_exception(env, EXCP_PREFETCH_ABORT,
|
||||
syn_breakpoint(same_el),
|
||||
arm_debug_target_el(env));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11319,11 +11319,18 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
|
|||
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
|
||||
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
||||
if (bp->pc == dc->pc) {
|
||||
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
|
||||
/* Advance PC so that clearing the breakpoint will
|
||||
invalidate this TB. */
|
||||
dc->pc += 2;
|
||||
goto done_generating;
|
||||
if (bp->flags & BP_CPU) {
|
||||
gen_helper_check_breakpoints(tcg_ctx, tcg_ctx->cpu_env);
|
||||
/* End the TB early; it likely won't be executed */
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
} else {
|
||||
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
|
||||
/* Advance PC so that clearing the breakpoint will
|
||||
invalidate this TB. */
|
||||
dc->pc += 4;
|
||||
goto done_generating;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11534,11 +11534,20 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
|||
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
|
||||
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
||||
if (bp->pc == dc->pc) {
|
||||
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
|
||||
/* Advance PC so that clearing the breakpoint will
|
||||
invalidate this TB. */
|
||||
dc->pc += 2;
|
||||
goto done_generating;
|
||||
if (bp->flags & BP_CPU) {
|
||||
gen_helper_check_breakpoints(tcg_ctx, tcg_ctx->cpu_env);
|
||||
/* End the TB early; it's likely not going to be executed */
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
} else {
|
||||
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
|
||||
/* Advance PC so that clearing the breakpoint will
|
||||
invalidate this TB. */
|
||||
/* TODO: Advance PC by correct instruction length to
|
||||
* avoid disassembler error messages */
|
||||
dc->pc += 2;
|
||||
goto done_generating;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -667,6 +667,7 @@
|
|||
#define gen_helper_access_check_cp_reg gen_helper_access_check_cp_reg_x86_64
|
||||
#define gen_helper_add_saturate gen_helper_add_saturate_x86_64
|
||||
#define gen_helper_add_setq gen_helper_add_setq_x86_64
|
||||
#define gen_helper_check_breakpoints gen_helper_check_breakpoints_x86_64
|
||||
#define gen_helper_clear_pstate_ss gen_helper_clear_pstate_ss_x86_64
|
||||
#define gen_helper_clz32 gen_helper_clz32_x86_64
|
||||
#define gen_helper_clz64 gen_helper_clz64_x86_64
|
||||
|
|
Loading…
Reference in a new issue