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
