aboutsummaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-04-26 16:49:24 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-04-26 16:49:24 +0100
commit66b9b43c42049bcae37668e890fedde9a72c8167 (patch)
tree03be988ee0be12432fb993745b3823974e348040 /exec.c
parent500131154d677930fce35ec3a6f0b5a26bcd2973 (diff)
downloadqemu-66b9b43c42049bcae37668e890fedde9a72c8167.zip
qemu-66b9b43c42049bcae37668e890fedde9a72c8167.tar.gz
qemu-66b9b43c42049bcae37668e890fedde9a72c8167.tar.bz2
exec.c: Capture the memory attributes for a watchpoint hit
Capture the memory attributes for the transaction which triggered a watchpoint; this allows CPU specific code to implement features like ARM's "user-mode only WPs also hit for LDRT/STRT accesses made from privileged code". This change also correctly passes through the memory attributes to the underlying device when a watchpoint access doesn't hit. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Diffstat (limited to 'exec.c')
-rw-r--r--exec.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/exec.c b/exec.c
index 399543e..53d59bb 100644
--- a/exec.c
+++ b/exec.c
@@ -1858,7 +1858,7 @@ static const MemoryRegionOps notdirty_mem_ops = {
};
/* Generate a debug exception if a watchpoint has been hit. */
-static void check_watchpoint(int offset, int len, int flags)
+static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
{
CPUState *cpu = current_cpu;
CPUArchState *env = cpu->env_ptr;
@@ -1884,6 +1884,7 @@ static void check_watchpoint(int offset, int len, int flags)
wp->flags |= BP_WATCHPOINT_HIT_WRITE;
}
wp->hitaddr = vaddr;
+ wp->hitattrs = attrs;
if (!cpu->watchpoint_hit) {
cpu->watchpoint_hit = wp;
tb_check_watchpoint(cpu);
@@ -1905,39 +1906,54 @@ static void check_watchpoint(int offset, int len, int flags)
/* 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. */
-static uint64_t watch_mem_read(void *opaque, hwaddr addr,
- unsigned size)
+static MemTxResult watch_mem_read(void *opaque, hwaddr addr, uint64_t *pdata,
+ unsigned size, MemTxAttrs attrs)
{
- check_watchpoint(addr & ~TARGET_PAGE_MASK, size, BP_MEM_READ);
+ MemTxResult res;
+ uint64_t data;
+
+ check_watchpoint(addr & ~TARGET_PAGE_MASK, size, attrs, BP_MEM_READ);
switch (size) {
- case 1: return ldub_phys(&address_space_memory, addr);
- case 2: return lduw_phys(&address_space_memory, addr);
- case 4: return ldl_phys(&address_space_memory, addr);
+ case 1:
+ data = address_space_ldub(&address_space_memory, addr, attrs, &res);
+ break;
+ case 2:
+ data = address_space_lduw(&address_space_memory, addr, attrs, &res);
+ break;
+ case 4:
+ data = address_space_ldl(&address_space_memory, addr, attrs, &res);
+ break;
default: abort();
}
+ *pdata = data;
+ return res;
}
-static void watch_mem_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
+static MemTxResult watch_mem_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size,
+ MemTxAttrs attrs)
{
- check_watchpoint(addr & ~TARGET_PAGE_MASK, size, BP_MEM_WRITE);
+ MemTxResult res;
+
+ check_watchpoint(addr & ~TARGET_PAGE_MASK, size, attrs, BP_MEM_WRITE);
switch (size) {
case 1:
- stb_phys(&address_space_memory, addr, val);
+ address_space_stb(&address_space_memory, addr, val, attrs, &res);
break;
case 2:
- stw_phys(&address_space_memory, addr, val);
+ address_space_stw(&address_space_memory, addr, val, attrs, &res);
break;
case 4:
- stl_phys(&address_space_memory, addr, val);
+ address_space_stl(&address_space_memory, addr, val, attrs, &res);
break;
default: abort();
}
+ return res;
}
static const MemoryRegionOps watch_mem_ops = {
- .read = watch_mem_read,
- .write = watch_mem_write,
+ .read_with_attrs = watch_mem_read,
+ .write_with_attrs = watch_mem_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};