Plugs a hole in the API by which one cannot watch the entire
address space with one range.  Eliminates a workaround in
s390x where we used 2 watchpoints for exactly that.

Signed-off-by: Richard Henderson <[email protected]>
---
 include/exec/breakpoint.h           |  2 +-
 accel/tcg/tcg-accel-ops.c           |  7 +++++--
 accel/tcg/user-exec-stub.c          |  2 +-
 system/watchpoint.c                 |  4 +---
 target/arm/tcg/debug.c              | 10 +++++-----
 target/i386/tcg/system/bpt_helper.c |  4 ++--
 target/ppc/cpu.c                    |  2 +-
 target/riscv/debug.c                |  4 ++--
 target/s390x/tcg/debug.c            | 16 ++++------------
 9 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/include/exec/breakpoint.h b/include/exec/breakpoint.h
index e9b77081e7..79a1453a45 100644
--- a/include/exec/breakpoint.h
+++ b/include/exec/breakpoint.h
@@ -44,7 +44,7 @@ void cpu_breakpoint_remove_by_ref(CPUState *cpu, 
CPUBreakpoint *breakpoint);
 void cpu_breakpoint_remove_all(CPUState *cpu, BreakpointFlags mask);
 bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, BreakpointFlags mask);
 
-CPUBreakpoint *cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
+CPUBreakpoint *cpu_watchpoint_insert(CPUState *cpu, vaddr first, vaddr last,
                                      BreakpointFlags flags, unsigned id);
 int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
                           vaddr len, BreakpointFlags flags);
diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c
index 79289bf7b2..fd14459f7d 100644
--- a/accel/tcg/tcg-accel-ops.c
+++ b/accel/tcg/tcg-accel-ops.c
@@ -131,6 +131,7 @@ static int tcg_insert_gdbstub_breakpoint(CPUState *cs, 
GdbBreakpointType type,
                                          vaddr addr, vaddr len)
 {
     CPUState *cpu;
+    vaddr last;
 
     switch (type) {
     case GDB_BREAKPOINT_SW:
@@ -142,11 +143,13 @@ static int tcg_insert_gdbstub_breakpoint(CPUState *cs, 
GdbBreakpointType type,
     case GDB_WATCHPOINT_WRITE:
     case GDB_WATCHPOINT_READ:
     case GDB_WATCHPOINT_ACCESS:
-        if (len == 0 || addr + (len - 1) < addr) {
+        last = addr + (len - 1);
+        if (len == 0 || last < addr) {
             return -EINVAL;
         }
         CPU_FOREACH(cpu) {
-            cpu_watchpoint_insert(cpu, addr, len, xlat_gdb_type(cpu, type), 0);
+            cpu_watchpoint_insert(cpu, addr, last,
+                                  xlat_gdb_type(cpu, type), 0);
         }
         return 0;
     default:
diff --git a/accel/tcg/user-exec-stub.c b/accel/tcg/user-exec-stub.c
index c45e31e2fa..a989aeaa60 100644
--- a/accel/tcg/user-exec-stub.c
+++ b/accel/tcg/user-exec-stub.c
@@ -21,7 +21,7 @@ void cpu_exec_reset_hold(CPUState *cpu)
 {
 }
 
-CPUBreakpoint *cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
+CPUBreakpoint *cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr last,
                                      BreakpointFlags flags, unsigned id)
 {
     g_assert_not_reached();
diff --git a/system/watchpoint.c b/system/watchpoint.c
index fe7e0ac59f..cb9f41269c 100644
--- a/system/watchpoint.c
+++ b/system/watchpoint.c
@@ -24,13 +24,11 @@
 #include "hw/core/cpu.h"
 
 /* Add a watchpoint.  */
-CPUBreakpoint *cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
+CPUBreakpoint *cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr last,
                                      BreakpointFlags flags, unsigned id)
 {
     CPUBreakpoint *wp;
-    vaddr last = addr + len - 1;
 
-    assert(len != 0);
     assert(last >= addr);
     assert(flags & BP_MEM_ACCESS);
     assert(ctpop32(flags & BP_ANY) == 1);
diff --git a/target/arm/tcg/debug.c b/target/arm/tcg/debug.c
index 1dec39c0bf..b3e7df7876 100644
--- a/target/arm/tcg/debug.c
+++ b/target/arm/tcg/debug.c
@@ -524,7 +524,7 @@ static void hw_watchpoint_update_v6(ARMCPU *cpu, int n, 
BreakpointFlags flags)
      * of the BAS bits until breakpoint hit.
      */
     CPUARMState *env = &cpu->env;
-    uint32_t wvr = env->cp15.dbgwvr[n] & ~3;
+    uint32_t wvr = env->cp15.dbgwvr[n];
     uint32_t wcr = env->cp15.dbgwcr[n];
     uint32_t bas = FIELD_EX64(wcr, DBGWCR, BAS) & 0xf;
 
@@ -533,8 +533,8 @@ static void hw_watchpoint_update_v6(ARMCPU *cpu, int n, 
BreakpointFlags flags)
         return;
     }
 
-    env->cpu_watchpoint[n] = cpu_watchpoint_insert(CPU(cpu), wvr, 4,
-                                                   flags, n);
+    env->cpu_watchpoint[n] =
+        cpu_watchpoint_insert(CPU(cpu), wvr & ~3, wvr | 3, flags, n);
 }
 
 static void hw_watchpoint_update_v7(ARMCPU *cpu, int n, BreakpointFlags flags)
@@ -595,8 +595,8 @@ static void hw_watchpoint_update_v7(ARMCPU *cpu, int n, 
BreakpointFlags flags)
         wvr += basstart;
     }
 
-    env->cpu_watchpoint[n] = cpu_watchpoint_insert(CPU(cpu), wvr, len,
-                                                   flags, n);
+    env->cpu_watchpoint[n] =
+        cpu_watchpoint_insert(CPU(cpu), wvr, wvr + len - 1, flags, n);
 }
 
 void hw_watchpoint_update(ARMCPU *cpu, int n)
diff --git a/target/i386/tcg/system/bpt_helper.c 
b/target/i386/tcg/system/bpt_helper.c
index 86562fc946..3307b2f52e 100644
--- a/target/i386/tcg/system/bpt_helper.c
+++ b/target/i386/tcg/system/bpt_helper.c
@@ -74,7 +74,7 @@ static int hw_breakpoint_insert(CPUX86State *env, int index)
         if (hw_breakpoint_enabled(dr7, index)) {
             env->cpu_watchpoint[index] =
                 cpu_watchpoint_insert(cs, drN,
-                                      hw_breakpoint_len(dr7, index),
+                                      drN + hw_breakpoint_len(dr7, index) - 1,
                                       BP_CPU | BP_MEM_WRITE, index);
         }
         break;
@@ -83,7 +83,7 @@ static int hw_breakpoint_insert(CPUX86State *env, int index)
         if (hw_breakpoint_enabled(dr7, index)) {
             env->cpu_watchpoint[index] =
                 cpu_watchpoint_insert(cs, drN,
-                                      hw_breakpoint_len(dr7, index),
+                                      drN + hw_breakpoint_len(dr7, index) - 1,
                                       BP_CPU | BP_MEM_ACCESS, index);
         }
         break;
diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
index fbd199c08d..f153d2fece 100644
--- a/target/ppc/cpu.c
+++ b/target/ppc/cpu.c
@@ -172,7 +172,7 @@ void ppc_update_daw(CPUPPCState *env, int rid)
     }
 
     env->dawr_watchpoint[rid] =
-        cpu_watchpoint_insert(cs, deaw, len, flags, rid);
+        cpu_watchpoint_insert(cs, deaw, deaw + len - 1, flags, rid);
 }
 
 void ppc_store_dawr0(CPUPPCState *env, target_ulong val)
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 803418f390..0995ad157c 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -503,7 +503,7 @@ static void type2_breakpoint_insert(CPURISCVState *env, 
target_ulong index)
             size = riscv_cpu_mxl(env) == MXL_RV64 ? 8 : 4;
         }
         env->cpu_watchpoint[index] =
-            cpu_watchpoint_insert(cs, addr, size, flags, index);
+            cpu_watchpoint_insert(cs, addr, addr + size - 1, flags, index);
     }
 }
 
@@ -622,7 +622,7 @@ static void type6_breakpoint_insert(CPURISCVState *env, 
target_ulong index)
         uint32_t size = extract32(ctrl, 16, 4) ? : 8;
 
         env->cpu_watchpoint[index] =
-            cpu_watchpoint_insert(cs, addr, size, flags, index);
+            cpu_watchpoint_insert(cs, addr, addr + size - 1, flags, index);
     }
 }
 
diff --git a/target/s390x/tcg/debug.c b/target/s390x/tcg/debug.c
index ef0d953e01..22f75fd3a5 100644
--- a/target/s390x/tcg/debug.c
+++ b/target/s390x/tcg/debug.c
@@ -31,21 +31,13 @@ void s390_cpu_recompute_watchpoints(CPUState *cs)
         return;
     }
 
-    if (env->cregs[10] == 0 && env->cregs[11] == -1LL) {
-        /* We can't create a watchoint spanning the whole memory range, so
-           split it in two parts.   */
-        cpu_watchpoint_insert(cs, 0, 1ULL << 63, wp_flags, 0);
-        cpu_watchpoint_insert(cs, 1ULL << 63, 1ULL << 63, wp_flags, 0);
-    } else if (env->cregs[10] > env->cregs[11]) {
+    if (env->cregs[10] > env->cregs[11]) {
         /* The address range loops, create two watchpoints.  */
-        cpu_watchpoint_insert(cs, env->cregs[10], -env->cregs[10],
-                              wp_flags, 0);
-        cpu_watchpoint_insert(cs, 0, env->cregs[11] + 1, wp_flags, 0);
+        cpu_watchpoint_insert(cs, env->cregs[10], -1, wp_flags, 0);
+        cpu_watchpoint_insert(cs, 0, env->cregs[11], wp_flags, 0);
     } else {
         /* Default case, create a single watchpoint.  */
-        cpu_watchpoint_insert(cs, env->cregs[10],
-                              env->cregs[11] - env->cregs[10] + 1,
-                              wp_flags, 0);
+        cpu_watchpoint_insert(cs, env->cregs[10], env->cregs[11], wp_flags, 0);
     }
 }
 
-- 
2.43.0


Reply via email to