aboutsummaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorDavid Hildenbrand <david@redhat.com>2019-08-23 12:07:40 +0200
committerRichard Henderson <richard.henderson@linaro.org>2019-09-03 08:30:39 -0700
commit0026348b48fe532279e8c12b100c16c1aa991373 (patch)
treecbb0e35f93d6dff9770be449729c95441cc423c6 /exec.c
parent74841f044e96644d8ed8a388fe505df5ab843d0a (diff)
exec: Factor out core logic of check_watchpoint()
We want to perform the same checks in probe_write() to trigger a cpu exit before doing any modifications. We'll have to pass a PC. Signed-off-by: David Hildenbrand <david@redhat.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20190823100741.9621-9-david@redhat.com> [rth: Use vaddr for len, like other watchpoint functions; Move user-only stub to static inline.] Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'exec.c')
-rw-r--r--exec.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/exec.c b/exec.c
index 31fb75901f..cb6f5763dc 100644
--- a/exec.c
+++ b/exec.c
@@ -2789,11 +2789,10 @@ static const MemoryRegionOps notdirty_mem_ops = {
};
/* Generate a debug exception if a watchpoint has been hit. */
-static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
+void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
+ MemTxAttrs attrs, int flags, uintptr_t ra)
{
- CPUState *cpu = current_cpu;
CPUClass *cc = CPU_GET_CLASS(cpu);
- target_ulong vaddr;
CPUWatchpoint *wp;
assert(tcg_enabled());
@@ -2804,17 +2803,17 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
cpu_interrupt(cpu, CPU_INTERRUPT_DEBUG);
return;
}
- vaddr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
- vaddr = cc->adjust_watchpoint_address(cpu, vaddr, len);
+
+ addr = cc->adjust_watchpoint_address(cpu, addr, len);
QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
- if (cpu_watchpoint_address_matches(wp, vaddr, len)
+ if (cpu_watchpoint_address_matches(wp, addr, len)
&& (wp->flags & flags)) {
if (flags == BP_MEM_READ) {
wp->flags |= BP_WATCHPOINT_HIT_READ;
} else {
wp->flags |= BP_WATCHPOINT_HIT_WRITE;
}
- wp->hitaddr = vaddr;
+ wp->hitaddr = MAX(addr, wp->vaddr);
wp->hitattrs = attrs;
if (!cpu->watchpoint_hit) {
if (wp->flags & BP_CPU &&
@@ -2829,11 +2828,14 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
cpu->exception_index = EXCP_DEBUG;
mmap_unlock();
- cpu_loop_exit(cpu);
+ cpu_loop_exit_restore(cpu, ra);
} else {
/* Force execution of one insn next time. */
cpu->cflags_next_tb = 1 | curr_cflags();
mmap_unlock();
+ if (ra) {
+ cpu_restore_state(cpu, ra, true);
+ }
cpu_loop_exit_noexc(cpu);
}
}
@@ -2843,6 +2845,14 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
}
}
+static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
+{
+ CPUState *cpu = current_cpu;
+ vaddr addr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
+
+ cpu_check_watchpoint(cpu, addr, len, attrs, flags, 0);
+}
+
/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
so these check for a hit then pass through to the normal out-of-line
phys routines. */