target-arm: Implement checking of fired watchpoint

ARM stops before access to a location covered by watchpoint. Also, QEMU
watchpoint fire is not necessarily an architectural watchpoint match.
Unfortunately, that is hardly possible to ignore a fired watchpoint in
debug exception handler. So move watchpoint check from debug exception
handler to the dedicated watchpoint checking callback.

Backports commit 3826121d9298cde1d29ead05910e1f40125ee9b0 from qemu
This commit is contained in:
Sergey Fedorov 2018-02-20 11:50:26 -05:00 committed by Lioncash
parent 6a3038db7c
commit dfb78118ff
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
17 changed files with 38 additions and 14 deletions

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_aarch64
#define arm_current_el arm_current_el_aarch64
#define arm_dc_feature arm_dc_feature_aarch64
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_aarch64
#define arm_debug_excp_handler arm_debug_excp_handler_aarch64
#define arm_debug_target_el arm_debug_target_el_aarch64
#define arm_el_is_aa64 arm_el_is_aa64_aarch64

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_aarch64eb
#define arm_current_el arm_current_el_aarch64eb
#define arm_dc_feature arm_dc_feature_aarch64eb
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_aarch64eb
#define arm_debug_excp_handler arm_debug_excp_handler_aarch64eb
#define arm_debug_target_el arm_debug_target_el_aarch64eb
#define arm_el_is_aa64 arm_el_is_aa64_aarch64eb

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_arm
#define arm_current_el arm_current_el_arm
#define arm_dc_feature arm_dc_feature_arm
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_arm
#define arm_debug_excp_handler arm_debug_excp_handler_arm
#define arm_debug_target_el arm_debug_target_el_arm
#define arm_el_is_aa64 arm_el_is_aa64_arm

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_armeb
#define arm_current_el arm_current_el_armeb
#define arm_dc_feature arm_dc_feature_armeb
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_armeb
#define arm_debug_excp_handler arm_debug_excp_handler_armeb
#define arm_debug_target_el arm_debug_target_el_armeb
#define arm_el_is_aa64 arm_el_is_aa64_armeb

View file

@ -150,6 +150,7 @@ symbols = (
'arm_cp_write_ignore',
'arm_current_el',
'arm_dc_feature',
'arm_debug_check_watchpoint',
'arm_debug_excp_handler',
'arm_debug_target_el',
'arm_el_is_aa64',

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_m68k
#define arm_current_el arm_current_el_m68k
#define arm_dc_feature arm_dc_feature_m68k
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_m68k
#define arm_debug_excp_handler arm_debug_excp_handler_m68k
#define arm_debug_target_el arm_debug_target_el_m68k
#define arm_el_is_aa64 arm_el_is_aa64_m68k

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_mips
#define arm_current_el arm_current_el_mips
#define arm_dc_feature arm_dc_feature_mips
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_mips
#define arm_debug_excp_handler arm_debug_excp_handler_mips
#define arm_debug_target_el arm_debug_target_el_mips
#define arm_el_is_aa64 arm_el_is_aa64_mips

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_mips64
#define arm_current_el arm_current_el_mips64
#define arm_dc_feature arm_dc_feature_mips64
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_mips64
#define arm_debug_excp_handler arm_debug_excp_handler_mips64
#define arm_debug_target_el arm_debug_target_el_mips64
#define arm_el_is_aa64 arm_el_is_aa64_mips64

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_mips64el
#define arm_current_el arm_current_el_mips64el
#define arm_dc_feature arm_dc_feature_mips64el
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_mips64el
#define arm_debug_excp_handler arm_debug_excp_handler_mips64el
#define arm_debug_target_el arm_debug_target_el_mips64el
#define arm_el_is_aa64 arm_el_is_aa64_mips64el

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_mipsel
#define arm_current_el arm_current_el_mipsel
#define arm_dc_feature arm_dc_feature_mipsel
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_mipsel
#define arm_debug_excp_handler arm_debug_excp_handler_mipsel
#define arm_debug_target_el arm_debug_target_el_mipsel
#define arm_el_is_aa64 arm_el_is_aa64_mipsel

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_powerpc
#define arm_current_el arm_current_el_powerpc
#define arm_dc_feature arm_dc_feature_powerpc
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_powerpc
#define arm_debug_excp_handler arm_debug_excp_handler_powerpc
#define arm_debug_target_el arm_debug_target_el_powerpc
#define arm_el_is_aa64 arm_el_is_aa64_powerpc

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_sparc
#define arm_current_el arm_current_el_sparc
#define arm_dc_feature arm_dc_feature_sparc
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_sparc
#define arm_debug_excp_handler arm_debug_excp_handler_sparc
#define arm_debug_target_el arm_debug_target_el_sparc
#define arm_el_is_aa64 arm_el_is_aa64_sparc

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_sparc64
#define arm_current_el arm_current_el_sparc64
#define arm_dc_feature arm_dc_feature_sparc64
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_sparc64
#define arm_debug_excp_handler arm_debug_excp_handler_sparc64
#define arm_debug_target_el arm_debug_target_el_sparc64
#define arm_el_is_aa64 arm_el_is_aa64_sparc64

View file

@ -1343,6 +1343,7 @@ static void arm_cpu_class_init(struct uc_struct *uc, ObjectClass *oc, void *data
//cc->virtio_is_big_endian = arm_cpu_is_big_endian;
#endif
cc->debug_excp_handler = arm_debug_excp_handler;
cc->debug_check_watchpoint = arm_debug_check_watchpoint;
}
static void cpu_register(struct uc_struct *uc, const ARMCPUInfo *info)

View file

@ -411,6 +411,9 @@ void hw_breakpoint_update(ARMCPU *cpu, int n);
*/
void hw_breakpoint_update_all(ARMCPU *cpu);
/* Callback function for checking if a watchpoint should trigger. */
bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
/* Callback function for when a watchpoint or breakpoint triggers. */
void arm_debug_excp_handler(CPUState *cs);

View file

@ -973,6 +973,16 @@ void HELPER(check_breakpoints)(CPUARMState *env)
}
}
bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
{
/* Called by core code when a CPU watchpoint fires; need to check if this
* is also an architectural watchpoint match.
*/
ARMCPU *cpu = ARM_CPU(cs->uc, cs);
return check_watchpoints(cpu);
}
void arm_debug_excp_handler(CPUState *cs)
{
/* Called by core code when a watchpoint or breakpoint fires;
@ -984,23 +994,19 @@ void arm_debug_excp_handler(CPUState *cs)
if (wp_hit) {
if (wp_hit->flags & BP_CPU) {
cs->watchpoint_hit = NULL;
if (check_watchpoints(cpu)) {
bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
bool same_el = arm_debug_target_el(env) == arm_current_el(env);
bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
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;
}
env->exception.vaddress = wp_hit->hitaddr;
raise_exception(env, EXCP_DATA_ABORT,
syn_watchpoint(same_el, 0, wnr),
arm_debug_target_el(env));
cs->watchpoint_hit = NULL;
if (extended_addresses_enabled(env)) {
env->exception.fsr = (1 << 9) | 0x22;
} else {
cpu_resume_from_signal(cs, NULL);
env->exception.fsr = 0x2;
}
env->exception.vaddress = wp_hit->hitaddr;
raise_exception(env, EXCP_DATA_ABORT,
syn_watchpoint(same_el, 0, wnr),
arm_debug_target_el(env));
}
} else {
uint64_t pc = is_a64(env) ? env->pc : env->regs[15];

View file

@ -144,6 +144,7 @@
#define arm_cp_write_ignore arm_cp_write_ignore_x86_64
#define arm_current_el arm_current_el_x86_64
#define arm_dc_feature arm_dc_feature_x86_64
#define arm_debug_check_watchpoint arm_debug_check_watchpoint_x86_64
#define arm_debug_excp_handler arm_debug_excp_handler_x86_64
#define arm_debug_target_el arm_debug_target_el_x86_64
#define arm_el_is_aa64 arm_el_is_aa64_x86_64