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 <da...@redhat.com>
---
 exec.c                | 23 +++++++++++++++++------
 include/hw/core/cpu.h |  2 ++
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/exec.c b/exec.c
index 1df966d17a..d233a4250b 100644
--- a/exec.c
+++ b/exec.c
@@ -2810,12 +2810,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 vaddr, int 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());
@@ -2826,7 +2824,7 @@ 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);
     QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
         if (cpu_watchpoint_address_matches(wp, vaddr, len)
@@ -2851,11 +2849,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);
                 }
             }
@@ -2865,6 +2866,16 @@ static void check_watchpoint(int offset, int len, 
MemTxAttrs attrs, int flags)
     }
 }
 
+/* Generate a debug exception if a watchpoint has been hit.  */
+static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
+{
+    CPUState *cpu = current_cpu;
+    vaddr vaddr;
+
+    vaddr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
+    cpu_check_watchpoint(cpu, vaddr, 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.  */
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 77fca95a40..3a2d76b32c 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -1070,6 +1070,8 @@ static inline bool cpu_breakpoint_test(CPUState *cpu, 
vaddr pc, int mask)
     return false;
 }
 
+void cpu_check_watchpoint(CPUState *cpu, vaddr vaddr, int len,
+                          MemTxAttrs attrs, int flags, uintptr_t ra);
 int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
                           int flags, CPUWatchpoint **watchpoint);
 int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
-- 
2.21.0


Reply via email to