softmmu: Check watchpoints for read+write at once

Atomic operations are read-modify-write, and we'd like to
be able to test both read and write with one call.  This is
easy enough, with BP_MEM_READ | BP_MEM_WRITE.

Add BP_HIT_SHIFT to make it easy to set BP_WATCHPOINT_HIT_*.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-02-22 22:16:51 -10:00
parent 0953674ed0
commit 019a98083a
2 changed files with 14 additions and 12 deletions

View File

@ -923,9 +923,10 @@ void cpu_single_step(CPUState *cpu, int enabled);
#define BP_GDB 0x10 #define BP_GDB 0x10
#define BP_CPU 0x20 #define BP_CPU 0x20
#define BP_ANY (BP_GDB | BP_CPU) #define BP_ANY (BP_GDB | BP_CPU)
#define BP_WATCHPOINT_HIT_READ 0x40 #define BP_HIT_SHIFT 6
#define BP_WATCHPOINT_HIT_WRITE 0x80 #define BP_WATCHPOINT_HIT_READ (BP_MEM_READ << BP_HIT_SHIFT)
#define BP_WATCHPOINT_HIT (BP_WATCHPOINT_HIT_READ | BP_WATCHPOINT_HIT_WRITE) #define BP_WATCHPOINT_HIT_WRITE (BP_MEM_WRITE << BP_HIT_SHIFT)
#define BP_WATCHPOINT_HIT (BP_MEM_ACCESS << BP_HIT_SHIFT)
int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags,
CPUBreakpoint **breakpoint); CPUBreakpoint **breakpoint);

View File

@ -162,9 +162,12 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
/* this is currently used only by ARM BE32 */ /* this is currently used only by ARM BE32 */
addr = cc->tcg_ops->adjust_watchpoint_address(cpu, addr, len); addr = cc->tcg_ops->adjust_watchpoint_address(cpu, addr, len);
} }
assert((flags & ~BP_MEM_ACCESS) == 0);
QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
if (watchpoint_address_matches(wp, addr, len) int hit_flags = wp->flags & flags;
&& (wp->flags & flags)) {
if (hit_flags && watchpoint_address_matches(wp, addr, len)) {
if (replay_running_debug()) { if (replay_running_debug()) {
/* /*
* replay_breakpoint reads icount. * replay_breakpoint reads icount.
@ -184,16 +187,14 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
replay_breakpoint(); replay_breakpoint();
return; return;
} }
if (flags == BP_MEM_READ) {
wp->flags |= BP_WATCHPOINT_HIT_READ; wp->flags |= hit_flags << BP_HIT_SHIFT;
} else {
wp->flags |= BP_WATCHPOINT_HIT_WRITE;
}
wp->hitaddr = MAX(addr, wp->vaddr); wp->hitaddr = MAX(addr, wp->vaddr);
wp->hitattrs = attrs; wp->hitattrs = attrs;
if (wp->flags & BP_CPU && cc->tcg_ops->debug_check_watchpoint && if (wp->flags & BP_CPU
!cc->tcg_ops->debug_check_watchpoint(cpu, wp)) { && cc->tcg_ops->debug_check_watchpoint
&& !cc->tcg_ops->debug_check_watchpoint(cpu, wp)) {
wp->flags &= ~BP_WATCHPOINT_HIT; wp->flags &= ~BP_WATCHPOINT_HIT;
continue; continue;
} }