[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 8/15] Respect length of watchpoints
From: |
Jan Kiszka |
Subject: |
[Qemu-devel] [PATCH 8/15] Respect length of watchpoints |
Date: |
Mon, 23 Jun 2008 16:28:48 +0200 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686 (x86_64); de; rv:1.8.1.12) Gecko/20080226 SUSE/2.0.0.12-1.1 Thunderbird/2.0.0.12 Mnenhy/0.7.5.666 |
This adds length support for watchpoints. To keep things simple, only
aligned watchpoints are accepted.
Signed-off-by: Jan Kiszka <address@hidden>
---
cpu-defs.h | 2 +-
exec.c | 28 ++++++++++++++++++----------
2 files changed, 19 insertions(+), 11 deletions(-)
Index: b/exec.c
===================================================================
--- a/exec.c
+++ b/exec.c
@@ -1145,14 +1145,19 @@ static void breakpoint_invalidate(CPUSta
int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
int flags, CPUWatchpoint **watchpoint)
{
+ target_ulong len_mask = ~(len - 1);
CPUWatchpoint *wp;
+ /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
+ if ((len != 1 && len != 2 && len != 4) || (addr & ~len_mask))
+ return -EINVAL;
+
wp = qemu_malloc(sizeof(*wp));
if (!wp)
return -ENOBUFS;
wp->vaddr = addr;
- wp->len = len;
+ wp->len_mask = len_mask;
wp->flags = flags;
wp->next = env->watchpoints;
@@ -1176,10 +1181,12 @@ int cpu_watchpoint_insert(CPUState *env,
int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
int flags)
{
+ target_ulong len_mask = ~(len - 1);
CPUWatchpoint *wp;
for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
- if (addr == wp->vaddr && len == wp->len && flags == wp->flags) {
+ if (addr == wp->vaddr && len_mask == wp->len_mask
+ && flags == wp->flags) {
cpu_watchpoint_remove_by_ref(env, wp);
return 0;
}
@@ -2273,7 +2280,7 @@ static CPUWriteMemoryFunc *notdirty_mem_
};
/* Generate a debug exception if a watchpoint has been hit. */
-static void check_watchpoint(int offset, int flags)
+static void check_watchpoint(int offset, int len_mask, int flags)
{
CPUState *env = cpu_single_env;
target_ulong vaddr;
@@ -2281,7 +2288,8 @@ static void check_watchpoint(int offset,
vaddr = (env->mem_access_vaddr & TARGET_PAGE_MASK) + offset;
for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
- if (vaddr == wp->vaddr && (wp->flags & flags)) {
+ if ((vaddr == (wp->vaddr & len_mask) ||
+ (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
env->watchpoint_hit = wp;
cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
break;
@@ -2294,40 +2302,40 @@ static void check_watchpoint(int offset,
phys routines. */
static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
{
- check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ);
+ check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
return ldub_phys(addr);
}
static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
{
- check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ);
+ check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
return lduw_phys(addr);
}
static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
{
- check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ);
+ check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
return ldl_phys(addr);
}
static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
- check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE);
+ check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
stb_phys(addr, val);
}
static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
- check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE);
+ check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
stw_phys(addr, val);
}
static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
- check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE);
+ check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
stl_phys(addr, val);
}
Index: b/cpu-defs.h
===================================================================
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -136,7 +136,7 @@ typedef struct CPUBreakpoint {
typedef struct CPUWatchpoint {
target_ulong vaddr;
- target_ulong len;
+ target_ulong len_mask;
int flags; /* BP_* */
struct CPUWatchpoint *prev, *next;
} CPUWatchpoint;
- [Qemu-devel] [PATCH 0/15] Enhance debugging support, Jan Kiszka, 2008/06/23
- [Qemu-devel] [PATCH 8/15] Respect length of watchpoints,
Jan Kiszka <=
- [Qemu-devel] [PATCH 2/15] Introduce SSTEP_INTERNAL, Jan Kiszka, 2008/06/23
- [Qemu-devel] [PATCH 12/15] Introduce BP_WATCHPOINT_HIT flag, Jan Kiszka, 2008/06/23
- [Qemu-devel] [PATCH 5/15] Return appropriate watch message to gdb, Jan Kiszka, 2008/06/23
- [Qemu-devel] [PATCH 6/15] Refactor and enhance break/watchpoint API - v5, Jan Kiszka, 2008/06/23
- [Qemu-devel] [PATCH 14/15] Introduce BP_CPU as a breakpoint type, Jan Kiszka, 2008/06/23
- [Qemu-devel] [PATCH 1/15] Convert remaining __builtin_expect to likely/unlikely, Jan Kiszka, 2008/06/23
- [Qemu-devel] [PATCH 7/15] Extend mem_write_* to mem_access_*, Jan Kiszka, 2008/06/23
- [Qemu-devel] [PATCH 13/15] Add debug exception hook, Jan Kiszka, 2008/06/23
- [Qemu-devel] [PATCH 3/15] Replace CF_SINGLE_INSN with SSTEP_INTERNAL - v2, Jan Kiszka, 2008/06/23
- [Qemu-devel] [PATCH 15/15] x86: Debug register emulation, Jan Kiszka, 2008/06/23