diff mbox

[09/14] exec.c: Capture the memory attributes for a watchpoint hit

Message ID 1428437400-8474-10-git-send-email-peter.maydell@linaro.org
State Superseded
Headers show

Commit Message

Peter Maydell April 7, 2015, 8:09 p.m. UTC
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".

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 exec.c            | 52 +++++++++++++++++++++++++++++++---------------------
 include/qom/cpu.h |  2 ++
 2 files changed, 33 insertions(+), 21 deletions(-)

Comments

Peter Maydell April 8, 2015, 11:14 a.m. UTC | #1
On 8 April 2015 at 12:04, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 07/04/2015 22:09, Peter Maydell wrote:
>> 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".
>>
>> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
>
> Oops, here we are. :)
>
> If you want to move the patch early, and possibly convert
> watch_mem_read/write to use a buffer in the style of subpages, that
> would be great.

Yeah, you got me -- I forgot about watchpoints and then didn't
want to wrestle with moving this patch before the big
coccinelle patch... Just laziness, so I'll shift it.

-- PMM
diff mbox

Patch

diff --git a/exec.c b/exec.c
index a0d18ee..b6a11c0 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,45 +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 address_space_ldub(&address_space_memory, addr,
-                                      MEMTXATTRS_UNSPECIFIED, NULL);
-    case 2: return address_space_lduw(&address_space_memory, addr,
-                                      MEMTXATTRS_UNSPECIFIED, NULL);
-    case 4: return address_space_ldl(&address_space_memory, addr,
-                                     MEMTXATTRS_UNSPECIFIED, NULL);
+    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:
-        address_space_stb(&address_space_memory, addr, val,
-                          MEMTXATTRS_UNSPECIFIED, NULL);
+        address_space_stb(&address_space_memory, addr, val, attrs, &res);
         break;
     case 2:
-        address_space_stw(&address_space_memory, addr, val,
-                          MEMTXATTRS_UNSPECIFIED, NULL);
+        address_space_stw(&address_space_memory, addr, val, attrs, &res);
         break;
     case 4:
-        address_space_stl(&address_space_memory, addr, val,
-                          MEMTXATTRS_UNSPECIFIED, NULL);
+        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,
 };
 
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 9dafb48..39f0f19 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -24,6 +24,7 @@ 
 #include <setjmp.h>
 #include "hw/qdev-core.h"
 #include "exec/hwaddr.h"
+#include "exec/memattrs.h"
 #include "qemu/queue.h"
 #include "qemu/thread.h"
 #include "qemu/tls.h"
@@ -195,6 +196,7 @@  typedef struct CPUWatchpoint {
     vaddr vaddr;
     vaddr len;
     vaddr hitaddr;
+    MemTxAttrs hitattrs;
     int flags; /* BP_* */
     QTAILQ_ENTRY(CPUWatchpoint) entry;
 } CPUWatchpoint;