All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM
@ 2015-04-07 20:09 Peter Maydell
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status Peter Maydell
                   ` (14 more replies)
  0 siblings, 15 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Following from my previous RFC about transaction memory attributes,
here's some code I think is good enough to drop the 'RFC' tag :-)
(read: I would like to land this when master reopens for 2.4.)

I've included both the changes to the core memory system code
and the target-arm changes as a usage example, but the ARM stuff
is all at the end of the series, so if we want to split it and
take it via separate subtrees that's fine.

I think I have followed the outcome of our discussions on the
RFC; please let me know if I got confused or missed something.
What we have here is:
 * MemoryRegions can provide read_with_attrs and write_with_attrs
   so they can get memory attributes and return a success/error
   indication
 * the attributes and error indication are plumbed through the
   core memory system code
 * new functions address_space_ld*/st* are provided which are
   like the old ld/st*_phys but have extra args for MemTxAttrs
   and MemTxResult*
 * callers have been auto-converted from the old ld/st*_phys
   unless they were using the CPUState::as address space
   [those will be moved to some cpu-specific API later]
 * TCG frontends can use tlb_set_page_with_attrs() to provide
   attributes when they add an entry to the TLB
 * two attributes: MEMTXATTRS_SECURE [ARM TrustZone secure access]
   and MEMTXATTRS_USER [access is unprivileged], both implemented
   for the ARM CPU frontend (these both correspond to AMBA/AXI
   bus sideband signals, more or less)


I believe this code contains enough changes that all the memory
transactions issued by the ARM CPU will correctly be marked as
S or NS. Obviously nothing currently pays attention to this, but
the patches to make the GIC model support TrustZone can be easily
wired up to this.

The diffstat's quite big but the biggest patch is a Coccinelle
generated automated rename of the callers of ld/st*_phys to
address_space_ld/st* where they don't use the CPUState::as.

thanks
-- PMM

Peter Maydell (14):
  memory: Define API for MemoryRegionOps to take attrs and return status
  memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write
  Make CPU iotlb a structure rather than a plain hwaddr
  Add MemTxAttrs to the IOTLB
  exec.c: Convert subpage memory ops to _with_attrs
  exec.c: Make address_space_rw take transaction attributes
  exec.c: Add new address_space_ld*/st* functions
  Switch non-CPU callers from ld/st*_phys to address_space_ld/st*
  exec.c: Capture the memory attributes for a watchpoint hit
  target-arm: Honour NS bits in page tables
  target-arm: Use correct memory attributes for page table walks
  target-arm: Add user-mode transaction attribute
  target-arm: Use attribute info to handle user-only watchpoints
  target-arm: Check watchpoints against CPU security state

 cputlb.c                          |  22 +-
 dma-helpers.c                     |   3 +-
 exec.c                            | 418 +++++++++++++++++++++++++++++---------
 hw/alpha/dp264.c                  |   9 +-
 hw/alpha/typhoon.c                |   3 +-
 hw/arm/boot.c                     |   6 +-
 hw/arm/highbank.c                 |  12 +-
 hw/dma/pl080.c                    |  20 +-
 hw/dma/sun4m_iommu.c              |   3 +-
 hw/i386/intel_iommu.c             |   3 +-
 hw/mips/mips_jazz.c               |   6 +-
 hw/pci-host/apb.c                 |   3 +-
 hw/pci-host/prep.c                |   6 +-
 hw/pci/msi.c                      |   3 +-
 hw/pci/msix.c                     |   3 +-
 hw/s390x/css.c                    |  19 +-
 hw/s390x/s390-pci-bus.c           |   9 +-
 hw/s390x/s390-pci-inst.c          |   7 +-
 hw/s390x/s390-virtio-bus.c        |  73 ++++---
 hw/s390x/s390-virtio.c            |   4 +-
 hw/s390x/virtio-ccw.c             |  87 +++++---
 hw/sh4/r2d.c                      |   6 +-
 hw/timer/hpet.c                   |   5 +-
 hw/vfio/pci.c                     |   4 +-
 include/exec/cpu-defs.h           |  15 +-
 include/exec/exec-all.h           |   7 +-
 include/exec/memattrs.h           |  40 ++++
 include/exec/memory.h             | 128 +++++++++++-
 include/qom/cpu.h                 |   2 +
 include/sysemu/dma.h              |   3 +-
 ioport.c                          |  16 +-
 kvm-all.c                         |   3 +-
 memory.c                          | 212 ++++++++++++-------
 monitor.c                         |   3 +-
 scripts/coverity-model.c          |   8 +-
 softmmu_template.h                |  36 ++--
 target-arm/helper.c               | 134 ++++++++++--
 target-arm/op_helper.c            |  29 +--
 target-i386/arch_memory_mapping.c |  15 +-
 39 files changed, 1038 insertions(+), 347 deletions(-)
 create mode 100644 include/exec/memattrs.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-08 10:49   ` Paolo Bonzini
  2015-04-09  8:55   ` Edgar E. Iglesias
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 02/14] memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write Peter Maydell
                   ` (13 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Define an API so that devices can register MemoryRegionOps whose read
and write callback functions are passed an arbitrary pointer to some
transaction attributes and can return a success-or-failure status code.
This will allow us to model devices which:
 * behave differently for ARM Secure/NonSecure memory accesses
 * behave differently for privileged/unprivileged accesses
 * may return a transaction failure (causing a guest exception)
   for erroneous accesses

This patch defines the new API and plumbs the attributes parameter through
to the memory.c public level functions io_mem_read() and io_mem_write(),
where it is currently dummied out.

The success/failure response indication is also propagated out to
io_mem_read() and io_mem_write(), which retain the old-style
boolean true-for-error return.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/exec/memattrs.h |  34 ++++++++
 include/exec/memory.h   |  22 +++++
 memory.c                | 207 ++++++++++++++++++++++++++++++++----------------
 3 files changed, 196 insertions(+), 67 deletions(-)
 create mode 100644 include/exec/memattrs.h

diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
new file mode 100644
index 0000000..b8d7808
--- /dev/null
+++ b/include/exec/memattrs.h
@@ -0,0 +1,34 @@
+/*
+ * Memory transaction attributes
+ *
+ * Copyright (c) 2015 Linaro Limited.
+ *
+ * Authors:
+ *  Peter Maydell <peter.maydell@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef MEMATTRS_H
+#define MEMATTRS_H
+
+/* Every memory transaction has associated with it a set of
+ * attributes. Some of these are generic (such as the ID of
+ * the bus master); some are specific to a particular kind of
+ * bus (such as the ARM Secure/NonSecure bit). We define them
+ * all as non-overlapping bits in a single integer to avoid
+ * confusion if different parts of QEMU used the same bit for
+ * different semantics.
+ */
+typedef uint64_t MemTxAttrs;
+
+/* Bus masters which don't specify any attributes will get this,
+ * which has all attribute bits clear except the topmost one
+ * (so that we can distinguish "all attributes deliberately clear"
+ * from "didn't specify" if necessary).
+ */
+#define MEMTXATTRS_UNSPECIFIED (1ULL << 63)
+
+#endif
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 06ffa1d..703d9e5 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -28,6 +28,7 @@
 #ifndef CONFIG_USER_ONLY
 #include "exec/hwaddr.h"
 #endif
+#include "exec/memattrs.h"
 #include "qemu/queue.h"
 #include "qemu/int128.h"
 #include "qemu/notify.h"
@@ -68,6 +69,16 @@ struct IOMMUTLBEntry {
     IOMMUAccessFlags perm;
 };
 
+/* New-style MMIO accessors can indicate that the transaction failed.
+ * A zero (MEMTX_OK) response means success; anything else is a failure
+ * of some kind. The memory subsystem will bitwise-OR together results
+ * if it is synthesizing an operation from multiple smaller accesses.
+ */
+#define MEMTX_OK 0
+#define MEMTX_ERROR             (1U << 0) /* device returned an error */
+#define MEMTX_DECODE_ERROR      (1U << 1) /* nothing at that address */
+typedef uint32_t MemTxResult;
+
 /*
  * Memory region callbacks
  */
@@ -84,6 +95,17 @@ struct MemoryRegionOps {
                   uint64_t data,
                   unsigned size);
 
+    MemTxResult (*read_with_attrs)(void *opaque,
+                                   hwaddr addr,
+                                   uint64_t *data,
+                                   unsigned size,
+                                   MemTxAttrs attrs);
+    MemTxResult (*write_with_attrs)(void *opaque,
+                                    hwaddr addr,
+                                    uint64_t data,
+                                    unsigned size,
+                                    MemTxAttrs attrs);
+
     enum device_endian endianness;
     /* Guest-visible constraints: */
     struct {
diff --git a/memory.c b/memory.c
index ee3f2a8..9bb5674 100644
--- a/memory.c
+++ b/memory.c
@@ -368,57 +368,84 @@ static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
     }
 }
 
-static void memory_region_oldmmio_read_accessor(MemoryRegion *mr,
+static MemTxResult memory_region_oldmmio_read_accessor(MemoryRegion *mr,
+                                                       hwaddr addr,
+                                                       uint64_t *value,
+                                                       unsigned size,
+                                                       unsigned shift,
+                                                       uint64_t mask,
+                                                       MemTxAttrs attrs)
+{
+    uint64_t tmp;
+
+    tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
+    trace_memory_region_ops_read(mr, addr, tmp, size);
+    *value |= (tmp & mask) << shift;
+    return MEMTX_OK;
+}
+
+static MemTxResult  memory_region_read_accessor(MemoryRegion *mr,
                                                 hwaddr addr,
                                                 uint64_t *value,
                                                 unsigned size,
                                                 unsigned shift,
-                                                uint64_t mask)
+                                                uint64_t mask,
+                                                MemTxAttrs attrs)
 {
     uint64_t tmp;
 
-    tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
+    if (mr->flush_coalesced_mmio) {
+        qemu_flush_coalesced_mmio_buffer();
+    }
+    tmp = mr->ops->read(mr->opaque, addr, size);
     trace_memory_region_ops_read(mr, addr, tmp, size);
     *value |= (tmp & mask) << shift;
+    return MEMTX_OK;
 }
 
-static void memory_region_read_accessor(MemoryRegion *mr,
-                                        hwaddr addr,
-                                        uint64_t *value,
-                                        unsigned size,
-                                        unsigned shift,
-                                        uint64_t mask)
+static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr,
+                                                          hwaddr addr,
+                                                          uint64_t *value,
+                                                          unsigned size,
+                                                          unsigned shift,
+                                                          uint64_t mask,
+                                                          MemTxAttrs attrs)
 {
-    uint64_t tmp;
+    uint64_t tmp = 0;
+    MemTxResult r;
 
     if (mr->flush_coalesced_mmio) {
         qemu_flush_coalesced_mmio_buffer();
     }
-    tmp = mr->ops->read(mr->opaque, addr, size);
+    r = mr->ops->read_with_attrs(mr->opaque, addr, &tmp, size, attrs);
     trace_memory_region_ops_read(mr, addr, tmp, size);
     *value |= (tmp & mask) << shift;
+    return r;
 }
 
-static void memory_region_oldmmio_write_accessor(MemoryRegion *mr,
-                                                 hwaddr addr,
-                                                 uint64_t *value,
-                                                 unsigned size,
-                                                 unsigned shift,
-                                                 uint64_t mask)
+static MemTxResult memory_region_oldmmio_write_accessor(MemoryRegion *mr,
+                                                        hwaddr addr,
+                                                        uint64_t *value,
+                                                        unsigned size,
+                                                        unsigned shift,
+                                                        uint64_t mask,
+                                                        MemTxAttrs attrs)
 {
     uint64_t tmp;
 
     tmp = (*value >> shift) & mask;
     trace_memory_region_ops_write(mr, addr, tmp, size);
     mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp);
+    return MEMTX_OK;
 }
 
-static void memory_region_write_accessor(MemoryRegion *mr,
-                                         hwaddr addr,
-                                         uint64_t *value,
-                                         unsigned size,
-                                         unsigned shift,
-                                         uint64_t mask)
+static MemTxResult memory_region_write_accessor(MemoryRegion *mr,
+                                                hwaddr addr,
+                                                uint64_t *value,
+                                                unsigned size,
+                                                unsigned shift,
+                                                uint64_t mask,
+                                                MemTxAttrs attrs)
 {
     uint64_t tmp;
 
@@ -428,24 +455,46 @@ static void memory_region_write_accessor(MemoryRegion *mr,
     tmp = (*value >> shift) & mask;
     trace_memory_region_ops_write(mr, addr, tmp, size);
     mr->ops->write(mr->opaque, addr, tmp, size);
+    return MEMTX_OK;
 }
 
-static void access_with_adjusted_size(hwaddr addr,
+static MemTxResult memory_region_write_with_attrs_accessor(MemoryRegion *mr,
+                                                           hwaddr addr,
+                                                           uint64_t *value,
+                                                           unsigned size,
+                                                           unsigned shift,
+                                                           uint64_t mask,
+                                                           MemTxAttrs attrs)
+{
+    uint64_t tmp;
+
+    if (mr->flush_coalesced_mmio) {
+        qemu_flush_coalesced_mmio_buffer();
+    }
+    tmp = (*value >> shift) & mask;
+    trace_memory_region_ops_write(mr, addr, tmp, size);
+    return mr->ops->write_with_attrs(mr->opaque, addr, tmp, size, attrs);
+}
+
+static MemTxResult access_with_adjusted_size(hwaddr addr,
                                       uint64_t *value,
                                       unsigned size,
                                       unsigned access_size_min,
                                       unsigned access_size_max,
-                                      void (*access)(MemoryRegion *mr,
-                                                     hwaddr addr,
-                                                     uint64_t *value,
-                                                     unsigned size,
-                                                     unsigned shift,
-                                                     uint64_t mask),
-                                      MemoryRegion *mr)
+                                      MemTxResult (*access)(MemoryRegion *mr,
+                                                            hwaddr addr,
+                                                            uint64_t *value,
+                                                            unsigned size,
+                                                            unsigned shift,
+                                                            uint64_t mask,
+                                                            MemTxAttrs attrs),
+                                      MemoryRegion *mr,
+                                      MemTxAttrs attrs)
 {
     uint64_t access_mask;
     unsigned access_size;
     unsigned i;
+    MemTxResult r = MEMTX_OK;
 
     if (!access_size_min) {
         access_size_min = 1;
@@ -459,14 +508,16 @@ static void access_with_adjusted_size(hwaddr addr,
     access_mask = -1ULL >> (64 - access_size * 8);
     if (memory_region_big_endian(mr)) {
         for (i = 0; i < size; i += access_size) {
-            access(mr, addr + i, value, access_size,
-                   (size - access_size - i) * 8, access_mask);
+            r |= access(mr, addr + i, value, access_size,
+                        (size - access_size - i) * 8, access_mask, attrs);
         }
     } else {
         for (i = 0; i < size; i += access_size) {
-            access(mr, addr + i, value, access_size, i * 8, access_mask);
+            r |= access(mr, addr + i, value, access_size, i * 8,
+                        access_mask, attrs);
         }
     }
+    return r;
 }
 
 static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
@@ -1053,62 +1104,82 @@ bool memory_region_access_valid(MemoryRegion *mr,
     return true;
 }
 
-static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
-                                             hwaddr addr,
-                                             unsigned size)
+static MemTxResult memory_region_dispatch_read1(MemoryRegion *mr,
+                                                hwaddr addr,
+                                                uint64_t *pval,
+                                                unsigned size,
+                                                MemTxAttrs attrs)
 {
-    uint64_t data = 0;
+    *pval = 0;
 
     if (mr->ops->read) {
-        access_with_adjusted_size(addr, &data, size,
-                                  mr->ops->impl.min_access_size,
-                                  mr->ops->impl.max_access_size,
-                                  memory_region_read_accessor, mr);
+        return access_with_adjusted_size(addr, pval, size,
+                                         mr->ops->impl.min_access_size,
+                                         mr->ops->impl.max_access_size,
+                                         memory_region_read_accessor,
+                                         mr, attrs);
+    } else if (mr->ops->read_with_attrs) {
+        return access_with_adjusted_size(addr, pval, size,
+                                         mr->ops->impl.min_access_size,
+                                         mr->ops->impl.max_access_size,
+                                         memory_region_read_with_attrs_accessor,
+                                         mr, attrs);
     } else {
-        access_with_adjusted_size(addr, &data, size, 1, 4,
-                                  memory_region_oldmmio_read_accessor, mr);
+        return access_with_adjusted_size(addr, pval, size, 1, 4,
+                                         memory_region_oldmmio_read_accessor,
+                                         mr, attrs);
     }
-
-    return data;
 }
 
-static bool memory_region_dispatch_read(MemoryRegion *mr,
-                                        hwaddr addr,
-                                        uint64_t *pval,
-                                        unsigned size)
+static MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
+                                               hwaddr addr,
+                                               uint64_t *pval,
+                                               unsigned size,
+                                               MemTxAttrs attrs)
 {
+    MemTxResult r;
+
     if (!memory_region_access_valid(mr, addr, size, false)) {
         *pval = unassigned_mem_read(mr, addr, size);
-        return true;
+        return MEMTX_DECODE_ERROR;
     }
 
-    *pval = memory_region_dispatch_read1(mr, addr, size);
+    r = memory_region_dispatch_read1(mr, addr, pval, size, attrs);
     adjust_endianness(mr, pval, size);
-    return false;
+    return r;
 }
 
-static bool memory_region_dispatch_write(MemoryRegion *mr,
-                                         hwaddr addr,
-                                         uint64_t data,
-                                         unsigned size)
+static MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
+                                                hwaddr addr,
+                                                uint64_t data,
+                                                unsigned size,
+                                                MemTxAttrs attrs)
 {
     if (!memory_region_access_valid(mr, addr, size, true)) {
         unassigned_mem_write(mr, addr, data, size);
-        return true;
+        return MEMTX_DECODE_ERROR;
     }
 
     adjust_endianness(mr, &data, size);
 
     if (mr->ops->write) {
-        access_with_adjusted_size(addr, &data, size,
-                                  mr->ops->impl.min_access_size,
-                                  mr->ops->impl.max_access_size,
-                                  memory_region_write_accessor, mr);
+        return access_with_adjusted_size(addr, &data, size,
+                                         mr->ops->impl.min_access_size,
+                                         mr->ops->impl.max_access_size,
+                                         memory_region_write_accessor, mr,
+                                         attrs);
+    } else if (mr->ops->write_with_attrs) {
+        return
+            access_with_adjusted_size(addr, &data, size,
+                                      mr->ops->impl.min_access_size,
+                                      mr->ops->impl.max_access_size,
+                                      memory_region_write_with_attrs_accessor,
+                                      mr, attrs);
     } else {
-        access_with_adjusted_size(addr, &data, size, 1, 4,
-                                  memory_region_oldmmio_write_accessor, mr);
+        return access_with_adjusted_size(addr, &data, size, 1, 4,
+                                         memory_region_oldmmio_write_accessor,
+                                         mr, attrs);
     }
-    return false;
 }
 
 void memory_region_init_io(MemoryRegion *mr,
@@ -1994,13 +2065,15 @@ void address_space_destroy(AddressSpace *as)
 
 bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size)
 {
-    return memory_region_dispatch_read(mr, addr, pval, size);
+    return memory_region_dispatch_read(mr, addr, pval, size,
+                                       MEMTXATTRS_UNSPECIFIED);
 }
 
 bool io_mem_write(MemoryRegion *mr, hwaddr addr,
                   uint64_t val, unsigned size)
 {
-    return memory_region_dispatch_write(mr, addr, val, size);
+    return memory_region_dispatch_write(mr, addr, val, size,
+                                        MEMTXATTRS_UNSPECIFIED);
 }
 
 typedef struct MemoryRegionList MemoryRegionList;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 02/14] memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-08 10:51   ` Paolo Bonzini
  2015-04-09  8:59   ` Edgar E. Iglesias
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 03/14] Make CPU iotlb a structure rather than a plain hwaddr Peter Maydell
                   ` (12 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Add a MemTxAttrs argument to the io_mem_read() and io_mem_write()
functions, and make them return MemTxResult rather than bool,
thus pushing these new arguments out one level of the callstack
(all the callers callers currently pass MEMTXATTRS_UNSPECIFIED
and convert the return value back to bool or ignore it).

Note that this involves moving the io_mem_read and io_mem_write
prototypes from exec-all.h to memory.h. This allows them to
see the MemTxResult type, and is a better location anyway,
since they are implemented in memory.c and are operations on
MemoryRegions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 exec.c                   | 33 +++++++++++++++++----------------
 hw/s390x/s390-pci-inst.c |  7 ++++---
 hw/vfio/pci.c            |  4 ++--
 include/exec/exec-all.h  |  4 ----
 include/exec/memory.h    | 12 ++++++++++++
 memory.c                 | 13 ++++++-------
 softmmu_template.h       |  4 ++--
 7 files changed, 43 insertions(+), 34 deletions(-)

diff --git a/exec.c b/exec.c
index 874ecfc..52e7a2a 100644
--- a/exec.c
+++ b/exec.c
@@ -2312,7 +2312,8 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
     uint64_t val;
     hwaddr addr1;
     MemoryRegion *mr;
-    bool error = false;
+    MemTxResult result = MEMTX_OK;
+    MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
 
     while (len > 0) {
         l = len;
@@ -2327,22 +2328,22 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                 case 8:
                     /* 64 bit write access */
                     val = ldq_p(buf);
-                    error |= io_mem_write(mr, addr1, val, 8);
+                    result |= io_mem_write(mr, addr1, val, 8, attrs);
                     break;
                 case 4:
                     /* 32 bit write access */
                     val = ldl_p(buf);
-                    error |= io_mem_write(mr, addr1, val, 4);
+                    result |= io_mem_write(mr, addr1, val, 4, attrs);
                     break;
                 case 2:
                     /* 16 bit write access */
                     val = lduw_p(buf);
-                    error |= io_mem_write(mr, addr1, val, 2);
+                    result |= io_mem_write(mr, addr1, val, 2, attrs);
                     break;
                 case 1:
                     /* 8 bit write access */
                     val = ldub_p(buf);
-                    error |= io_mem_write(mr, addr1, val, 1);
+                    result |= io_mem_write(mr, addr1, val, 1, attrs);
                     break;
                 default:
                     abort();
@@ -2361,22 +2362,22 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                 switch (l) {
                 case 8:
                     /* 64 bit read access */
-                    error |= io_mem_read(mr, addr1, &val, 8);
+                    result |= io_mem_read(mr, addr1, &val, 8, attrs);
                     stq_p(buf, val);
                     break;
                 case 4:
                     /* 32 bit read access */
-                    error |= io_mem_read(mr, addr1, &val, 4);
+                    result |= io_mem_read(mr, addr1, &val, 4, attrs);
                     stl_p(buf, val);
                     break;
                 case 2:
                     /* 16 bit read access */
-                    error |= io_mem_read(mr, addr1, &val, 2);
+                    result |= io_mem_read(mr, addr1, &val, 2, attrs);
                     stw_p(buf, val);
                     break;
                 case 1:
                     /* 8 bit read access */
-                    error |= io_mem_read(mr, addr1, &val, 1);
+                    result |= io_mem_read(mr, addr1, &val, 1, attrs);
                     stb_p(buf, val);
                     break;
                 default:
@@ -2393,7 +2394,7 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
         addr += l;
     }
 
-    return error;
+    return result;
 }
 
 bool address_space_write(AddressSpace *as, hwaddr addr,
@@ -2669,7 +2670,7 @@ static inline uint32_t ldl_phys_internal(AddressSpace *as, hwaddr addr,
     mr = address_space_translate(as, addr, &addr1, &l, false);
     if (l < 4 || !memory_access_is_direct(mr, false)) {
         /* I/O case */
-        io_mem_read(mr, addr1, &val, 4);
+        io_mem_read(mr, addr1, &val, 4, MEMTXATTRS_UNSPECIFIED);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap32(val);
@@ -2728,7 +2729,7 @@ static inline uint64_t ldq_phys_internal(AddressSpace *as, hwaddr addr,
                                  false);
     if (l < 8 || !memory_access_is_direct(mr, false)) {
         /* I/O case */
-        io_mem_read(mr, addr1, &val, 8);
+        io_mem_read(mr, addr1, &val, 8, MEMTXATTRS_UNSPECIFIED);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap64(val);
@@ -2795,7 +2796,7 @@ static inline uint32_t lduw_phys_internal(AddressSpace *as, hwaddr addr,
                                  false);
     if (l < 2 || !memory_access_is_direct(mr, false)) {
         /* I/O case */
-        io_mem_read(mr, addr1, &val, 2);
+        io_mem_read(mr, addr1, &val, 2, MEMTXATTRS_UNSPECIFIED);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap16(val);
@@ -2853,7 +2854,7 @@ void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
     mr = address_space_translate(as, addr, &addr1, &l,
                                  true);
     if (l < 4 || !memory_access_is_direct(mr, true)) {
-        io_mem_write(mr, addr1, val, 4);
+        io_mem_write(mr, addr1, val, 4, MEMTXATTRS_UNSPECIFIED);
     } else {
         addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
         ptr = qemu_get_ram_ptr(addr1);
@@ -2892,7 +2893,7 @@ static inline void stl_phys_internal(AddressSpace *as,
             val = bswap32(val);
         }
 #endif
-        io_mem_write(mr, addr1, val, 4);
+        io_mem_write(mr, addr1, val, 4, MEMTXATTRS_UNSPECIFIED);
     } else {
         /* RAM case */
         addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
@@ -2955,7 +2956,7 @@ static inline void stw_phys_internal(AddressSpace *as,
             val = bswap16(val);
         }
 #endif
-        io_mem_write(mr, addr1, val, 2);
+        io_mem_write(mr, addr1, val, 2, MEMTXATTRS_UNSPECIFIED);
     } else {
         /* RAM case */
         addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 08d8aa6..78ff9c0 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -331,7 +331,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
             return 0;
         }
         MemoryRegion *mr = pbdev->pdev->io_regions[pcias].memory;
-        io_mem_read(mr, offset, &data, len);
+        io_mem_read(mr, offset, &data, len, MEMTXATTRS_UNSPECIFIED);
     } else if (pcias == 15) {
         if ((4 - (offset & 0x3)) < len) {
             program_interrupt(env, PGM_OPERAND, 4);
@@ -456,7 +456,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
             mr = pbdev->pdev->io_regions[pcias].memory;
         }
 
-        io_mem_write(mr, offset, data, len);
+        io_mem_write(mr, offset, data, len, MEMTXATTRS_UNSPECIFIED);
     } else if (pcias == 15) {
         if ((4 - (offset & 0x3)) < len) {
             program_interrupt(env, PGM_OPERAND, 4);
@@ -606,7 +606,8 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr)
     }
 
     for (i = 0; i < len / 8; i++) {
-        io_mem_write(mr, env->regs[r3] + i * 8, ldq_p(buffer + i * 8), 8);
+        io_mem_write(mr, env->regs[r3] + i * 8, ldq_p(buffer + i * 8), 8,
+                     MEMTXATTRS_UNSPECIFIED);
     }
 
     setcc(cpu, ZPCI_PCI_LS_OK);
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 6b80539..3e1df0c 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -1533,7 +1533,7 @@ static uint64_t vfio_rtl8168_window_quirk_read(void *opaque,
 
             io_mem_read(&vdev->pdev.msix_table_mmio,
                         (hwaddr)(quirk->data.address_match & 0xfff),
-                        &val, size);
+                        &val, size, MEMTXATTRS_UNSPECIFIED);
             return val;
         }
     }
@@ -1563,7 +1563,7 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr,
 
                 io_mem_write(&vdev->pdev.msix_table_mmio,
                              (hwaddr)(quirk->data.address_match & 0xfff),
-                             data, size);
+                             data, size, MEMTXATTRS_UNSPECIFIED);
             }
 
             quirk->data.flags = 1;
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 8eb0db3..ff1bc3e 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -341,10 +341,6 @@ void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
 
 struct MemoryRegion *iotlb_to_region(CPUState *cpu,
                                      hwaddr index);
-bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
-                 uint64_t *pvalue, unsigned size);
-bool io_mem_write(struct MemoryRegion *mr, hwaddr addr,
-                  uint64_t value, unsigned size);
 
 void tlb_fill(CPUState *cpu, target_ulong addr, int is_write, int mmu_idx,
               uintptr_t retaddr);
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 703d9e5..de2849d 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1053,6 +1053,18 @@ void memory_global_dirty_log_stop(void);
 void mtree_info(fprintf_function mon_printf, void *f);
 
 /**
+ * io_mem_read: perform an IO read directly to the specified MemoryRegion
+ */
+MemTxResult io_mem_read(struct MemoryRegion *mr, hwaddr addr,
+                        uint64_t *pvalue, unsigned size, MemTxAttrs attrs);
+
+/**
+ * io_mem_write: perform an IO write directly to the specified MemoryRegion
+ */
+MemTxResult io_mem_write(struct MemoryRegion *mr, hwaddr addr,
+                         uint64_t value, unsigned size, MemTxAttrs attrs);
+
+/**
  * address_space_init: initializes an address space
  *
  * @as: an uninitialized #AddressSpace
diff --git a/memory.c b/memory.c
index 9bb5674..14cda7f 100644
--- a/memory.c
+++ b/memory.c
@@ -2063,17 +2063,16 @@ void address_space_destroy(AddressSpace *as)
     call_rcu(as, do_address_space_destroy, rcu);
 }
 
-bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size)
+MemTxResult io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval,
+                        unsigned size, MemTxAttrs attrs)
 {
-    return memory_region_dispatch_read(mr, addr, pval, size,
-                                       MEMTXATTRS_UNSPECIFIED);
+    return memory_region_dispatch_read(mr, addr, pval, size, attrs);
 }
 
-bool io_mem_write(MemoryRegion *mr, hwaddr addr,
-                  uint64_t val, unsigned size)
+MemTxResult io_mem_write(MemoryRegion *mr, hwaddr addr,
+                         uint64_t val, unsigned size, MemTxAttrs attrs)
 {
-    return memory_region_dispatch_write(mr, addr, val, size,
-                                        MEMTXATTRS_UNSPECIFIED);
+    return memory_region_dispatch_write(mr, addr, val, size, attrs);
 }
 
 typedef struct MemoryRegionList MemoryRegionList;
diff --git a/softmmu_template.h b/softmmu_template.h
index 0e3dd35..4b9bae7 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -158,7 +158,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
     }
 
     cpu->mem_io_vaddr = addr;
-    io_mem_read(mr, physaddr, &val, 1 << SHIFT);
+    io_mem_read(mr, physaddr, &val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
     return val;
 }
 #endif
@@ -378,7 +378,7 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
 
     cpu->mem_io_vaddr = addr;
     cpu->mem_io_pc = retaddr;
-    io_mem_write(mr, physaddr, val, 1 << SHIFT);
+    io_mem_write(mr, physaddr, val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
 }
 
 void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 03/14] Make CPU iotlb a structure rather than a plain hwaddr
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status Peter Maydell
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 02/14] memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-08 10:52   ` Paolo Bonzini
  2015-04-09  9:02   ` Edgar E. Iglesias
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 04/14] Add MemTxAttrs to the IOTLB Peter Maydell
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Make the CPU iotlb a structure rather than a plain hwaddr;
this will allow us to add transaction attributes to it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 cputlb.c                |  4 ++--
 include/exec/cpu-defs.h | 13 +++++++++++--
 softmmu_template.h      | 32 +++++++++++++++++---------------
 3 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index 38f2151..5e1cb8f 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -301,7 +301,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
     env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
 
     /* refill the tlb */
-    env->iotlb[mmu_idx][index] = iotlb - vaddr;
+    env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
     te->addend = addend - vaddr;
     if (prot & PAGE_READ) {
         te->addr_read = address;
@@ -349,7 +349,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
                  (addr & TARGET_PAGE_MASK))) {
         cpu_ldub_code(env1, addr);
     }
-    pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
+    pd = env1->iotlb[mmu_idx][page_index].addr & ~TARGET_PAGE_MASK;
     mr = iotlb_to_region(cpu, pd);
     if (memory_region_is_unassigned(mr)) {
         CPUClass *cc = CPU_GET_CLASS(cpu);
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 0ca6f0b..7f88185 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -102,12 +102,21 @@ typedef struct CPUTLBEntry {
 
 QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
 
+/* The IOTLB is not accessed directly inline by generated TCG code,
+ * so the CPUIOTLBEntry layout is not as critical as that of the
+ * CPUTLBEntry. (This is also why we don't want to combine the two
+ * structs into one.)
+ */
+typedef struct CPUIOTLBEntry {
+    hwaddr addr;
+} CPUIOTLBEntry;
+
 #define CPU_COMMON_TLB \
     /* The meaning of the MMU modes is defined in the target code. */   \
     CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE];                  \
     CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE];               \
-    hwaddr iotlb[NB_MMU_MODES][CPU_TLB_SIZE];                           \
-    hwaddr iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE];                        \
+    CPUIOTLBEntry iotlb[NB_MMU_MODES][CPU_TLB_SIZE];                    \
+    CPUIOTLBEntry iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE];                 \
     target_ulong tlb_flush_addr;                                        \
     target_ulong tlb_flush_mask;                                        \
     target_ulong vtlb_index;                                            \
diff --git a/softmmu_template.h b/softmmu_template.h
index 4b9bae7..7a36550 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -123,7 +123,7 @@
      * victim tlb. try to refill from the victim tlb before walking the       \
      * page table. */                                                         \
     int vidx;                                                                 \
-    hwaddr tmpiotlb;                                                          \
+    CPUIOTLBEntry tmpiotlb;                                                   \
     CPUTLBEntry tmptlb;                                                       \
     for (vidx = CPU_VTLB_SIZE-1; vidx >= 0; --vidx) {                         \
         if (env->tlb_v_table[mmu_idx][vidx].ty == (addr & TARGET_PAGE_MASK)) {\
@@ -143,12 +143,13 @@
 
 #ifndef SOFTMMU_CODE_ACCESS
 static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
-                                              hwaddr physaddr,
+                                              CPUIOTLBEntry *iotlbentry,
                                               target_ulong addr,
                                               uintptr_t retaddr)
 {
     uint64_t val;
     CPUState *cpu = ENV_GET_CPU(env);
+    hwaddr physaddr = iotlbentry->addr;
     MemoryRegion *mr = iotlb_to_region(cpu, physaddr);
 
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
@@ -195,15 +196,15 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
 
     /* Handle an IO access.  */
     if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
-        hwaddr ioaddr;
+        CPUIOTLBEntry *iotlbentry;
         if ((addr & (DATA_SIZE - 1)) != 0) {
             goto do_unaligned_access;
         }
-        ioaddr = env->iotlb[mmu_idx][index];
+        iotlbentry = &env->iotlb[mmu_idx][index];
 
         /* ??? Note that the io helpers always read data in the target
            byte ordering.  We should push the LE/BE request down into io.  */
-        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
+        res = glue(io_read, SUFFIX)(env, iotlbentry, addr, retaddr);
         res = TGT_LE(res);
         return res;
     }
@@ -283,15 +284,15 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
 
     /* Handle an IO access.  */
     if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
-        hwaddr ioaddr;
+        CPUIOTLBEntry *iotlbentry;
         if ((addr & (DATA_SIZE - 1)) != 0) {
             goto do_unaligned_access;
         }
-        ioaddr = env->iotlb[mmu_idx][index];
+        iotlbentry = &env->iotlb[mmu_idx][index];
 
         /* ??? Note that the io helpers always read data in the target
            byte ordering.  We should push the LE/BE request down into io.  */
-        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
+        res = glue(io_read, SUFFIX)(env, iotlbentry, addr, retaddr);
         res = TGT_BE(res);
         return res;
     }
@@ -363,12 +364,13 @@ WORD_TYPE helper_be_lds_name(CPUArchState *env, target_ulong addr,
 #endif
 
 static inline void glue(io_write, SUFFIX)(CPUArchState *env,
-                                          hwaddr physaddr,
+                                          CPUIOTLBEntry *iotlbentry,
                                           DATA_TYPE val,
                                           target_ulong addr,
                                           uintptr_t retaddr)
 {
     CPUState *cpu = ENV_GET_CPU(env);
+    hwaddr physaddr = iotlbentry->addr;
     MemoryRegion *mr = iotlb_to_region(cpu, physaddr);
 
     physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
@@ -408,16 +410,16 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
 
     /* Handle an IO access.  */
     if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
-        hwaddr ioaddr;
+        CPUIOTLBEntry *iotlbentry;
         if ((addr & (DATA_SIZE - 1)) != 0) {
             goto do_unaligned_access;
         }
-        ioaddr = env->iotlb[mmu_idx][index];
+        iotlbentry = &env->iotlb[mmu_idx][index];
 
         /* ??? Note that the io helpers always read data in the target
            byte ordering.  We should push the LE/BE request down into io.  */
         val = TGT_LE(val);
-        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
+        glue(io_write, SUFFIX)(env, iotlbentry, val, addr, retaddr);
         return;
     }
 
@@ -489,16 +491,16 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
 
     /* Handle an IO access.  */
     if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
-        hwaddr ioaddr;
+        CPUIOTLBEntry *iotlbentry;
         if ((addr & (DATA_SIZE - 1)) != 0) {
             goto do_unaligned_access;
         }
-        ioaddr = env->iotlb[mmu_idx][index];
+        iotlbentry = &env->iotlb[mmu_idx][index];
 
         /* ??? Note that the io helpers always read data in the target
            byte ordering.  We should push the LE/BE request down into io.  */
         val = TGT_BE(val);
-        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
+        glue(io_write, SUFFIX)(env, iotlbentry, val, addr, retaddr);
         return;
     }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 04/14] Add MemTxAttrs to the IOTLB
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (2 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 03/14] Make CPU iotlb a structure rather than a plain hwaddr Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-08 10:53   ` Paolo Bonzini
  2015-04-09  9:04   ` Edgar E. Iglesias
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 05/14] exec.c: Convert subpage memory ops to _with_attrs Peter Maydell
                   ` (10 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Add a MemTxAttrs field to the IOTLB, and allow target-specific
code to set it via a new tlb_set_page_with_attrs() function;
pass the attributes through to the device when making IO accesses.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 cputlb.c                | 18 +++++++++++++++---
 include/exec/cpu-defs.h |  2 ++
 include/exec/exec-all.h |  3 +++
 softmmu_template.h      |  4 ++--
 4 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index 5e1cb8f..7606548 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -249,9 +249,9 @@ static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
  * Called from TCG-generated code, which is under an RCU read-side
  * critical section.
  */
-void tlb_set_page(CPUState *cpu, target_ulong vaddr,
-                  hwaddr paddr, int prot,
-                  int mmu_idx, target_ulong size)
+void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
+                             hwaddr paddr, MemTxAttrs attrs, int prot,
+                             int mmu_idx, target_ulong size)
 {
     CPUArchState *env = cpu->env_ptr;
     MemoryRegionSection *section;
@@ -302,6 +302,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
 
     /* refill the tlb */
     env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
+    env->iotlb[mmu_idx][index].attrs = attrs;
     te->addend = addend - vaddr;
     if (prot & PAGE_READ) {
         te->addr_read = address;
@@ -331,6 +332,17 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
     }
 }
 
+/* Add a new TLB entry, but without specifying the memory
+ * transaction attributes to be used.
+ */
+void tlb_set_page(CPUState *cpu, target_ulong vaddr,
+                  hwaddr paddr, int prot,
+                  int mmu_idx, target_ulong size)
+{
+    tlb_set_page_with_attrs(cpu, vaddr, paddr, MEMTXATTRS_UNSPECIFIED,
+                            prot, mmu_idx, size);
+}
+
 /* NOTE: this function can trigger an exception */
 /* NOTE2: the returned address is not exactly the physical address: it
  * is actually a ram_addr_t (in system mode; the user mode emulation
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 7f88185..3f56546 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -30,6 +30,7 @@
 #ifndef CONFIG_USER_ONLY
 #include "exec/hwaddr.h"
 #endif
+#include "exec/memattrs.h"
 
 #ifndef TARGET_LONG_BITS
 #error TARGET_LONG_BITS must be defined before including this header
@@ -109,6 +110,7 @@ QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
  */
 typedef struct CPUIOTLBEntry {
     hwaddr addr;
+    MemTxAttrs attrs;
 } CPUIOTLBEntry;
 
 #define CPU_COMMON_TLB \
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index ff1bc3e..b58cd47 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -105,6 +105,9 @@ void tlb_flush(CPUState *cpu, int flush_global);
 void tlb_set_page(CPUState *cpu, target_ulong vaddr,
                   hwaddr paddr, int prot,
                   int mmu_idx, target_ulong size);
+void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
+                             hwaddr paddr, MemTxAttrs attrs,
+                             int prot, int mmu_idx, target_ulong size);
 void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr);
 #else
 static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
diff --git a/softmmu_template.h b/softmmu_template.h
index 7a36550..7310a93 100644
--- a/softmmu_template.h
+++ b/softmmu_template.h
@@ -159,7 +159,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
     }
 
     cpu->mem_io_vaddr = addr;
-    io_mem_read(mr, physaddr, &val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
+    io_mem_read(mr, physaddr, &val, 1 << SHIFT, iotlbentry->attrs);
     return val;
 }
 #endif
@@ -380,7 +380,7 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
 
     cpu->mem_io_vaddr = addr;
     cpu->mem_io_pc = retaddr;
-    io_mem_write(mr, physaddr, val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
+    io_mem_write(mr, physaddr, val, 1 << SHIFT, iotlbentry->attrs);
 }
 
 void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 05/14] exec.c: Convert subpage memory ops to _with_attrs
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (3 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 04/14] Add MemTxAttrs to the IOTLB Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-08 10:54   ` Paolo Bonzini
  2015-04-09  9:07   ` Edgar E. Iglesias
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes Peter Maydell
                   ` (9 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Convert the subpage memory ops to _with_attrs; this will allow
us to pass the attributes through to the underlying access
functions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 exec.c | 33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/exec.c b/exec.c
index 52e7a2a..7e53f52 100644
--- a/exec.c
+++ b/exec.c
@@ -1941,8 +1941,8 @@ static const MemoryRegionOps watch_mem_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static uint64_t subpage_read(void *opaque, hwaddr addr,
-                             unsigned len)
+static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
+                                unsigned len, MemTxAttrs attrs)
 {
     subpage_t *subpage = opaque;
     uint8_t buf[8];
@@ -1951,23 +1951,29 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
     printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
            subpage, len, addr);
 #endif
-    address_space_read(subpage->as, addr + subpage->base, buf, len);
+    if (address_space_read(subpage->as, addr + subpage->base, buf, len)) {
+        return MEMTX_DECODE_ERROR;
+    }
     switch (len) {
     case 1:
-        return ldub_p(buf);
+        *data = ldub_p(buf);
+        return MEMTX_OK;
     case 2:
-        return lduw_p(buf);
+        *data = lduw_p(buf);
+        return MEMTX_OK;
     case 4:
-        return ldl_p(buf);
+        *data = ldl_p(buf);
+        return MEMTX_OK;
     case 8:
-        return ldq_p(buf);
+        *data = ldq_p(buf);
+        return MEMTX_OK;
     default:
         abort();
     }
 }
 
-static void subpage_write(void *opaque, hwaddr addr,
-                          uint64_t value, unsigned len)
+static MemTxResult subpage_write(void *opaque, hwaddr addr,
+                                 uint64_t value, unsigned len, MemTxAttrs attrs)
 {
     subpage_t *subpage = opaque;
     uint8_t buf[8];
@@ -1993,7 +1999,10 @@ static void subpage_write(void *opaque, hwaddr addr,
     default:
         abort();
     }
-    address_space_write(subpage->as, addr + subpage->base, buf, len);
+    if (address_space_write(subpage->as, addr + subpage->base, buf, len)) {
+        return MEMTX_DECODE_ERROR;
+    }
+    return MEMTX_OK;
 }
 
 static bool subpage_accepts(void *opaque, hwaddr addr,
@@ -2010,8 +2019,8 @@ static bool subpage_accepts(void *opaque, hwaddr addr,
 }
 
 static const MemoryRegionOps subpage_ops = {
-    .read = subpage_read,
-    .write = subpage_write,
+    .read_with_attrs = subpage_read,
+    .write_with_attrs = subpage_write,
     .impl.min_access_size = 1,
     .impl.max_access_size = 8,
     .valid.min_access_size = 1,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (4 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 05/14] exec.c: Convert subpage memory ops to _with_attrs Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-08 12:55   ` Paolo Bonzini
  2015-04-09  9:59   ` Edgar E. Iglesias
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions Peter Maydell
                   ` (8 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Make address_space_rw take transaction attributes, rather
than always using the 'unspecified' attributes.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 dma-helpers.c            |  3 ++-
 exec.c                   | 51 ++++++++++++++++++++++++++----------------------
 hw/mips/mips_jazz.c      |  6 ++++--
 hw/pci-host/prep.c       |  6 ++++--
 include/exec/memory.h    | 31 ++++++++++++++++++-----------
 include/sysemu/dma.h     |  3 ++-
 ioport.c                 | 16 +++++++++------
 kvm-all.c                |  3 ++-
 scripts/coverity-model.c |  8 +++++---
 9 files changed, 77 insertions(+), 50 deletions(-)

diff --git a/dma-helpers.c b/dma-helpers.c
index 6918572..33b1983 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -28,7 +28,8 @@ int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len)
     memset(fillbuf, c, FILLBUF_SIZE);
     while (len > 0) {
         l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
-        error |= address_space_rw(as, addr, fillbuf, l, true);
+        error |= address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED,
+                                  fillbuf, l, true);
         len -= l;
         addr += l;
     }
diff --git a/exec.c b/exec.c
index 7e53f52..29a12fa 100644
--- a/exec.c
+++ b/exec.c
@@ -1946,13 +1946,16 @@ static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
 {
     subpage_t *subpage = opaque;
     uint8_t buf[8];
+    MemTxResult res;
 
 #if defined(DEBUG_SUBPAGE)
     printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
            subpage, len, addr);
 #endif
-    if (address_space_read(subpage->as, addr + subpage->base, buf, len)) {
-        return MEMTX_DECODE_ERROR;
+    res = address_space_read(subpage->as, addr + subpage->base,
+                             attrs, buf, len);
+    if (res) {
+        return res;
     }
     switch (len) {
     case 1:
@@ -1999,10 +2002,8 @@ static MemTxResult subpage_write(void *opaque, hwaddr addr,
     default:
         abort();
     }
-    if (address_space_write(subpage->as, addr + subpage->base, buf, len)) {
-        return MEMTX_DECODE_ERROR;
-    }
-    return MEMTX_OK;
+    return address_space_write(subpage->as, addr + subpage->base,
+                               attrs, buf, len);
 }
 
 static bool subpage_accepts(void *opaque, hwaddr addr,
@@ -2313,8 +2314,8 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
     return l;
 }
 
-bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
-                      int len, bool is_write)
+MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
+                             uint8_t *buf, int len, bool is_write)
 {
     hwaddr l;
     uint8_t *ptr;
@@ -2322,7 +2323,6 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
     hwaddr addr1;
     MemoryRegion *mr;
     MemTxResult result = MEMTX_OK;
-    MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
 
     while (len > 0) {
         l = len;
@@ -2406,22 +2406,24 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
     return result;
 }
 
-bool address_space_write(AddressSpace *as, hwaddr addr,
-                         const uint8_t *buf, int len)
+MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
+                                const uint8_t *buf, int len)
 {
-    return address_space_rw(as, addr, (uint8_t *)buf, len, true);
+    return address_space_rw(as, addr, attrs, (uint8_t *)buf, len, true);
 }
 
-bool address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len)
+MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
+                               uint8_t *buf, int len)
 {
-    return address_space_rw(as, addr, buf, len, false);
+    return address_space_rw(as, addr, attrs, buf, len, false);
 }
 
 
 void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
                             int len, int is_write)
 {
-    address_space_rw(&address_space_memory, addr, buf, len, is_write);
+    address_space_rw(&address_space_memory, addr, MEMTXATTRS_UNSPECIFIED,
+                     buf, len, is_write);
 }
 
 enum write_rom_type {
@@ -2592,7 +2594,8 @@ void *address_space_map(AddressSpace *as,
         memory_region_ref(mr);
         bounce.mr = mr;
         if (!is_write) {
-            address_space_read(as, addr, bounce.buffer, l);
+            address_space_read(as, addr, MEMTXATTRS_UNSPECIFIED,
+                               bounce.buffer, l);
         }
 
         *plen = l;
@@ -2645,7 +2648,8 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
         return;
     }
     if (is_write) {
-        address_space_write(as, bounce.addr, bounce.buffer, access_len);
+        address_space_write(as, bounce.addr, MEMTXATTRS_UNSPECIFIED,
+                            bounce.buffer, access_len);
     }
     qemu_vfree(bounce.buffer);
     bounce.buffer = NULL;
@@ -2787,7 +2791,7 @@ uint64_t ldq_be_phys(AddressSpace *as, hwaddr addr)
 uint32_t ldub_phys(AddressSpace *as, hwaddr addr)
 {
     uint8_t val;
-    address_space_rw(as, addr, &val, 1, 0);
+    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, &val, 1, 0);
     return val;
 }
 
@@ -2941,7 +2945,7 @@ void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
 void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val)
 {
     uint8_t v = val;
-    address_space_rw(as, addr, &v, 1, 1);
+    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, &v, 1, 1);
 }
 
 /* warning: addr must be aligned */
@@ -3004,19 +3008,19 @@ void stw_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
 void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val)
 {
     val = tswap64(val);
-    address_space_rw(as, addr, (void *) &val, 8, 1);
+    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
 }
 
 void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val)
 {
     val = cpu_to_le64(val);
-    address_space_rw(as, addr, (void *) &val, 8, 1);
+    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
 }
 
 void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val)
 {
     val = cpu_to_be64(val);
-    address_space_rw(as, addr, (void *) &val, 8, 1);
+    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
 }
 
 /* virtual memory access for debug (includes writing to ROM) */
@@ -3040,7 +3044,8 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
         if (is_write) {
             cpu_physical_memory_write_rom(cpu->as, phys_addr, buf, l);
         } else {
-            address_space_rw(cpu->as, phys_addr, buf, l, 0);
+            address_space_rw(cpu->as, phys_addr, MEMTXATTRS_UNSPECIFIED,
+                             buf, l, 0);
         }
         len -= l;
         buf += l;
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 07f3c27..2c153e0 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -61,7 +61,8 @@ static void main_cpu_reset(void *opaque)
 static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size)
 {
     uint8_t val;
-    address_space_read(&address_space_memory, 0x90000071, &val, 1);
+    address_space_read(&address_space_memory, 0x90000071,
+                       MEMTXATTRS_UNSPECIFIED, &val, 1);
     return val;
 }
 
@@ -69,7 +70,8 @@ static void rtc_write(void *opaque, hwaddr addr,
                       uint64_t val, unsigned size)
 {
     uint8_t buf = val & 0xff;
-    address_space_write(&address_space_memory, 0x90000071, &buf, 1);
+    address_space_write(&address_space_memory, 0x90000071,
+                        MEMTXATTRS_UNSPECIFIED, &buf, 1);
 }
 
 static const MemoryRegionOps rtc_ops = {
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index 6cea6ff..c63f45d 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -140,7 +140,8 @@ static uint64_t raven_io_read(void *opaque, hwaddr addr,
     uint8_t buf[4];
 
     addr = raven_io_address(s, addr);
-    address_space_read(&s->pci_io_as, addr + 0x80000000, buf, size);
+    address_space_read(&s->pci_io_as, addr + 0x80000000,
+                       MEMTXATTRS_UNSPECIFIED, buf, size);
 
     if (size == 1) {
         return buf[0];
@@ -171,7 +172,8 @@ static void raven_io_write(void *opaque, hwaddr addr,
         g_assert_not_reached();
     }
 
-    address_space_write(&s->pci_io_as, addr + 0x80000000, buf, size);
+    address_space_write(&s->pci_io_as, addr + 0x80000000,
+                        MEMTXATTRS_UNSPECIFIED, buf, size);
 }
 
 static const MemoryRegionOps raven_io_ops = {
diff --git a/include/exec/memory.h b/include/exec/memory.h
index de2849d..4d6afc8 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1089,41 +1089,50 @@ void address_space_destroy(AddressSpace *as);
 /**
  * address_space_rw: read from or write to an address space.
  *
- * Return true if the operation hit any unassigned memory or encountered an
- * IOMMU fault.
+ * Return a MemTxResult indicating whether the operation succeeded
+ * or failed (eg unassigned memory, device rejected the transaction,
+ * IOMMU fault).
  *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
+ * @attrs: memory transaction attributes
  * @buf: buffer with the data transferred
  * @is_write: indicates the transfer direction
  */
-bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
-                      int len, bool is_write);
+MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
+                             MemTxAttrs attrs, uint8_t *buf,
+                             int len, bool is_write);
 
 /**
  * address_space_write: write to address space.
  *
- * Return true if the operation hit any unassigned memory or encountered an
- * IOMMU fault.
+ * Return a MemTxResult indicating whether the operation succeeded
+ * or failed (eg unassigned memory, device rejected the transaction,
+ * IOMMU fault).
  *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
+ * @attrs: memory transaction attributes
  * @buf: buffer with the data transferred
  */
-bool address_space_write(AddressSpace *as, hwaddr addr,
-                         const uint8_t *buf, int len);
+MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
+                                MemTxAttrs attrs,
+                                const uint8_t *buf, int len);
 
 /**
  * address_space_read: read from an address space.
  *
- * Return true if the operation hit any unassigned memory or encountered an
- * IOMMU fault.
+ * Return a MemTxResult indicating whether the operation succeeded
+ * or failed (eg unassigned memory, device rejected the transaction,
+ * IOMMU fault).
  *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
+ * @attrs: memory transaction attributes
  * @buf: buffer with the data transferred
  */
-bool address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
+MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
+                               uint8_t *buf, int len);
 
 /* address_space_translate: translate an address range into an address space
  * into a MemoryRegion and an address range into that section
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
index 3f2f4c8..efa8b99 100644
--- a/include/sysemu/dma.h
+++ b/include/sysemu/dma.h
@@ -88,7 +88,8 @@ static inline int dma_memory_rw_relaxed(AddressSpace *as, dma_addr_t addr,
                                         void *buf, dma_addr_t len,
                                         DMADirection dir)
 {
-    return address_space_rw(as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
+    return (bool)address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED,
+                                  buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
 }
 
 static inline int dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr,
diff --git a/ioport.c b/ioport.c
index 783a3ae..b345bd9 100644
--- a/ioport.c
+++ b/ioport.c
@@ -64,7 +64,8 @@ void cpu_outb(pio_addr_t addr, uint8_t val)
 {
     LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
     trace_cpu_out(addr, val);
-    address_space_write(&address_space_io, addr, &val, 1);
+    address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
+                        &val, 1);
 }
 
 void cpu_outw(pio_addr_t addr, uint16_t val)
@@ -74,7 +75,8 @@ void cpu_outw(pio_addr_t addr, uint16_t val)
     LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
     trace_cpu_out(addr, val);
     stw_p(buf, val);
-    address_space_write(&address_space_io, addr, buf, 2);
+    address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
+                        buf, 2);
 }
 
 void cpu_outl(pio_addr_t addr, uint32_t val)
@@ -84,14 +86,16 @@ void cpu_outl(pio_addr_t addr, uint32_t val)
     LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
     trace_cpu_out(addr, val);
     stl_p(buf, val);
-    address_space_write(&address_space_io, addr, buf, 4);
+    address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
+                        buf, 4);
 }
 
 uint8_t cpu_inb(pio_addr_t addr)
 {
     uint8_t val;
 
-    address_space_read(&address_space_io, addr, &val, 1);
+    address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
+                       &val, 1);
     trace_cpu_in(addr, val);
     LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
     return val;
@@ -102,7 +106,7 @@ uint16_t cpu_inw(pio_addr_t addr)
     uint8_t buf[2];
     uint16_t val;
 
-    address_space_read(&address_space_io, addr, buf, 2);
+    address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED, buf, 2);
     val = lduw_p(buf);
     trace_cpu_in(addr, val);
     LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
@@ -114,7 +118,7 @@ uint32_t cpu_inl(pio_addr_t addr)
     uint8_t buf[4];
     uint32_t val;
 
-    address_space_read(&address_space_io, addr, buf, 4);
+    address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED, buf, 4);
     val = ldl_p(buf);
     trace_cpu_in(addr, val);
     LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
diff --git a/kvm-all.c b/kvm-all.c
index dd44f8c..4ec153d 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1667,7 +1667,8 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
     uint8_t *ptr = data;
 
     for (i = 0; i < count; i++) {
-        address_space_rw(&address_space_io, port, ptr, size,
+        address_space_rw(&address_space_io, port, MEMTXATTRS_UNSPECIFIED,
+                         ptr, size,
                          direction == KVM_EXIT_IO_OUT);
         ptr += size;
     }
diff --git a/scripts/coverity-model.c b/scripts/coverity-model.c
index cdda259..224d2d1 100644
--- a/scripts/coverity-model.c
+++ b/scripts/coverity-model.c
@@ -46,6 +46,8 @@ typedef struct va_list_str *va_list;
 
 typedef struct AddressSpace AddressSpace;
 typedef uint64_t hwaddr;
+typedef uint32_t MemTxResult;
+typedef uint64_t MemTxAttrs;
 
 static void __write(uint8_t *buf, ssize_t len)
 {
@@ -65,10 +67,10 @@ static void __read(uint8_t *buf, ssize_t len)
     int last = buf[len-1];
 }
 
-bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
-                      int len, bool is_write)
+MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
+                             uint8_t *buf, int len, bool is_write)
 {
-    bool result;
+    MemTxResult result;
 
     // TODO: investigate impact of treating reads as producing
     // tainted data, with __coverity_tainted_data_argument__(buf).
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (5 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-08 11:03   ` Paolo Bonzini
  2015-04-09 10:34   ` Edgar E. Iglesias
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 08/14] Switch non-CPU callers from ld/st*_phys to address_space_ld/st* Peter Maydell
                   ` (7 subsequent siblings)
  14 siblings, 2 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Add new address_space_ld*/st* functions which allow transaction
attributes and error reporting for basic load and stores. These
are named to be in line with the address_space_read/write/rw
buffer operations.

The existing ld/st*_phys functions are now wrappers around
the new functions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 exec.c                | 291 ++++++++++++++++++++++++++++++++++++++++++--------
 include/exec/memory.h |  63 +++++++++++
 2 files changed, 310 insertions(+), 44 deletions(-)

diff --git a/exec.c b/exec.c
index 29a12fa..013032a 100644
--- a/exec.c
+++ b/exec.c
@@ -2671,19 +2671,22 @@ void cpu_physical_memory_unmap(void *buffer, hwaddr len,
 }
 
 /* warning: addr must be aligned */
-static inline uint32_t ldl_phys_internal(AddressSpace *as, hwaddr addr,
-                                         enum device_endian endian)
+static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr,
+                                                  MemTxAttrs attrs,
+                                                  MemTxResult *result,
+                                                  enum device_endian endian)
 {
     uint8_t *ptr;
     uint64_t val;
     MemoryRegion *mr;
     hwaddr l = 4;
     hwaddr addr1;
+    MemTxResult r;
 
     mr = address_space_translate(as, addr, &addr1, &l, false);
     if (l < 4 || !memory_access_is_direct(mr, false)) {
         /* I/O case */
-        io_mem_read(mr, addr1, &val, 4, MEMTXATTRS_UNSPECIFIED);
+        r = io_mem_read(mr, addr1, &val, 4, attrs);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap32(val);
@@ -2709,40 +2712,68 @@ static inline uint32_t ldl_phys_internal(AddressSpace *as, hwaddr addr,
             val = ldl_p(ptr);
             break;
         }
+        r = MEMTX_OK;
+    }
+    if (result) {
+        *result = r;
     }
     return val;
 }
 
+uint32_t address_space_ldl(AddressSpace *as, hwaddr addr,
+                           MemTxAttrs attrs, MemTxResult *result)
+{
+    return address_space_ldl_internal(as, addr, attrs, result,
+                                      DEVICE_NATIVE_ENDIAN);
+}
+
+uint32_t address_space_ldl_le(AddressSpace *as, hwaddr addr,
+                              MemTxAttrs attrs, MemTxResult *result)
+{
+    return address_space_ldl_internal(as, addr, attrs, result,
+                                      DEVICE_LITTLE_ENDIAN);
+}
+
+uint32_t address_space_ldl_be(AddressSpace *as, hwaddr addr,
+                              MemTxAttrs attrs, MemTxResult *result)
+{
+    return address_space_ldl_internal(as, addr, attrs, result,
+                                      DEVICE_BIG_ENDIAN);
+}
+
 uint32_t ldl_phys(AddressSpace *as, hwaddr addr)
 {
-    return ldl_phys_internal(as, addr, DEVICE_NATIVE_ENDIAN);
+    return address_space_ldl(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 uint32_t ldl_le_phys(AddressSpace *as, hwaddr addr)
 {
-    return ldl_phys_internal(as, addr, DEVICE_LITTLE_ENDIAN);
+    return address_space_ldl_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 uint32_t ldl_be_phys(AddressSpace *as, hwaddr addr)
 {
-    return ldl_phys_internal(as, addr, DEVICE_BIG_ENDIAN);
+    return address_space_ldl_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 /* warning: addr must be aligned */
-static inline uint64_t ldq_phys_internal(AddressSpace *as, hwaddr addr,
-                                         enum device_endian endian)
+static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr,
+                                                  MemTxAttrs attrs,
+                                                  MemTxResult *result,
+                                                  enum device_endian endian)
 {
     uint8_t *ptr;
     uint64_t val;
     MemoryRegion *mr;
     hwaddr l = 8;
     hwaddr addr1;
+    MemTxResult r;
 
     mr = address_space_translate(as, addr, &addr1, &l,
                                  false);
     if (l < 8 || !memory_access_is_direct(mr, false)) {
         /* I/O case */
-        io_mem_read(mr, addr1, &val, 8, MEMTXATTRS_UNSPECIFIED);
+        r = io_mem_read(mr, addr1, &val, 8, attrs);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap64(val);
@@ -2768,48 +2799,88 @@ static inline uint64_t ldq_phys_internal(AddressSpace *as, hwaddr addr,
             val = ldq_p(ptr);
             break;
         }
+        r = MEMTX_OK;
+    }
+    if (result) {
+        *result = r;
     }
     return val;
 }
 
+uint64_t address_space_ldq(AddressSpace *as, hwaddr addr,
+                           MemTxAttrs attrs, MemTxResult *result)
+{
+    return address_space_ldq_internal(as, addr, attrs, result,
+                                      DEVICE_NATIVE_ENDIAN);
+}
+
+uint64_t address_space_ldq_le(AddressSpace *as, hwaddr addr,
+                           MemTxAttrs attrs, MemTxResult *result)
+{
+    return address_space_ldq_internal(as, addr, attrs, result,
+                                      DEVICE_LITTLE_ENDIAN);
+}
+
+uint64_t address_space_ldq_be(AddressSpace *as, hwaddr addr,
+                           MemTxAttrs attrs, MemTxResult *result)
+{
+    return address_space_ldq_internal(as, addr, attrs, result,
+                                      DEVICE_BIG_ENDIAN);
+}
+
 uint64_t ldq_phys(AddressSpace *as, hwaddr addr)
 {
-    return ldq_phys_internal(as, addr, DEVICE_NATIVE_ENDIAN);
+    return address_space_ldq(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 uint64_t ldq_le_phys(AddressSpace *as, hwaddr addr)
 {
-    return ldq_phys_internal(as, addr, DEVICE_LITTLE_ENDIAN);
+    return address_space_ldq_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 uint64_t ldq_be_phys(AddressSpace *as, hwaddr addr)
 {
-    return ldq_phys_internal(as, addr, DEVICE_BIG_ENDIAN);
+    return address_space_ldq_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 /* XXX: optimize */
-uint32_t ldub_phys(AddressSpace *as, hwaddr addr)
+uint32_t address_space_ldub(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result)
 {
     uint8_t val;
-    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, &val, 1, 0);
+    MemTxResult r;
+
+    r = address_space_rw(as, addr, attrs, &val, 1, 0);
+    if (result) {
+        *result = r;
+    }
     return val;
 }
 
+uint32_t ldub_phys(AddressSpace *as, hwaddr addr)
+{
+    return address_space_ldub(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
+}
+
 /* warning: addr must be aligned */
-static inline uint32_t lduw_phys_internal(AddressSpace *as, hwaddr addr,
-                                          enum device_endian endian)
+static inline uint32_t address_space_lduw_internal(AddressSpace *as,
+                                                   hwaddr addr,
+                                                   MemTxAttrs attrs,
+                                                   MemTxResult *result,
+                                                   enum device_endian endian)
 {
     uint8_t *ptr;
     uint64_t val;
     MemoryRegion *mr;
     hwaddr l = 2;
     hwaddr addr1;
+    MemTxResult r;
 
     mr = address_space_translate(as, addr, &addr1, &l,
                                  false);
     if (l < 2 || !memory_access_is_direct(mr, false)) {
         /* I/O case */
-        io_mem_read(mr, addr1, &val, 2, MEMTXATTRS_UNSPECIFIED);
+        r = io_mem_read(mr, addr1, &val, 2, attrs);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap16(val);
@@ -2835,39 +2906,66 @@ static inline uint32_t lduw_phys_internal(AddressSpace *as, hwaddr addr,
             val = lduw_p(ptr);
             break;
         }
+        r = MEMTX_OK;
+    }
+    if (result) {
+        *result = r;
     }
     return val;
 }
 
+uint32_t address_space_lduw(AddressSpace *as, hwaddr addr,
+                           MemTxAttrs attrs, MemTxResult *result)
+{
+    return address_space_lduw_internal(as, addr, attrs, result,
+                                       DEVICE_NATIVE_ENDIAN);
+}
+
+uint32_t address_space_lduw_le(AddressSpace *as, hwaddr addr,
+                           MemTxAttrs attrs, MemTxResult *result)
+{
+    return address_space_lduw_internal(as, addr, attrs, result,
+                                       DEVICE_LITTLE_ENDIAN);
+}
+
+uint32_t address_space_lduw_be(AddressSpace *as, hwaddr addr,
+                           MemTxAttrs attrs, MemTxResult *result)
+{
+    return address_space_lduw_internal(as, addr, attrs, result,
+                                       DEVICE_BIG_ENDIAN);
+}
+
 uint32_t lduw_phys(AddressSpace *as, hwaddr addr)
 {
-    return lduw_phys_internal(as, addr, DEVICE_NATIVE_ENDIAN);
+    return address_space_lduw(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 uint32_t lduw_le_phys(AddressSpace *as, hwaddr addr)
 {
-    return lduw_phys_internal(as, addr, DEVICE_LITTLE_ENDIAN);
+    return address_space_lduw_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 uint32_t lduw_be_phys(AddressSpace *as, hwaddr addr)
 {
-    return lduw_phys_internal(as, addr, DEVICE_BIG_ENDIAN);
+    return address_space_lduw_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 /* warning: addr must be aligned. The ram page is not masked as dirty
    and the code inside is not invalidated. It is useful if the dirty
    bits are used to track modified PTEs */
-void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
+void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
+                                MemTxAttrs attrs, MemTxResult *result)
 {
     uint8_t *ptr;
     MemoryRegion *mr;
     hwaddr l = 4;
     hwaddr addr1;
+    MemTxResult r;
 
     mr = address_space_translate(as, addr, &addr1, &l,
                                  true);
     if (l < 4 || !memory_access_is_direct(mr, true)) {
-        io_mem_write(mr, addr1, val, 4, MEMTXATTRS_UNSPECIFIED);
+        r = io_mem_write(mr, addr1, val, 4, attrs);
     } else {
         addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
         ptr = qemu_get_ram_ptr(addr1);
@@ -2881,18 +2979,30 @@ void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
                 cpu_physical_memory_set_dirty_range_nocode(addr1, 4);
             }
         }
+        r = MEMTX_OK;
+    }
+    if (result) {
+        *result = r;
     }
 }
 
+void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
+{
+    address_space_stl_notdirty(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
+}
+
 /* warning: addr must be aligned */
-static inline void stl_phys_internal(AddressSpace *as,
-                                     hwaddr addr, uint32_t val,
-                                     enum device_endian endian)
+static inline void address_space_stl_internal(AddressSpace *as,
+                                              hwaddr addr, uint32_t val,
+                                              MemTxAttrs attrs,
+                                              MemTxResult *result,
+                                              enum device_endian endian)
 {
     uint8_t *ptr;
     MemoryRegion *mr;
     hwaddr l = 4;
     hwaddr addr1;
+    MemTxResult r;
 
     mr = address_space_translate(as, addr, &addr1, &l,
                                  true);
@@ -2906,7 +3016,7 @@ static inline void stl_phys_internal(AddressSpace *as,
             val = bswap32(val);
         }
 #endif
-        io_mem_write(mr, addr1, val, 4, MEMTXATTRS_UNSPECIFIED);
+        r = io_mem_write(mr, addr1, val, 4, attrs);
     } else {
         /* RAM case */
         addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
@@ -2923,40 +3033,79 @@ static inline void stl_phys_internal(AddressSpace *as,
             break;
         }
         invalidate_and_set_dirty(addr1, 4);
+        r = MEMTX_OK;
+    }
+    if (result) {
+        *result = r;
     }
 }
 
+void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
+                       MemTxAttrs attrs, MemTxResult *result)
+{
+    address_space_stl_internal(as, addr, val, attrs, result,
+                               DEVICE_NATIVE_ENDIAN);
+}
+
+void address_space_stl_le(AddressSpace *as, hwaddr addr, uint32_t val,
+                       MemTxAttrs attrs, MemTxResult *result)
+{
+    address_space_stl_internal(as, addr, val, attrs, result,
+                               DEVICE_LITTLE_ENDIAN);
+}
+
+void address_space_stl_be(AddressSpace *as, hwaddr addr, uint32_t val,
+                       MemTxAttrs attrs, MemTxResult *result)
+{
+    address_space_stl_internal(as, addr, val, attrs, result,
+                               DEVICE_BIG_ENDIAN);
+}
+
 void stl_phys(AddressSpace *as, hwaddr addr, uint32_t val)
 {
-    stl_phys_internal(as, addr, val, DEVICE_NATIVE_ENDIAN);
+    address_space_stl(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 void stl_le_phys(AddressSpace *as, hwaddr addr, uint32_t val)
 {
-    stl_phys_internal(as, addr, val, DEVICE_LITTLE_ENDIAN);
+    address_space_stl_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
 {
-    stl_phys_internal(as, addr, val, DEVICE_BIG_ENDIAN);
+    address_space_stl_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 /* XXX: optimize */
-void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val)
+void address_space_stb(AddressSpace *as, hwaddr addr, uint32_t val,
+                       MemTxAttrs attrs, MemTxResult *result)
 {
     uint8_t v = val;
-    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, &v, 1, 1);
+    MemTxResult r;
+
+    r = address_space_rw(as, addr, attrs, &v, 1, 1);
+    if (result) {
+        *result = r;
+    }
+}
+
+void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val)
+{
+    address_space_stb(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 /* warning: addr must be aligned */
-static inline void stw_phys_internal(AddressSpace *as,
-                                     hwaddr addr, uint32_t val,
-                                     enum device_endian endian)
+static inline void address_space_stw_internal(AddressSpace *as,
+                                              hwaddr addr, uint32_t val,
+                                              MemTxAttrs attrs,
+                                              MemTxResult *result,
+                                              enum device_endian endian)
 {
     uint8_t *ptr;
     MemoryRegion *mr;
     hwaddr l = 2;
     hwaddr addr1;
+    MemTxResult r;
 
     mr = address_space_translate(as, addr, &addr1, &l, true);
     if (l < 2 || !memory_access_is_direct(mr, true)) {
@@ -2969,7 +3118,7 @@ static inline void stw_phys_internal(AddressSpace *as,
             val = bswap16(val);
         }
 #endif
-        io_mem_write(mr, addr1, val, 2, MEMTXATTRS_UNSPECIFIED);
+        r = io_mem_write(mr, addr1, val, 2, attrs);
     } else {
         /* RAM case */
         addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
@@ -2986,41 +3135,95 @@ static inline void stw_phys_internal(AddressSpace *as,
             break;
         }
         invalidate_and_set_dirty(addr1, 2);
+        r = MEMTX_OK;
+    }
+    if (result) {
+        *result = r;
     }
 }
 
+void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val,
+                       MemTxAttrs attrs, MemTxResult *result)
+{
+    address_space_stw_internal(as, addr, val, attrs, result,
+                               DEVICE_NATIVE_ENDIAN);
+}
+
+void address_space_stw_le(AddressSpace *as, hwaddr addr, uint32_t val,
+                       MemTxAttrs attrs, MemTxResult *result)
+{
+    address_space_stw_internal(as, addr, val, attrs, result,
+                               DEVICE_LITTLE_ENDIAN);
+}
+
+void address_space_stw_be(AddressSpace *as, hwaddr addr, uint32_t val,
+                       MemTxAttrs attrs, MemTxResult *result)
+{
+    address_space_stw_internal(as, addr, val, attrs, result,
+                               DEVICE_BIG_ENDIAN);
+}
+
 void stw_phys(AddressSpace *as, hwaddr addr, uint32_t val)
 {
-    stw_phys_internal(as, addr, val, DEVICE_NATIVE_ENDIAN);
+    address_space_stw(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 void stw_le_phys(AddressSpace *as, hwaddr addr, uint32_t val)
 {
-    stw_phys_internal(as, addr, val, DEVICE_LITTLE_ENDIAN);
+    address_space_stw_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 void stw_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
 {
-    stw_phys_internal(as, addr, val, DEVICE_BIG_ENDIAN);
+    address_space_stw_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 /* XXX: optimize */
-void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val)
+void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
+                       MemTxAttrs attrs, MemTxResult *result)
 {
+    MemTxResult r;
     val = tswap64(val);
-    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
+    r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
+    if (result) {
+        *result = r;
+    }
 }
 
-void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val)
+void address_space_stq_le(AddressSpace *as, hwaddr addr, uint64_t val,
+                       MemTxAttrs attrs, MemTxResult *result)
 {
+    MemTxResult r;
     val = cpu_to_le64(val);
-    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
+    r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
+    if (result) {
+        *result = r;
+    }
+}
+void address_space_stq_be(AddressSpace *as, hwaddr addr, uint64_t val,
+                       MemTxAttrs attrs, MemTxResult *result)
+{
+    MemTxResult r;
+    val = cpu_to_be64(val);
+    r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
+    if (result) {
+        *result = r;
+    }
+}
+
+void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val)
+{
+    address_space_stq(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
+}
+
+void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val)
+{
+    address_space_stq_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val)
 {
-    val = cpu_to_be64(val);
-    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
+    address_space_stq_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 /* virtual memory access for debug (includes writing to ROM) */
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 4d6afc8..0a048ab 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1134,6 +1134,69 @@ MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
 MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
                                uint8_t *buf, int len);
 
+/**
+ * address_space_ld*: load from an address space
+ * address_space_st*: store to an address space
+ *
+ * These functions perform a load or store of the byte, word,
+ * longword or quad to the specified address within the AddressSpace.
+ * The _le suffixed functions treat the data as little endian;
+ * _be indicates big endian; no suffix indicates "same endianness
+ * as guest CPU".
+ *
+ * @as #AddressSpace to be accessed
+ * @addr: address within that address space
+ * @val: data value, for stores
+ * @attrs: memory transaction attributes
+ * @result: location to write the success/failure of the transaction;
+ *   if NULL, this information is discarded
+ */
+uint32_t address_space_ldub(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result);
+uint32_t address_space_lduw_le(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result);
+uint32_t address_space_lduw_be(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result);
+uint32_t address_space_ldl_le(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result);
+uint32_t address_space_ldl_be(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result);
+uint64_t address_space_ldq_le(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result);
+uint64_t address_space_ldq_be(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stb(AddressSpace *as, hwaddr addr, uint32_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stw_le(AddressSpace *as, hwaddr addr, uint32_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stw_be(AddressSpace *as, hwaddr addr, uint32_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stl_le(AddressSpace *as, hwaddr addr, uint32_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stl_be(AddressSpace *as, hwaddr addr, uint32_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stq_le(AddressSpace *as, hwaddr addr, uint64_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stq_be(AddressSpace *as, hwaddr addr, uint64_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+
+#ifdef NEED_CPU_H
+uint32_t address_space_lduw(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result);
+uint32_t address_space_ldl(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result);
+uint64_t address_space_ldq(AddressSpace *as, hwaddr addr,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
+                            MemTxAttrs attrs, MemTxResult *result);
+#endif
+
 /* address_space_translate: translate an address range into an address space
  * into a MemoryRegion and an address range into that section
  *
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 08/14] Switch non-CPU callers from ld/st*_phys to address_space_ld/st*
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (6 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-09 10:44   ` Edgar E. Iglesias
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 09/14] exec.c: Capture the memory attributes for a watchpoint hit Peter Maydell
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Switch all the uses of ld/st*_phys to address_space_ld/st*,
except for those cases where the address space is the CPU's
(ie cs->as). This was done with the following script which
generates a Coccinelle patch.

A few over-80-columns lines in the result were rewrapped by
hand where Coccinelle failed to do the wrapping automatically,
as well as one location where it didn't put a line-continuation
'\' when wrapping lines on a change made to a match inside
a macro definition.

===begin===
#!/bin/sh -e
# Usage:
# ./ldst-phys.spatch.sh > ldst-phys.spatch
# spatch -sp_file ldst-phys.spatch -dir . | sed -e '/^+/s/\t/        /g' > out.patch
# patch -p1 < out.patch

for FN in ub uw_le uw_be l_le l_be q_le q_be uw l q; do
cat <<EOF
@ cpu_matches_ld_${FN} @
expression E1,E2;
identifier as;
@@

ld${FN}_phys(E1->as,E2)

@ other_matches_ld_${FN} depends on !cpu_matches_ld_${FN} @
expression E1,E2;
@@

-ld${FN}_phys(E1,E2)
+address_space_ld${FN}(E1,E2, MEMTXATTRS_UNSPECIFIED, NULL)

EOF

done

for FN in b w_le w_be l_le l_be q_le q_be w l q; do
cat <<EOF
@ cpu_matches_st_${FN} @
expression E1,E2,E3;
identifier as;
@@

st${FN}_phys(E1->as,E2,E3)

@ other_matches_st_${FN} depends on !cpu_matches_st_${FN} @
expression E1,E2,E3;
@@

-st${FN}_phys(E1,E2,E3)
+address_space_st${FN}(E1,E2,E3, MEMTXATTRS_UNSPECIFIED, NULL)

EOF

done
===endit===

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 exec.c                            | 18 +++++---
 hw/alpha/dp264.c                  |  9 ++--
 hw/alpha/typhoon.c                |  3 +-
 hw/arm/boot.c                     |  6 ++-
 hw/arm/highbank.c                 | 12 ++++--
 hw/dma/pl080.c                    | 20 +++++++--
 hw/dma/sun4m_iommu.c              |  3 +-
 hw/i386/intel_iommu.c             |  3 +-
 hw/pci-host/apb.c                 |  3 +-
 hw/pci/msi.c                      |  3 +-
 hw/pci/msix.c                     |  3 +-
 hw/s390x/css.c                    | 19 ++++++---
 hw/s390x/s390-pci-bus.c           |  9 ++--
 hw/s390x/s390-virtio-bus.c        | 73 +++++++++++++++++++++-----------
 hw/s390x/s390-virtio.c            |  4 +-
 hw/s390x/virtio-ccw.c             | 87 +++++++++++++++++++++++++++------------
 hw/sh4/r2d.c                      |  6 ++-
 hw/timer/hpet.c                   |  5 ++-
 monitor.c                         |  3 +-
 target-i386/arch_memory_mapping.c | 15 +++----
 20 files changed, 207 insertions(+), 97 deletions(-)

diff --git a/exec.c b/exec.c
index 013032a..a0d18ee 100644
--- a/exec.c
+++ b/exec.c
@@ -1910,9 +1910,12 @@ static uint64_t watch_mem_read(void *opaque, hwaddr addr,
 {
     check_watchpoint(addr & ~TARGET_PAGE_MASK, size, 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: 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);
     default: abort();
     }
 }
@@ -1923,13 +1926,16 @@ static void watch_mem_write(void *opaque, hwaddr addr,
     check_watchpoint(addr & ~TARGET_PAGE_MASK, size, BP_MEM_WRITE);
     switch (size) {
     case 1:
-        stb_phys(&address_space_memory, addr, val);
+        address_space_stb(&address_space_memory, addr, val,
+                          MEMTXATTRS_UNSPECIFIED, NULL);
         break;
     case 2:
-        stw_phys(&address_space_memory, addr, val);
+        address_space_stw(&address_space_memory, addr, val,
+                          MEMTXATTRS_UNSPECIFIED, NULL);
         break;
     case 4:
-        stl_phys(&address_space_memory, addr, val);
+        address_space_stl(&address_space_memory, addr, val,
+                          MEMTXATTRS_UNSPECIFIED, NULL);
         break;
     default: abort();
     }
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index e82d61d..9fe7e8b 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -157,9 +157,12 @@ static void clipper_init(MachineState *machine)
             load_image_targphys(initrd_filename, initrd_base,
                                 ram_size - initrd_base);
 
-            stq_phys(&address_space_memory,
-                     param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL);
-            stq_phys(&address_space_memory, param_offset + 0x108, initrd_size);
+            address_space_stq(&address_space_memory, param_offset + 0x100,
+                              initrd_base + 0xfffffc0000000000ULL,
+                              MEMTXATTRS_UNSPECIFIED,
+                              NULL);
+            address_space_stq(&address_space_memory, param_offset + 0x108,
+                              initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
         }
     }
 }
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index 62af946..e6ac993 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -613,7 +613,8 @@ static bool make_iommu_tlbe(hwaddr taddr, hwaddr mask, IOMMUTLBEntry *ret)
    translation, given the address of the PTE.  */
 static bool pte_translate(hwaddr pte_addr, IOMMUTLBEntry *ret)
 {
-    uint64_t pte = ldq_phys(&address_space_memory, pte_addr);
+    uint64_t pte = address_space_ldq(&address_space_memory, pte_addr,
+                                     MEMTXATTRS_UNSPECIFIED, NULL);
 
     /* Check valid bit.  */
     if ((pte & 1) == 0) {
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index a48d1b2..fa69503 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -170,7 +170,8 @@ static void default_reset_secondary(ARMCPU *cpu,
 {
     CPUARMState *env = &cpu->env;
 
-    stl_phys_notdirty(&address_space_memory, info->smp_bootreg_addr, 0);
+    address_space_stl_notdirty(&address_space_memory, info->smp_bootreg_addr,
+                               0, MEMTXATTRS_UNSPECIFIED, NULL);
     env->regs[15] = info->smp_loader_start;
 }
 
@@ -180,7 +181,8 @@ static inline bool have_dtb(const struct arm_boot_info *info)
 }
 
 #define WRITE_WORD(p, value) do { \
-    stl_phys_notdirty(&address_space_memory, p, value);  \
+    address_space_stl_notdirty(&address_space_memory, p, value, \
+                               MEMTXATTRS_UNSPECIFIED, NULL);  \
     p += 4;                       \
 } while (0)
 
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index 07cb4e0..00167c9 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -69,11 +69,17 @@ static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
 
     switch (info->nb_cpus) {
     case 4:
-        stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x30, 0);
+        address_space_stl_notdirty(&address_space_memory,
+                                   SMP_BOOT_REG + 0x30, 0,
+                                   MEMTXATTRS_UNSPECIFIED, NULL);
     case 3:
-        stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x20, 0);
+        address_space_stl_notdirty(&address_space_memory,
+                                   SMP_BOOT_REG + 0x20, 0,
+                                   MEMTXATTRS_UNSPECIFIED, NULL);
     case 2:
-        stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x10, 0);
+        address_space_stl_notdirty(&address_space_memory,
+                                   SMP_BOOT_REG + 0x10, 0,
+                                   MEMTXATTRS_UNSPECIFIED, NULL);
         env->regs[15] = SMP_BOOT_ADDR;
         break;
     default:
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
index 741dd20..b89b474 100644
--- a/hw/dma/pl080.c
+++ b/hw/dma/pl080.c
@@ -205,10 +205,22 @@ again:
             if (size == 0) {
                 /* Transfer complete.  */
                 if (ch->lli) {
-                    ch->src = ldl_le_phys(&address_space_memory, ch->lli);
-                    ch->dest = ldl_le_phys(&address_space_memory, ch->lli + 4);
-                    ch->ctrl = ldl_le_phys(&address_space_memory, ch->lli + 12);
-                    ch->lli = ldl_le_phys(&address_space_memory, ch->lli + 8);
+                    ch->src = address_space_ldl_le(&address_space_memory,
+                                                   ch->lli,
+                                                   MEMTXATTRS_UNSPECIFIED,
+                                                   NULL);
+                    ch->dest = address_space_ldl_le(&address_space_memory,
+                                                    ch->lli + 4,
+                                                    MEMTXATTRS_UNSPECIFIED,
+                                                    NULL);
+                    ch->ctrl = address_space_ldl_le(&address_space_memory,
+                                                    ch->lli + 12,
+                                                    MEMTXATTRS_UNSPECIFIED,
+                                                    NULL);
+                    ch->lli = address_space_ldl_le(&address_space_memory,
+                                                   ch->lli + 8,
+                                                   MEMTXATTRS_UNSPECIFIED,
+                                                   NULL);
                 } else {
                     ch->conf &= ~PL080_CCONF_E;
                 }
diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c
index ec7c2ef..9a488bc 100644
--- a/hw/dma/sun4m_iommu.c
+++ b/hw/dma/sun4m_iommu.c
@@ -263,7 +263,8 @@ static uint32_t iommu_page_get_flags(IOMMUState *s, hwaddr addr)
     iopte = s->regs[IOMMU_BASE] << 4;
     addr &= ~s->iostart;
     iopte += (addr >> (IOMMU_PAGE_SHIFT - 2)) & ~3;
-    ret = ldl_be_phys(&address_space_memory, iopte);
+    ret = address_space_ldl_be(&address_space_memory, iopte,
+                               MEMTXATTRS_UNSPECIFIED, NULL);
     trace_sun4m_iommu_page_get_flags(pa, iopte, ret);
     return ret;
 }
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 7da70ff..08055a8 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -246,7 +246,8 @@ static void vtd_generate_interrupt(IntelIOMMUState *s, hwaddr mesg_addr_reg,
     data = vtd_get_long_raw(s, mesg_data_reg);
 
     VTD_DPRINTF(FLOG, "msi: addr 0x%"PRIx64 " data 0x%"PRIx32, addr, data);
-    stl_le_phys(&address_space_memory, addr, data);
+    address_space_stl_le(&address_space_memory, addr, data,
+                         MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 /* Generate a fault event to software via MSI if conditions are met.
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 312fa70..599768e 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -289,7 +289,8 @@ static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
         }
     }
 
-    tte = ldq_be_phys(&address_space_memory, baseaddr + offset);
+    tte = address_space_ldq_be(&address_space_memory, baseaddr + offset,
+                               MEMTXATTRS_UNSPECIFIED, NULL);
 
     if (!(tte & IOMMU_TTE_DATA_V)) {
         /* Invalid mapping */
diff --git a/hw/pci/msi.c b/hw/pci/msi.c
index 52d2313..916e1a1 100644
--- a/hw/pci/msi.c
+++ b/hw/pci/msi.c
@@ -291,7 +291,8 @@ void msi_notify(PCIDevice *dev, unsigned int vector)
                    "notify vector 0x%x"
                    " address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
                    vector, msg.address, msg.data);
-    stl_le_phys(&dev->bus_master_as, msg.address, msg.data);
+    address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
+                         MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 /* Normally called by pci_default_write_config(). */
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index 24de260..031eaab 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -435,7 +435,8 @@ void msix_notify(PCIDevice *dev, unsigned vector)
 
     msg = msix_get_message(dev, vector);
 
-    stl_le_phys(&dev->bus_master_as, msg.address, msg.data);
+    address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
+                         MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 void msix_reset(PCIDevice *dev)
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 9a13b00..5561d80 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -745,20 +745,27 @@ static void css_update_chnmon(SubchDev *sch)
         /* Format 1, per-subchannel area. */
         uint32_t count;
 
-        count = ldl_phys(&address_space_memory, sch->curr_status.mba);
+        count = address_space_ldl(&address_space_memory,
+                                  sch->curr_status.mba,
+                                  MEMTXATTRS_UNSPECIFIED,
+                                  NULL);
         count++;
-        stl_phys(&address_space_memory, sch->curr_status.mba, count);
+        address_space_stl(&address_space_memory, sch->curr_status.mba, count,
+                          MEMTXATTRS_UNSPECIFIED, NULL);
     } else {
         /* Format 0, global area. */
         uint32_t offset;
         uint16_t count;
 
         offset = sch->curr_status.pmcw.mbi << 5;
-        count = lduw_phys(&address_space_memory,
-                          channel_subsys->chnmon_area + offset);
+        count = address_space_lduw(&address_space_memory,
+                                   channel_subsys->chnmon_area + offset,
+                                   MEMTXATTRS_UNSPECIFIED,
+                                   NULL);
         count++;
-        stw_phys(&address_space_memory,
-                 channel_subsys->chnmon_area + offset, count);
+        address_space_stw(&address_space_memory,
+                          channel_subsys->chnmon_area + offset, count,
+                          MEMTXATTRS_UNSPECIFIED, NULL);
     }
 }
 
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 3c086f6..560b66a 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -278,7 +278,8 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota,
     px = calc_px(guest_dma_address);
 
     sto_a = guest_iota + rtx * sizeof(uint64_t);
-    sto = ldq_phys(&address_space_memory, sto_a);
+    sto = address_space_ldq(&address_space_memory, sto_a,
+                            MEMTXATTRS_UNSPECIFIED, NULL);
     sto = get_rt_sto(sto);
     if (!sto) {
         pte = 0;
@@ -286,7 +287,8 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota,
     }
 
     pto_a = sto + sx * sizeof(uint64_t);
-    pto = ldq_phys(&address_space_memory, pto_a);
+    pto = address_space_ldq(&address_space_memory, pto_a,
+                            MEMTXATTRS_UNSPECIFIED, NULL);
     pto = get_st_pto(pto);
     if (!pto) {
         pte = 0;
@@ -294,7 +296,8 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota,
     }
 
     px_a = pto + px * sizeof(uint64_t);
-    pte = ldq_phys(&address_space_memory, px_a);
+    pte = address_space_ldq(&address_space_memory, px_a,
+                            MEMTXATTRS_UNSPECIFIED, NULL);
 
 out:
     return pte;
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 047c963..0f93a64 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -75,10 +75,12 @@ void s390_virtio_reset_idx(VirtIOS390Device *dev)
     for (i = 0; i < num_vq; i++) {
         idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) +
             VIRTIO_VRING_AVAIL_IDX_OFFS;
-        stw_phys(&address_space_memory, idx_addr, 0);
+        address_space_stw(&address_space_memory, idx_addr, 0,
+                          MEMTXATTRS_UNSPECIFIED, NULL);
         idx_addr = virtio_queue_get_used_addr(dev->vdev, i) +
             VIRTIO_VRING_USED_IDX_OFFS;
-        stw_phys(&address_space_memory, idx_addr, 0);
+        address_space_stw(&address_space_memory, idx_addr, 0,
+                          MEMTXATTRS_UNSPECIFIED, NULL);
     }
 }
 
@@ -336,7 +338,8 @@ static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
                 (vq * VIRTIO_VQCONFIG_LEN) +
                 VIRTIO_VQCONFIG_OFFS_TOKEN;
 
-    return ldq_be_phys(&address_space_memory, token_off);
+    return address_space_ldq_be(&address_space_memory, token_off,
+                                MEMTXATTRS_UNSPECIFIED, NULL);
 }
 
 static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev)
@@ -371,21 +374,33 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
     virtio_reset(dev->vdev);
 
     /* Sync dev space */
-    stb_phys(&address_space_memory,
-             dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, dev->vdev->device_id);
-
-    stb_phys(&address_space_memory,
-             dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ,
-             s390_virtio_device_num_vq(dev));
-    stb_phys(&address_space_memory,
-             dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, dev->feat_len);
-
-    stb_phys(&address_space_memory,
-             dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, dev->vdev->config_len);
+    address_space_stb(&address_space_memory,
+                      dev->dev_offs + VIRTIO_DEV_OFFS_TYPE,
+                      dev->vdev->device_id,
+                      MEMTXATTRS_UNSPECIFIED,
+                      NULL);
+
+    address_space_stb(&address_space_memory,
+                      dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ,
+                      s390_virtio_device_num_vq(dev),
+                      MEMTXATTRS_UNSPECIFIED,
+                      NULL);
+    address_space_stb(&address_space_memory,
+                      dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN,
+                      dev->feat_len,
+                      MEMTXATTRS_UNSPECIFIED,
+                      NULL);
+
+    address_space_stb(&address_space_memory,
+                      dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN,
+                      dev->vdev->config_len,
+                      MEMTXATTRS_UNSPECIFIED,
+                      NULL);
 
     num_vq = s390_virtio_device_num_vq(dev);
-    stb_phys(&address_space_memory,
-             dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq);
+    address_space_stb(&address_space_memory,
+                      dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq,
+                      MEMTXATTRS_UNSPECIFIED, NULL);
 
     /* Sync virtqueues */
     for (i = 0; i < num_vq; i++) {
@@ -396,11 +411,14 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
         vring = s390_virtio_next_ring(bus);
         virtio_queue_set_addr(dev->vdev, i, vring);
         virtio_queue_set_vector(dev->vdev, i, i);
-        stq_be_phys(&address_space_memory,
-                    vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring);
-        stw_be_phys(&address_space_memory,
-                    vq + VIRTIO_VQCONFIG_OFFS_NUM,
-                    virtio_queue_get_num(dev->vdev, i));
+        address_space_stq_be(&address_space_memory,
+                             vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring,
+                             MEMTXATTRS_UNSPECIFIED, NULL);
+        address_space_stw_be(&address_space_memory,
+                             vq + VIRTIO_VQCONFIG_OFFS_NUM,
+                             virtio_queue_get_num(dev->vdev, i),
+                             MEMTXATTRS_UNSPECIFIED,
+                             NULL);
     }
 
     cur_offs = dev->dev_offs;
@@ -408,7 +426,8 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
     cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
 
     /* Sync feature bitmap */
-    stl_le_phys(&address_space_memory, cur_offs, dev->host_features);
+    address_space_stl_le(&address_space_memory, cur_offs, dev->host_features,
+                         MEMTXATTRS_UNSPECIFIED, NULL);
 
     dev->feat_offs = cur_offs + dev->feat_len;
     cur_offs += dev->feat_len * 2;
@@ -426,12 +445,16 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
     VirtIODevice *vdev = dev->vdev;
     uint32_t features;
 
-    virtio_set_status(vdev, ldub_phys(&address_space_memory,
-                                      dev->dev_offs + VIRTIO_DEV_OFFS_STATUS));
+    virtio_set_status(vdev,
+                      address_space_ldub(&address_space_memory,
+                                         dev->dev_offs + VIRTIO_DEV_OFFS_STATUS,
+                                         MEMTXATTRS_UNSPECIFIED, NULL));
 
     /* Update guest supported feature bitmap */
 
-    features = bswap32(ldl_be_phys(&address_space_memory, dev->feat_offs));
+    features = bswap32(address_space_ldl_be(&address_space_memory,
+                                            dev->feat_offs,
+                                            MEMTXATTRS_UNSPECIFIED, NULL));
     virtio_set_features(vdev, features);
 }
 
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index bdb5388..3a1b9ee 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -97,7 +97,9 @@ static int s390_virtio_hcall_reset(const uint64_t *args)
         return -EINVAL;
     }
     virtio_reset(dev->vdev);
-    stb_phys(&address_space_memory, dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
+    address_space_stb(&address_space_memory,
+                      dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0,
+                      MEMTXATTRS_UNSPECIFIED, NULL);
     s390_virtio_device_sync(dev);
     s390_virtio_reset_idx(dev);
 
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index d32ecaf..ed75c63 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -335,16 +335,23 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            info.queue = ldq_phys(&address_space_memory, ccw.cda);
-            info.align = ldl_phys(&address_space_memory,
-                                  ccw.cda + sizeof(info.queue));
-            info.index = lduw_phys(&address_space_memory,
-                                   ccw.cda + sizeof(info.queue)
-                                   + sizeof(info.align));
-            info.num = lduw_phys(&address_space_memory,
-                                 ccw.cda + sizeof(info.queue)
-                                 + sizeof(info.align)
-                                 + sizeof(info.index));
+            info.queue = address_space_ldq(&address_space_memory, ccw.cda,
+                                           MEMTXATTRS_UNSPECIFIED, NULL);
+            info.align = address_space_ldl(&address_space_memory,
+                                           ccw.cda + sizeof(info.queue),
+                                           MEMTXATTRS_UNSPECIFIED,
+                                           NULL);
+            info.index = address_space_lduw(&address_space_memory,
+                                            ccw.cda + sizeof(info.queue)
+                                            + sizeof(info.align),
+                                            MEMTXATTRS_UNSPECIFIED,
+                                            NULL);
+            info.num = address_space_lduw(&address_space_memory,
+                                          ccw.cda + sizeof(info.queue)
+                                          + sizeof(info.align)
+                                          + sizeof(info.index),
+                                          MEMTXATTRS_UNSPECIFIED,
+                                          NULL);
             ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index,
                                      info.num);
             sch->curr_status.scsw.count = 0;
@@ -369,15 +376,20 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            features.index = ldub_phys(&address_space_memory,
-                                       ccw.cda + sizeof(features.features));
+            features.index = address_space_ldub(&address_space_memory,
+                                                ccw.cda
+                                                + sizeof(features.features),
+                                                MEMTXATTRS_UNSPECIFIED,
+                                                NULL);
             if (features.index < ARRAY_SIZE(dev->host_features)) {
                 features.features = dev->host_features[features.index];
             } else {
                 /* Return zeroes if the guest supports more feature bits. */
                 features.features = 0;
             }
-            stl_le_phys(&address_space_memory, ccw.cda, features.features);
+            address_space_stl_le(&address_space_memory, ccw.cda,
+                                 features.features, MEMTXATTRS_UNSPECIFIED,
+                                 NULL);
             sch->curr_status.scsw.count = ccw.count - sizeof(features);
             ret = 0;
         }
@@ -396,9 +408,15 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            features.index = ldub_phys(&address_space_memory,
-                                       ccw.cda + sizeof(features.features));
-            features.features = ldl_le_phys(&address_space_memory, ccw.cda);
+            features.index = address_space_ldub(&address_space_memory,
+                                                ccw.cda
+                                                + sizeof(features.features),
+                                                MEMTXATTRS_UNSPECIFIED,
+                                                NULL);
+            features.features = address_space_ldl_le(&address_space_memory,
+                                                     ccw.cda,
+                                                     MEMTXATTRS_UNSPECIFIED,
+                                                     NULL);
             if (features.index < ARRAY_SIZE(dev->host_features)) {
                 virtio_set_features(vdev, features.features);
             } else {
@@ -474,7 +492,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            status = ldub_phys(&address_space_memory, ccw.cda);
+            status = address_space_ldub(&address_space_memory, ccw.cda,
+                                        MEMTXATTRS_UNSPECIFIED, NULL);
             if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
                 virtio_ccw_stop_ioeventfd(dev);
             }
@@ -508,7 +527,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            indicators = ldq_be_phys(&address_space_memory, ccw.cda);
+            indicators = address_space_ldq_be(&address_space_memory, ccw.cda,
+                                              MEMTXATTRS_UNSPECIFIED, NULL);
             dev->indicators = get_indicator(indicators, sizeof(uint64_t));
             sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
             ret = 0;
@@ -528,7 +548,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            indicators = ldq_be_phys(&address_space_memory, ccw.cda);
+            indicators = address_space_ldq_be(&address_space_memory, ccw.cda,
+                                              MEMTXATTRS_UNSPECIFIED, NULL);
             dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
             sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
             ret = 0;
@@ -548,15 +569,21 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            vq_config.index = lduw_be_phys(&address_space_memory, ccw.cda);
+            vq_config.index = address_space_lduw_be(&address_space_memory,
+                                                    ccw.cda,
+                                                    MEMTXATTRS_UNSPECIFIED,
+                                                    NULL);
             if (vq_config.index >= VIRTIO_PCI_QUEUE_MAX) {
                 ret = -EINVAL;
                 break;
             }
             vq_config.num_max = virtio_queue_get_num(vdev,
                                                      vq_config.index);
-            stw_be_phys(&address_space_memory,
-                        ccw.cda + sizeof(vq_config.index), vq_config.num_max);
+            address_space_stw_be(&address_space_memory,
+                                 ccw.cda + sizeof(vq_config.index),
+                                 vq_config.num_max,
+                                 MEMTXATTRS_UNSPECIFIED,
+                                 NULL);
             sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
             ret = 0;
         }
@@ -1068,9 +1095,13 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
                 css_adapter_interrupt(dev->thinint_isc);
             }
         } else {
-            indicators = ldq_phys(&address_space_memory, dev->indicators->addr);
+            indicators = address_space_ldq(&address_space_memory,
+                                           dev->indicators->addr,
+                                           MEMTXATTRS_UNSPECIFIED,
+                                           NULL);
             indicators |= 1ULL << vector;
-            stq_phys(&address_space_memory, dev->indicators->addr, indicators);
+            address_space_stq(&address_space_memory, dev->indicators->addr,
+                              indicators, MEMTXATTRS_UNSPECIFIED, NULL);
             css_conditional_io_interrupt(sch);
         }
     } else {
@@ -1078,9 +1109,13 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
             return;
         }
         vector = 0;
-        indicators = ldq_phys(&address_space_memory, dev->indicators2->addr);
+        indicators = address_space_ldq(&address_space_memory,
+                                       dev->indicators2->addr,
+                                       MEMTXATTRS_UNSPECIFIED,
+                                       NULL);
         indicators |= 1ULL << vector;
-        stq_phys(&address_space_memory, dev->indicators2->addr, indicators);
+        address_space_stq(&address_space_memory, dev->indicators2->addr,
+                          indicators, MEMTXATTRS_UNSPECIFIED, NULL);
         css_conditional_io_interrupt(sch);
     }
 }
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index d1d0847..4221060 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -318,8 +318,10 @@ static void r2d_init(MachineState *machine)
         }
 
         /* initialization which should be done by firmware */
-        stl_phys(&address_space_memory, SH7750_BCR1, 1<<3); /* cs3 SDRAM */
-        stw_phys(&address_space_memory, SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
+        address_space_stl(&address_space_memory, SH7750_BCR1, 1 << 3,
+                          MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 SDRAM */
+        address_space_stw(&address_space_memory, SH7750_BCR2, 3 << (3 * 2),
+                          MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 32bit */
         reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
     }
 
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index 78d86be..b6b8a20 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -206,8 +206,9 @@ static void update_irq(struct HPETTimer *timer, int set)
             }
         }
     } else if (timer_fsb_route(timer)) {
-        stl_le_phys(&address_space_memory,
-                    timer->fsb >> 32, timer->fsb & 0xffffffff);
+        address_space_stl_le(&address_space_memory, timer->fsb >> 32,
+                             timer->fsb & 0xffffffff, MEMTXATTRS_UNSPECIFIED,
+                             NULL);
     } else if (timer->config & HPET_TN_TYPE_LEVEL) {
         s->isr |= mask;
         /* fold the ICH PIRQ# pin's internal inversion logic into hpet */
diff --git a/monitor.c b/monitor.c
index 68873ec..c7a4db6 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1385,7 +1385,8 @@ static void hmp_sum(Monitor *mon, const QDict *qdict)
 
     sum = 0;
     for(addr = start; addr < (start + size); addr++) {
-        uint8_t val = ldub_phys(&address_space_memory, addr);
+        uint8_t val = address_space_ldub(&address_space_memory, addr,
+                                         MEMTXATTRS_UNSPECIFIED, NULL);
         /* BSD sum algorithm ('sum' Unix command) */
         sum = (sum >> 1) | (sum << 15);
         sum += val;
diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
index 2d35f63..01563fe 100644
--- a/target-i386/arch_memory_mapping.c
+++ b/target-i386/arch_memory_mapping.c
@@ -27,7 +27,7 @@ static void walk_pte(MemoryMappingList *list, AddressSpace *as,
 
     for (i = 0; i < 512; i++) {
         pte_addr = (pte_start_addr + i * 8) & a20_mask;
-        pte = ldq_phys(as, pte_addr);
+        pte = address_space_ldq(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
         if (!(pte & PG_PRESENT_MASK)) {
             /* not present */
             continue;
@@ -57,7 +57,7 @@ static void walk_pte2(MemoryMappingList *list, AddressSpace *as,
 
     for (i = 0; i < 1024; i++) {
         pte_addr = (pte_start_addr + i * 4) & a20_mask;
-        pte = ldl_phys(as, pte_addr);
+        pte = address_space_ldl(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
         if (!(pte & PG_PRESENT_MASK)) {
             /* not present */
             continue;
@@ -89,7 +89,7 @@ static void walk_pde(MemoryMappingList *list, AddressSpace *as,
 
     for (i = 0; i < 512; i++) {
         pde_addr = (pde_start_addr + i * 8) & a20_mask;
-        pde = ldq_phys(as, pde_addr);
+        pde = address_space_ldq(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
         if (!(pde & PG_PRESENT_MASK)) {
             /* not present */
             continue;
@@ -126,7 +126,7 @@ static void walk_pde2(MemoryMappingList *list, AddressSpace *as,
 
     for (i = 0; i < 1024; i++) {
         pde_addr = (pde_start_addr + i * 4) & a20_mask;
-        pde = ldl_phys(as, pde_addr);
+        pde = address_space_ldl(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
         if (!(pde & PG_PRESENT_MASK)) {
             /* not present */
             continue;
@@ -167,7 +167,7 @@ static void walk_pdpe2(MemoryMappingList *list, AddressSpace *as,
 
     for (i = 0; i < 4; i++) {
         pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
-        pdpe = ldq_phys(as, pdpe_addr);
+        pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
         if (!(pdpe & PG_PRESENT_MASK)) {
             /* not present */
             continue;
@@ -192,7 +192,7 @@ static void walk_pdpe(MemoryMappingList *list, AddressSpace *as,
 
     for (i = 0; i < 512; i++) {
         pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
-        pdpe = ldq_phys(as, pdpe_addr);
+        pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
         if (!(pdpe & PG_PRESENT_MASK)) {
             /* not present */
             continue;
@@ -228,7 +228,8 @@ static void walk_pml4e(MemoryMappingList *list, AddressSpace *as,
 
     for (i = 0; i < 512; i++) {
         pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
-        pml4e = ldq_phys(as, pml4e_addr);
+        pml4e = address_space_ldq(as, pml4e_addr, MEMTXATTRS_UNSPECIFIED,
+                                  NULL);
         if (!(pml4e & PG_PRESENT_MASK)) {
             /* not present */
             continue;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 09/14] exec.c: Capture the memory attributes for a watchpoint hit
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (7 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 08/14] Switch non-CPU callers from ld/st*_phys to address_space_ld/st* Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-08 11:04   ` Paolo Bonzini
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 10/14] target-arm: Honour NS bits in page tables Peter Maydell
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

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(-)

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;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 10/14] target-arm: Honour NS bits in page tables
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (8 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 09/14] exec.c: Capture the memory attributes for a watchpoint hit Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-09 11:23   ` Edgar E. Iglesias
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 11/14] target-arm: Use correct memory attributes for page table walks Peter Maydell
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Honour the NS bit in ARM page tables:
 * when adding entries to the TLB, include the Secure/NonSecure
   transaction attribute
 * set the NS bit in the PAR when doing ATS operations

Note that we don't yet correctly use the NSTable bit to
cause the page table walk itself to use the right attributes.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/exec/memattrs.h |  3 ++
 target-arm/helper.c     | 83 ++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 74 insertions(+), 12 deletions(-)

diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
index b8d7808..5df180e 100644
--- a/include/exec/memattrs.h
+++ b/include/exec/memattrs.h
@@ -24,6 +24,9 @@
  */
 typedef uint64_t MemTxAttrs;
 
+/* ARM/AMBA TrustZone Secure access */
+#define MEMTXATTRS_SECURE (1ULL << 0)
+
 /* Bus masters which don't specify any attributes will get this,
  * which has all attribute bits clear except the topmost one
  * (so that we can distinguish "all attributes deliberately clear"
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d77c6de..c359d0c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -14,7 +14,7 @@
 #ifndef CONFIG_USER_ONLY
 static inline int get_phys_addr(CPUARMState *env, target_ulong address,
                                 int access_type, ARMMMUIdx mmu_idx,
-                                hwaddr *phys_ptr, int *prot,
+                                hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
                                 target_ulong *page_size);
 
 /* Definitions for the PMCCNTR and PMCR registers */
@@ -1466,9 +1466,10 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
     int prot;
     int ret;
     uint64_t par64;
+    MemTxAttrs attrs;
 
     ret = get_phys_addr(env, value, access_type, mmu_idx,
-                        &phys_addr, &prot, &page_size);
+                        &phys_addr, &attrs, &prot, &page_size);
     if (extended_addresses_enabled(env)) {
         /* ret is a DFSR/IFSR value for the long descriptor
          * translation table format, but with WnR always clear.
@@ -1477,6 +1478,9 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
         par64 = (1 << 11); /* LPAE bit always set */
         if (ret == 0) {
             par64 |= phys_addr & ~0xfffULL;
+            if (!(attrs & MEMTXATTRS_SECURE)) {
+                par64 |= (1 << 9); /* NS */
+            }
             /* We don't set the ATTR or SH fields in the PAR. */
         } else {
             par64 |= 1; /* F */
@@ -1499,6 +1503,9 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
             } else {
                 par64 = phys_addr & 0xfffff000;
             }
+            if (!(attrs & MEMTXATTRS_SECURE)) {
+                par64 |= (1 << 9); /* NS */
+            }
         } else {
             par64 = ((ret & (1 << 10)) >> 5) | ((ret & (1 << 12)) >> 6) |
                     ((ret & 0xf) << 1) | 1;
@@ -4858,6 +4865,26 @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
     }
 }
 
+/* Return true if this address translation regime is secure */
+static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
+{
+    switch (mmu_idx) {
+    case ARMMMUIdx_S12NSE0:
+    case ARMMMUIdx_S12NSE1:
+    case ARMMMUIdx_S1NSE0:
+    case ARMMMUIdx_S1NSE1:
+    case ARMMMUIdx_S1E2:
+    case ARMMMUIdx_S2NS:
+        return false;
+    case ARMMMUIdx_S1E3:
+    case ARMMMUIdx_S1SE0:
+    case ARMMMUIdx_S1SE1:
+        return true;
+    default:
+        g_assert_not_reached();
+    }
+}
+
 /* Return the SCTLR value which controls this address translation regime */
 static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
 {
@@ -5210,6 +5237,7 @@ do_fault:
 
 static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
                             ARMMMUIdx mmu_idx, hwaddr *phys_ptr,
+                            MemTxAttrs *attrs,
                             int *prot, target_ulong *page_size)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
@@ -5224,6 +5252,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
     int domain_prot;
     hwaddr phys_addr;
     uint32_t dacr;
+    bool ns;
 
     /* Pagetable walk.  */
     /* Lookup l1 descriptor.  */
@@ -5273,10 +5302,12 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
         xn = desc & (1 << 4);
         pxn = desc & 1;
         code = 13;
+        ns = extract32(desc, 19, 1);
     } else {
         if (arm_feature(env, ARM_FEATURE_PXN)) {
             pxn = (desc >> 2) & 1;
         }
+        ns = extract32(desc, 3, 1);
         /* Lookup l2 entry.  */
         table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
         desc = ldl_phys(cs->as, table);
@@ -5330,6 +5361,13 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
             goto do_fault;
         }
     }
+    if (ns) {
+        /* The NS bit will (as required by the architecture) have no effect if
+         * the CPU doesn't support TZ or this is a non-secure translation
+         * regime, because the attribute will already be non-secure.
+         */
+        *attrs &= ~MEMTXATTRS_SECURE;
+    }
     *phys_ptr = phys_addr;
     return 0;
 do_fault:
@@ -5347,7 +5385,7 @@ typedef enum {
 
 static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
                               int access_type, ARMMMUIdx mmu_idx,
-                              hwaddr *phys_ptr, int *prot,
+                              hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
                               target_ulong *page_size_ptr)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
@@ -5552,6 +5590,13 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
         goto do_fault;
     }
 
+    if (ns) {
+        /* The NS bit will (as required by the architecture) have no effect if
+         * the CPU doesn't support TZ or this is a non-secure translation
+         * regime, because the attribute will already be non-secure.
+         */
+        *txattrs &= ~MEMTXATTRS_SECURE;
+    }
     *phys_ptr = descaddr;
     *page_size_ptr = page_size;
     return 0;
@@ -5635,8 +5680,8 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
  * by doing a translation table walk on MMU based systems or using the
  * MPU state on MPU based systems.
  *
- * Returns 0 if the translation was successful. Otherwise, phys_ptr,
- * prot and page_size are not filled in, and the return value provides
+ * Returns 0 if the translation was successful. Otherwise, phys_ptr, attrs,
+ * prot and page_size may not be filled in, and the return value provides
  * information on why the translation aborted, in the format of a
  * DFSR/IFSR fault register, with the following caveats:
  *  * we honour the short vs long DFSR format differences.
@@ -5649,12 +5694,13 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
  * @access_type: 0 for read, 1 for write, 2 for execute
  * @mmu_idx: MMU index indicating required translation regime
  * @phys_ptr: set to the physical address corresponding to the virtual address
+ * @attrs: set to the memory transaction attributes to use
  * @prot: set to the permissions for the page containing phys_ptr
  * @page_size: set to the size of the page containing phys_ptr
  */
 static inline int get_phys_addr(CPUARMState *env, target_ulong address,
                                 int access_type, ARMMMUIdx mmu_idx,
-                                hwaddr *phys_ptr, int *prot,
+                                hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
                                 target_ulong *page_size)
 {
     if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
@@ -5667,6 +5713,16 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
         mmu_idx += ARMMMUIdx_S1NSE0;
     }
 
+    if (regime_is_secure(env, mmu_idx)) {
+        /* The page table entries may downgrade this to non-secure, but
+         * cannot upgrade an non-secure translation regime's attributes
+         * to secure.
+         */
+        *attrs = MEMTXATTRS_SECURE;
+    } else {
+        *attrs = 0;
+    }
+
     /* Fast Context Switch Extension. This doesn't exist at all in v8.
      * In v7 and earlier it affects all stage 1 translations.
      */
@@ -5695,10 +5751,10 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
 
     if (regime_using_lpae_format(env, mmu_idx)) {
         return get_phys_addr_lpae(env, address, access_type, mmu_idx, phys_ptr,
-                                  prot, page_size);
+                                  attrs, prot, page_size);
     } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
         return get_phys_addr_v6(env, address, access_type, mmu_idx, phys_ptr,
-                                prot, page_size);
+                                attrs, prot, page_size);
     } else {
         return get_phys_addr_v5(env, address, access_type, mmu_idx, phys_ptr,
                                 prot, page_size);
@@ -5716,14 +5772,16 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
     int ret;
     uint32_t syn;
     bool same_el = (arm_current_el(env) != 0);
+    MemTxAttrs attrs;
 
-    ret = get_phys_addr(env, address, access_type, mmu_idx, &phys_addr, &prot,
-                        &page_size);
+    ret = get_phys_addr(env, address, access_type, mmu_idx, &phys_addr,
+                        &attrs, &prot, &page_size);
     if (ret == 0) {
         /* Map a single [sub]page.  */
         phys_addr &= TARGET_PAGE_MASK;
         address &= TARGET_PAGE_MASK;
-        tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size);
+        tlb_set_page_with_attrs(cs, address, phys_addr, attrs,
+                                prot, mmu_idx, page_size);
         return 0;
     }
 
@@ -5758,9 +5816,10 @@ hwaddr arm_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
     target_ulong page_size;
     int prot;
     int ret;
+    MemTxAttrs attrs;
 
     ret = get_phys_addr(env, addr, 0, cpu_mmu_index(env), &phys_addr,
-                        &prot, &page_size);
+                        &attrs, &prot, &page_size);
 
     if (ret != 0) {
         return -1;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 11/14] target-arm: Use correct memory attributes for page table walks
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (9 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 10/14] target-arm: Honour NS bits in page tables Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-09 11:34   ` Edgar E. Iglesias
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 12/14] target-arm: Add user-mode transaction attribute Peter Maydell
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Factor out the page table walk memory accesses into their own function,
so that we can specify the correct S/NS memory attributes for them.
This will also provide a place to use the correct endianness and
handle the need for a stage-2 translation when virtualization is
supported.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/helper.c | 47 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index c359d0c..fdeb2b7 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5129,6 +5129,27 @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
     return true;
 }
 
+/* All loads done in the course of a page table walk go through here.
+ * TODO: rather than ignoring errors from physical memory reads (which
+ * are external aborts in ARM terminology) we should propagate this
+ * error out so that we can turn it into a Data Abort if this walk
+ * was being done for a CPU load/store or an address translation instruction
+ * (but not if it was for a debug access).
+ */
+static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure)
+{
+    MemTxAttrs attrs = is_secure ? MEMTXATTRS_SECURE : 0;
+
+    return address_space_ldl(cs->as, addr, attrs, NULL);
+}
+
+static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure)
+{
+    MemTxAttrs attrs = is_secure ? MEMTXATTRS_SECURE : 0;
+
+    return address_space_ldq(cs->as, addr, attrs, NULL);
+}
+
 static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
                             ARMMMUIdx mmu_idx, hwaddr *phys_ptr,
                             int *prot, target_ulong *page_size)
@@ -5151,7 +5172,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
         code = 5;
         goto do_fault;
     }
-    desc = ldl_phys(cs->as, table);
+    desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
     type = (desc & 3);
     domain = (desc >> 5) & 0x0f;
     if (regime_el(env, mmu_idx) == 1) {
@@ -5187,7 +5208,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
             /* Fine pagetable.  */
             table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
         }
-        desc = ldl_phys(cs->as, table);
+        desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
         switch (desc & 3) {
         case 0: /* Page translation fault.  */
             code = 7;
@@ -5261,7 +5282,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
         code = 5;
         goto do_fault;
     }
-    desc = ldl_phys(cs->as, table);
+    desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
     type = (desc & 3);
     if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
         /* Section translation fault, or attempt to use the encoding
@@ -5310,7 +5331,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
         ns = extract32(desc, 3, 1);
         /* Lookup l2 entry.  */
         table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
-        desc = ldl_phys(cs->as, table);
+        desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
         ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
         switch (desc & 3) {
         case 0: /* Page translation fault.  */
@@ -5525,13 +5546,20 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
     descaddr = extract64(ttbr, 0, 48);
     descaddr &= ~((1ULL << (va_size - tsz - (granule_sz * (4 - level)))) - 1);
 
-    tableattrs = 0;
+    /* Secure accesses start with the page table in secure memory and
+     * can be downgraded to non-secure at any step. Non-secure accesses
+     * remain non-secure. We implement this by just ORing in the NSTable/NS
+     * bits at each step.
+     */
+    tableattrs = regime_is_secure(env, mmu_idx) ? 0 : (1 << 4);
     for (;;) {
         uint64_t descriptor;
+        bool nstable;
 
         descaddr |= (address >> (granule_sz * (4 - level))) & descmask;
         descaddr &= ~7ULL;
-        descriptor = ldq_phys(cs->as, descaddr);
+        nstable = extract32(tableattrs, 4, 1);
+        descriptor = arm_ldq_ptw(cs, descaddr, !nstable);
         if (!(descriptor & 1) ||
             (!(descriptor & 2) && (level == 3))) {
             /* Invalid, or the Reserved level 3 encoding */
@@ -5566,7 +5594,7 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
         if (extract32(tableattrs, 2, 1)) {
             attrs &= ~(1 << 4);
         }
-        attrs |= extract32(tableattrs, 4, 1) << 3; /* NS */
+        attrs |= nstable << 3; /* NS */
         break;
     }
     /* Here descaddr is the final physical address, and attributes
@@ -5705,8 +5733,9 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
 {
     if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
         /* TODO: when we support EL2 we should here call ourselves recursively
-         * to do the stage 1 and then stage 2 translations. The ldl_phys
-         * calls for stage 1 will also need changing.
+         * to do the stage 1 and then stage 2 translations. The arm_ld*_ptw
+         * functions will also need changing to perform ARMMMUIdx_S2NS loads
+         * rather than direct physical memory loads when appropriate.
          * For non-EL2 CPUs a stage1+stage2 translation is just stage 1.
          */
         assert(!arm_feature(env, ARM_FEATURE_EL2));
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 12/14] target-arm: Add user-mode transaction attribute
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (10 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 11/14] target-arm: Use correct memory attributes for page table walks Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 13/14] target-arm: Use attribute info to handle user-only watchpoints Peter Maydell
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Add a transaction attribute indicating that a memory access is being
done from user-mode (unprivileged). This corresponds to an equivalent
signal in ARM AMBA buses.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/exec/memattrs.h | 3 +++
 target-arm/helper.c     | 4 ++++
 2 files changed, 7 insertions(+)

diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
index 5df180e..458c0ea 100644
--- a/include/exec/memattrs.h
+++ b/include/exec/memattrs.h
@@ -27,6 +27,9 @@ typedef uint64_t MemTxAttrs;
 /* ARM/AMBA TrustZone Secure access */
 #define MEMTXATTRS_SECURE (1ULL << 0)
 
+/* Memory access is usermode (unprivileged) */
+#define MEMTXATTRS_USER (1ULL << 1)
+
 /* Bus masters which don't specify any attributes will get this,
  * which has all attribute bits clear except the topmost one
  * (so that we can distinguish "all attributes deliberately clear"
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fdeb2b7..6fca8f8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5752,6 +5752,10 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
         *attrs = 0;
     }
 
+    if (regime_is_user(env, mmu_idx)) {
+        *attrs |= MEMTXATTRS_USER;
+    }
+
     /* Fast Context Switch Extension. This doesn't exist at all in v8.
      * In v7 and earlier it affects all stage 1 translations.
      */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 13/14] target-arm: Use attribute info to handle user-only watchpoints
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (11 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 12/14] target-arm: Add user-mode transaction attribute Peter Maydell
@ 2015-04-07 20:09 ` Peter Maydell
  2015-04-09 11:37   ` Edgar E. Iglesias
  2015-04-07 20:10 ` [Qemu-devel] [PATCH 14/14] target-arm: Check watchpoints against CPU security state Peter Maydell
  2015-04-09  9:37 ` [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Edgar E. Iglesias
  14 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Now that we have memory access attribute information in the watchpoint
checking code, we can correctly implement handling of watchpoints
which should match only on userspace accesses, where LDRT/STRT/LDT/STT
from EL1 are treated as userspace accesses.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/op_helper.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 7713022..ce09ab3 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -602,13 +602,22 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
     int pac, hmc, ssc, wt, lbn;
     /* TODO: check against CPU security state when we implement TrustZone */
     bool is_secure = false;
+    int access_el = arm_current_el(env);
 
     if (is_wp) {
-        if (!env->cpu_watchpoint[n]
-            || !(env->cpu_watchpoint[n]->flags & BP_WATCHPOINT_HIT)) {
+        CPUWatchpoint *wp = env->cpu_watchpoint[n];
+
+        if (!wp || !(wp->flags & BP_WATCHPOINT_HIT)) {
             return false;
         }
         cr = env->cp15.dbgwcr[n];
+        if (wp->hitattrs & MEMTXATTRS_USER) {
+            /* The LDRT/STRT/LDT/STT "unprivileged access" instructions should
+             * match watchpoints as if they were accesses done at EL0, even if
+             * the CPU is at EL1 or higher.
+             */
+            access_el = 0;
+        }
     } else {
         uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
 
@@ -649,15 +658,7 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
         break;
     }
 
-    /* TODO: this is not strictly correct because the LDRT/STRT/LDT/STT
-     * "unprivileged access" instructions should match watchpoints as if
-     * they were accesses done at EL0, even if the CPU is at EL1 or higher.
-     * Implementing this would require reworking the core watchpoint code
-     * to plumb the mmu_idx through to this point. Luckily Linux does not
-     * rely on this behaviour currently.
-     * For breakpoints we do want to use the current CPU state.
-     */
-    switch (arm_current_el(env)) {
+    switch (access_el) {
     case 3:
     case 2:
         if (!hmc) {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PATCH 14/14] target-arm: Check watchpoints against CPU security state
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (12 preceding siblings ...)
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 13/14] target-arm: Use attribute info to handle user-only watchpoints Peter Maydell
@ 2015-04-07 20:10 ` Peter Maydell
  2015-04-09 11:38   ` Edgar E. Iglesias
  2015-04-09  9:37 ` [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Edgar E. Iglesias
  14 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-07 20:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Crosthwaite, patches, Edgar E. Iglesias, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

Fix a TODO in bp_wp_matches() now that we have a function for
testing whether the CPU is currently in Secure mode or not.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/op_helper.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index ce09ab3..d8a1054 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -600,8 +600,10 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
     CPUARMState *env = &cpu->env;
     uint64_t cr;
     int pac, hmc, ssc, wt, lbn;
-    /* TODO: check against CPU security state when we implement TrustZone */
-    bool is_secure = false;
+    /* Note that for watchpoints the check is against the CPU security
+     * state, not the S/NS attribute on the offending data access.
+     */
+    bool is_secure = arm_is_secure(env);
     int access_el = arm_current_el(env);
 
     if (is_wp) {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status Peter Maydell
@ 2015-04-08 10:49   ` Paolo Bonzini
  2015-04-09  8:55   ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-08 10:49 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Peter Crosthwaite, patches, Greg Bellows, Edgar E. Iglesias,
	Alex Bennée, Richard Henderson



On 07/04/2015 22:09, Peter Maydell wrote:
> Define an API so that devices can register MemoryRegionOps whose read
> and write callback functions are passed an arbitrary pointer to some
> transaction attributes and can return a success-or-failure status code.
> This will allow us to model devices which:
>  * behave differently for ARM Secure/NonSecure memory accesses
>  * behave differently for privileged/unprivileged accesses
>  * may return a transaction failure (causing a guest exception)
>    for erroneous accesses
> 
> This patch defines the new API and plumbs the attributes parameter through
> to the memory.c public level functions io_mem_read() and io_mem_write(),
> where it is currently dummied out.
> 
> The success/failure response indication is also propagated out to
> io_mem_read() and io_mem_write(), which retain the old-style
> boolean true-for-error return.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  include/exec/memattrs.h |  34 ++++++++
>  include/exec/memory.h   |  22 +++++
>  memory.c                | 207 ++++++++++++++++++++++++++++++++----------------
>  3 files changed, 196 insertions(+), 67 deletions(-)
>  create mode 100644 include/exec/memattrs.h
> 
> diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
> new file mode 100644
> index 0000000..b8d7808
> --- /dev/null
> +++ b/include/exec/memattrs.h
> @@ -0,0 +1,34 @@
> +/*
> + * Memory transaction attributes
> + *
> + * Copyright (c) 2015 Linaro Limited.
> + *
> + * Authors:
> + *  Peter Maydell <peter.maydell@linaro.org>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#ifndef MEMATTRS_H
> +#define MEMATTRS_H
> +
> +/* Every memory transaction has associated with it a set of
> + * attributes. Some of these are generic (such as the ID of
> + * the bus master); some are specific to a particular kind of
> + * bus (such as the ARM Secure/NonSecure bit). We define them
> + * all as non-overlapping bits in a single integer to avoid
> + * confusion if different parts of QEMU used the same bit for
> + * different semantics.
> + */
> +typedef uint64_t MemTxAttrs;
> +
> +/* Bus masters which don't specify any attributes will get this,
> + * which has all attribute bits clear except the topmost one
> + * (so that we can distinguish "all attributes deliberately clear"
> + * from "didn't specify" if necessary).
> + */
> +#define MEMTXATTRS_UNSPECIFIED (1ULL << 63)
> +
> +#endif
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 06ffa1d..703d9e5 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -28,6 +28,7 @@
>  #ifndef CONFIG_USER_ONLY
>  #include "exec/hwaddr.h"
>  #endif
> +#include "exec/memattrs.h"
>  #include "qemu/queue.h"
>  #include "qemu/int128.h"
>  #include "qemu/notify.h"
> @@ -68,6 +69,16 @@ struct IOMMUTLBEntry {
>      IOMMUAccessFlags perm;
>  };
>  
> +/* New-style MMIO accessors can indicate that the transaction failed.
> + * A zero (MEMTX_OK) response means success; anything else is a failure
> + * of some kind. The memory subsystem will bitwise-OR together results
> + * if it is synthesizing an operation from multiple smaller accesses.
> + */
> +#define MEMTX_OK 0
> +#define MEMTX_ERROR             (1U << 0) /* device returned an error */
> +#define MEMTX_DECODE_ERROR      (1U << 1) /* nothing at that address */
> +typedef uint32_t MemTxResult;
> +
>  /*
>   * Memory region callbacks
>   */
> @@ -84,6 +95,17 @@ struct MemoryRegionOps {
>                    uint64_t data,
>                    unsigned size);
>  
> +    MemTxResult (*read_with_attrs)(void *opaque,
> +                                   hwaddr addr,
> +                                   uint64_t *data,
> +                                   unsigned size,
> +                                   MemTxAttrs attrs);
> +    MemTxResult (*write_with_attrs)(void *opaque,
> +                                    hwaddr addr,
> +                                    uint64_t data,
> +                                    unsigned size,
> +                                    MemTxAttrs attrs);
> +
>      enum device_endian endianness;
>      /* Guest-visible constraints: */
>      struct {
> diff --git a/memory.c b/memory.c
> index ee3f2a8..9bb5674 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -368,57 +368,84 @@ static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
>      }
>  }
>  
> -static void memory_region_oldmmio_read_accessor(MemoryRegion *mr,
> +static MemTxResult memory_region_oldmmio_read_accessor(MemoryRegion *mr,
> +                                                       hwaddr addr,
> +                                                       uint64_t *value,
> +                                                       unsigned size,
> +                                                       unsigned shift,
> +                                                       uint64_t mask,
> +                                                       MemTxAttrs attrs)
> +{
> +    uint64_t tmp;
> +
> +    tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
> +    trace_memory_region_ops_read(mr, addr, tmp, size);
> +    *value |= (tmp & mask) << shift;
> +    return MEMTX_OK;
> +}
> +
> +static MemTxResult  memory_region_read_accessor(MemoryRegion *mr,
>                                                  hwaddr addr,
>                                                  uint64_t *value,
>                                                  unsigned size,
>                                                  unsigned shift,
> -                                                uint64_t mask)
> +                                                uint64_t mask,
> +                                                MemTxAttrs attrs)
>  {
>      uint64_t tmp;
>  
> -    tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
> +    if (mr->flush_coalesced_mmio) {
> +        qemu_flush_coalesced_mmio_buffer();
> +    }
> +    tmp = mr->ops->read(mr->opaque, addr, size);
>      trace_memory_region_ops_read(mr, addr, tmp, size);
>      *value |= (tmp & mask) << shift;
> +    return MEMTX_OK;
>  }
>  
> -static void memory_region_read_accessor(MemoryRegion *mr,
> -                                        hwaddr addr,
> -                                        uint64_t *value,
> -                                        unsigned size,
> -                                        unsigned shift,
> -                                        uint64_t mask)
> +static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr,
> +                                                          hwaddr addr,
> +                                                          uint64_t *value,
> +                                                          unsigned size,
> +                                                          unsigned shift,
> +                                                          uint64_t mask,
> +                                                          MemTxAttrs attrs)
>  {
> -    uint64_t tmp;
> +    uint64_t tmp = 0;
> +    MemTxResult r;
>  
>      if (mr->flush_coalesced_mmio) {
>          qemu_flush_coalesced_mmio_buffer();
>      }
> -    tmp = mr->ops->read(mr->opaque, addr, size);
> +    r = mr->ops->read_with_attrs(mr->opaque, addr, &tmp, size, attrs);
>      trace_memory_region_ops_read(mr, addr, tmp, size);
>      *value |= (tmp & mask) << shift;
> +    return r;
>  }
>  
> -static void memory_region_oldmmio_write_accessor(MemoryRegion *mr,
> -                                                 hwaddr addr,
> -                                                 uint64_t *value,
> -                                                 unsigned size,
> -                                                 unsigned shift,
> -                                                 uint64_t mask)
> +static MemTxResult memory_region_oldmmio_write_accessor(MemoryRegion *mr,
> +                                                        hwaddr addr,
> +                                                        uint64_t *value,
> +                                                        unsigned size,
> +                                                        unsigned shift,
> +                                                        uint64_t mask,
> +                                                        MemTxAttrs attrs)
>  {
>      uint64_t tmp;
>  
>      tmp = (*value >> shift) & mask;
>      trace_memory_region_ops_write(mr, addr, tmp, size);
>      mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp);
> +    return MEMTX_OK;
>  }
>  
> -static void memory_region_write_accessor(MemoryRegion *mr,
> -                                         hwaddr addr,
> -                                         uint64_t *value,
> -                                         unsigned size,
> -                                         unsigned shift,
> -                                         uint64_t mask)
> +static MemTxResult memory_region_write_accessor(MemoryRegion *mr,
> +                                                hwaddr addr,
> +                                                uint64_t *value,
> +                                                unsigned size,
> +                                                unsigned shift,
> +                                                uint64_t mask,
> +                                                MemTxAttrs attrs)
>  {
>      uint64_t tmp;
>  
> @@ -428,24 +455,46 @@ static void memory_region_write_accessor(MemoryRegion *mr,
>      tmp = (*value >> shift) & mask;
>      trace_memory_region_ops_write(mr, addr, tmp, size);
>      mr->ops->write(mr->opaque, addr, tmp, size);
> +    return MEMTX_OK;
>  }
>  
> -static void access_with_adjusted_size(hwaddr addr,
> +static MemTxResult memory_region_write_with_attrs_accessor(MemoryRegion *mr,
> +                                                           hwaddr addr,
> +                                                           uint64_t *value,
> +                                                           unsigned size,
> +                                                           unsigned shift,
> +                                                           uint64_t mask,
> +                                                           MemTxAttrs attrs)
> +{
> +    uint64_t tmp;
> +
> +    if (mr->flush_coalesced_mmio) {
> +        qemu_flush_coalesced_mmio_buffer();
> +    }
> +    tmp = (*value >> shift) & mask;
> +    trace_memory_region_ops_write(mr, addr, tmp, size);
> +    return mr->ops->write_with_attrs(mr->opaque, addr, tmp, size, attrs);
> +}
> +
> +static MemTxResult access_with_adjusted_size(hwaddr addr,
>                                        uint64_t *value,
>                                        unsigned size,
>                                        unsigned access_size_min,
>                                        unsigned access_size_max,
> -                                      void (*access)(MemoryRegion *mr,
> -                                                     hwaddr addr,
> -                                                     uint64_t *value,
> -                                                     unsigned size,
> -                                                     unsigned shift,
> -                                                     uint64_t mask),
> -                                      MemoryRegion *mr)
> +                                      MemTxResult (*access)(MemoryRegion *mr,
> +                                                            hwaddr addr,
> +                                                            uint64_t *value,
> +                                                            unsigned size,
> +                                                            unsigned shift,
> +                                                            uint64_t mask,
> +                                                            MemTxAttrs attrs),
> +                                      MemoryRegion *mr,
> +                                      MemTxAttrs attrs)
>  {
>      uint64_t access_mask;
>      unsigned access_size;
>      unsigned i;
> +    MemTxResult r = MEMTX_OK;
>  
>      if (!access_size_min) {
>          access_size_min = 1;
> @@ -459,14 +508,16 @@ static void access_with_adjusted_size(hwaddr addr,
>      access_mask = -1ULL >> (64 - access_size * 8);
>      if (memory_region_big_endian(mr)) {
>          for (i = 0; i < size; i += access_size) {
> -            access(mr, addr + i, value, access_size,
> -                   (size - access_size - i) * 8, access_mask);
> +            r |= access(mr, addr + i, value, access_size,
> +                        (size - access_size - i) * 8, access_mask, attrs);
>          }
>      } else {
>          for (i = 0; i < size; i += access_size) {
> -            access(mr, addr + i, value, access_size, i * 8, access_mask);
> +            r |= access(mr, addr + i, value, access_size, i * 8,
> +                        access_mask, attrs);
>          }
>      }
> +    return r;
>  }
>  
>  static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
> @@ -1053,62 +1104,82 @@ bool memory_region_access_valid(MemoryRegion *mr,
>      return true;
>  }
>  
> -static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
> -                                             hwaddr addr,
> -                                             unsigned size)
> +static MemTxResult memory_region_dispatch_read1(MemoryRegion *mr,
> +                                                hwaddr addr,
> +                                                uint64_t *pval,
> +                                                unsigned size,
> +                                                MemTxAttrs attrs)
>  {
> -    uint64_t data = 0;
> +    *pval = 0;
>  
>      if (mr->ops->read) {
> -        access_with_adjusted_size(addr, &data, size,
> -                                  mr->ops->impl.min_access_size,
> -                                  mr->ops->impl.max_access_size,
> -                                  memory_region_read_accessor, mr);
> +        return access_with_adjusted_size(addr, pval, size,
> +                                         mr->ops->impl.min_access_size,
> +                                         mr->ops->impl.max_access_size,
> +                                         memory_region_read_accessor,
> +                                         mr, attrs);
> +    } else if (mr->ops->read_with_attrs) {
> +        return access_with_adjusted_size(addr, pval, size,
> +                                         mr->ops->impl.min_access_size,
> +                                         mr->ops->impl.max_access_size,
> +                                         memory_region_read_with_attrs_accessor,
> +                                         mr, attrs);
>      } else {
> -        access_with_adjusted_size(addr, &data, size, 1, 4,
> -                                  memory_region_oldmmio_read_accessor, mr);
> +        return access_with_adjusted_size(addr, pval, size, 1, 4,
> +                                         memory_region_oldmmio_read_accessor,
> +                                         mr, attrs);
>      }
> -
> -    return data;
>  }
>  
> -static bool memory_region_dispatch_read(MemoryRegion *mr,
> -                                        hwaddr addr,
> -                                        uint64_t *pval,
> -                                        unsigned size)
> +static MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
> +                                               hwaddr addr,
> +                                               uint64_t *pval,
> +                                               unsigned size,
> +                                               MemTxAttrs attrs)
>  {
> +    MemTxResult r;
> +
>      if (!memory_region_access_valid(mr, addr, size, false)) {
>          *pval = unassigned_mem_read(mr, addr, size);
> -        return true;
> +        return MEMTX_DECODE_ERROR;
>      }
>  
> -    *pval = memory_region_dispatch_read1(mr, addr, size);
> +    r = memory_region_dispatch_read1(mr, addr, pval, size, attrs);
>      adjust_endianness(mr, pval, size);
> -    return false;
> +    return r;
>  }
>  
> -static bool memory_region_dispatch_write(MemoryRegion *mr,
> -                                         hwaddr addr,
> -                                         uint64_t data,
> -                                         unsigned size)
> +static MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
> +                                                hwaddr addr,
> +                                                uint64_t data,
> +                                                unsigned size,
> +                                                MemTxAttrs attrs)
>  {
>      if (!memory_region_access_valid(mr, addr, size, true)) {
>          unassigned_mem_write(mr, addr, data, size);
> -        return true;
> +        return MEMTX_DECODE_ERROR;
>      }
>  
>      adjust_endianness(mr, &data, size);
>  
>      if (mr->ops->write) {
> -        access_with_adjusted_size(addr, &data, size,
> -                                  mr->ops->impl.min_access_size,
> -                                  mr->ops->impl.max_access_size,
> -                                  memory_region_write_accessor, mr);
> +        return access_with_adjusted_size(addr, &data, size,
> +                                         mr->ops->impl.min_access_size,
> +                                         mr->ops->impl.max_access_size,
> +                                         memory_region_write_accessor, mr,
> +                                         attrs);
> +    } else if (mr->ops->write_with_attrs) {
> +        return
> +            access_with_adjusted_size(addr, &data, size,
> +                                      mr->ops->impl.min_access_size,
> +                                      mr->ops->impl.max_access_size,
> +                                      memory_region_write_with_attrs_accessor,
> +                                      mr, attrs);
>      } else {
> -        access_with_adjusted_size(addr, &data, size, 1, 4,
> -                                  memory_region_oldmmio_write_accessor, mr);
> +        return access_with_adjusted_size(addr, &data, size, 1, 4,
> +                                         memory_region_oldmmio_write_accessor,
> +                                         mr, attrs);
>      }
> -    return false;
>  }
>  
>  void memory_region_init_io(MemoryRegion *mr,
> @@ -1994,13 +2065,15 @@ void address_space_destroy(AddressSpace *as)
>  
>  bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size)
>  {
> -    return memory_region_dispatch_read(mr, addr, pval, size);
> +    return memory_region_dispatch_read(mr, addr, pval, size,
> +                                       MEMTXATTRS_UNSPECIFIED);
>  }
>  
>  bool io_mem_write(MemoryRegion *mr, hwaddr addr,
>                    uint64_t val, unsigned size)
>  {
> -    return memory_region_dispatch_write(mr, addr, val, size);
> +    return memory_region_dispatch_write(mr, addr, val, size,
> +                                        MEMTXATTRS_UNSPECIFIED);
>  }
>  
>  typedef struct MemoryRegionList MemoryRegionList;
> 

Will conflict with
http://lists.gnu.org/archive/html/qemu-devel/2015-03/msg03954.html but
not a huge problem.

Acked-by: Paolo Bonzini <pbonzini@redhat.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 02/14] memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 02/14] memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write Peter Maydell
@ 2015-04-08 10:51   ` Paolo Bonzini
  2015-04-08 10:59     ` Peter Maydell
  2015-04-09  8:59   ` Edgar E. Iglesias
  1 sibling, 1 reply; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-08 10:51 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Peter Crosthwaite, patches, Greg Bellows, Edgar E. Iglesias,
	Alex Bennée, Richard Henderson



On 07/04/2015 22:09, Peter Maydell wrote:
> Add a MemTxAttrs argument to the io_mem_read() and io_mem_write()
> functions, and make them return MemTxResult rather than bool,
> thus pushing these new arguments out one level of the callstack
> (all the callers callers currently pass MEMTXATTRS_UNSPECIFIED
> and convert the return value back to bool or ignore it).
> 
> Note that this involves moving the io_mem_read and io_mem_write
> prototypes from exec-all.h to memory.h. This allows them to
> see the MemTxResult type, and is a better location anyway,
> since they are implemented in memory.c and are operations on
> MemoryRegions.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  exec.c                   | 33 +++++++++++++++++----------------
>  hw/s390x/s390-pci-inst.c |  7 ++++---
>  hw/vfio/pci.c            |  4 ++--
>  include/exec/exec-all.h  |  4 ----
>  include/exec/memory.h    | 12 ++++++++++++
>  memory.c                 | 13 ++++++-------
>  softmmu_template.h       |  4 ++--
>  7 files changed, 43 insertions(+), 34 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index 874ecfc..52e7a2a 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2312,7 +2312,8 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>      uint64_t val;
>      hwaddr addr1;
>      MemoryRegion *mr;
> -    bool error = false;
> +    MemTxResult result = MEMTX_OK;
> +    MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
>  
>      while (len > 0) {
>          l = len;
> @@ -2327,22 +2328,22 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>                  case 8:
>                      /* 64 bit write access */
>                      val = ldq_p(buf);
> -                    error |= io_mem_write(mr, addr1, val, 8);
> +                    result |= io_mem_write(mr, addr1, val, 8, attrs);
>                      break;
>                  case 4:
>                      /* 32 bit write access */
>                      val = ldl_p(buf);
> -                    error |= io_mem_write(mr, addr1, val, 4);
> +                    result |= io_mem_write(mr, addr1, val, 4, attrs);
>                      break;
>                  case 2:
>                      /* 16 bit write access */
>                      val = lduw_p(buf);
> -                    error |= io_mem_write(mr, addr1, val, 2);
> +                    result |= io_mem_write(mr, addr1, val, 2, attrs);
>                      break;
>                  case 1:
>                      /* 8 bit write access */
>                      val = ldub_p(buf);
> -                    error |= io_mem_write(mr, addr1, val, 1);
> +                    result |= io_mem_write(mr, addr1, val, 1, attrs);
>                      break;
>                  default:
>                      abort();
> @@ -2361,22 +2362,22 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>                  switch (l) {
>                  case 8:
>                      /* 64 bit read access */
> -                    error |= io_mem_read(mr, addr1, &val, 8);
> +                    result |= io_mem_read(mr, addr1, &val, 8, attrs);
>                      stq_p(buf, val);
>                      break;
>                  case 4:
>                      /* 32 bit read access */
> -                    error |= io_mem_read(mr, addr1, &val, 4);
> +                    result |= io_mem_read(mr, addr1, &val, 4, attrs);
>                      stl_p(buf, val);
>                      break;
>                  case 2:
>                      /* 16 bit read access */
> -                    error |= io_mem_read(mr, addr1, &val, 2);
> +                    result |= io_mem_read(mr, addr1, &val, 2, attrs);
>                      stw_p(buf, val);
>                      break;
>                  case 1:
>                      /* 8 bit read access */
> -                    error |= io_mem_read(mr, addr1, &val, 1);
> +                    result |= io_mem_read(mr, addr1, &val, 1, attrs);
>                      stb_p(buf, val);
>                      break;
>                  default:
> @@ -2393,7 +2394,7 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>          addr += l;
>      }
>  
> -    return error;
> +    return result;
>  }
>  
>  bool address_space_write(AddressSpace *as, hwaddr addr,
> @@ -2669,7 +2670,7 @@ static inline uint32_t ldl_phys_internal(AddressSpace *as, hwaddr addr,
>      mr = address_space_translate(as, addr, &addr1, &l, false);
>      if (l < 4 || !memory_access_is_direct(mr, false)) {
>          /* I/O case */
> -        io_mem_read(mr, addr1, &val, 4);
> +        io_mem_read(mr, addr1, &val, 4, MEMTXATTRS_UNSPECIFIED);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap32(val);
> @@ -2728,7 +2729,7 @@ static inline uint64_t ldq_phys_internal(AddressSpace *as, hwaddr addr,
>                                   false);
>      if (l < 8 || !memory_access_is_direct(mr, false)) {
>          /* I/O case */
> -        io_mem_read(mr, addr1, &val, 8);
> +        io_mem_read(mr, addr1, &val, 8, MEMTXATTRS_UNSPECIFIED);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap64(val);
> @@ -2795,7 +2796,7 @@ static inline uint32_t lduw_phys_internal(AddressSpace *as, hwaddr addr,
>                                   false);
>      if (l < 2 || !memory_access_is_direct(mr, false)) {
>          /* I/O case */
> -        io_mem_read(mr, addr1, &val, 2);
> +        io_mem_read(mr, addr1, &val, 2, MEMTXATTRS_UNSPECIFIED);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap16(val);
> @@ -2853,7 +2854,7 @@ void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
>      mr = address_space_translate(as, addr, &addr1, &l,
>                                   true);
>      if (l < 4 || !memory_access_is_direct(mr, true)) {
> -        io_mem_write(mr, addr1, val, 4);
> +        io_mem_write(mr, addr1, val, 4, MEMTXATTRS_UNSPECIFIED);
>      } else {
>          addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
>          ptr = qemu_get_ram_ptr(addr1);
> @@ -2892,7 +2893,7 @@ static inline void stl_phys_internal(AddressSpace *as,
>              val = bswap32(val);
>          }
>  #endif
> -        io_mem_write(mr, addr1, val, 4);
> +        io_mem_write(mr, addr1, val, 4, MEMTXATTRS_UNSPECIFIED);
>      } else {
>          /* RAM case */
>          addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
> @@ -2955,7 +2956,7 @@ static inline void stw_phys_internal(AddressSpace *as,
>              val = bswap16(val);
>          }
>  #endif
> -        io_mem_write(mr, addr1, val, 2);
> +        io_mem_write(mr, addr1, val, 2, MEMTXATTRS_UNSPECIFIED);
>      } else {
>          /* RAM case */
>          addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
> diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
> index 08d8aa6..78ff9c0 100644
> --- a/hw/s390x/s390-pci-inst.c
> +++ b/hw/s390x/s390-pci-inst.c
> @@ -331,7 +331,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
>              return 0;
>          }
>          MemoryRegion *mr = pbdev->pdev->io_regions[pcias].memory;
> -        io_mem_read(mr, offset, &data, len);
> +        io_mem_read(mr, offset, &data, len, MEMTXATTRS_UNSPECIFIED);
>      } else if (pcias == 15) {
>          if ((4 - (offset & 0x3)) < len) {
>              program_interrupt(env, PGM_OPERAND, 4);
> @@ -456,7 +456,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
>              mr = pbdev->pdev->io_regions[pcias].memory;
>          }
>  
> -        io_mem_write(mr, offset, data, len);
> +        io_mem_write(mr, offset, data, len, MEMTXATTRS_UNSPECIFIED);
>      } else if (pcias == 15) {
>          if ((4 - (offset & 0x3)) < len) {
>              program_interrupt(env, PGM_OPERAND, 4);
> @@ -606,7 +606,8 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr)
>      }
>  
>      for (i = 0; i < len / 8; i++) {
> -        io_mem_write(mr, env->regs[r3] + i * 8, ldq_p(buffer + i * 8), 8);
> +        io_mem_write(mr, env->regs[r3] + i * 8, ldq_p(buffer + i * 8), 8,
> +                     MEMTXATTRS_UNSPECIFIED);
>      }
>  
>      setcc(cpu, ZPCI_PCI_LS_OK);
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index 6b80539..3e1df0c 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -1533,7 +1533,7 @@ static uint64_t vfio_rtl8168_window_quirk_read(void *opaque,
>  
>              io_mem_read(&vdev->pdev.msix_table_mmio,
>                          (hwaddr)(quirk->data.address_match & 0xfff),
> -                        &val, size);
> +                        &val, size, MEMTXATTRS_UNSPECIFIED);
>              return val;
>          }
>      }
> @@ -1563,7 +1563,7 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr,
>  
>                  io_mem_write(&vdev->pdev.msix_table_mmio,
>                               (hwaddr)(quirk->data.address_match & 0xfff),
> -                             data, size);
> +                             data, size, MEMTXATTRS_UNSPECIFIED);
>              }
>  
>              quirk->data.flags = 1;
> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index 8eb0db3..ff1bc3e 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -341,10 +341,6 @@ void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
>  
>  struct MemoryRegion *iotlb_to_region(CPUState *cpu,
>                                       hwaddr index);
> -bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
> -                 uint64_t *pvalue, unsigned size);
> -bool io_mem_write(struct MemoryRegion *mr, hwaddr addr,
> -                  uint64_t value, unsigned size);
>  
>  void tlb_fill(CPUState *cpu, target_ulong addr, int is_write, int mmu_idx,
>                uintptr_t retaddr);
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 703d9e5..de2849d 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -1053,6 +1053,18 @@ void memory_global_dirty_log_stop(void);
>  void mtree_info(fprintf_function mon_printf, void *f);
>  
>  /**
> + * io_mem_read: perform an IO read directly to the specified MemoryRegion
> + */
> +MemTxResult io_mem_read(struct MemoryRegion *mr, hwaddr addr,
> +                        uint64_t *pvalue, unsigned size, MemTxAttrs attrs);
> +
> +/**
> + * io_mem_write: perform an IO write directly to the specified MemoryRegion
> + */
> +MemTxResult io_mem_write(struct MemoryRegion *mr, hwaddr addr,
> +                         uint64_t value, unsigned size, MemTxAttrs attrs);
> +
> +/**
>   * address_space_init: initializes an address space
>   *
>   * @as: an uninitialized #AddressSpace
> diff --git a/memory.c b/memory.c
> index 9bb5674..14cda7f 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -2063,17 +2063,16 @@ void address_space_destroy(AddressSpace *as)
>      call_rcu(as, do_address_space_destroy, rcu);
>  }
>  
> -bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size)
> +MemTxResult io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval,
> +                        unsigned size, MemTxAttrs attrs)
>  {
> -    return memory_region_dispatch_read(mr, addr, pval, size,
> -                                       MEMTXATTRS_UNSPECIFIED);
> +    return memory_region_dispatch_read(mr, addr, pval, size, attrs);
>  }
>  
> -bool io_mem_write(MemoryRegion *mr, hwaddr addr,
> -                  uint64_t val, unsigned size)
> +MemTxResult io_mem_write(MemoryRegion *mr, hwaddr addr,
> +                         uint64_t val, unsigned size, MemTxAttrs attrs)
>  {
> -    return memory_region_dispatch_write(mr, addr, val, size,
> -                                        MEMTXATTRS_UNSPECIFIED);
> +    return memory_region_dispatch_write(mr, addr, val, size, attrs);
>  }
>  
>  typedef struct MemoryRegionList MemoryRegionList;
> diff --git a/softmmu_template.h b/softmmu_template.h
> index 0e3dd35..4b9bae7 100644
> --- a/softmmu_template.h
> +++ b/softmmu_template.h
> @@ -158,7 +158,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
>      }
>  
>      cpu->mem_io_vaddr = addr;
> -    io_mem_read(mr, physaddr, &val, 1 << SHIFT);
> +    io_mem_read(mr, physaddr, &val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
>      return val;
>  }
>  #endif
> @@ -378,7 +378,7 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
>  
>      cpu->mem_io_vaddr = addr;
>      cpu->mem_io_pc = retaddr;
> -    io_mem_write(mr, physaddr, val, 1 << SHIFT);
> +    io_mem_write(mr, physaddr, val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
>  }
>  
>  void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
> 

This could be the occasion to drop io_mem_read/io_mem_write and use
memory_region_dispatch_read/memory_region_dispatch_write altogether.  As
you prefer.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 03/14] Make CPU iotlb a structure rather than a plain hwaddr
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 03/14] Make CPU iotlb a structure rather than a plain hwaddr Peter Maydell
@ 2015-04-08 10:52   ` Paolo Bonzini
  2015-04-09  9:02   ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-08 10:52 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Peter Crosthwaite, patches, Greg Bellows, Edgar E. Iglesias,
	Alex Bennée, Richard Henderson



On 07/04/2015 22:09, Peter Maydell wrote:
> Make the CPU iotlb a structure rather than a plain hwaddr;
> this will allow us to add transaction attributes to it.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  cputlb.c                |  4 ++--
>  include/exec/cpu-defs.h | 13 +++++++++++--
>  softmmu_template.h      | 32 +++++++++++++++++---------------
>  3 files changed, 30 insertions(+), 19 deletions(-)
> 
> diff --git a/cputlb.c b/cputlb.c
> index 38f2151..5e1cb8f 100644
> --- a/cputlb.c
> +++ b/cputlb.c
> @@ -301,7 +301,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
>      env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
>  
>      /* refill the tlb */
> -    env->iotlb[mmu_idx][index] = iotlb - vaddr;
> +    env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
>      te->addend = addend - vaddr;
>      if (prot & PAGE_READ) {
>          te->addr_read = address;
> @@ -349,7 +349,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
>                   (addr & TARGET_PAGE_MASK))) {
>          cpu_ldub_code(env1, addr);
>      }
> -    pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
> +    pd = env1->iotlb[mmu_idx][page_index].addr & ~TARGET_PAGE_MASK;
>      mr = iotlb_to_region(cpu, pd);
>      if (memory_region_is_unassigned(mr)) {
>          CPUClass *cc = CPU_GET_CLASS(cpu);
> diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
> index 0ca6f0b..7f88185 100644
> --- a/include/exec/cpu-defs.h
> +++ b/include/exec/cpu-defs.h
> @@ -102,12 +102,21 @@ typedef struct CPUTLBEntry {
>  
>  QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
>  
> +/* The IOTLB is not accessed directly inline by generated TCG code,
> + * so the CPUIOTLBEntry layout is not as critical as that of the
> + * CPUTLBEntry. (This is also why we don't want to combine the two
> + * structs into one.)
> + */
> +typedef struct CPUIOTLBEntry {
> +    hwaddr addr;
> +} CPUIOTLBEntry;
> +
>  #define CPU_COMMON_TLB \
>      /* The meaning of the MMU modes is defined in the target code. */   \
>      CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE];                  \
>      CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE];               \
> -    hwaddr iotlb[NB_MMU_MODES][CPU_TLB_SIZE];                           \
> -    hwaddr iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE];                        \
> +    CPUIOTLBEntry iotlb[NB_MMU_MODES][CPU_TLB_SIZE];                    \
> +    CPUIOTLBEntry iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE];                 \
>      target_ulong tlb_flush_addr;                                        \
>      target_ulong tlb_flush_mask;                                        \
>      target_ulong vtlb_index;                                            \
> diff --git a/softmmu_template.h b/softmmu_template.h
> index 4b9bae7..7a36550 100644
> --- a/softmmu_template.h
> +++ b/softmmu_template.h
> @@ -123,7 +123,7 @@
>       * victim tlb. try to refill from the victim tlb before walking the       \
>       * page table. */                                                         \
>      int vidx;                                                                 \
> -    hwaddr tmpiotlb;                                                          \
> +    CPUIOTLBEntry tmpiotlb;                                                   \
>      CPUTLBEntry tmptlb;                                                       \
>      for (vidx = CPU_VTLB_SIZE-1; vidx >= 0; --vidx) {                         \
>          if (env->tlb_v_table[mmu_idx][vidx].ty == (addr & TARGET_PAGE_MASK)) {\
> @@ -143,12 +143,13 @@
>  
>  #ifndef SOFTMMU_CODE_ACCESS
>  static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
> -                                              hwaddr physaddr,
> +                                              CPUIOTLBEntry *iotlbentry,
>                                                target_ulong addr,
>                                                uintptr_t retaddr)
>  {
>      uint64_t val;
>      CPUState *cpu = ENV_GET_CPU(env);
> +    hwaddr physaddr = iotlbentry->addr;
>      MemoryRegion *mr = iotlb_to_region(cpu, physaddr);
>  
>      physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
> @@ -195,15 +196,15 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
>  
>      /* Handle an IO access.  */
>      if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
> -        hwaddr ioaddr;
> +        CPUIOTLBEntry *iotlbentry;
>          if ((addr & (DATA_SIZE - 1)) != 0) {
>              goto do_unaligned_access;
>          }
> -        ioaddr = env->iotlb[mmu_idx][index];
> +        iotlbentry = &env->iotlb[mmu_idx][index];
>  
>          /* ??? Note that the io helpers always read data in the target
>             byte ordering.  We should push the LE/BE request down into io.  */
> -        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
> +        res = glue(io_read, SUFFIX)(env, iotlbentry, addr, retaddr);
>          res = TGT_LE(res);
>          return res;
>      }
> @@ -283,15 +284,15 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
>  
>      /* Handle an IO access.  */
>      if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
> -        hwaddr ioaddr;
> +        CPUIOTLBEntry *iotlbentry;
>          if ((addr & (DATA_SIZE - 1)) != 0) {
>              goto do_unaligned_access;
>          }
> -        ioaddr = env->iotlb[mmu_idx][index];
> +        iotlbentry = &env->iotlb[mmu_idx][index];
>  
>          /* ??? Note that the io helpers always read data in the target
>             byte ordering.  We should push the LE/BE request down into io.  */
> -        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
> +        res = glue(io_read, SUFFIX)(env, iotlbentry, addr, retaddr);
>          res = TGT_BE(res);
>          return res;
>      }
> @@ -363,12 +364,13 @@ WORD_TYPE helper_be_lds_name(CPUArchState *env, target_ulong addr,
>  #endif
>  
>  static inline void glue(io_write, SUFFIX)(CPUArchState *env,
> -                                          hwaddr physaddr,
> +                                          CPUIOTLBEntry *iotlbentry,
>                                            DATA_TYPE val,
>                                            target_ulong addr,
>                                            uintptr_t retaddr)
>  {
>      CPUState *cpu = ENV_GET_CPU(env);
> +    hwaddr physaddr = iotlbentry->addr;
>      MemoryRegion *mr = iotlb_to_region(cpu, physaddr);
>  
>      physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
> @@ -408,16 +410,16 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
>  
>      /* Handle an IO access.  */
>      if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
> -        hwaddr ioaddr;
> +        CPUIOTLBEntry *iotlbentry;
>          if ((addr & (DATA_SIZE - 1)) != 0) {
>              goto do_unaligned_access;
>          }
> -        ioaddr = env->iotlb[mmu_idx][index];
> +        iotlbentry = &env->iotlb[mmu_idx][index];
>  
>          /* ??? Note that the io helpers always read data in the target
>             byte ordering.  We should push the LE/BE request down into io.  */
>          val = TGT_LE(val);
> -        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
> +        glue(io_write, SUFFIX)(env, iotlbentry, val, addr, retaddr);
>          return;
>      }
>  
> @@ -489,16 +491,16 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
>  
>      /* Handle an IO access.  */
>      if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
> -        hwaddr ioaddr;
> +        CPUIOTLBEntry *iotlbentry;
>          if ((addr & (DATA_SIZE - 1)) != 0) {
>              goto do_unaligned_access;
>          }
> -        ioaddr = env->iotlb[mmu_idx][index];
> +        iotlbentry = &env->iotlb[mmu_idx][index];
>  
>          /* ??? Note that the io helpers always read data in the target
>             byte ordering.  We should push the LE/BE request down into io.  */
>          val = TGT_BE(val);
> -        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
> +        glue(io_write, SUFFIX)(env, iotlbentry, val, addr, retaddr);
>          return;
>      }
>  
> 

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 04/14] Add MemTxAttrs to the IOTLB
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 04/14] Add MemTxAttrs to the IOTLB Peter Maydell
@ 2015-04-08 10:53   ` Paolo Bonzini
  2015-04-09  9:04   ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-08 10:53 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Peter Crosthwaite, patches, Greg Bellows, Edgar E. Iglesias,
	Alex Bennée, Richard Henderson



On 07/04/2015 22:09, Peter Maydell wrote:
> Add a MemTxAttrs field to the IOTLB, and allow target-specific
> code to set it via a new tlb_set_page_with_attrs() function;
> pass the attributes through to the device when making IO accesses.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  cputlb.c                | 18 +++++++++++++++---
>  include/exec/cpu-defs.h |  2 ++
>  include/exec/exec-all.h |  3 +++
>  softmmu_template.h      |  4 ++--
>  4 files changed, 22 insertions(+), 5 deletions(-)
> 
> diff --git a/cputlb.c b/cputlb.c
> index 5e1cb8f..7606548 100644
> --- a/cputlb.c
> +++ b/cputlb.c
> @@ -249,9 +249,9 @@ static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
>   * Called from TCG-generated code, which is under an RCU read-side
>   * critical section.
>   */
> -void tlb_set_page(CPUState *cpu, target_ulong vaddr,
> -                  hwaddr paddr, int prot,
> -                  int mmu_idx, target_ulong size)
> +void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
> +                             hwaddr paddr, MemTxAttrs attrs, int prot,
> +                             int mmu_idx, target_ulong size)
>  {
>      CPUArchState *env = cpu->env_ptr;
>      MemoryRegionSection *section;
> @@ -302,6 +302,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
>  
>      /* refill the tlb */
>      env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
> +    env->iotlb[mmu_idx][index].attrs = attrs;
>      te->addend = addend - vaddr;
>      if (prot & PAGE_READ) {
>          te->addr_read = address;
> @@ -331,6 +332,17 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
>      }
>  }
>  
> +/* Add a new TLB entry, but without specifying the memory
> + * transaction attributes to be used.
> + */
> +void tlb_set_page(CPUState *cpu, target_ulong vaddr,
> +                  hwaddr paddr, int prot,
> +                  int mmu_idx, target_ulong size)
> +{
> +    tlb_set_page_with_attrs(cpu, vaddr, paddr, MEMTXATTRS_UNSPECIFIED,
> +                            prot, mmu_idx, size);
> +}
> +
>  /* NOTE: this function can trigger an exception */
>  /* NOTE2: the returned address is not exactly the physical address: it
>   * is actually a ram_addr_t (in system mode; the user mode emulation
> diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
> index 7f88185..3f56546 100644
> --- a/include/exec/cpu-defs.h
> +++ b/include/exec/cpu-defs.h
> @@ -30,6 +30,7 @@
>  #ifndef CONFIG_USER_ONLY
>  #include "exec/hwaddr.h"
>  #endif
> +#include "exec/memattrs.h"
>  
>  #ifndef TARGET_LONG_BITS
>  #error TARGET_LONG_BITS must be defined before including this header
> @@ -109,6 +110,7 @@ QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
>   */
>  typedef struct CPUIOTLBEntry {
>      hwaddr addr;
> +    MemTxAttrs attrs;
>  } CPUIOTLBEntry;
>  
>  #define CPU_COMMON_TLB \
> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index ff1bc3e..b58cd47 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -105,6 +105,9 @@ void tlb_flush(CPUState *cpu, int flush_global);
>  void tlb_set_page(CPUState *cpu, target_ulong vaddr,
>                    hwaddr paddr, int prot,
>                    int mmu_idx, target_ulong size);
> +void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
> +                             hwaddr paddr, MemTxAttrs attrs,
> +                             int prot, int mmu_idx, target_ulong size);
>  void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr);
>  #else
>  static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
> diff --git a/softmmu_template.h b/softmmu_template.h
> index 7a36550..7310a93 100644
> --- a/softmmu_template.h
> +++ b/softmmu_template.h
> @@ -159,7 +159,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
>      }
>  
>      cpu->mem_io_vaddr = addr;
> -    io_mem_read(mr, physaddr, &val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
> +    io_mem_read(mr, physaddr, &val, 1 << SHIFT, iotlbentry->attrs);
>      return val;
>  }
>  #endif
> @@ -380,7 +380,7 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
>  
>      cpu->mem_io_vaddr = addr;
>      cpu->mem_io_pc = retaddr;
> -    io_mem_write(mr, physaddr, val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
> +    io_mem_write(mr, physaddr, val, 1 << SHIFT, iotlbentry->attrs);
>  }
>  
>  void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
> 

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 05/14] exec.c: Convert subpage memory ops to _with_attrs
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 05/14] exec.c: Convert subpage memory ops to _with_attrs Peter Maydell
@ 2015-04-08 10:54   ` Paolo Bonzini
  2015-04-09  9:07   ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-08 10:54 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Peter Crosthwaite, patches, Greg Bellows, Edgar E. Iglesias,
	Alex Bennée, Richard Henderson



On 07/04/2015 22:09, Peter Maydell wrote:
> Convert the subpage memory ops to _with_attrs; this will allow
> us to pass the attributes through to the underlying access
> functions.

Perhaps mention in the commit message that the attributes are not used yet.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  exec.c | 33 +++++++++++++++++++++------------
>  1 file changed, 21 insertions(+), 12 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index 52e7a2a..7e53f52 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -1941,8 +1941,8 @@ static const MemoryRegionOps watch_mem_ops = {
>      .endianness = DEVICE_NATIVE_ENDIAN,
>  };
>  
> -static uint64_t subpage_read(void *opaque, hwaddr addr,
> -                             unsigned len)
> +static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
> +                                unsigned len, MemTxAttrs attrs)
>  {
>      subpage_t *subpage = opaque;
>      uint8_t buf[8];
> @@ -1951,23 +1951,29 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
>      printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
>             subpage, len, addr);
>  #endif
> -    address_space_read(subpage->as, addr + subpage->base, buf, len);
> +    if (address_space_read(subpage->as, addr + subpage->base, buf, len)) {
> +        return MEMTX_DECODE_ERROR;
> +    }
>      switch (len) {
>      case 1:
> -        return ldub_p(buf);
> +        *data = ldub_p(buf);
> +        return MEMTX_OK;
>      case 2:
> -        return lduw_p(buf);
> +        *data = lduw_p(buf);
> +        return MEMTX_OK;
>      case 4:
> -        return ldl_p(buf);
> +        *data = ldl_p(buf);
> +        return MEMTX_OK;
>      case 8:
> -        return ldq_p(buf);
> +        *data = ldq_p(buf);
> +        return MEMTX_OK;
>      default:
>          abort();
>      }
>  }
>  
> -static void subpage_write(void *opaque, hwaddr addr,
> -                          uint64_t value, unsigned len)
> +static MemTxResult subpage_write(void *opaque, hwaddr addr,
> +                                 uint64_t value, unsigned len, MemTxAttrs attrs)
>  {
>      subpage_t *subpage = opaque;
>      uint8_t buf[8];
> @@ -1993,7 +1999,10 @@ static void subpage_write(void *opaque, hwaddr addr,
>      default:
>          abort();
>      }
> -    address_space_write(subpage->as, addr + subpage->base, buf, len);
> +    if (address_space_write(subpage->as, addr + subpage->base, buf, len)) {
> +        return MEMTX_DECODE_ERROR;
> +    }
> +    return MEMTX_OK;
>  }
>  
>  static bool subpage_accepts(void *opaque, hwaddr addr,
> @@ -2010,8 +2019,8 @@ static bool subpage_accepts(void *opaque, hwaddr addr,
>  }
>  
>  static const MemoryRegionOps subpage_ops = {
> -    .read = subpage_read,
> -    .write = subpage_write,
> +    .read_with_attrs = subpage_read,
> +    .write_with_attrs = subpage_write,
>      .impl.min_access_size = 1,
>      .impl.max_access_size = 8,
>      .valid.min_access_size = 1,
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 02/14] memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write
  2015-04-08 10:51   ` Paolo Bonzini
@ 2015-04-08 10:59     ` Peter Maydell
  2015-04-08 11:13       ` Paolo Bonzini
  0 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-08 10:59 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Edgar E. Iglesias, Alex Bennée, Richard Henderson

On 8 April 2015 at 11:51, Paolo Bonzini <pbonzini@redhat.com> wrote:
> This could be the occasion to drop io_mem_read/io_mem_write and use
> memory_region_dispatch_read/memory_region_dispatch_write altogether.  As
> you prefer.

Makes sense, I guess; memory_region_* are better named for
what they do, so promoting those to non-static and dropping
the wrappers seems a good move.

Incidentally in the course of this patch I noticed that we have
exactly two places outside the memory system that use these
functions: hw/s390x/s390-pci-inst.c and hw/vfio/pci.c. Is
this a reasonable thing, or should they in an ideal world
have created an AddressSpace to access things through?
(I have no opinion except that functions used in only one
or two places always look a little suspicious to me :-))

-- PMM

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions Peter Maydell
@ 2015-04-08 11:03   ` Paolo Bonzini
  2015-04-09 11:49     ` Peter Maydell
  2015-04-09 10:34   ` Edgar E. Iglesias
  1 sibling, 1 reply; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-08 11:03 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Peter Crosthwaite, patches, Greg Bellows, Edgar E. Iglesias,
	Alex Bennée, Richard Henderson



On 07/04/2015 22:09, Peter Maydell wrote:
> +#ifdef NEED_CPU_H
> +uint32_t address_space_lduw(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +uint32_t address_space_ldl(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +uint64_t address_space_ldq(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +#endif

I think we do not want to expose these at all (or at least, all users
should really be CPUs and hence use *_phys functions).

S390 is always big-endian, and watch_mem_read/write can use the same
buffer trick as subpages (and in fact should probably use memattrs as well).

So, please at least add a comment that these functions are deprecated,
and check if watch_mem_read/write should be handled like subpages.

Thanks,

Paolo

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 09/14] exec.c: Capture the memory attributes for a watchpoint hit
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 09/14] exec.c: Capture the memory attributes for a watchpoint hit Peter Maydell
@ 2015-04-08 11:04   ` Paolo Bonzini
  2015-04-08 11:14     ` Peter Maydell
  0 siblings, 1 reply; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-08 11:04 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Peter Crosthwaite, patches, Greg Bellows, Edgar E. Iglesias,
	Alex Bennée, Richard Henderson



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.

Paolo

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 02/14] memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write
  2015-04-08 10:59     ` Peter Maydell
@ 2015-04-08 11:13       ` Paolo Bonzini
  0 siblings, 0 replies; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-08 11:13 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Edgar E. Iglesias, Alex Bennée, Richard Henderson



On 08/04/2015 12:59, Peter Maydell wrote:
> Incidentally in the course of this patch I noticed that we have
> exactly two places outside the memory system that use these
> functions: hw/s390x/s390-pci-inst.c and hw/vfio/pci.c. Is
> this a reasonable thing, or should they in an ideal world
> have created an AddressSpace to access things through?

In the case of VFIO, I would just export pci_read/write_msix_table
functions from the PCI core.

In the case of s390 they would have to create an AddressSpace per BAR
per device: the current code doesn't work for BARs backed by a RAM
region, or with a complicated layout (aliases and the like).  This
reflects how s390 PCI is basically only used for VFIO, so it's passable:
having a separate AddressSpace per BAR per device probably wouldn't
scale too well.

Paolo

> (I have no opinion except that functions used in only one
> or two places always look a little suspicious to me :-))

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 09/14] exec.c: Capture the memory attributes for a watchpoint hit
  2015-04-08 11:04   ` Paolo Bonzini
@ 2015-04-08 11:14     ` Peter Maydell
  0 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-08 11:14 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Edgar E. Iglesias, Alex Bennée, Richard Henderson

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

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes Peter Maydell
@ 2015-04-08 12:55   ` Paolo Bonzini
  2015-04-09  9:59   ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-08 12:55 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Peter Crosthwaite, patches, Greg Bellows, Edgar E. Iglesias,
	Alex Bennée, Richard Henderson



On 07/04/2015 22:09, Peter Maydell wrote:
> Make address_space_rw take transaction attributes, rather
> than always using the 'unspecified' attributes.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  dma-helpers.c            |  3 ++-
>  exec.c                   | 51 ++++++++++++++++++++++++++----------------------
>  hw/mips/mips_jazz.c      |  6 ++++--
>  hw/pci-host/prep.c       |  6 ++++--
>  include/exec/memory.h    | 31 ++++++++++++++++++-----------
>  include/sysemu/dma.h     |  3 ++-
>  ioport.c                 | 16 +++++++++------
>  kvm-all.c                |  3 ++-
>  scripts/coverity-model.c |  8 +++++---
>  9 files changed, 77 insertions(+), 50 deletions(-)
> 
> diff --git a/dma-helpers.c b/dma-helpers.c
> index 6918572..33b1983 100644
> --- a/dma-helpers.c
> +++ b/dma-helpers.c
> @@ -28,7 +28,8 @@ int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len)
>      memset(fillbuf, c, FILLBUF_SIZE);
>      while (len > 0) {
>          l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
> -        error |= address_space_rw(as, addr, fillbuf, l, true);
> +        error |= address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED,
> +                                  fillbuf, l, true);
>          len -= l;
>          addr += l;
>      }
> diff --git a/exec.c b/exec.c
> index 7e53f52..29a12fa 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -1946,13 +1946,16 @@ static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
>  {
>      subpage_t *subpage = opaque;
>      uint8_t buf[8];
> +    MemTxResult res;
>  
>  #if defined(DEBUG_SUBPAGE)
>      printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
>             subpage, len, addr);
>  #endif
> -    if (address_space_read(subpage->as, addr + subpage->base, buf, len)) {
> -        return MEMTX_DECODE_ERROR;
> +    res = address_space_read(subpage->as, addr + subpage->base,
> +                             attrs, buf, len);
> +    if (res) {
> +        return res;
>      }
>      switch (len) {
>      case 1:
> @@ -1999,10 +2002,8 @@ static MemTxResult subpage_write(void *opaque, hwaddr addr,
>      default:
>          abort();
>      }
> -    if (address_space_write(subpage->as, addr + subpage->base, buf, len)) {
> -        return MEMTX_DECODE_ERROR;
> -    }
> -    return MEMTX_OK;
> +    return address_space_write(subpage->as, addr + subpage->base,
> +                               attrs, buf, len);
>  }
>  
>  static bool subpage_accepts(void *opaque, hwaddr addr,
> @@ -2313,8 +2314,8 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
>      return l;
>  }
>  
> -bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
> -                      int len, bool is_write)
> +MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
> +                             uint8_t *buf, int len, bool is_write)
>  {
>      hwaddr l;
>      uint8_t *ptr;
> @@ -2322,7 +2323,6 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>      hwaddr addr1;
>      MemoryRegion *mr;
>      MemTxResult result = MEMTX_OK;
> -    MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
>  
>      while (len > 0) {
>          l = len;
> @@ -2406,22 +2406,24 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>      return result;
>  }
>  
> -bool address_space_write(AddressSpace *as, hwaddr addr,
> -                         const uint8_t *buf, int len)
> +MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
> +                                const uint8_t *buf, int len)
>  {
> -    return address_space_rw(as, addr, (uint8_t *)buf, len, true);
> +    return address_space_rw(as, addr, attrs, (uint8_t *)buf, len, true);
>  }
>  
> -bool address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len)
> +MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
> +                               uint8_t *buf, int len)
>  {
> -    return address_space_rw(as, addr, buf, len, false);
> +    return address_space_rw(as, addr, attrs, buf, len, false);
>  }
>  
>  
>  void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
>                              int len, int is_write)
>  {
> -    address_space_rw(&address_space_memory, addr, buf, len, is_write);
> +    address_space_rw(&address_space_memory, addr, MEMTXATTRS_UNSPECIFIED,
> +                     buf, len, is_write);
>  }
>  
>  enum write_rom_type {
> @@ -2592,7 +2594,8 @@ void *address_space_map(AddressSpace *as,
>          memory_region_ref(mr);
>          bounce.mr = mr;
>          if (!is_write) {
> -            address_space_read(as, addr, bounce.buffer, l);
> +            address_space_read(as, addr, MEMTXATTRS_UNSPECIFIED,
> +                               bounce.buffer, l);
>          }
>  
>          *plen = l;
> @@ -2645,7 +2648,8 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
>          return;
>      }
>      if (is_write) {
> -        address_space_write(as, bounce.addr, bounce.buffer, access_len);
> +        address_space_write(as, bounce.addr, MEMTXATTRS_UNSPECIFIED,
> +                            bounce.buffer, access_len);
>      }
>      qemu_vfree(bounce.buffer);
>      bounce.buffer = NULL;
> @@ -2787,7 +2791,7 @@ uint64_t ldq_be_phys(AddressSpace *as, hwaddr addr)
>  uint32_t ldub_phys(AddressSpace *as, hwaddr addr)
>  {
>      uint8_t val;
> -    address_space_rw(as, addr, &val, 1, 0);
> +    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, &val, 1, 0);
>      return val;
>  }
>  
> @@ -2941,7 +2945,7 @@ void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  {
>      uint8_t v = val;
> -    address_space_rw(as, addr, &v, 1, 1);
> +    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, &v, 1, 1);
>  }
>  
>  /* warning: addr must be aligned */
> @@ -3004,19 +3008,19 @@ void stw_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val)
>  {
>      val = tswap64(val);
> -    address_space_rw(as, addr, (void *) &val, 8, 1);
> +    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
>  }
>  
>  void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val)
>  {
>      val = cpu_to_le64(val);
> -    address_space_rw(as, addr, (void *) &val, 8, 1);
> +    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
>  }
>  
>  void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val)
>  {
>      val = cpu_to_be64(val);
> -    address_space_rw(as, addr, (void *) &val, 8, 1);
> +    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
>  }
>  
>  /* virtual memory access for debug (includes writing to ROM) */
> @@ -3040,7 +3044,8 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>          if (is_write) {
>              cpu_physical_memory_write_rom(cpu->as, phys_addr, buf, l);
>          } else {
> -            address_space_rw(cpu->as, phys_addr, buf, l, 0);
> +            address_space_rw(cpu->as, phys_addr, MEMTXATTRS_UNSPECIFIED,
> +                             buf, l, 0);
>          }
>          len -= l;
>          buf += l;
> diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
> index 07f3c27..2c153e0 100644
> --- a/hw/mips/mips_jazz.c
> +++ b/hw/mips/mips_jazz.c
> @@ -61,7 +61,8 @@ static void main_cpu_reset(void *opaque)
>  static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size)
>  {
>      uint8_t val;
> -    address_space_read(&address_space_memory, 0x90000071, &val, 1);
> +    address_space_read(&address_space_memory, 0x90000071,
> +                       MEMTXATTRS_UNSPECIFIED, &val, 1);
>      return val;
>  }
>  
> @@ -69,7 +70,8 @@ static void rtc_write(void *opaque, hwaddr addr,
>                        uint64_t val, unsigned size)
>  {
>      uint8_t buf = val & 0xff;
> -    address_space_write(&address_space_memory, 0x90000071, &buf, 1);
> +    address_space_write(&address_space_memory, 0x90000071,
> +                        MEMTXATTRS_UNSPECIFIED, &buf, 1);
>  }
>  
>  static const MemoryRegionOps rtc_ops = {
> diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
> index 6cea6ff..c63f45d 100644
> --- a/hw/pci-host/prep.c
> +++ b/hw/pci-host/prep.c
> @@ -140,7 +140,8 @@ static uint64_t raven_io_read(void *opaque, hwaddr addr,
>      uint8_t buf[4];
>  
>      addr = raven_io_address(s, addr);
> -    address_space_read(&s->pci_io_as, addr + 0x80000000, buf, size);
> +    address_space_read(&s->pci_io_as, addr + 0x80000000,
> +                       MEMTXATTRS_UNSPECIFIED, buf, size);
>  
>      if (size == 1) {
>          return buf[0];
> @@ -171,7 +172,8 @@ static void raven_io_write(void *opaque, hwaddr addr,
>          g_assert_not_reached();
>      }
>  
> -    address_space_write(&s->pci_io_as, addr + 0x80000000, buf, size);
> +    address_space_write(&s->pci_io_as, addr + 0x80000000,
> +                        MEMTXATTRS_UNSPECIFIED, buf, size);
>  }
>  
>  static const MemoryRegionOps raven_io_ops = {
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index de2849d..4d6afc8 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -1089,41 +1089,50 @@ void address_space_destroy(AddressSpace *as);
>  /**
>   * address_space_rw: read from or write to an address space.
>   *
> - * Return true if the operation hit any unassigned memory or encountered an
> - * IOMMU fault.
> + * Return a MemTxResult indicating whether the operation succeeded
> + * or failed (eg unassigned memory, device rejected the transaction,
> + * IOMMU fault).
>   *
>   * @as: #AddressSpace to be accessed
>   * @addr: address within that address space
> + * @attrs: memory transaction attributes
>   * @buf: buffer with the data transferred
>   * @is_write: indicates the transfer direction
>   */
> -bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
> -                      int len, bool is_write);
> +MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
> +                             MemTxAttrs attrs, uint8_t *buf,
> +                             int len, bool is_write);
>  
>  /**
>   * address_space_write: write to address space.
>   *
> - * Return true if the operation hit any unassigned memory or encountered an
> - * IOMMU fault.
> + * Return a MemTxResult indicating whether the operation succeeded
> + * or failed (eg unassigned memory, device rejected the transaction,
> + * IOMMU fault).
>   *
>   * @as: #AddressSpace to be accessed
>   * @addr: address within that address space
> + * @attrs: memory transaction attributes
>   * @buf: buffer with the data transferred
>   */
> -bool address_space_write(AddressSpace *as, hwaddr addr,
> -                         const uint8_t *buf, int len);
> +MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
> +                                MemTxAttrs attrs,
> +                                const uint8_t *buf, int len);
>  
>  /**
>   * address_space_read: read from an address space.
>   *
> - * Return true if the operation hit any unassigned memory or encountered an
> - * IOMMU fault.
> + * Return a MemTxResult indicating whether the operation succeeded
> + * or failed (eg unassigned memory, device rejected the transaction,
> + * IOMMU fault).
>   *
>   * @as: #AddressSpace to be accessed
>   * @addr: address within that address space
> + * @attrs: memory transaction attributes
>   * @buf: buffer with the data transferred
>   */
> -bool address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
> +MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
> +                               uint8_t *buf, int len);
>  
>  /* address_space_translate: translate an address range into an address space
>   * into a MemoryRegion and an address range into that section
> diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
> index 3f2f4c8..efa8b99 100644
> --- a/include/sysemu/dma.h
> +++ b/include/sysemu/dma.h
> @@ -88,7 +88,8 @@ static inline int dma_memory_rw_relaxed(AddressSpace *as, dma_addr_t addr,
>                                          void *buf, dma_addr_t len,
>                                          DMADirection dir)
>  {
> -    return address_space_rw(as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
> +    return (bool)address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED,
> +                                  buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
>  }
>  
>  static inline int dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr,
> diff --git a/ioport.c b/ioport.c
> index 783a3ae..b345bd9 100644
> --- a/ioport.c
> +++ b/ioport.c
> @@ -64,7 +64,8 @@ void cpu_outb(pio_addr_t addr, uint8_t val)
>  {
>      LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
>      trace_cpu_out(addr, val);
> -    address_space_write(&address_space_io, addr, &val, 1);
> +    address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
> +                        &val, 1);
>  }
>  
>  void cpu_outw(pio_addr_t addr, uint16_t val)
> @@ -74,7 +75,8 @@ void cpu_outw(pio_addr_t addr, uint16_t val)
>      LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
>      trace_cpu_out(addr, val);
>      stw_p(buf, val);
> -    address_space_write(&address_space_io, addr, buf, 2);
> +    address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
> +                        buf, 2);
>  }
>  
>  void cpu_outl(pio_addr_t addr, uint32_t val)
> @@ -84,14 +86,16 @@ void cpu_outl(pio_addr_t addr, uint32_t val)
>      LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
>      trace_cpu_out(addr, val);
>      stl_p(buf, val);
> -    address_space_write(&address_space_io, addr, buf, 4);
> +    address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
> +                        buf, 4);
>  }
>  
>  uint8_t cpu_inb(pio_addr_t addr)
>  {
>      uint8_t val;
>  
> -    address_space_read(&address_space_io, addr, &val, 1);
> +    address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
> +                       &val, 1);
>      trace_cpu_in(addr, val);
>      LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
>      return val;
> @@ -102,7 +106,7 @@ uint16_t cpu_inw(pio_addr_t addr)
>      uint8_t buf[2];
>      uint16_t val;
>  
> -    address_space_read(&address_space_io, addr, buf, 2);
> +    address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED, buf, 2);
>      val = lduw_p(buf);
>      trace_cpu_in(addr, val);
>      LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
> @@ -114,7 +118,7 @@ uint32_t cpu_inl(pio_addr_t addr)
>      uint8_t buf[4];
>      uint32_t val;
>  
> -    address_space_read(&address_space_io, addr, buf, 4);
> +    address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED, buf, 4);
>      val = ldl_p(buf);
>      trace_cpu_in(addr, val);
>      LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
> diff --git a/kvm-all.c b/kvm-all.c
> index dd44f8c..4ec153d 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -1667,7 +1667,8 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
>      uint8_t *ptr = data;
>  
>      for (i = 0; i < count; i++) {
> -        address_space_rw(&address_space_io, port, ptr, size,
> +        address_space_rw(&address_space_io, port, MEMTXATTRS_UNSPECIFIED,
> +                         ptr, size,
>                           direction == KVM_EXIT_IO_OUT);
>          ptr += size;
>      }
> diff --git a/scripts/coverity-model.c b/scripts/coverity-model.c
> index cdda259..224d2d1 100644
> --- a/scripts/coverity-model.c
> +++ b/scripts/coverity-model.c
> @@ -46,6 +46,8 @@ typedef struct va_list_str *va_list;
>  
>  typedef struct AddressSpace AddressSpace;
>  typedef uint64_t hwaddr;
> +typedef uint32_t MemTxResult;
> +typedef uint64_t MemTxAttrs;
>  
>  static void __write(uint8_t *buf, ssize_t len)
>  {
> @@ -65,10 +67,10 @@ static void __read(uint8_t *buf, ssize_t len)
>      int last = buf[len-1];
>  }
>  
> -bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
> -                      int len, bool is_write)
> +MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
> +                             uint8_t *buf, int len, bool is_write)
>  {
> -    bool result;
> +    MemTxResult result;
>  
>      // TODO: investigate impact of treating reads as producing
>      // tainted data, with __coverity_tainted_data_argument__(buf).
> 

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status Peter Maydell
  2015-04-08 10:49   ` Paolo Bonzini
@ 2015-04-09  8:55   ` Edgar E. Iglesias
  2015-04-09  9:04     ` Peter Maydell
  1 sibling, 1 reply; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09  8:55 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:47PM +0100, Peter Maydell wrote:
> Define an API so that devices can register MemoryRegionOps whose read
> and write callback functions are passed an arbitrary pointer to some
> transaction attributes and can return a success-or-failure status code.
> This will allow us to model devices which:
>  * behave differently for ARM Secure/NonSecure memory accesses
>  * behave differently for privileged/unprivileged accesses
>  * may return a transaction failure (causing a guest exception)
>    for erroneous accesses
> 
> This patch defines the new API and plumbs the attributes parameter through
> to the memory.c public level functions io_mem_read() and io_mem_write(),
> where it is currently dummied out.
> 
> The success/failure response indication is also propagated out to
> io_mem_read() and io_mem_write(), which retain the old-style
> boolean true-for-error return.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  include/exec/memattrs.h |  34 ++++++++
>  include/exec/memory.h   |  22 +++++
>  memory.c                | 207 ++++++++++++++++++++++++++++++++----------------
>  3 files changed, 196 insertions(+), 67 deletions(-)
>  create mode 100644 include/exec/memattrs.h
> 
> diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
> new file mode 100644
> index 0000000..b8d7808
> --- /dev/null
> +++ b/include/exec/memattrs.h
> @@ -0,0 +1,34 @@
> +/*
> + * Memory transaction attributes
> + *
> + * Copyright (c) 2015 Linaro Limited.
> + *
> + * Authors:
> + *  Peter Maydell <peter.maydell@linaro.org>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#ifndef MEMATTRS_H
> +#define MEMATTRS_H
> +
> +/* Every memory transaction has associated with it a set of
> + * attributes. Some of these are generic (such as the ID of
> + * the bus master); some are specific to a particular kind of
> + * bus (such as the ARM Secure/NonSecure bit). We define them
> + * all as non-overlapping bits in a single integer to avoid
> + * confusion if different parts of QEMU used the same bit for
> + * different semantics.
> + */
> +typedef uint64_t MemTxAttrs;

Hi,

Did you consider using a struct here?
e.g:

typedef struct MemTxAttrs {
    unsigned int secure : 1;
    unsigned int master_id : 10;
    unsigned int etc : 1;
} MemTxAttrs;

I think you could still pass it by value and my understanding is
that the compiler will generate similar code.

I find it more readable, you ca go:

attrs.secure = 1;
attrs.master_id = 0x77;
if (!attrs.secure)

instead of: 

attrs |= MEMTXATTRS_SECURE
if (!(attrs & MEMTXATTRS_SECURE))

etc...

Or do you see any disadvantages with this?



> +
> +/* Bus masters which don't specify any attributes will get this,
> + * which has all attribute bits clear except the topmost one
> + * (so that we can distinguish "all attributes deliberately clear"
> + * from "didn't specify" if necessary).
> + */
> +#define MEMTXATTRS_UNSPECIFIED (1ULL << 63)
> +
> +#endif
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 06ffa1d..703d9e5 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -28,6 +28,7 @@
>  #ifndef CONFIG_USER_ONLY
>  #include "exec/hwaddr.h"
>  #endif
> +#include "exec/memattrs.h"
>  #include "qemu/queue.h"
>  #include "qemu/int128.h"
>  #include "qemu/notify.h"
> @@ -68,6 +69,16 @@ struct IOMMUTLBEntry {
>      IOMMUAccessFlags perm;
>  };
>  
> +/* New-style MMIO accessors can indicate that the transaction failed.
> + * A zero (MEMTX_OK) response means success; anything else is a failure
> + * of some kind. The memory subsystem will bitwise-OR together results
> + * if it is synthesizing an operation from multiple smaller accesses.
> + */
> +#define MEMTX_OK 0
> +#define MEMTX_ERROR             (1U << 0) /* device returned an error */
> +#define MEMTX_DECODE_ERROR      (1U << 1) /* nothing at that address */
> +typedef uint32_t MemTxResult;
> +
>  /*
>   * Memory region callbacks
>   */
> @@ -84,6 +95,17 @@ struct MemoryRegionOps {
>                    uint64_t data,
>                    unsigned size);
>  
> +    MemTxResult (*read_with_attrs)(void *opaque,
> +                                   hwaddr addr,
> +                                   uint64_t *data,
> +                                   unsigned size,
> +                                   MemTxAttrs attrs);
> +    MemTxResult (*write_with_attrs)(void *opaque,
> +                                    hwaddr addr,
> +                                    uint64_t data,
> +                                    unsigned size,
> +                                    MemTxAttrs attrs);
> +
>      enum device_endian endianness;
>      /* Guest-visible constraints: */
>      struct {
> diff --git a/memory.c b/memory.c
> index ee3f2a8..9bb5674 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -368,57 +368,84 @@ static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
>      }
>  }
>  
> -static void memory_region_oldmmio_read_accessor(MemoryRegion *mr,
> +static MemTxResult memory_region_oldmmio_read_accessor(MemoryRegion *mr,
> +                                                       hwaddr addr,
> +                                                       uint64_t *value,
> +                                                       unsigned size,
> +                                                       unsigned shift,
> +                                                       uint64_t mask,
> +                                                       MemTxAttrs attrs)
> +{
> +    uint64_t tmp;
> +
> +    tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
> +    trace_memory_region_ops_read(mr, addr, tmp, size);
> +    *value |= (tmp & mask) << shift;
> +    return MEMTX_OK;
> +}
> +
> +static MemTxResult  memory_region_read_accessor(MemoryRegion *mr,
>                                                  hwaddr addr,
>                                                  uint64_t *value,
>                                                  unsigned size,
>                                                  unsigned shift,
> -                                                uint64_t mask)
> +                                                uint64_t mask,
> +                                                MemTxAttrs attrs)
>  {
>      uint64_t tmp;
>  
> -    tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
> +    if (mr->flush_coalesced_mmio) {
> +        qemu_flush_coalesced_mmio_buffer();
> +    }
> +    tmp = mr->ops->read(mr->opaque, addr, size);
>      trace_memory_region_ops_read(mr, addr, tmp, size);
>      *value |= (tmp & mask) << shift;
> +    return MEMTX_OK;
>  }
>  
> -static void memory_region_read_accessor(MemoryRegion *mr,
> -                                        hwaddr addr,
> -                                        uint64_t *value,
> -                                        unsigned size,
> -                                        unsigned shift,
> -                                        uint64_t mask)
> +static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr,
> +                                                          hwaddr addr,
> +                                                          uint64_t *value,
> +                                                          unsigned size,
> +                                                          unsigned shift,
> +                                                          uint64_t mask,
> +                                                          MemTxAttrs attrs)
>  {
> -    uint64_t tmp;
> +    uint64_t tmp = 0;
> +    MemTxResult r;
>  
>      if (mr->flush_coalesced_mmio) {
>          qemu_flush_coalesced_mmio_buffer();
>      }
> -    tmp = mr->ops->read(mr->opaque, addr, size);
> +    r = mr->ops->read_with_attrs(mr->opaque, addr, &tmp, size, attrs);
>      trace_memory_region_ops_read(mr, addr, tmp, size);
>      *value |= (tmp & mask) << shift;
> +    return r;
>  }
>  
> -static void memory_region_oldmmio_write_accessor(MemoryRegion *mr,
> -                                                 hwaddr addr,
> -                                                 uint64_t *value,
> -                                                 unsigned size,
> -                                                 unsigned shift,
> -                                                 uint64_t mask)
> +static MemTxResult memory_region_oldmmio_write_accessor(MemoryRegion *mr,
> +                                                        hwaddr addr,
> +                                                        uint64_t *value,
> +                                                        unsigned size,
> +                                                        unsigned shift,
> +                                                        uint64_t mask,
> +                                                        MemTxAttrs attrs)
>  {
>      uint64_t tmp;
>  
>      tmp = (*value >> shift) & mask;
>      trace_memory_region_ops_write(mr, addr, tmp, size);
>      mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp);
> +    return MEMTX_OK;
>  }
>  
> -static void memory_region_write_accessor(MemoryRegion *mr,
> -                                         hwaddr addr,
> -                                         uint64_t *value,
> -                                         unsigned size,
> -                                         unsigned shift,
> -                                         uint64_t mask)
> +static MemTxResult memory_region_write_accessor(MemoryRegion *mr,
> +                                                hwaddr addr,
> +                                                uint64_t *value,
> +                                                unsigned size,
> +                                                unsigned shift,
> +                                                uint64_t mask,
> +                                                MemTxAttrs attrs)
>  {
>      uint64_t tmp;
>  
> @@ -428,24 +455,46 @@ static void memory_region_write_accessor(MemoryRegion *mr,
>      tmp = (*value >> shift) & mask;
>      trace_memory_region_ops_write(mr, addr, tmp, size);
>      mr->ops->write(mr->opaque, addr, tmp, size);
> +    return MEMTX_OK;
>  }
>  
> -static void access_with_adjusted_size(hwaddr addr,
> +static MemTxResult memory_region_write_with_attrs_accessor(MemoryRegion *mr,
> +                                                           hwaddr addr,
> +                                                           uint64_t *value,
> +                                                           unsigned size,
> +                                                           unsigned shift,
> +                                                           uint64_t mask,
> +                                                           MemTxAttrs attrs)
> +{
> +    uint64_t tmp;
> +
> +    if (mr->flush_coalesced_mmio) {
> +        qemu_flush_coalesced_mmio_buffer();
> +    }
> +    tmp = (*value >> shift) & mask;
> +    trace_memory_region_ops_write(mr, addr, tmp, size);
> +    return mr->ops->write_with_attrs(mr->opaque, addr, tmp, size, attrs);
> +}
> +
> +static MemTxResult access_with_adjusted_size(hwaddr addr,
>                                        uint64_t *value,
>                                        unsigned size,
>                                        unsigned access_size_min,
>                                        unsigned access_size_max,
> -                                      void (*access)(MemoryRegion *mr,
> -                                                     hwaddr addr,
> -                                                     uint64_t *value,
> -                                                     unsigned size,
> -                                                     unsigned shift,
> -                                                     uint64_t mask),
> -                                      MemoryRegion *mr)
> +                                      MemTxResult (*access)(MemoryRegion *mr,
> +                                                            hwaddr addr,
> +                                                            uint64_t *value,
> +                                                            unsigned size,
> +                                                            unsigned shift,
> +                                                            uint64_t mask,
> +                                                            MemTxAttrs attrs),
> +                                      MemoryRegion *mr,
> +                                      MemTxAttrs attrs)
>  {
>      uint64_t access_mask;
>      unsigned access_size;
>      unsigned i;
> +    MemTxResult r = MEMTX_OK;
>  
>      if (!access_size_min) {
>          access_size_min = 1;
> @@ -459,14 +508,16 @@ static void access_with_adjusted_size(hwaddr addr,
>      access_mask = -1ULL >> (64 - access_size * 8);
>      if (memory_region_big_endian(mr)) {
>          for (i = 0; i < size; i += access_size) {
> -            access(mr, addr + i, value, access_size,
> -                   (size - access_size - i) * 8, access_mask);
> +            r |= access(mr, addr + i, value, access_size,
> +                        (size - access_size - i) * 8, access_mask, attrs);
>          }
>      } else {
>          for (i = 0; i < size; i += access_size) {
> -            access(mr, addr + i, value, access_size, i * 8, access_mask);
> +            r |= access(mr, addr + i, value, access_size, i * 8,
> +                        access_mask, attrs);
>          }
>      }
> +    return r;
>  }
>  
>  static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
> @@ -1053,62 +1104,82 @@ bool memory_region_access_valid(MemoryRegion *mr,
>      return true;
>  }
>  
> -static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
> -                                             hwaddr addr,
> -                                             unsigned size)
> +static MemTxResult memory_region_dispatch_read1(MemoryRegion *mr,
> +                                                hwaddr addr,
> +                                                uint64_t *pval,
> +                                                unsigned size,
> +                                                MemTxAttrs attrs)
>  {
> -    uint64_t data = 0;
> +    *pval = 0;
>  
>      if (mr->ops->read) {
> -        access_with_adjusted_size(addr, &data, size,
> -                                  mr->ops->impl.min_access_size,
> -                                  mr->ops->impl.max_access_size,
> -                                  memory_region_read_accessor, mr);
> +        return access_with_adjusted_size(addr, pval, size,
> +                                         mr->ops->impl.min_access_size,
> +                                         mr->ops->impl.max_access_size,
> +                                         memory_region_read_accessor,
> +                                         mr, attrs);
> +    } else if (mr->ops->read_with_attrs) {
> +        return access_with_adjusted_size(addr, pval, size,
> +                                         mr->ops->impl.min_access_size,
> +                                         mr->ops->impl.max_access_size,
> +                                         memory_region_read_with_attrs_accessor,
> +                                         mr, attrs);
>      } else {
> -        access_with_adjusted_size(addr, &data, size, 1, 4,
> -                                  memory_region_oldmmio_read_accessor, mr);
> +        return access_with_adjusted_size(addr, pval, size, 1, 4,
> +                                         memory_region_oldmmio_read_accessor,
> +                                         mr, attrs);
>      }
> -
> -    return data;
>  }
>  
> -static bool memory_region_dispatch_read(MemoryRegion *mr,
> -                                        hwaddr addr,
> -                                        uint64_t *pval,
> -                                        unsigned size)
> +static MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
> +                                               hwaddr addr,
> +                                               uint64_t *pval,
> +                                               unsigned size,
> +                                               MemTxAttrs attrs)
>  {
> +    MemTxResult r;
> +
>      if (!memory_region_access_valid(mr, addr, size, false)) {
>          *pval = unassigned_mem_read(mr, addr, size);
> -        return true;
> +        return MEMTX_DECODE_ERROR;
>      }
>  
> -    *pval = memory_region_dispatch_read1(mr, addr, size);
> +    r = memory_region_dispatch_read1(mr, addr, pval, size, attrs);
>      adjust_endianness(mr, pval, size);
> -    return false;
> +    return r;
>  }
>  
> -static bool memory_region_dispatch_write(MemoryRegion *mr,
> -                                         hwaddr addr,
> -                                         uint64_t data,
> -                                         unsigned size)
> +static MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
> +                                                hwaddr addr,
> +                                                uint64_t data,
> +                                                unsigned size,
> +                                                MemTxAttrs attrs)
>  {
>      if (!memory_region_access_valid(mr, addr, size, true)) {
>          unassigned_mem_write(mr, addr, data, size);
> -        return true;
> +        return MEMTX_DECODE_ERROR;
>      }
>  
>      adjust_endianness(mr, &data, size);
>  
>      if (mr->ops->write) {
> -        access_with_adjusted_size(addr, &data, size,
> -                                  mr->ops->impl.min_access_size,
> -                                  mr->ops->impl.max_access_size,
> -                                  memory_region_write_accessor, mr);
> +        return access_with_adjusted_size(addr, &data, size,
> +                                         mr->ops->impl.min_access_size,
> +                                         mr->ops->impl.max_access_size,
> +                                         memory_region_write_accessor, mr,
> +                                         attrs);
> +    } else if (mr->ops->write_with_attrs) {
> +        return
> +            access_with_adjusted_size(addr, &data, size,
> +                                      mr->ops->impl.min_access_size,
> +                                      mr->ops->impl.max_access_size,
> +                                      memory_region_write_with_attrs_accessor,
> +                                      mr, attrs);
>      } else {
> -        access_with_adjusted_size(addr, &data, size, 1, 4,
> -                                  memory_region_oldmmio_write_accessor, mr);
> +        return access_with_adjusted_size(addr, &data, size, 1, 4,
> +                                         memory_region_oldmmio_write_accessor,
> +                                         mr, attrs);
>      }
> -    return false;
>  }
>  
>  void memory_region_init_io(MemoryRegion *mr,
> @@ -1994,13 +2065,15 @@ void address_space_destroy(AddressSpace *as)
>  
>  bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size)
>  {
> -    return memory_region_dispatch_read(mr, addr, pval, size);
> +    return memory_region_dispatch_read(mr, addr, pval, size,
> +                                       MEMTXATTRS_UNSPECIFIED);
>  }
>  
>  bool io_mem_write(MemoryRegion *mr, hwaddr addr,
>                    uint64_t val, unsigned size)
>  {
> -    return memory_region_dispatch_write(mr, addr, val, size);
> +    return memory_region_dispatch_write(mr, addr, val, size,
> +                                        MEMTXATTRS_UNSPECIFIED);
>  }
>  
>  typedef struct MemoryRegionList MemoryRegionList;
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 02/14] memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 02/14] memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write Peter Maydell
  2015-04-08 10:51   ` Paolo Bonzini
@ 2015-04-09  8:59   ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09  8:59 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:48PM +0100, Peter Maydell wrote:
> Add a MemTxAttrs argument to the io_mem_read() and io_mem_write()
> functions, and make them return MemTxResult rather than bool,
> thus pushing these new arguments out one level of the callstack
> (all the callers callers currently pass MEMTXATTRS_UNSPECIFIED
> and convert the return value back to bool or ignore it).
> 
> Note that this involves moving the io_mem_read and io_mem_write
> prototypes from exec-all.h to memory.h. This allows them to
> see the MemTxResult type, and is a better location anyway,
> since they are implemented in memory.c and are operations on
> MemoryRegions.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> ---
>  exec.c                   | 33 +++++++++++++++++----------------
>  hw/s390x/s390-pci-inst.c |  7 ++++---
>  hw/vfio/pci.c            |  4 ++--
>  include/exec/exec-all.h  |  4 ----
>  include/exec/memory.h    | 12 ++++++++++++
>  memory.c                 | 13 ++++++-------
>  softmmu_template.h       |  4 ++--
>  7 files changed, 43 insertions(+), 34 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index 874ecfc..52e7a2a 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2312,7 +2312,8 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>      uint64_t val;
>      hwaddr addr1;
>      MemoryRegion *mr;
> -    bool error = false;
> +    MemTxResult result = MEMTX_OK;
> +    MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
>  
>      while (len > 0) {
>          l = len;
> @@ -2327,22 +2328,22 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>                  case 8:
>                      /* 64 bit write access */
>                      val = ldq_p(buf);
> -                    error |= io_mem_write(mr, addr1, val, 8);
> +                    result |= io_mem_write(mr, addr1, val, 8, attrs);
>                      break;
>                  case 4:
>                      /* 32 bit write access */
>                      val = ldl_p(buf);
> -                    error |= io_mem_write(mr, addr1, val, 4);
> +                    result |= io_mem_write(mr, addr1, val, 4, attrs);
>                      break;
>                  case 2:
>                      /* 16 bit write access */
>                      val = lduw_p(buf);
> -                    error |= io_mem_write(mr, addr1, val, 2);
> +                    result |= io_mem_write(mr, addr1, val, 2, attrs);
>                      break;
>                  case 1:
>                      /* 8 bit write access */
>                      val = ldub_p(buf);
> -                    error |= io_mem_write(mr, addr1, val, 1);
> +                    result |= io_mem_write(mr, addr1, val, 1, attrs);
>                      break;
>                  default:
>                      abort();
> @@ -2361,22 +2362,22 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>                  switch (l) {
>                  case 8:
>                      /* 64 bit read access */
> -                    error |= io_mem_read(mr, addr1, &val, 8);
> +                    result |= io_mem_read(mr, addr1, &val, 8, attrs);
>                      stq_p(buf, val);
>                      break;
>                  case 4:
>                      /* 32 bit read access */
> -                    error |= io_mem_read(mr, addr1, &val, 4);
> +                    result |= io_mem_read(mr, addr1, &val, 4, attrs);
>                      stl_p(buf, val);
>                      break;
>                  case 2:
>                      /* 16 bit read access */
> -                    error |= io_mem_read(mr, addr1, &val, 2);
> +                    result |= io_mem_read(mr, addr1, &val, 2, attrs);
>                      stw_p(buf, val);
>                      break;
>                  case 1:
>                      /* 8 bit read access */
> -                    error |= io_mem_read(mr, addr1, &val, 1);
> +                    result |= io_mem_read(mr, addr1, &val, 1, attrs);
>                      stb_p(buf, val);
>                      break;
>                  default:
> @@ -2393,7 +2394,7 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>          addr += l;
>      }
>  
> -    return error;
> +    return result;
>  }
>  
>  bool address_space_write(AddressSpace *as, hwaddr addr,
> @@ -2669,7 +2670,7 @@ static inline uint32_t ldl_phys_internal(AddressSpace *as, hwaddr addr,
>      mr = address_space_translate(as, addr, &addr1, &l, false);
>      if (l < 4 || !memory_access_is_direct(mr, false)) {
>          /* I/O case */
> -        io_mem_read(mr, addr1, &val, 4);
> +        io_mem_read(mr, addr1, &val, 4, MEMTXATTRS_UNSPECIFIED);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap32(val);
> @@ -2728,7 +2729,7 @@ static inline uint64_t ldq_phys_internal(AddressSpace *as, hwaddr addr,
>                                   false);
>      if (l < 8 || !memory_access_is_direct(mr, false)) {
>          /* I/O case */
> -        io_mem_read(mr, addr1, &val, 8);
> +        io_mem_read(mr, addr1, &val, 8, MEMTXATTRS_UNSPECIFIED);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap64(val);
> @@ -2795,7 +2796,7 @@ static inline uint32_t lduw_phys_internal(AddressSpace *as, hwaddr addr,
>                                   false);
>      if (l < 2 || !memory_access_is_direct(mr, false)) {
>          /* I/O case */
> -        io_mem_read(mr, addr1, &val, 2);
> +        io_mem_read(mr, addr1, &val, 2, MEMTXATTRS_UNSPECIFIED);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap16(val);
> @@ -2853,7 +2854,7 @@ void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
>      mr = address_space_translate(as, addr, &addr1, &l,
>                                   true);
>      if (l < 4 || !memory_access_is_direct(mr, true)) {
> -        io_mem_write(mr, addr1, val, 4);
> +        io_mem_write(mr, addr1, val, 4, MEMTXATTRS_UNSPECIFIED);
>      } else {
>          addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
>          ptr = qemu_get_ram_ptr(addr1);
> @@ -2892,7 +2893,7 @@ static inline void stl_phys_internal(AddressSpace *as,
>              val = bswap32(val);
>          }
>  #endif
> -        io_mem_write(mr, addr1, val, 4);
> +        io_mem_write(mr, addr1, val, 4, MEMTXATTRS_UNSPECIFIED);
>      } else {
>          /* RAM case */
>          addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
> @@ -2955,7 +2956,7 @@ static inline void stw_phys_internal(AddressSpace *as,
>              val = bswap16(val);
>          }
>  #endif
> -        io_mem_write(mr, addr1, val, 2);
> +        io_mem_write(mr, addr1, val, 2, MEMTXATTRS_UNSPECIFIED);
>      } else {
>          /* RAM case */
>          addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
> diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
> index 08d8aa6..78ff9c0 100644
> --- a/hw/s390x/s390-pci-inst.c
> +++ b/hw/s390x/s390-pci-inst.c
> @@ -331,7 +331,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
>              return 0;
>          }
>          MemoryRegion *mr = pbdev->pdev->io_regions[pcias].memory;
> -        io_mem_read(mr, offset, &data, len);
> +        io_mem_read(mr, offset, &data, len, MEMTXATTRS_UNSPECIFIED);
>      } else if (pcias == 15) {
>          if ((4 - (offset & 0x3)) < len) {
>              program_interrupt(env, PGM_OPERAND, 4);
> @@ -456,7 +456,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
>              mr = pbdev->pdev->io_regions[pcias].memory;
>          }
>  
> -        io_mem_write(mr, offset, data, len);
> +        io_mem_write(mr, offset, data, len, MEMTXATTRS_UNSPECIFIED);
>      } else if (pcias == 15) {
>          if ((4 - (offset & 0x3)) < len) {
>              program_interrupt(env, PGM_OPERAND, 4);
> @@ -606,7 +606,8 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr)
>      }
>  
>      for (i = 0; i < len / 8; i++) {
> -        io_mem_write(mr, env->regs[r3] + i * 8, ldq_p(buffer + i * 8), 8);
> +        io_mem_write(mr, env->regs[r3] + i * 8, ldq_p(buffer + i * 8), 8,
> +                     MEMTXATTRS_UNSPECIFIED);
>      }
>  
>      setcc(cpu, ZPCI_PCI_LS_OK);
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index 6b80539..3e1df0c 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -1533,7 +1533,7 @@ static uint64_t vfio_rtl8168_window_quirk_read(void *opaque,
>  
>              io_mem_read(&vdev->pdev.msix_table_mmio,
>                          (hwaddr)(quirk->data.address_match & 0xfff),
> -                        &val, size);
> +                        &val, size, MEMTXATTRS_UNSPECIFIED);
>              return val;
>          }
>      }
> @@ -1563,7 +1563,7 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr,
>  
>                  io_mem_write(&vdev->pdev.msix_table_mmio,
>                               (hwaddr)(quirk->data.address_match & 0xfff),
> -                             data, size);
> +                             data, size, MEMTXATTRS_UNSPECIFIED);
>              }
>  
>              quirk->data.flags = 1;
> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index 8eb0db3..ff1bc3e 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -341,10 +341,6 @@ void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
>  
>  struct MemoryRegion *iotlb_to_region(CPUState *cpu,
>                                       hwaddr index);
> -bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
> -                 uint64_t *pvalue, unsigned size);
> -bool io_mem_write(struct MemoryRegion *mr, hwaddr addr,
> -                  uint64_t value, unsigned size);
>  
>  void tlb_fill(CPUState *cpu, target_ulong addr, int is_write, int mmu_idx,
>                uintptr_t retaddr);
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 703d9e5..de2849d 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -1053,6 +1053,18 @@ void memory_global_dirty_log_stop(void);
>  void mtree_info(fprintf_function mon_printf, void *f);
>  
>  /**
> + * io_mem_read: perform an IO read directly to the specified MemoryRegion
> + */
> +MemTxResult io_mem_read(struct MemoryRegion *mr, hwaddr addr,
> +                        uint64_t *pvalue, unsigned size, MemTxAttrs attrs);
> +
> +/**
> + * io_mem_write: perform an IO write directly to the specified MemoryRegion
> + */
> +MemTxResult io_mem_write(struct MemoryRegion *mr, hwaddr addr,
> +                         uint64_t value, unsigned size, MemTxAttrs attrs);
> +
> +/**
>   * address_space_init: initializes an address space
>   *
>   * @as: an uninitialized #AddressSpace
> diff --git a/memory.c b/memory.c
> index 9bb5674..14cda7f 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -2063,17 +2063,16 @@ void address_space_destroy(AddressSpace *as)
>      call_rcu(as, do_address_space_destroy, rcu);
>  }
>  
> -bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size)
> +MemTxResult io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval,
> +                        unsigned size, MemTxAttrs attrs)
>  {
> -    return memory_region_dispatch_read(mr, addr, pval, size,
> -                                       MEMTXATTRS_UNSPECIFIED);
> +    return memory_region_dispatch_read(mr, addr, pval, size, attrs);
>  }
>  
> -bool io_mem_write(MemoryRegion *mr, hwaddr addr,
> -                  uint64_t val, unsigned size)
> +MemTxResult io_mem_write(MemoryRegion *mr, hwaddr addr,
> +                         uint64_t val, unsigned size, MemTxAttrs attrs)
>  {
> -    return memory_region_dispatch_write(mr, addr, val, size,
> -                                        MEMTXATTRS_UNSPECIFIED);
> +    return memory_region_dispatch_write(mr, addr, val, size, attrs);
>  }
>  
>  typedef struct MemoryRegionList MemoryRegionList;
> diff --git a/softmmu_template.h b/softmmu_template.h
> index 0e3dd35..4b9bae7 100644
> --- a/softmmu_template.h
> +++ b/softmmu_template.h
> @@ -158,7 +158,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
>      }
>  
>      cpu->mem_io_vaddr = addr;
> -    io_mem_read(mr, physaddr, &val, 1 << SHIFT);
> +    io_mem_read(mr, physaddr, &val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
>      return val;
>  }
>  #endif
> @@ -378,7 +378,7 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
>  
>      cpu->mem_io_vaddr = addr;
>      cpu->mem_io_pc = retaddr;
> -    io_mem_write(mr, physaddr, val, 1 << SHIFT);
> +    io_mem_write(mr, physaddr, val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
>  }
>  
>  void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 03/14] Make CPU iotlb a structure rather than a plain hwaddr
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 03/14] Make CPU iotlb a structure rather than a plain hwaddr Peter Maydell
  2015-04-08 10:52   ` Paolo Bonzini
@ 2015-04-09  9:02   ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09  9:02 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:49PM +0100, Peter Maydell wrote:
> Make the CPU iotlb a structure rather than a plain hwaddr;
> this will allow us to add transaction attributes to it.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

> ---
>  cputlb.c                |  4 ++--
>  include/exec/cpu-defs.h | 13 +++++++++++--
>  softmmu_template.h      | 32 +++++++++++++++++---------------
>  3 files changed, 30 insertions(+), 19 deletions(-)
> 
> diff --git a/cputlb.c b/cputlb.c
> index 38f2151..5e1cb8f 100644
> --- a/cputlb.c
> +++ b/cputlb.c
> @@ -301,7 +301,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
>      env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
>  
>      /* refill the tlb */
> -    env->iotlb[mmu_idx][index] = iotlb - vaddr;
> +    env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
>      te->addend = addend - vaddr;
>      if (prot & PAGE_READ) {
>          te->addr_read = address;
> @@ -349,7 +349,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
>                   (addr & TARGET_PAGE_MASK))) {
>          cpu_ldub_code(env1, addr);
>      }
> -    pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
> +    pd = env1->iotlb[mmu_idx][page_index].addr & ~TARGET_PAGE_MASK;
>      mr = iotlb_to_region(cpu, pd);
>      if (memory_region_is_unassigned(mr)) {
>          CPUClass *cc = CPU_GET_CLASS(cpu);
> diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
> index 0ca6f0b..7f88185 100644
> --- a/include/exec/cpu-defs.h
> +++ b/include/exec/cpu-defs.h
> @@ -102,12 +102,21 @@ typedef struct CPUTLBEntry {
>  
>  QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
>  
> +/* The IOTLB is not accessed directly inline by generated TCG code,
> + * so the CPUIOTLBEntry layout is not as critical as that of the
> + * CPUTLBEntry. (This is also why we don't want to combine the two
> + * structs into one.)
> + */
> +typedef struct CPUIOTLBEntry {
> +    hwaddr addr;
> +} CPUIOTLBEntry;
> +
>  #define CPU_COMMON_TLB \
>      /* The meaning of the MMU modes is defined in the target code. */   \
>      CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE];                  \
>      CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE];               \
> -    hwaddr iotlb[NB_MMU_MODES][CPU_TLB_SIZE];                           \
> -    hwaddr iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE];                        \
> +    CPUIOTLBEntry iotlb[NB_MMU_MODES][CPU_TLB_SIZE];                    \
> +    CPUIOTLBEntry iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE];                 \
>      target_ulong tlb_flush_addr;                                        \
>      target_ulong tlb_flush_mask;                                        \
>      target_ulong vtlb_index;                                            \
> diff --git a/softmmu_template.h b/softmmu_template.h
> index 4b9bae7..7a36550 100644
> --- a/softmmu_template.h
> +++ b/softmmu_template.h
> @@ -123,7 +123,7 @@
>       * victim tlb. try to refill from the victim tlb before walking the       \
>       * page table. */                                                         \
>      int vidx;                                                                 \
> -    hwaddr tmpiotlb;                                                          \
> +    CPUIOTLBEntry tmpiotlb;                                                   \
>      CPUTLBEntry tmptlb;                                                       \
>      for (vidx = CPU_VTLB_SIZE-1; vidx >= 0; --vidx) {                         \
>          if (env->tlb_v_table[mmu_idx][vidx].ty == (addr & TARGET_PAGE_MASK)) {\
> @@ -143,12 +143,13 @@
>  
>  #ifndef SOFTMMU_CODE_ACCESS
>  static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
> -                                              hwaddr physaddr,
> +                                              CPUIOTLBEntry *iotlbentry,
>                                                target_ulong addr,
>                                                uintptr_t retaddr)
>  {
>      uint64_t val;
>      CPUState *cpu = ENV_GET_CPU(env);
> +    hwaddr physaddr = iotlbentry->addr;
>      MemoryRegion *mr = iotlb_to_region(cpu, physaddr);
>  
>      physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
> @@ -195,15 +196,15 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
>  
>      /* Handle an IO access.  */
>      if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
> -        hwaddr ioaddr;
> +        CPUIOTLBEntry *iotlbentry;
>          if ((addr & (DATA_SIZE - 1)) != 0) {
>              goto do_unaligned_access;
>          }
> -        ioaddr = env->iotlb[mmu_idx][index];
> +        iotlbentry = &env->iotlb[mmu_idx][index];
>  
>          /* ??? Note that the io helpers always read data in the target
>             byte ordering.  We should push the LE/BE request down into io.  */
> -        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
> +        res = glue(io_read, SUFFIX)(env, iotlbentry, addr, retaddr);
>          res = TGT_LE(res);
>          return res;
>      }
> @@ -283,15 +284,15 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
>  
>      /* Handle an IO access.  */
>      if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
> -        hwaddr ioaddr;
> +        CPUIOTLBEntry *iotlbentry;
>          if ((addr & (DATA_SIZE - 1)) != 0) {
>              goto do_unaligned_access;
>          }
> -        ioaddr = env->iotlb[mmu_idx][index];
> +        iotlbentry = &env->iotlb[mmu_idx][index];
>  
>          /* ??? Note that the io helpers always read data in the target
>             byte ordering.  We should push the LE/BE request down into io.  */
> -        res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr);
> +        res = glue(io_read, SUFFIX)(env, iotlbentry, addr, retaddr);
>          res = TGT_BE(res);
>          return res;
>      }
> @@ -363,12 +364,13 @@ WORD_TYPE helper_be_lds_name(CPUArchState *env, target_ulong addr,
>  #endif
>  
>  static inline void glue(io_write, SUFFIX)(CPUArchState *env,
> -                                          hwaddr physaddr,
> +                                          CPUIOTLBEntry *iotlbentry,
>                                            DATA_TYPE val,
>                                            target_ulong addr,
>                                            uintptr_t retaddr)
>  {
>      CPUState *cpu = ENV_GET_CPU(env);
> +    hwaddr physaddr = iotlbentry->addr;
>      MemoryRegion *mr = iotlb_to_region(cpu, physaddr);
>  
>      physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
> @@ -408,16 +410,16 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
>  
>      /* Handle an IO access.  */
>      if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
> -        hwaddr ioaddr;
> +        CPUIOTLBEntry *iotlbentry;
>          if ((addr & (DATA_SIZE - 1)) != 0) {
>              goto do_unaligned_access;
>          }
> -        ioaddr = env->iotlb[mmu_idx][index];
> +        iotlbentry = &env->iotlb[mmu_idx][index];
>  
>          /* ??? Note that the io helpers always read data in the target
>             byte ordering.  We should push the LE/BE request down into io.  */
>          val = TGT_LE(val);
> -        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
> +        glue(io_write, SUFFIX)(env, iotlbentry, val, addr, retaddr);
>          return;
>      }
>  
> @@ -489,16 +491,16 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
>  
>      /* Handle an IO access.  */
>      if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
> -        hwaddr ioaddr;
> +        CPUIOTLBEntry *iotlbentry;
>          if ((addr & (DATA_SIZE - 1)) != 0) {
>              goto do_unaligned_access;
>          }
> -        ioaddr = env->iotlb[mmu_idx][index];
> +        iotlbentry = &env->iotlb[mmu_idx][index];
>  
>          /* ??? Note that the io helpers always read data in the target
>             byte ordering.  We should push the LE/BE request down into io.  */
>          val = TGT_BE(val);
> -        glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr);
> +        glue(io_write, SUFFIX)(env, iotlbentry, val, addr, retaddr);
>          return;
>      }
>  
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 04/14] Add MemTxAttrs to the IOTLB
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 04/14] Add MemTxAttrs to the IOTLB Peter Maydell
  2015-04-08 10:53   ` Paolo Bonzini
@ 2015-04-09  9:04   ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09  9:04 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:50PM +0100, Peter Maydell wrote:
> Add a MemTxAttrs field to the IOTLB, and allow target-specific
> code to set it via a new tlb_set_page_with_attrs() function;
> pass the attributes through to the device when making IO accesses.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> ---
>  cputlb.c                | 18 +++++++++++++++---
>  include/exec/cpu-defs.h |  2 ++
>  include/exec/exec-all.h |  3 +++
>  softmmu_template.h      |  4 ++--
>  4 files changed, 22 insertions(+), 5 deletions(-)
> 
> diff --git a/cputlb.c b/cputlb.c
> index 5e1cb8f..7606548 100644
> --- a/cputlb.c
> +++ b/cputlb.c
> @@ -249,9 +249,9 @@ static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
>   * Called from TCG-generated code, which is under an RCU read-side
>   * critical section.
>   */
> -void tlb_set_page(CPUState *cpu, target_ulong vaddr,
> -                  hwaddr paddr, int prot,
> -                  int mmu_idx, target_ulong size)
> +void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
> +                             hwaddr paddr, MemTxAttrs attrs, int prot,
> +                             int mmu_idx, target_ulong size)
>  {
>      CPUArchState *env = cpu->env_ptr;
>      MemoryRegionSection *section;
> @@ -302,6 +302,7 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
>  
>      /* refill the tlb */
>      env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
> +    env->iotlb[mmu_idx][index].attrs = attrs;
>      te->addend = addend - vaddr;
>      if (prot & PAGE_READ) {
>          te->addr_read = address;
> @@ -331,6 +332,17 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
>      }
>  }
>  
> +/* Add a new TLB entry, but without specifying the memory
> + * transaction attributes to be used.
> + */
> +void tlb_set_page(CPUState *cpu, target_ulong vaddr,
> +                  hwaddr paddr, int prot,
> +                  int mmu_idx, target_ulong size)
> +{
> +    tlb_set_page_with_attrs(cpu, vaddr, paddr, MEMTXATTRS_UNSPECIFIED,
> +                            prot, mmu_idx, size);
> +}
> +
>  /* NOTE: this function can trigger an exception */
>  /* NOTE2: the returned address is not exactly the physical address: it
>   * is actually a ram_addr_t (in system mode; the user mode emulation
> diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
> index 7f88185..3f56546 100644
> --- a/include/exec/cpu-defs.h
> +++ b/include/exec/cpu-defs.h
> @@ -30,6 +30,7 @@
>  #ifndef CONFIG_USER_ONLY
>  #include "exec/hwaddr.h"
>  #endif
> +#include "exec/memattrs.h"
>  
>  #ifndef TARGET_LONG_BITS
>  #error TARGET_LONG_BITS must be defined before including this header
> @@ -109,6 +110,7 @@ QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
>   */
>  typedef struct CPUIOTLBEntry {
>      hwaddr addr;
> +    MemTxAttrs attrs;
>  } CPUIOTLBEntry;
>  
>  #define CPU_COMMON_TLB \
> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index ff1bc3e..b58cd47 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -105,6 +105,9 @@ void tlb_flush(CPUState *cpu, int flush_global);
>  void tlb_set_page(CPUState *cpu, target_ulong vaddr,
>                    hwaddr paddr, int prot,
>                    int mmu_idx, target_ulong size);
> +void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
> +                             hwaddr paddr, MemTxAttrs attrs,
> +                             int prot, int mmu_idx, target_ulong size);
>  void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr);
>  #else
>  static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
> diff --git a/softmmu_template.h b/softmmu_template.h
> index 7a36550..7310a93 100644
> --- a/softmmu_template.h
> +++ b/softmmu_template.h
> @@ -159,7 +159,7 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
>      }
>  
>      cpu->mem_io_vaddr = addr;
> -    io_mem_read(mr, physaddr, &val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
> +    io_mem_read(mr, physaddr, &val, 1 << SHIFT, iotlbentry->attrs);
>      return val;
>  }
>  #endif
> @@ -380,7 +380,7 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
>  
>      cpu->mem_io_vaddr = addr;
>      cpu->mem_io_pc = retaddr;
> -    io_mem_write(mr, physaddr, val, 1 << SHIFT, MEMTXATTRS_UNSPECIFIED);
> +    io_mem_write(mr, physaddr, val, 1 << SHIFT, iotlbentry->attrs);
>  }
>  
>  void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status
  2015-04-09  8:55   ` Edgar E. Iglesias
@ 2015-04-09  9:04     ` Peter Maydell
  2015-04-09  9:21       ` Paolo Bonzini
  2015-04-09  9:32       ` Edgar E. Iglesias
  0 siblings, 2 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-09  9:04 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On 9 April 2015 at 09:55, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> Did you consider using a struct here?
> e.g:
>
> typedef struct MemTxAttrs {
>     unsigned int secure : 1;
>     unsigned int master_id : 10;
>     unsigned int etc : 1;
> } MemTxAttrs;
>
> I think you could still pass it by value and my understanding is
> that the compiler will generate similar code.

We discussed this last time round, I think. Whether structs get
passed in registers depends on the host CPU ABI/calling convention.

> I find it more readable, you ca go:
>
> attrs.secure = 1;
> attrs.master_id = 0x77;
> if (!attrs.secure)
>
> instead of:
>
> attrs |= MEMTXATTRS_SECURE
> if (!(attrs & MEMTXATTRS_SECURE))
>
> etc...
>
> Or do you see any disadvantages with this?

I prefer the traditional integer-and-bitops approach, then you
know what you're getting everywhere...

-- PMM

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 05/14] exec.c: Convert subpage memory ops to _with_attrs
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 05/14] exec.c: Convert subpage memory ops to _with_attrs Peter Maydell
  2015-04-08 10:54   ` Paolo Bonzini
@ 2015-04-09  9:07   ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09  9:07 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:51PM +0100, Peter Maydell wrote:
> Convert the subpage memory ops to _with_attrs; this will allow
> us to pass the attributes through to the underlying access
> functions.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> ---
>  exec.c | 33 +++++++++++++++++++++------------
>  1 file changed, 21 insertions(+), 12 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index 52e7a2a..7e53f52 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -1941,8 +1941,8 @@ static const MemoryRegionOps watch_mem_ops = {
>      .endianness = DEVICE_NATIVE_ENDIAN,
>  };
>  
> -static uint64_t subpage_read(void *opaque, hwaddr addr,
> -                             unsigned len)
> +static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
> +                                unsigned len, MemTxAttrs attrs)
>  {
>      subpage_t *subpage = opaque;
>      uint8_t buf[8];
> @@ -1951,23 +1951,29 @@ static uint64_t subpage_read(void *opaque, hwaddr addr,
>      printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
>             subpage, len, addr);
>  #endif
> -    address_space_read(subpage->as, addr + subpage->base, buf, len);
> +    if (address_space_read(subpage->as, addr + subpage->base, buf, len)) {
> +        return MEMTX_DECODE_ERROR;
> +    }
>      switch (len) {
>      case 1:
> -        return ldub_p(buf);
> +        *data = ldub_p(buf);
> +        return MEMTX_OK;
>      case 2:
> -        return lduw_p(buf);
> +        *data = lduw_p(buf);
> +        return MEMTX_OK;
>      case 4:
> -        return ldl_p(buf);
> +        *data = ldl_p(buf);
> +        return MEMTX_OK;
>      case 8:
> -        return ldq_p(buf);
> +        *data = ldq_p(buf);
> +        return MEMTX_OK;
>      default:
>          abort();
>      }
>  }
>  
> -static void subpage_write(void *opaque, hwaddr addr,
> -                          uint64_t value, unsigned len)
> +static MemTxResult subpage_write(void *opaque, hwaddr addr,
> +                                 uint64_t value, unsigned len, MemTxAttrs attrs)
>  {
>      subpage_t *subpage = opaque;
>      uint8_t buf[8];
> @@ -1993,7 +1999,10 @@ static void subpage_write(void *opaque, hwaddr addr,
>      default:
>          abort();
>      }
> -    address_space_write(subpage->as, addr + subpage->base, buf, len);
> +    if (address_space_write(subpage->as, addr + subpage->base, buf, len)) {
> +        return MEMTX_DECODE_ERROR;
> +    }
> +    return MEMTX_OK;
>  }
>  
>  static bool subpage_accepts(void *opaque, hwaddr addr,
> @@ -2010,8 +2019,8 @@ static bool subpage_accepts(void *opaque, hwaddr addr,
>  }
>  
>  static const MemoryRegionOps subpage_ops = {
> -    .read = subpage_read,
> -    .write = subpage_write,
> +    .read_with_attrs = subpage_read,
> +    .write_with_attrs = subpage_write,
>      .impl.min_access_size = 1,
>      .impl.max_access_size = 8,
>      .valid.min_access_size = 1,
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status
  2015-04-09  9:04     ` Peter Maydell
@ 2015-04-09  9:21       ` Paolo Bonzini
  2015-04-10  2:07         ` Edgar E. Iglesias
  2015-04-09  9:32       ` Edgar E. Iglesias
  1 sibling, 1 reply; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-09  9:21 UTC (permalink / raw)
  To: Peter Maydell, Edgar E. Iglesias
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Alex Bennée, Richard Henderson



On 09/04/2015 11:04, Peter Maydell wrote:
> We discussed this last time round, I think. Whether structs get
> passed in registers depends on the host CPU ABI/calling convention.

Because of C++, structs up to pointer size are in practice always passed
in registers.  64-bit structs may or may not.

The main advantage of structs is that it's impossible to mismatch the
parameter order.  That even trumps readability in my opinion.

I'm ambivalent, but I wouldn't mind at all using structs.

Paolo

>> > I find it more readable, you ca go:
>> >
>> > attrs.secure = 1;
>> > attrs.master_id = 0x77;
>> > if (!attrs.secure)
>> >
>> > instead of:
>> >
>> > attrs |= MEMTXATTRS_SECURE
>> > if (!(attrs & MEMTXATTRS_SECURE))
>> >
>> > etc...
>> >
>> > Or do you see any disadvantages with this?
> I prefer the traditional integer-and-bitops approach, then you
> know what you're getting everywhere...

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status
  2015-04-09  9:04     ` Peter Maydell
  2015-04-09  9:21       ` Paolo Bonzini
@ 2015-04-09  9:32       ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09  9:32 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Thu, Apr 09, 2015 at 10:04:39AM +0100, Peter Maydell wrote:
> On 9 April 2015 at 09:55, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> > Did you consider using a struct here?
> > e.g:
> >
> > typedef struct MemTxAttrs {
> >     unsigned int secure : 1;
> >     unsigned int master_id : 10;
> >     unsigned int etc : 1;
> > } MemTxAttrs;
> >
> > I think you could still pass it by value and my understanding is
> > that the compiler will generate similar code.
> 
> We discussed this last time round, I think. Whether structs get
> passed in registers depends on the host CPU ABI/calling convention.

Ah sorry, I must have missed that response...

> 
> > I find it more readable, you ca go:
> >
> > attrs.secure = 1;
> > attrs.master_id = 0x77;
> > if (!attrs.secure)
> >
> > instead of:
> >
> > attrs |= MEMTXATTRS_SECURE
> > if (!(attrs & MEMTXATTRS_SECURE))
> >
> > etc...
> >
> > Or do you see any disadvantages with this?
> 
> I prefer the traditional integer-and-bitops approach, then you
> know what you're getting everywhere...

OK :-)

Cheers,
Edgar

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM
  2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
                   ` (13 preceding siblings ...)
  2015-04-07 20:10 ` [Qemu-devel] [PATCH 14/14] target-arm: Check watchpoints against CPU security state Peter Maydell
@ 2015-04-09  9:37 ` Edgar E. Iglesias
  14 siblings, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09  9:37 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:46PM +0100, Peter Maydell wrote:
> Following from my previous RFC about transaction memory attributes,
> here's some code I think is good enough to drop the 'RFC' tag :-)
> (read: I would like to land this when master reopens for 2.4.)
> 
> I've included both the changes to the core memory system code
> and the target-arm changes as a usage example, but the ARM stuff
> is all at the end of the series, so if we want to split it and
> take it via separate subtrees that's fine.

Hi Peter,

More of a general comment. This is maybe follow-up patches but
at somepoint we will need to add attributes to the IOMMU
translate functions.

Thanks,
Edgar


> 
> I think I have followed the outcome of our discussions on the
> RFC; please let me know if I got confused or missed something.
> What we have here is:
>  * MemoryRegions can provide read_with_attrs and write_with_attrs
>    so they can get memory attributes and return a success/error
>    indication
>  * the attributes and error indication are plumbed through the
>    core memory system code
>  * new functions address_space_ld*/st* are provided which are
>    like the old ld/st*_phys but have extra args for MemTxAttrs
>    and MemTxResult*
>  * callers have been auto-converted from the old ld/st*_phys
>    unless they were using the CPUState::as address space
>    [those will be moved to some cpu-specific API later]
>  * TCG frontends can use tlb_set_page_with_attrs() to provide
>    attributes when they add an entry to the TLB
>  * two attributes: MEMTXATTRS_SECURE [ARM TrustZone secure access]
>    and MEMTXATTRS_USER [access is unprivileged], both implemented
>    for the ARM CPU frontend (these both correspond to AMBA/AXI
>    bus sideband signals, more or less)
> 
> 
> I believe this code contains enough changes that all the memory
> transactions issued by the ARM CPU will correctly be marked as
> S or NS. Obviously nothing currently pays attention to this, but
> the patches to make the GIC model support TrustZone can be easily
> wired up to this.
> 
> The diffstat's quite big but the biggest patch is a Coccinelle
> generated automated rename of the callers of ld/st*_phys to
> address_space_ld/st* where they don't use the CPUState::as.
> 
> thanks
> -- PMM
> 
> Peter Maydell (14):
>   memory: Define API for MemoryRegionOps to take attrs and return status
>   memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write
>   Make CPU iotlb a structure rather than a plain hwaddr
>   Add MemTxAttrs to the IOTLB
>   exec.c: Convert subpage memory ops to _with_attrs
>   exec.c: Make address_space_rw take transaction attributes
>   exec.c: Add new address_space_ld*/st* functions
>   Switch non-CPU callers from ld/st*_phys to address_space_ld/st*
>   exec.c: Capture the memory attributes for a watchpoint hit
>   target-arm: Honour NS bits in page tables
>   target-arm: Use correct memory attributes for page table walks
>   target-arm: Add user-mode transaction attribute
>   target-arm: Use attribute info to handle user-only watchpoints
>   target-arm: Check watchpoints against CPU security state
> 
>  cputlb.c                          |  22 +-
>  dma-helpers.c                     |   3 +-
>  exec.c                            | 418 +++++++++++++++++++++++++++++---------
>  hw/alpha/dp264.c                  |   9 +-
>  hw/alpha/typhoon.c                |   3 +-
>  hw/arm/boot.c                     |   6 +-
>  hw/arm/highbank.c                 |  12 +-
>  hw/dma/pl080.c                    |  20 +-
>  hw/dma/sun4m_iommu.c              |   3 +-
>  hw/i386/intel_iommu.c             |   3 +-
>  hw/mips/mips_jazz.c               |   6 +-
>  hw/pci-host/apb.c                 |   3 +-
>  hw/pci-host/prep.c                |   6 +-
>  hw/pci/msi.c                      |   3 +-
>  hw/pci/msix.c                     |   3 +-
>  hw/s390x/css.c                    |  19 +-
>  hw/s390x/s390-pci-bus.c           |   9 +-
>  hw/s390x/s390-pci-inst.c          |   7 +-
>  hw/s390x/s390-virtio-bus.c        |  73 ++++---
>  hw/s390x/s390-virtio.c            |   4 +-
>  hw/s390x/virtio-ccw.c             |  87 +++++---
>  hw/sh4/r2d.c                      |   6 +-
>  hw/timer/hpet.c                   |   5 +-
>  hw/vfio/pci.c                     |   4 +-
>  include/exec/cpu-defs.h           |  15 +-
>  include/exec/exec-all.h           |   7 +-
>  include/exec/memattrs.h           |  40 ++++
>  include/exec/memory.h             | 128 +++++++++++-
>  include/qom/cpu.h                 |   2 +
>  include/sysemu/dma.h              |   3 +-
>  ioport.c                          |  16 +-
>  kvm-all.c                         |   3 +-
>  memory.c                          | 212 ++++++++++++-------
>  monitor.c                         |   3 +-
>  scripts/coverity-model.c          |   8 +-
>  softmmu_template.h                |  36 ++--
>  target-arm/helper.c               | 134 ++++++++++--
>  target-arm/op_helper.c            |  29 +--
>  target-i386/arch_memory_mapping.c |  15 +-
>  39 files changed, 1038 insertions(+), 347 deletions(-)
>  create mode 100644 include/exec/memattrs.h
> 
> -- 
> 1.9.1
> 
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes Peter Maydell
  2015-04-08 12:55   ` Paolo Bonzini
@ 2015-04-09  9:59   ` Edgar E. Iglesias
  2015-04-09 10:14     ` Peter Maydell
  1 sibling, 1 reply; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09  9:59 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:52PM +0100, Peter Maydell wrote:
> Make address_space_rw take transaction attributes, rather
> than always using the 'unspecified' attributes.

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

I guess that we eventually will need to convert the dma_
functions?



> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  dma-helpers.c            |  3 ++-
>  exec.c                   | 51 ++++++++++++++++++++++++++----------------------
>  hw/mips/mips_jazz.c      |  6 ++++--
>  hw/pci-host/prep.c       |  6 ++++--
>  include/exec/memory.h    | 31 ++++++++++++++++++-----------
>  include/sysemu/dma.h     |  3 ++-
>  ioport.c                 | 16 +++++++++------
>  kvm-all.c                |  3 ++-
>  scripts/coverity-model.c |  8 +++++---
>  9 files changed, 77 insertions(+), 50 deletions(-)
> 
> diff --git a/dma-helpers.c b/dma-helpers.c
> index 6918572..33b1983 100644
> --- a/dma-helpers.c
> +++ b/dma-helpers.c
> @@ -28,7 +28,8 @@ int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len)
>      memset(fillbuf, c, FILLBUF_SIZE);
>      while (len > 0) {
>          l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
> -        error |= address_space_rw(as, addr, fillbuf, l, true);
> +        error |= address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED,
> +                                  fillbuf, l, true);
>          len -= l;
>          addr += l;
>      }
> diff --git a/exec.c b/exec.c
> index 7e53f52..29a12fa 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -1946,13 +1946,16 @@ static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
>  {
>      subpage_t *subpage = opaque;
>      uint8_t buf[8];
> +    MemTxResult res;
>  
>  #if defined(DEBUG_SUBPAGE)
>      printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
>             subpage, len, addr);
>  #endif
> -    if (address_space_read(subpage->as, addr + subpage->base, buf, len)) {
> -        return MEMTX_DECODE_ERROR;
> +    res = address_space_read(subpage->as, addr + subpage->base,
> +                             attrs, buf, len);
> +    if (res) {
> +        return res;
>      }
>      switch (len) {
>      case 1:
> @@ -1999,10 +2002,8 @@ static MemTxResult subpage_write(void *opaque, hwaddr addr,
>      default:
>          abort();
>      }
> -    if (address_space_write(subpage->as, addr + subpage->base, buf, len)) {
> -        return MEMTX_DECODE_ERROR;
> -    }
> -    return MEMTX_OK;
> +    return address_space_write(subpage->as, addr + subpage->base,
> +                               attrs, buf, len);
>  }
>  
>  static bool subpage_accepts(void *opaque, hwaddr addr,
> @@ -2313,8 +2314,8 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
>      return l;
>  }
>  
> -bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
> -                      int len, bool is_write)
> +MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
> +                             uint8_t *buf, int len, bool is_write)
>  {
>      hwaddr l;
>      uint8_t *ptr;
> @@ -2322,7 +2323,6 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>      hwaddr addr1;
>      MemoryRegion *mr;
>      MemTxResult result = MEMTX_OK;
> -    MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
>  
>      while (len > 0) {
>          l = len;
> @@ -2406,22 +2406,24 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>      return result;
>  }
>  
> -bool address_space_write(AddressSpace *as, hwaddr addr,
> -                         const uint8_t *buf, int len)
> +MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
> +                                const uint8_t *buf, int len)
>  {
> -    return address_space_rw(as, addr, (uint8_t *)buf, len, true);
> +    return address_space_rw(as, addr, attrs, (uint8_t *)buf, len, true);
>  }
>  
> -bool address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len)
> +MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
> +                               uint8_t *buf, int len)
>  {
> -    return address_space_rw(as, addr, buf, len, false);
> +    return address_space_rw(as, addr, attrs, buf, len, false);
>  }
>  
>  
>  void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
>                              int len, int is_write)
>  {
> -    address_space_rw(&address_space_memory, addr, buf, len, is_write);
> +    address_space_rw(&address_space_memory, addr, MEMTXATTRS_UNSPECIFIED,
> +                     buf, len, is_write);
>  }
>  
>  enum write_rom_type {
> @@ -2592,7 +2594,8 @@ void *address_space_map(AddressSpace *as,
>          memory_region_ref(mr);
>          bounce.mr = mr;
>          if (!is_write) {
> -            address_space_read(as, addr, bounce.buffer, l);
> +            address_space_read(as, addr, MEMTXATTRS_UNSPECIFIED,
> +                               bounce.buffer, l);
>          }
>  
>          *plen = l;
> @@ -2645,7 +2648,8 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
>          return;
>      }
>      if (is_write) {
> -        address_space_write(as, bounce.addr, bounce.buffer, access_len);
> +        address_space_write(as, bounce.addr, MEMTXATTRS_UNSPECIFIED,
> +                            bounce.buffer, access_len);
>      }
>      qemu_vfree(bounce.buffer);
>      bounce.buffer = NULL;
> @@ -2787,7 +2791,7 @@ uint64_t ldq_be_phys(AddressSpace *as, hwaddr addr)
>  uint32_t ldub_phys(AddressSpace *as, hwaddr addr)
>  {
>      uint8_t val;
> -    address_space_rw(as, addr, &val, 1, 0);
> +    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, &val, 1, 0);
>      return val;
>  }
>  
> @@ -2941,7 +2945,7 @@ void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  {
>      uint8_t v = val;
> -    address_space_rw(as, addr, &v, 1, 1);
> +    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, &v, 1, 1);
>  }
>  
>  /* warning: addr must be aligned */
> @@ -3004,19 +3008,19 @@ void stw_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val)
>  {
>      val = tswap64(val);
> -    address_space_rw(as, addr, (void *) &val, 8, 1);
> +    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
>  }
>  
>  void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val)
>  {
>      val = cpu_to_le64(val);
> -    address_space_rw(as, addr, (void *) &val, 8, 1);
> +    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
>  }
>  
>  void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val)
>  {
>      val = cpu_to_be64(val);
> -    address_space_rw(as, addr, (void *) &val, 8, 1);
> +    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
>  }
>  
>  /* virtual memory access for debug (includes writing to ROM) */
> @@ -3040,7 +3044,8 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>          if (is_write) {
>              cpu_physical_memory_write_rom(cpu->as, phys_addr, buf, l);
>          } else {
> -            address_space_rw(cpu->as, phys_addr, buf, l, 0);
> +            address_space_rw(cpu->as, phys_addr, MEMTXATTRS_UNSPECIFIED,
> +                             buf, l, 0);
>          }
>          len -= l;
>          buf += l;
> diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
> index 07f3c27..2c153e0 100644
> --- a/hw/mips/mips_jazz.c
> +++ b/hw/mips/mips_jazz.c
> @@ -61,7 +61,8 @@ static void main_cpu_reset(void *opaque)
>  static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size)
>  {
>      uint8_t val;
> -    address_space_read(&address_space_memory, 0x90000071, &val, 1);
> +    address_space_read(&address_space_memory, 0x90000071,
> +                       MEMTXATTRS_UNSPECIFIED, &val, 1);
>      return val;
>  }
>  
> @@ -69,7 +70,8 @@ static void rtc_write(void *opaque, hwaddr addr,
>                        uint64_t val, unsigned size)
>  {
>      uint8_t buf = val & 0xff;
> -    address_space_write(&address_space_memory, 0x90000071, &buf, 1);
> +    address_space_write(&address_space_memory, 0x90000071,
> +                        MEMTXATTRS_UNSPECIFIED, &buf, 1);
>  }
>  
>  static const MemoryRegionOps rtc_ops = {
> diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
> index 6cea6ff..c63f45d 100644
> --- a/hw/pci-host/prep.c
> +++ b/hw/pci-host/prep.c
> @@ -140,7 +140,8 @@ static uint64_t raven_io_read(void *opaque, hwaddr addr,
>      uint8_t buf[4];
>  
>      addr = raven_io_address(s, addr);
> -    address_space_read(&s->pci_io_as, addr + 0x80000000, buf, size);
> +    address_space_read(&s->pci_io_as, addr + 0x80000000,
> +                       MEMTXATTRS_UNSPECIFIED, buf, size);
>  
>      if (size == 1) {
>          return buf[0];
> @@ -171,7 +172,8 @@ static void raven_io_write(void *opaque, hwaddr addr,
>          g_assert_not_reached();
>      }
>  
> -    address_space_write(&s->pci_io_as, addr + 0x80000000, buf, size);
> +    address_space_write(&s->pci_io_as, addr + 0x80000000,
> +                        MEMTXATTRS_UNSPECIFIED, buf, size);
>  }
>  
>  static const MemoryRegionOps raven_io_ops = {
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index de2849d..4d6afc8 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -1089,41 +1089,50 @@ void address_space_destroy(AddressSpace *as);
>  /**
>   * address_space_rw: read from or write to an address space.
>   *
> - * Return true if the operation hit any unassigned memory or encountered an
> - * IOMMU fault.
> + * Return a MemTxResult indicating whether the operation succeeded
> + * or failed (eg unassigned memory, device rejected the transaction,
> + * IOMMU fault).
>   *
>   * @as: #AddressSpace to be accessed
>   * @addr: address within that address space
> + * @attrs: memory transaction attributes
>   * @buf: buffer with the data transferred
>   * @is_write: indicates the transfer direction
>   */
> -bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
> -                      int len, bool is_write);
> +MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
> +                             MemTxAttrs attrs, uint8_t *buf,
> +                             int len, bool is_write);
>  
>  /**
>   * address_space_write: write to address space.
>   *
> - * Return true if the operation hit any unassigned memory or encountered an
> - * IOMMU fault.
> + * Return a MemTxResult indicating whether the operation succeeded
> + * or failed (eg unassigned memory, device rejected the transaction,
> + * IOMMU fault).
>   *
>   * @as: #AddressSpace to be accessed
>   * @addr: address within that address space
> + * @attrs: memory transaction attributes
>   * @buf: buffer with the data transferred
>   */
> -bool address_space_write(AddressSpace *as, hwaddr addr,
> -                         const uint8_t *buf, int len);
> +MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
> +                                MemTxAttrs attrs,
> +                                const uint8_t *buf, int len);
>  
>  /**
>   * address_space_read: read from an address space.
>   *
> - * Return true if the operation hit any unassigned memory or encountered an
> - * IOMMU fault.
> + * Return a MemTxResult indicating whether the operation succeeded
> + * or failed (eg unassigned memory, device rejected the transaction,
> + * IOMMU fault).
>   *
>   * @as: #AddressSpace to be accessed
>   * @addr: address within that address space
> + * @attrs: memory transaction attributes
>   * @buf: buffer with the data transferred
>   */
> -bool address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
> +MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
> +                               uint8_t *buf, int len);
>  
>  /* address_space_translate: translate an address range into an address space
>   * into a MemoryRegion and an address range into that section
> diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
> index 3f2f4c8..efa8b99 100644
> --- a/include/sysemu/dma.h
> +++ b/include/sysemu/dma.h
> @@ -88,7 +88,8 @@ static inline int dma_memory_rw_relaxed(AddressSpace *as, dma_addr_t addr,
>                                          void *buf, dma_addr_t len,
>                                          DMADirection dir)
>  {
> -    return address_space_rw(as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
> +    return (bool)address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED,
> +                                  buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
>  }
>  
>  static inline int dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr,
> diff --git a/ioport.c b/ioport.c
> index 783a3ae..b345bd9 100644
> --- a/ioport.c
> +++ b/ioport.c
> @@ -64,7 +64,8 @@ void cpu_outb(pio_addr_t addr, uint8_t val)
>  {
>      LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
>      trace_cpu_out(addr, val);
> -    address_space_write(&address_space_io, addr, &val, 1);
> +    address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
> +                        &val, 1);
>  }
>  
>  void cpu_outw(pio_addr_t addr, uint16_t val)
> @@ -74,7 +75,8 @@ void cpu_outw(pio_addr_t addr, uint16_t val)
>      LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
>      trace_cpu_out(addr, val);
>      stw_p(buf, val);
> -    address_space_write(&address_space_io, addr, buf, 2);
> +    address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
> +                        buf, 2);
>  }
>  
>  void cpu_outl(pio_addr_t addr, uint32_t val)
> @@ -84,14 +86,16 @@ void cpu_outl(pio_addr_t addr, uint32_t val)
>      LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
>      trace_cpu_out(addr, val);
>      stl_p(buf, val);
> -    address_space_write(&address_space_io, addr, buf, 4);
> +    address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
> +                        buf, 4);
>  }
>  
>  uint8_t cpu_inb(pio_addr_t addr)
>  {
>      uint8_t val;
>  
> -    address_space_read(&address_space_io, addr, &val, 1);
> +    address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
> +                       &val, 1);
>      trace_cpu_in(addr, val);
>      LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
>      return val;
> @@ -102,7 +106,7 @@ uint16_t cpu_inw(pio_addr_t addr)
>      uint8_t buf[2];
>      uint16_t val;
>  
> -    address_space_read(&address_space_io, addr, buf, 2);
> +    address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED, buf, 2);
>      val = lduw_p(buf);
>      trace_cpu_in(addr, val);
>      LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
> @@ -114,7 +118,7 @@ uint32_t cpu_inl(pio_addr_t addr)
>      uint8_t buf[4];
>      uint32_t val;
>  
> -    address_space_read(&address_space_io, addr, buf, 4);
> +    address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED, buf, 4);
>      val = ldl_p(buf);
>      trace_cpu_in(addr, val);
>      LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
> diff --git a/kvm-all.c b/kvm-all.c
> index dd44f8c..4ec153d 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -1667,7 +1667,8 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
>      uint8_t *ptr = data;
>  
>      for (i = 0; i < count; i++) {
> -        address_space_rw(&address_space_io, port, ptr, size,
> +        address_space_rw(&address_space_io, port, MEMTXATTRS_UNSPECIFIED,
> +                         ptr, size,
>                           direction == KVM_EXIT_IO_OUT);
>          ptr += size;
>      }
> diff --git a/scripts/coverity-model.c b/scripts/coverity-model.c
> index cdda259..224d2d1 100644
> --- a/scripts/coverity-model.c
> +++ b/scripts/coverity-model.c
> @@ -46,6 +46,8 @@ typedef struct va_list_str *va_list;
>  
>  typedef struct AddressSpace AddressSpace;
>  typedef uint64_t hwaddr;
> +typedef uint32_t MemTxResult;
> +typedef uint64_t MemTxAttrs;
>  
>  static void __write(uint8_t *buf, ssize_t len)
>  {
> @@ -65,10 +67,10 @@ static void __read(uint8_t *buf, ssize_t len)
>      int last = buf[len-1];
>  }
>  
> -bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
> -                      int len, bool is_write)
> +MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
> +                             uint8_t *buf, int len, bool is_write)
>  {
> -    bool result;
> +    MemTxResult result;
>  
>      // TODO: investigate impact of treating reads as producing
>      // tainted data, with __coverity_tainted_data_argument__(buf).
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes
  2015-04-09  9:59   ` Edgar E. Iglesias
@ 2015-04-09 10:14     ` Peter Maydell
  2015-04-09 10:21       ` Paolo Bonzini
  0 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-09 10:14 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On 9 April 2015 at 10:59, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> On Tue, Apr 07, 2015 at 09:09:52PM +0100, Peter Maydell wrote:
>> Make address_space_rw take transaction attributes, rather
>> than always using the 'unspecified' attributes.
>
> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>
> I guess that we eventually will need to convert the dma_
> functions?

Probably, though I'm not clear what they bring to the party
that the basic address_space_* functions don't (part of why
I left them alone).

-- PMM

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes
  2015-04-09 10:14     ` Peter Maydell
@ 2015-04-09 10:21       ` Paolo Bonzini
  2015-04-09 10:43         ` Peter Maydell
  0 siblings, 1 reply; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-09 10:21 UTC (permalink / raw)
  To: Peter Maydell, Edgar E. Iglesias
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Alex Bennée, Richard Henderson



On 09/04/2015 12:14, Peter Maydell wrote:
> On 9 April 2015 at 10:59, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
>> > On Tue, Apr 07, 2015 at 09:09:52PM +0100, Peter Maydell wrote:
>>> >> Make address_space_rw take transaction attributes, rather
>>> >> than always using the 'unspecified' attributes.
>> >
>> > Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>> >
>> > I guess that we eventually will need to convert the dma_
>> > functions?
> Probably, though I'm not clear what they bring to the party
> that the basic address_space_* functions don't (part of why
> I left them alone).

At this point, some memory barriers, basically.

Initially the IOMMU implementation was done in the dma_* functions
(using something called IIRC a DMAContext), but now they just take an
AddressSpace.

Paolo

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions Peter Maydell
  2015-04-08 11:03   ` Paolo Bonzini
@ 2015-04-09 10:34   ` Edgar E. Iglesias
  1 sibling, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09 10:34 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:53PM +0100, Peter Maydell wrote:
> Add new address_space_ld*/st* functions which allow transaction
> attributes and error reporting for basic load and stores. These
> are named to be in line with the address_space_read/write/rw
> buffer operations.
> 
> The existing ld/st*_phys functions are now wrappers around
> the new functions.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> ---
>  exec.c                | 291 ++++++++++++++++++++++++++++++++++++++++++--------
>  include/exec/memory.h |  63 +++++++++++
>  2 files changed, 310 insertions(+), 44 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index 29a12fa..013032a 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2671,19 +2671,22 @@ void cpu_physical_memory_unmap(void *buffer, hwaddr len,
>  }
>  
>  /* warning: addr must be aligned */
> -static inline uint32_t ldl_phys_internal(AddressSpace *as, hwaddr addr,
> -                                         enum device_endian endian)
> +static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr,
> +                                                  MemTxAttrs attrs,
> +                                                  MemTxResult *result,
> +                                                  enum device_endian endian)
>  {
>      uint8_t *ptr;
>      uint64_t val;
>      MemoryRegion *mr;
>      hwaddr l = 4;
>      hwaddr addr1;
> +    MemTxResult r;
>  
>      mr = address_space_translate(as, addr, &addr1, &l, false);
>      if (l < 4 || !memory_access_is_direct(mr, false)) {
>          /* I/O case */
> -        io_mem_read(mr, addr1, &val, 4, MEMTXATTRS_UNSPECIFIED);
> +        r = io_mem_read(mr, addr1, &val, 4, attrs);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap32(val);
> @@ -2709,40 +2712,68 @@ static inline uint32_t ldl_phys_internal(AddressSpace *as, hwaddr addr,
>              val = ldl_p(ptr);
>              break;
>          }
> +        r = MEMTX_OK;
> +    }
> +    if (result) {
> +        *result = r;
>      }
>      return val;
>  }
>  
> +uint32_t address_space_ldl(AddressSpace *as, hwaddr addr,
> +                           MemTxAttrs attrs, MemTxResult *result)
> +{
> +    return address_space_ldl_internal(as, addr, attrs, result,
> +                                      DEVICE_NATIVE_ENDIAN);
> +}
> +
> +uint32_t address_space_ldl_le(AddressSpace *as, hwaddr addr,
> +                              MemTxAttrs attrs, MemTxResult *result)
> +{
> +    return address_space_ldl_internal(as, addr, attrs, result,
> +                                      DEVICE_LITTLE_ENDIAN);
> +}
> +
> +uint32_t address_space_ldl_be(AddressSpace *as, hwaddr addr,
> +                              MemTxAttrs attrs, MemTxResult *result)
> +{
> +    return address_space_ldl_internal(as, addr, attrs, result,
> +                                      DEVICE_BIG_ENDIAN);
> +}
> +
>  uint32_t ldl_phys(AddressSpace *as, hwaddr addr)
>  {
> -    return ldl_phys_internal(as, addr, DEVICE_NATIVE_ENDIAN);
> +    return address_space_ldl(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  uint32_t ldl_le_phys(AddressSpace *as, hwaddr addr)
>  {
> -    return ldl_phys_internal(as, addr, DEVICE_LITTLE_ENDIAN);
> +    return address_space_ldl_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  uint32_t ldl_be_phys(AddressSpace *as, hwaddr addr)
>  {
> -    return ldl_phys_internal(as, addr, DEVICE_BIG_ENDIAN);
> +    return address_space_ldl_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  /* warning: addr must be aligned */
> -static inline uint64_t ldq_phys_internal(AddressSpace *as, hwaddr addr,
> -                                         enum device_endian endian)
> +static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr,
> +                                                  MemTxAttrs attrs,
> +                                                  MemTxResult *result,
> +                                                  enum device_endian endian)
>  {
>      uint8_t *ptr;
>      uint64_t val;
>      MemoryRegion *mr;
>      hwaddr l = 8;
>      hwaddr addr1;
> +    MemTxResult r;
>  
>      mr = address_space_translate(as, addr, &addr1, &l,
>                                   false);
>      if (l < 8 || !memory_access_is_direct(mr, false)) {
>          /* I/O case */
> -        io_mem_read(mr, addr1, &val, 8, MEMTXATTRS_UNSPECIFIED);
> +        r = io_mem_read(mr, addr1, &val, 8, attrs);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap64(val);
> @@ -2768,48 +2799,88 @@ static inline uint64_t ldq_phys_internal(AddressSpace *as, hwaddr addr,
>              val = ldq_p(ptr);
>              break;
>          }
> +        r = MEMTX_OK;
> +    }
> +    if (result) {
> +        *result = r;
>      }
>      return val;
>  }
>  
> +uint64_t address_space_ldq(AddressSpace *as, hwaddr addr,
> +                           MemTxAttrs attrs, MemTxResult *result)
> +{
> +    return address_space_ldq_internal(as, addr, attrs, result,
> +                                      DEVICE_NATIVE_ENDIAN);
> +}
> +
> +uint64_t address_space_ldq_le(AddressSpace *as, hwaddr addr,
> +                           MemTxAttrs attrs, MemTxResult *result)
> +{
> +    return address_space_ldq_internal(as, addr, attrs, result,
> +                                      DEVICE_LITTLE_ENDIAN);
> +}
> +
> +uint64_t address_space_ldq_be(AddressSpace *as, hwaddr addr,
> +                           MemTxAttrs attrs, MemTxResult *result)
> +{
> +    return address_space_ldq_internal(as, addr, attrs, result,
> +                                      DEVICE_BIG_ENDIAN);
> +}
> +
>  uint64_t ldq_phys(AddressSpace *as, hwaddr addr)
>  {
> -    return ldq_phys_internal(as, addr, DEVICE_NATIVE_ENDIAN);
> +    return address_space_ldq(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  uint64_t ldq_le_phys(AddressSpace *as, hwaddr addr)
>  {
> -    return ldq_phys_internal(as, addr, DEVICE_LITTLE_ENDIAN);
> +    return address_space_ldq_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  uint64_t ldq_be_phys(AddressSpace *as, hwaddr addr)
>  {
> -    return ldq_phys_internal(as, addr, DEVICE_BIG_ENDIAN);
> +    return address_space_ldq_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  /* XXX: optimize */
> -uint32_t ldub_phys(AddressSpace *as, hwaddr addr)
> +uint32_t address_space_ldub(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result)
>  {
>      uint8_t val;
> -    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, &val, 1, 0);
> +    MemTxResult r;
> +
> +    r = address_space_rw(as, addr, attrs, &val, 1, 0);
> +    if (result) {
> +        *result = r;
> +    }
>      return val;
>  }
>  
> +uint32_t ldub_phys(AddressSpace *as, hwaddr addr)
> +{
> +    return address_space_ldub(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
> +}
> +
>  /* warning: addr must be aligned */
> -static inline uint32_t lduw_phys_internal(AddressSpace *as, hwaddr addr,
> -                                          enum device_endian endian)
> +static inline uint32_t address_space_lduw_internal(AddressSpace *as,
> +                                                   hwaddr addr,
> +                                                   MemTxAttrs attrs,
> +                                                   MemTxResult *result,
> +                                                   enum device_endian endian)
>  {
>      uint8_t *ptr;
>      uint64_t val;
>      MemoryRegion *mr;
>      hwaddr l = 2;
>      hwaddr addr1;
> +    MemTxResult r;
>  
>      mr = address_space_translate(as, addr, &addr1, &l,
>                                   false);
>      if (l < 2 || !memory_access_is_direct(mr, false)) {
>          /* I/O case */
> -        io_mem_read(mr, addr1, &val, 2, MEMTXATTRS_UNSPECIFIED);
> +        r = io_mem_read(mr, addr1, &val, 2, attrs);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap16(val);
> @@ -2835,39 +2906,66 @@ static inline uint32_t lduw_phys_internal(AddressSpace *as, hwaddr addr,
>              val = lduw_p(ptr);
>              break;
>          }
> +        r = MEMTX_OK;
> +    }
> +    if (result) {
> +        *result = r;
>      }
>      return val;
>  }
>  
> +uint32_t address_space_lduw(AddressSpace *as, hwaddr addr,
> +                           MemTxAttrs attrs, MemTxResult *result)
> +{
> +    return address_space_lduw_internal(as, addr, attrs, result,
> +                                       DEVICE_NATIVE_ENDIAN);
> +}
> +
> +uint32_t address_space_lduw_le(AddressSpace *as, hwaddr addr,
> +                           MemTxAttrs attrs, MemTxResult *result)
> +{
> +    return address_space_lduw_internal(as, addr, attrs, result,
> +                                       DEVICE_LITTLE_ENDIAN);
> +}
> +
> +uint32_t address_space_lduw_be(AddressSpace *as, hwaddr addr,
> +                           MemTxAttrs attrs, MemTxResult *result)
> +{
> +    return address_space_lduw_internal(as, addr, attrs, result,
> +                                       DEVICE_BIG_ENDIAN);
> +}
> +
>  uint32_t lduw_phys(AddressSpace *as, hwaddr addr)
>  {
> -    return lduw_phys_internal(as, addr, DEVICE_NATIVE_ENDIAN);
> +    return address_space_lduw(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  uint32_t lduw_le_phys(AddressSpace *as, hwaddr addr)
>  {
> -    return lduw_phys_internal(as, addr, DEVICE_LITTLE_ENDIAN);
> +    return address_space_lduw_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  uint32_t lduw_be_phys(AddressSpace *as, hwaddr addr)
>  {
> -    return lduw_phys_internal(as, addr, DEVICE_BIG_ENDIAN);
> +    return address_space_lduw_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  /* warning: addr must be aligned. The ram page is not masked as dirty
>     and the code inside is not invalidated. It is useful if the dirty
>     bits are used to track modified PTEs */
> -void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
> +void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
> +                                MemTxAttrs attrs, MemTxResult *result)
>  {
>      uint8_t *ptr;
>      MemoryRegion *mr;
>      hwaddr l = 4;
>      hwaddr addr1;
> +    MemTxResult r;
>  
>      mr = address_space_translate(as, addr, &addr1, &l,
>                                   true);
>      if (l < 4 || !memory_access_is_direct(mr, true)) {
> -        io_mem_write(mr, addr1, val, 4, MEMTXATTRS_UNSPECIFIED);
> +        r = io_mem_write(mr, addr1, val, 4, attrs);
>      } else {
>          addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
>          ptr = qemu_get_ram_ptr(addr1);
> @@ -2881,18 +2979,30 @@ void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
>                  cpu_physical_memory_set_dirty_range_nocode(addr1, 4);
>              }
>          }
> +        r = MEMTX_OK;
> +    }
> +    if (result) {
> +        *result = r;
>      }
>  }
>  
> +void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
> +{
> +    address_space_stl_notdirty(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
> +}
> +
>  /* warning: addr must be aligned */
> -static inline void stl_phys_internal(AddressSpace *as,
> -                                     hwaddr addr, uint32_t val,
> -                                     enum device_endian endian)
> +static inline void address_space_stl_internal(AddressSpace *as,
> +                                              hwaddr addr, uint32_t val,
> +                                              MemTxAttrs attrs,
> +                                              MemTxResult *result,
> +                                              enum device_endian endian)
>  {
>      uint8_t *ptr;
>      MemoryRegion *mr;
>      hwaddr l = 4;
>      hwaddr addr1;
> +    MemTxResult r;
>  
>      mr = address_space_translate(as, addr, &addr1, &l,
>                                   true);
> @@ -2906,7 +3016,7 @@ static inline void stl_phys_internal(AddressSpace *as,
>              val = bswap32(val);
>          }
>  #endif
> -        io_mem_write(mr, addr1, val, 4, MEMTXATTRS_UNSPECIFIED);
> +        r = io_mem_write(mr, addr1, val, 4, attrs);
>      } else {
>          /* RAM case */
>          addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
> @@ -2923,40 +3033,79 @@ static inline void stl_phys_internal(AddressSpace *as,
>              break;
>          }
>          invalidate_and_set_dirty(addr1, 4);
> +        r = MEMTX_OK;
> +    }
> +    if (result) {
> +        *result = r;
>      }
>  }
>  
> +void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
> +                       MemTxAttrs attrs, MemTxResult *result)
> +{
> +    address_space_stl_internal(as, addr, val, attrs, result,
> +                               DEVICE_NATIVE_ENDIAN);
> +}
> +
> +void address_space_stl_le(AddressSpace *as, hwaddr addr, uint32_t val,
> +                       MemTxAttrs attrs, MemTxResult *result)
> +{
> +    address_space_stl_internal(as, addr, val, attrs, result,
> +                               DEVICE_LITTLE_ENDIAN);
> +}
> +
> +void address_space_stl_be(AddressSpace *as, hwaddr addr, uint32_t val,
> +                       MemTxAttrs attrs, MemTxResult *result)
> +{
> +    address_space_stl_internal(as, addr, val, attrs, result,
> +                               DEVICE_BIG_ENDIAN);
> +}
> +
>  void stl_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  {
> -    stl_phys_internal(as, addr, val, DEVICE_NATIVE_ENDIAN);
> +    address_space_stl(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  void stl_le_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  {
> -    stl_phys_internal(as, addr, val, DEVICE_LITTLE_ENDIAN);
> +    address_space_stl_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  {
> -    stl_phys_internal(as, addr, val, DEVICE_BIG_ENDIAN);
> +    address_space_stl_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  /* XXX: optimize */
> -void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val)
> +void address_space_stb(AddressSpace *as, hwaddr addr, uint32_t val,
> +                       MemTxAttrs attrs, MemTxResult *result)
>  {
>      uint8_t v = val;
> -    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, &v, 1, 1);
> +    MemTxResult r;
> +
> +    r = address_space_rw(as, addr, attrs, &v, 1, 1);
> +    if (result) {
> +        *result = r;
> +    }
> +}
> +
> +void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val)
> +{
> +    address_space_stb(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  /* warning: addr must be aligned */
> -static inline void stw_phys_internal(AddressSpace *as,
> -                                     hwaddr addr, uint32_t val,
> -                                     enum device_endian endian)
> +static inline void address_space_stw_internal(AddressSpace *as,
> +                                              hwaddr addr, uint32_t val,
> +                                              MemTxAttrs attrs,
> +                                              MemTxResult *result,
> +                                              enum device_endian endian)
>  {
>      uint8_t *ptr;
>      MemoryRegion *mr;
>      hwaddr l = 2;
>      hwaddr addr1;
> +    MemTxResult r;
>  
>      mr = address_space_translate(as, addr, &addr1, &l, true);
>      if (l < 2 || !memory_access_is_direct(mr, true)) {
> @@ -2969,7 +3118,7 @@ static inline void stw_phys_internal(AddressSpace *as,
>              val = bswap16(val);
>          }
>  #endif
> -        io_mem_write(mr, addr1, val, 2, MEMTXATTRS_UNSPECIFIED);
> +        r = io_mem_write(mr, addr1, val, 2, attrs);
>      } else {
>          /* RAM case */
>          addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
> @@ -2986,41 +3135,95 @@ static inline void stw_phys_internal(AddressSpace *as,
>              break;
>          }
>          invalidate_and_set_dirty(addr1, 2);
> +        r = MEMTX_OK;
> +    }
> +    if (result) {
> +        *result = r;
>      }
>  }
>  
> +void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val,
> +                       MemTxAttrs attrs, MemTxResult *result)
> +{
> +    address_space_stw_internal(as, addr, val, attrs, result,
> +                               DEVICE_NATIVE_ENDIAN);
> +}
> +
> +void address_space_stw_le(AddressSpace *as, hwaddr addr, uint32_t val,
> +                       MemTxAttrs attrs, MemTxResult *result)
> +{
> +    address_space_stw_internal(as, addr, val, attrs, result,
> +                               DEVICE_LITTLE_ENDIAN);
> +}
> +
> +void address_space_stw_be(AddressSpace *as, hwaddr addr, uint32_t val,
> +                       MemTxAttrs attrs, MemTxResult *result)
> +{
> +    address_space_stw_internal(as, addr, val, attrs, result,
> +                               DEVICE_BIG_ENDIAN);
> +}
> +
>  void stw_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  {
> -    stw_phys_internal(as, addr, val, DEVICE_NATIVE_ENDIAN);
> +    address_space_stw(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  void stw_le_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  {
> -    stw_phys_internal(as, addr, val, DEVICE_LITTLE_ENDIAN);
> +    address_space_stw_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  void stw_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
>  {
> -    stw_phys_internal(as, addr, val, DEVICE_BIG_ENDIAN);
> +    address_space_stw_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  /* XXX: optimize */
> -void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val)
> +void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
> +                       MemTxAttrs attrs, MemTxResult *result)
>  {
> +    MemTxResult r;
>      val = tswap64(val);
> -    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
> +    r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
> +    if (result) {
> +        *result = r;
> +    }
>  }
>  
> -void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val)
> +void address_space_stq_le(AddressSpace *as, hwaddr addr, uint64_t val,
> +                       MemTxAttrs attrs, MemTxResult *result)
>  {
> +    MemTxResult r;
>      val = cpu_to_le64(val);
> -    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
> +    r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
> +    if (result) {
> +        *result = r;
> +    }
> +}
> +void address_space_stq_be(AddressSpace *as, hwaddr addr, uint64_t val,
> +                       MemTxAttrs attrs, MemTxResult *result)
> +{
> +    MemTxResult r;
> +    val = cpu_to_be64(val);
> +    r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
> +    if (result) {
> +        *result = r;
> +    }
> +}
> +
> +void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val)
> +{
> +    address_space_stq(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
> +}
> +
> +void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val)
> +{
> +    address_space_stq_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val)
>  {
> -    val = cpu_to_be64(val);
> -    address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, (void *) &val, 8, 1);
> +    address_space_stq_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  /* virtual memory access for debug (includes writing to ROM) */
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 4d6afc8..0a048ab 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -1134,6 +1134,69 @@ MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
>  MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
>                                 uint8_t *buf, int len);
>  
> +/**
> + * address_space_ld*: load from an address space
> + * address_space_st*: store to an address space
> + *
> + * These functions perform a load or store of the byte, word,
> + * longword or quad to the specified address within the AddressSpace.
> + * The _le suffixed functions treat the data as little endian;
> + * _be indicates big endian; no suffix indicates "same endianness
> + * as guest CPU".
> + *
> + * @as #AddressSpace to be accessed
> + * @addr: address within that address space
> + * @val: data value, for stores
> + * @attrs: memory transaction attributes
> + * @result: location to write the success/failure of the transaction;
> + *   if NULL, this information is discarded
> + */
> +uint32_t address_space_ldub(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +uint32_t address_space_lduw_le(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +uint32_t address_space_lduw_be(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +uint32_t address_space_ldl_le(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +uint32_t address_space_ldl_be(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +uint64_t address_space_ldq_le(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +uint64_t address_space_ldq_be(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stb(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stw_le(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stw_be(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stl_le(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stl_be(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stq_le(AddressSpace *as, hwaddr addr, uint64_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stq_be(AddressSpace *as, hwaddr addr, uint64_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +
> +#ifdef NEED_CPU_H
> +uint32_t address_space_lduw(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +uint32_t address_space_ldl(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +uint64_t address_space_ldq(AddressSpace *as, hwaddr addr,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
> +                            MemTxAttrs attrs, MemTxResult *result);
> +#endif
> +
>  /* address_space_translate: translate an address range into an address space
>   * into a MemoryRegion and an address range into that section
>   *
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes
  2015-04-09 10:21       ` Paolo Bonzini
@ 2015-04-09 10:43         ` Peter Maydell
  2015-04-09 11:40           ` Paolo Bonzini
  0 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-09 10:43 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Edgar E. Iglesias, Alex Bennée, Richard Henderson

On 9 April 2015 at 11:21, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 09/04/2015 12:14, Peter Maydell wrote:
>> On 9 April 2015 at 10:59, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
>>> > On Tue, Apr 07, 2015 at 09:09:52PM +0100, Peter Maydell wrote:
>>>> >> Make address_space_rw take transaction attributes, rather
>>>> >> than always using the 'unspecified' attributes.
>>> >
>>> > Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>>> >
>>> > I guess that we eventually will need to convert the dma_
>>> > functions?
>> Probably, though I'm not clear what they bring to the party
>> that the basic address_space_* functions don't (part of why
>> I left them alone).
>
> At this point, some memory barriers, basically.

So what distinguishes a device that needs the memory barriers
and does its accesses via dma_* from a device that doesn't and
uses address_space_* or ld/st*_phys ? (Or for that matter a
non-device that does memory accesses...)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 08/14] Switch non-CPU callers from ld/st*_phys to address_space_ld/st*
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 08/14] Switch non-CPU callers from ld/st*_phys to address_space_ld/st* Peter Maydell
@ 2015-04-09 10:44   ` Edgar E. Iglesias
  0 siblings, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09 10:44 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:54PM +0100, Peter Maydell wrote:
> Switch all the uses of ld/st*_phys to address_space_ld/st*,
> except for those cases where the address space is the CPU's
> (ie cs->as). This was done with the following script which
> generates a Coccinelle patch.
> 
> A few over-80-columns lines in the result were rewrapped by
> hand where Coccinelle failed to do the wrapping automatically,
> as well as one location where it didn't put a line-continuation
> '\' when wrapping lines on a change made to a match inside
> a macro definition.
> 
> ===begin===
> #!/bin/sh -e
> # Usage:
> # ./ldst-phys.spatch.sh > ldst-phys.spatch
> # spatch -sp_file ldst-phys.spatch -dir . | sed -e '/^+/s/\t/        /g' > out.patch
> # patch -p1 < out.patch
> 
> for FN in ub uw_le uw_be l_le l_be q_le q_be uw l q; do
> cat <<EOF
> @ cpu_matches_ld_${FN} @
> expression E1,E2;
> identifier as;
> @@
> 
> ld${FN}_phys(E1->as,E2)
> 
> @ other_matches_ld_${FN} depends on !cpu_matches_ld_${FN} @
> expression E1,E2;
> @@
> 
> -ld${FN}_phys(E1,E2)
> +address_space_ld${FN}(E1,E2, MEMTXATTRS_UNSPECIFIED, NULL)
> 
> EOF
> 
> done
> 
> for FN in b w_le w_be l_le l_be q_le q_be w l q; do
> cat <<EOF
> @ cpu_matches_st_${FN} @
> expression E1,E2,E3;
> identifier as;
> @@
> 
> st${FN}_phys(E1->as,E2,E3)
> 
> @ other_matches_st_${FN} depends on !cpu_matches_st_${FN} @
> expression E1,E2,E3;
> @@
> 
> -st${FN}_phys(E1,E2,E3)
> +address_space_st${FN}(E1,E2,E3, MEMTXATTRS_UNSPECIFIED, NULL)
> 
> EOF
> 
> done
> ===endit===


Cool stuff!

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  exec.c                            | 18 +++++---
>  hw/alpha/dp264.c                  |  9 ++--
>  hw/alpha/typhoon.c                |  3 +-
>  hw/arm/boot.c                     |  6 ++-
>  hw/arm/highbank.c                 | 12 ++++--
>  hw/dma/pl080.c                    | 20 +++++++--
>  hw/dma/sun4m_iommu.c              |  3 +-
>  hw/i386/intel_iommu.c             |  3 +-
>  hw/pci-host/apb.c                 |  3 +-
>  hw/pci/msi.c                      |  3 +-
>  hw/pci/msix.c                     |  3 +-
>  hw/s390x/css.c                    | 19 ++++++---
>  hw/s390x/s390-pci-bus.c           |  9 ++--
>  hw/s390x/s390-virtio-bus.c        | 73 +++++++++++++++++++++-----------
>  hw/s390x/s390-virtio.c            |  4 +-
>  hw/s390x/virtio-ccw.c             | 87 +++++++++++++++++++++++++++------------
>  hw/sh4/r2d.c                      |  6 ++-
>  hw/timer/hpet.c                   |  5 ++-
>  monitor.c                         |  3 +-
>  target-i386/arch_memory_mapping.c | 15 +++----
>  20 files changed, 207 insertions(+), 97 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index 013032a..a0d18ee 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -1910,9 +1910,12 @@ static uint64_t watch_mem_read(void *opaque, hwaddr addr,
>  {
>      check_watchpoint(addr & ~TARGET_PAGE_MASK, size, 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: 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);
>      default: abort();
>      }
>  }
> @@ -1923,13 +1926,16 @@ static void watch_mem_write(void *opaque, hwaddr addr,
>      check_watchpoint(addr & ~TARGET_PAGE_MASK, size, BP_MEM_WRITE);
>      switch (size) {
>      case 1:
> -        stb_phys(&address_space_memory, addr, val);
> +        address_space_stb(&address_space_memory, addr, val,
> +                          MEMTXATTRS_UNSPECIFIED, NULL);
>          break;
>      case 2:
> -        stw_phys(&address_space_memory, addr, val);
> +        address_space_stw(&address_space_memory, addr, val,
> +                          MEMTXATTRS_UNSPECIFIED, NULL);
>          break;
>      case 4:
> -        stl_phys(&address_space_memory, addr, val);
> +        address_space_stl(&address_space_memory, addr, val,
> +                          MEMTXATTRS_UNSPECIFIED, NULL);
>          break;
>      default: abort();
>      }
> diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
> index e82d61d..9fe7e8b 100644
> --- a/hw/alpha/dp264.c
> +++ b/hw/alpha/dp264.c
> @@ -157,9 +157,12 @@ static void clipper_init(MachineState *machine)
>              load_image_targphys(initrd_filename, initrd_base,
>                                  ram_size - initrd_base);
>  
> -            stq_phys(&address_space_memory,
> -                     param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL);
> -            stq_phys(&address_space_memory, param_offset + 0x108, initrd_size);
> +            address_space_stq(&address_space_memory, param_offset + 0x100,
> +                              initrd_base + 0xfffffc0000000000ULL,
> +                              MEMTXATTRS_UNSPECIFIED,
> +                              NULL);
> +            address_space_stq(&address_space_memory, param_offset + 0x108,
> +                              initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
>          }
>      }
>  }
> diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
> index 62af946..e6ac993 100644
> --- a/hw/alpha/typhoon.c
> +++ b/hw/alpha/typhoon.c
> @@ -613,7 +613,8 @@ static bool make_iommu_tlbe(hwaddr taddr, hwaddr mask, IOMMUTLBEntry *ret)
>     translation, given the address of the PTE.  */
>  static bool pte_translate(hwaddr pte_addr, IOMMUTLBEntry *ret)
>  {
> -    uint64_t pte = ldq_phys(&address_space_memory, pte_addr);
> +    uint64_t pte = address_space_ldq(&address_space_memory, pte_addr,
> +                                     MEMTXATTRS_UNSPECIFIED, NULL);
>  
>      /* Check valid bit.  */
>      if ((pte & 1) == 0) {
> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> index a48d1b2..fa69503 100644
> --- a/hw/arm/boot.c
> +++ b/hw/arm/boot.c
> @@ -170,7 +170,8 @@ static void default_reset_secondary(ARMCPU *cpu,
>  {
>      CPUARMState *env = &cpu->env;
>  
> -    stl_phys_notdirty(&address_space_memory, info->smp_bootreg_addr, 0);
> +    address_space_stl_notdirty(&address_space_memory, info->smp_bootreg_addr,
> +                               0, MEMTXATTRS_UNSPECIFIED, NULL);
>      env->regs[15] = info->smp_loader_start;
>  }
>  
> @@ -180,7 +181,8 @@ static inline bool have_dtb(const struct arm_boot_info *info)
>  }
>  
>  #define WRITE_WORD(p, value) do { \
> -    stl_phys_notdirty(&address_space_memory, p, value);  \
> +    address_space_stl_notdirty(&address_space_memory, p, value, \
> +                               MEMTXATTRS_UNSPECIFIED, NULL);  \
>      p += 4;                       \
>  } while (0)
>  
> diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
> index 07cb4e0..00167c9 100644
> --- a/hw/arm/highbank.c
> +++ b/hw/arm/highbank.c
> @@ -69,11 +69,17 @@ static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
>  
>      switch (info->nb_cpus) {
>      case 4:
> -        stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x30, 0);
> +        address_space_stl_notdirty(&address_space_memory,
> +                                   SMP_BOOT_REG + 0x30, 0,
> +                                   MEMTXATTRS_UNSPECIFIED, NULL);
>      case 3:
> -        stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x20, 0);
> +        address_space_stl_notdirty(&address_space_memory,
> +                                   SMP_BOOT_REG + 0x20, 0,
> +                                   MEMTXATTRS_UNSPECIFIED, NULL);
>      case 2:
> -        stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x10, 0);
> +        address_space_stl_notdirty(&address_space_memory,
> +                                   SMP_BOOT_REG + 0x10, 0,
> +                                   MEMTXATTRS_UNSPECIFIED, NULL);
>          env->regs[15] = SMP_BOOT_ADDR;
>          break;
>      default:
> diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
> index 741dd20..b89b474 100644
> --- a/hw/dma/pl080.c
> +++ b/hw/dma/pl080.c
> @@ -205,10 +205,22 @@ again:
>              if (size == 0) {
>                  /* Transfer complete.  */
>                  if (ch->lli) {
> -                    ch->src = ldl_le_phys(&address_space_memory, ch->lli);
> -                    ch->dest = ldl_le_phys(&address_space_memory, ch->lli + 4);
> -                    ch->ctrl = ldl_le_phys(&address_space_memory, ch->lli + 12);
> -                    ch->lli = ldl_le_phys(&address_space_memory, ch->lli + 8);
> +                    ch->src = address_space_ldl_le(&address_space_memory,
> +                                                   ch->lli,
> +                                                   MEMTXATTRS_UNSPECIFIED,
> +                                                   NULL);
> +                    ch->dest = address_space_ldl_le(&address_space_memory,
> +                                                    ch->lli + 4,
> +                                                    MEMTXATTRS_UNSPECIFIED,
> +                                                    NULL);
> +                    ch->ctrl = address_space_ldl_le(&address_space_memory,
> +                                                    ch->lli + 12,
> +                                                    MEMTXATTRS_UNSPECIFIED,
> +                                                    NULL);
> +                    ch->lli = address_space_ldl_le(&address_space_memory,
> +                                                   ch->lli + 8,
> +                                                   MEMTXATTRS_UNSPECIFIED,
> +                                                   NULL);
>                  } else {
>                      ch->conf &= ~PL080_CCONF_E;
>                  }
> diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c
> index ec7c2ef..9a488bc 100644
> --- a/hw/dma/sun4m_iommu.c
> +++ b/hw/dma/sun4m_iommu.c
> @@ -263,7 +263,8 @@ static uint32_t iommu_page_get_flags(IOMMUState *s, hwaddr addr)
>      iopte = s->regs[IOMMU_BASE] << 4;
>      addr &= ~s->iostart;
>      iopte += (addr >> (IOMMU_PAGE_SHIFT - 2)) & ~3;
> -    ret = ldl_be_phys(&address_space_memory, iopte);
> +    ret = address_space_ldl_be(&address_space_memory, iopte,
> +                               MEMTXATTRS_UNSPECIFIED, NULL);
>      trace_sun4m_iommu_page_get_flags(pa, iopte, ret);
>      return ret;
>  }
> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> index 7da70ff..08055a8 100644
> --- a/hw/i386/intel_iommu.c
> +++ b/hw/i386/intel_iommu.c
> @@ -246,7 +246,8 @@ static void vtd_generate_interrupt(IntelIOMMUState *s, hwaddr mesg_addr_reg,
>      data = vtd_get_long_raw(s, mesg_data_reg);
>  
>      VTD_DPRINTF(FLOG, "msi: addr 0x%"PRIx64 " data 0x%"PRIx32, addr, data);
> -    stl_le_phys(&address_space_memory, addr, data);
> +    address_space_stl_le(&address_space_memory, addr, data,
> +                         MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  /* Generate a fault event to software via MSI if conditions are met.
> diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
> index 312fa70..599768e 100644
> --- a/hw/pci-host/apb.c
> +++ b/hw/pci-host/apb.c
> @@ -289,7 +289,8 @@ static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
>          }
>      }
>  
> -    tte = ldq_be_phys(&address_space_memory, baseaddr + offset);
> +    tte = address_space_ldq_be(&address_space_memory, baseaddr + offset,
> +                               MEMTXATTRS_UNSPECIFIED, NULL);
>  
>      if (!(tte & IOMMU_TTE_DATA_V)) {
>          /* Invalid mapping */
> diff --git a/hw/pci/msi.c b/hw/pci/msi.c
> index 52d2313..916e1a1 100644
> --- a/hw/pci/msi.c
> +++ b/hw/pci/msi.c
> @@ -291,7 +291,8 @@ void msi_notify(PCIDevice *dev, unsigned int vector)
>                     "notify vector 0x%x"
>                     " address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
>                     vector, msg.address, msg.data);
> -    stl_le_phys(&dev->bus_master_as, msg.address, msg.data);
> +    address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
> +                         MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  /* Normally called by pci_default_write_config(). */
> diff --git a/hw/pci/msix.c b/hw/pci/msix.c
> index 24de260..031eaab 100644
> --- a/hw/pci/msix.c
> +++ b/hw/pci/msix.c
> @@ -435,7 +435,8 @@ void msix_notify(PCIDevice *dev, unsigned vector)
>  
>      msg = msix_get_message(dev, vector);
>  
> -    stl_le_phys(&dev->bus_master_as, msg.address, msg.data);
> +    address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
> +                         MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  void msix_reset(PCIDevice *dev)
> diff --git a/hw/s390x/css.c b/hw/s390x/css.c
> index 9a13b00..5561d80 100644
> --- a/hw/s390x/css.c
> +++ b/hw/s390x/css.c
> @@ -745,20 +745,27 @@ static void css_update_chnmon(SubchDev *sch)
>          /* Format 1, per-subchannel area. */
>          uint32_t count;
>  
> -        count = ldl_phys(&address_space_memory, sch->curr_status.mba);
> +        count = address_space_ldl(&address_space_memory,
> +                                  sch->curr_status.mba,
> +                                  MEMTXATTRS_UNSPECIFIED,
> +                                  NULL);
>          count++;
> -        stl_phys(&address_space_memory, sch->curr_status.mba, count);
> +        address_space_stl(&address_space_memory, sch->curr_status.mba, count,
> +                          MEMTXATTRS_UNSPECIFIED, NULL);
>      } else {
>          /* Format 0, global area. */
>          uint32_t offset;
>          uint16_t count;
>  
>          offset = sch->curr_status.pmcw.mbi << 5;
> -        count = lduw_phys(&address_space_memory,
> -                          channel_subsys->chnmon_area + offset);
> +        count = address_space_lduw(&address_space_memory,
> +                                   channel_subsys->chnmon_area + offset,
> +                                   MEMTXATTRS_UNSPECIFIED,
> +                                   NULL);
>          count++;
> -        stw_phys(&address_space_memory,
> -                 channel_subsys->chnmon_area + offset, count);
> +        address_space_stw(&address_space_memory,
> +                          channel_subsys->chnmon_area + offset, count,
> +                          MEMTXATTRS_UNSPECIFIED, NULL);
>      }
>  }
>  
> diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
> index 3c086f6..560b66a 100644
> --- a/hw/s390x/s390-pci-bus.c
> +++ b/hw/s390x/s390-pci-bus.c
> @@ -278,7 +278,8 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota,
>      px = calc_px(guest_dma_address);
>  
>      sto_a = guest_iota + rtx * sizeof(uint64_t);
> -    sto = ldq_phys(&address_space_memory, sto_a);
> +    sto = address_space_ldq(&address_space_memory, sto_a,
> +                            MEMTXATTRS_UNSPECIFIED, NULL);
>      sto = get_rt_sto(sto);
>      if (!sto) {
>          pte = 0;
> @@ -286,7 +287,8 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota,
>      }
>  
>      pto_a = sto + sx * sizeof(uint64_t);
> -    pto = ldq_phys(&address_space_memory, pto_a);
> +    pto = address_space_ldq(&address_space_memory, pto_a,
> +                            MEMTXATTRS_UNSPECIFIED, NULL);
>      pto = get_st_pto(pto);
>      if (!pto) {
>          pte = 0;
> @@ -294,7 +296,8 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota,
>      }
>  
>      px_a = pto + px * sizeof(uint64_t);
> -    pte = ldq_phys(&address_space_memory, px_a);
> +    pte = address_space_ldq(&address_space_memory, px_a,
> +                            MEMTXATTRS_UNSPECIFIED, NULL);
>  
>  out:
>      return pte;
> diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
> index 047c963..0f93a64 100644
> --- a/hw/s390x/s390-virtio-bus.c
> +++ b/hw/s390x/s390-virtio-bus.c
> @@ -75,10 +75,12 @@ void s390_virtio_reset_idx(VirtIOS390Device *dev)
>      for (i = 0; i < num_vq; i++) {
>          idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) +
>              VIRTIO_VRING_AVAIL_IDX_OFFS;
> -        stw_phys(&address_space_memory, idx_addr, 0);
> +        address_space_stw(&address_space_memory, idx_addr, 0,
> +                          MEMTXATTRS_UNSPECIFIED, NULL);
>          idx_addr = virtio_queue_get_used_addr(dev->vdev, i) +
>              VIRTIO_VRING_USED_IDX_OFFS;
> -        stw_phys(&address_space_memory, idx_addr, 0);
> +        address_space_stw(&address_space_memory, idx_addr, 0,
> +                          MEMTXATTRS_UNSPECIFIED, NULL);
>      }
>  }
>  
> @@ -336,7 +338,8 @@ static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
>                  (vq * VIRTIO_VQCONFIG_LEN) +
>                  VIRTIO_VQCONFIG_OFFS_TOKEN;
>  
> -    return ldq_be_phys(&address_space_memory, token_off);
> +    return address_space_ldq_be(&address_space_memory, token_off,
> +                                MEMTXATTRS_UNSPECIFIED, NULL);
>  }
>  
>  static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev)
> @@ -371,21 +374,33 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
>      virtio_reset(dev->vdev);
>  
>      /* Sync dev space */
> -    stb_phys(&address_space_memory,
> -             dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, dev->vdev->device_id);
> -
> -    stb_phys(&address_space_memory,
> -             dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ,
> -             s390_virtio_device_num_vq(dev));
> -    stb_phys(&address_space_memory,
> -             dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, dev->feat_len);
> -
> -    stb_phys(&address_space_memory,
> -             dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, dev->vdev->config_len);
> +    address_space_stb(&address_space_memory,
> +                      dev->dev_offs + VIRTIO_DEV_OFFS_TYPE,
> +                      dev->vdev->device_id,
> +                      MEMTXATTRS_UNSPECIFIED,
> +                      NULL);
> +
> +    address_space_stb(&address_space_memory,
> +                      dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ,
> +                      s390_virtio_device_num_vq(dev),
> +                      MEMTXATTRS_UNSPECIFIED,
> +                      NULL);
> +    address_space_stb(&address_space_memory,
> +                      dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN,
> +                      dev->feat_len,
> +                      MEMTXATTRS_UNSPECIFIED,
> +                      NULL);
> +
> +    address_space_stb(&address_space_memory,
> +                      dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN,
> +                      dev->vdev->config_len,
> +                      MEMTXATTRS_UNSPECIFIED,
> +                      NULL);
>  
>      num_vq = s390_virtio_device_num_vq(dev);
> -    stb_phys(&address_space_memory,
> -             dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq);
> +    address_space_stb(&address_space_memory,
> +                      dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq,
> +                      MEMTXATTRS_UNSPECIFIED, NULL);
>  
>      /* Sync virtqueues */
>      for (i = 0; i < num_vq; i++) {
> @@ -396,11 +411,14 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
>          vring = s390_virtio_next_ring(bus);
>          virtio_queue_set_addr(dev->vdev, i, vring);
>          virtio_queue_set_vector(dev->vdev, i, i);
> -        stq_be_phys(&address_space_memory,
> -                    vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring);
> -        stw_be_phys(&address_space_memory,
> -                    vq + VIRTIO_VQCONFIG_OFFS_NUM,
> -                    virtio_queue_get_num(dev->vdev, i));
> +        address_space_stq_be(&address_space_memory,
> +                             vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring,
> +                             MEMTXATTRS_UNSPECIFIED, NULL);
> +        address_space_stw_be(&address_space_memory,
> +                             vq + VIRTIO_VQCONFIG_OFFS_NUM,
> +                             virtio_queue_get_num(dev->vdev, i),
> +                             MEMTXATTRS_UNSPECIFIED,
> +                             NULL);
>      }
>  
>      cur_offs = dev->dev_offs;
> @@ -408,7 +426,8 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
>      cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
>  
>      /* Sync feature bitmap */
> -    stl_le_phys(&address_space_memory, cur_offs, dev->host_features);
> +    address_space_stl_le(&address_space_memory, cur_offs, dev->host_features,
> +                         MEMTXATTRS_UNSPECIFIED, NULL);
>  
>      dev->feat_offs = cur_offs + dev->feat_len;
>      cur_offs += dev->feat_len * 2;
> @@ -426,12 +445,16 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
>      VirtIODevice *vdev = dev->vdev;
>      uint32_t features;
>  
> -    virtio_set_status(vdev, ldub_phys(&address_space_memory,
> -                                      dev->dev_offs + VIRTIO_DEV_OFFS_STATUS));
> +    virtio_set_status(vdev,
> +                      address_space_ldub(&address_space_memory,
> +                                         dev->dev_offs + VIRTIO_DEV_OFFS_STATUS,
> +                                         MEMTXATTRS_UNSPECIFIED, NULL));
>  
>      /* Update guest supported feature bitmap */
>  
> -    features = bswap32(ldl_be_phys(&address_space_memory, dev->feat_offs));
> +    features = bswap32(address_space_ldl_be(&address_space_memory,
> +                                            dev->feat_offs,
> +                                            MEMTXATTRS_UNSPECIFIED, NULL));
>      virtio_set_features(vdev, features);
>  }
>  
> diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
> index bdb5388..3a1b9ee 100644
> --- a/hw/s390x/s390-virtio.c
> +++ b/hw/s390x/s390-virtio.c
> @@ -97,7 +97,9 @@ static int s390_virtio_hcall_reset(const uint64_t *args)
>          return -EINVAL;
>      }
>      virtio_reset(dev->vdev);
> -    stb_phys(&address_space_memory, dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
> +    address_space_stb(&address_space_memory,
> +                      dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0,
> +                      MEMTXATTRS_UNSPECIFIED, NULL);
>      s390_virtio_device_sync(dev);
>      s390_virtio_reset_idx(dev);
>  
> diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
> index d32ecaf..ed75c63 100644
> --- a/hw/s390x/virtio-ccw.c
> +++ b/hw/s390x/virtio-ccw.c
> @@ -335,16 +335,23 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>          if (!ccw.cda) {
>              ret = -EFAULT;
>          } else {
> -            info.queue = ldq_phys(&address_space_memory, ccw.cda);
> -            info.align = ldl_phys(&address_space_memory,
> -                                  ccw.cda + sizeof(info.queue));
> -            info.index = lduw_phys(&address_space_memory,
> -                                   ccw.cda + sizeof(info.queue)
> -                                   + sizeof(info.align));
> -            info.num = lduw_phys(&address_space_memory,
> -                                 ccw.cda + sizeof(info.queue)
> -                                 + sizeof(info.align)
> -                                 + sizeof(info.index));
> +            info.queue = address_space_ldq(&address_space_memory, ccw.cda,
> +                                           MEMTXATTRS_UNSPECIFIED, NULL);
> +            info.align = address_space_ldl(&address_space_memory,
> +                                           ccw.cda + sizeof(info.queue),
> +                                           MEMTXATTRS_UNSPECIFIED,
> +                                           NULL);
> +            info.index = address_space_lduw(&address_space_memory,
> +                                            ccw.cda + sizeof(info.queue)
> +                                            + sizeof(info.align),
> +                                            MEMTXATTRS_UNSPECIFIED,
> +                                            NULL);
> +            info.num = address_space_lduw(&address_space_memory,
> +                                          ccw.cda + sizeof(info.queue)
> +                                          + sizeof(info.align)
> +                                          + sizeof(info.index),
> +                                          MEMTXATTRS_UNSPECIFIED,
> +                                          NULL);
>              ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index,
>                                       info.num);
>              sch->curr_status.scsw.count = 0;
> @@ -369,15 +376,20 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>          if (!ccw.cda) {
>              ret = -EFAULT;
>          } else {
> -            features.index = ldub_phys(&address_space_memory,
> -                                       ccw.cda + sizeof(features.features));
> +            features.index = address_space_ldub(&address_space_memory,
> +                                                ccw.cda
> +                                                + sizeof(features.features),
> +                                                MEMTXATTRS_UNSPECIFIED,
> +                                                NULL);
>              if (features.index < ARRAY_SIZE(dev->host_features)) {
>                  features.features = dev->host_features[features.index];
>              } else {
>                  /* Return zeroes if the guest supports more feature bits. */
>                  features.features = 0;
>              }
> -            stl_le_phys(&address_space_memory, ccw.cda, features.features);
> +            address_space_stl_le(&address_space_memory, ccw.cda,
> +                                 features.features, MEMTXATTRS_UNSPECIFIED,
> +                                 NULL);
>              sch->curr_status.scsw.count = ccw.count - sizeof(features);
>              ret = 0;
>          }
> @@ -396,9 +408,15 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>          if (!ccw.cda) {
>              ret = -EFAULT;
>          } else {
> -            features.index = ldub_phys(&address_space_memory,
> -                                       ccw.cda + sizeof(features.features));
> -            features.features = ldl_le_phys(&address_space_memory, ccw.cda);
> +            features.index = address_space_ldub(&address_space_memory,
> +                                                ccw.cda
> +                                                + sizeof(features.features),
> +                                                MEMTXATTRS_UNSPECIFIED,
> +                                                NULL);
> +            features.features = address_space_ldl_le(&address_space_memory,
> +                                                     ccw.cda,
> +                                                     MEMTXATTRS_UNSPECIFIED,
> +                                                     NULL);
>              if (features.index < ARRAY_SIZE(dev->host_features)) {
>                  virtio_set_features(vdev, features.features);
>              } else {
> @@ -474,7 +492,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>          if (!ccw.cda) {
>              ret = -EFAULT;
>          } else {
> -            status = ldub_phys(&address_space_memory, ccw.cda);
> +            status = address_space_ldub(&address_space_memory, ccw.cda,
> +                                        MEMTXATTRS_UNSPECIFIED, NULL);
>              if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
>                  virtio_ccw_stop_ioeventfd(dev);
>              }
> @@ -508,7 +527,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>          if (!ccw.cda) {
>              ret = -EFAULT;
>          } else {
> -            indicators = ldq_be_phys(&address_space_memory, ccw.cda);
> +            indicators = address_space_ldq_be(&address_space_memory, ccw.cda,
> +                                              MEMTXATTRS_UNSPECIFIED, NULL);
>              dev->indicators = get_indicator(indicators, sizeof(uint64_t));
>              sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
>              ret = 0;
> @@ -528,7 +548,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>          if (!ccw.cda) {
>              ret = -EFAULT;
>          } else {
> -            indicators = ldq_be_phys(&address_space_memory, ccw.cda);
> +            indicators = address_space_ldq_be(&address_space_memory, ccw.cda,
> +                                              MEMTXATTRS_UNSPECIFIED, NULL);
>              dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
>              sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
>              ret = 0;
> @@ -548,15 +569,21 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
>          if (!ccw.cda) {
>              ret = -EFAULT;
>          } else {
> -            vq_config.index = lduw_be_phys(&address_space_memory, ccw.cda);
> +            vq_config.index = address_space_lduw_be(&address_space_memory,
> +                                                    ccw.cda,
> +                                                    MEMTXATTRS_UNSPECIFIED,
> +                                                    NULL);
>              if (vq_config.index >= VIRTIO_PCI_QUEUE_MAX) {
>                  ret = -EINVAL;
>                  break;
>              }
>              vq_config.num_max = virtio_queue_get_num(vdev,
>                                                       vq_config.index);
> -            stw_be_phys(&address_space_memory,
> -                        ccw.cda + sizeof(vq_config.index), vq_config.num_max);
> +            address_space_stw_be(&address_space_memory,
> +                                 ccw.cda + sizeof(vq_config.index),
> +                                 vq_config.num_max,
> +                                 MEMTXATTRS_UNSPECIFIED,
> +                                 NULL);
>              sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
>              ret = 0;
>          }
> @@ -1068,9 +1095,13 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
>                  css_adapter_interrupt(dev->thinint_isc);
>              }
>          } else {
> -            indicators = ldq_phys(&address_space_memory, dev->indicators->addr);
> +            indicators = address_space_ldq(&address_space_memory,
> +                                           dev->indicators->addr,
> +                                           MEMTXATTRS_UNSPECIFIED,
> +                                           NULL);
>              indicators |= 1ULL << vector;
> -            stq_phys(&address_space_memory, dev->indicators->addr, indicators);
> +            address_space_stq(&address_space_memory, dev->indicators->addr,
> +                              indicators, MEMTXATTRS_UNSPECIFIED, NULL);
>              css_conditional_io_interrupt(sch);
>          }
>      } else {
> @@ -1078,9 +1109,13 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
>              return;
>          }
>          vector = 0;
> -        indicators = ldq_phys(&address_space_memory, dev->indicators2->addr);
> +        indicators = address_space_ldq(&address_space_memory,
> +                                       dev->indicators2->addr,
> +                                       MEMTXATTRS_UNSPECIFIED,
> +                                       NULL);
>          indicators |= 1ULL << vector;
> -        stq_phys(&address_space_memory, dev->indicators2->addr, indicators);
> +        address_space_stq(&address_space_memory, dev->indicators2->addr,
> +                          indicators, MEMTXATTRS_UNSPECIFIED, NULL);
>          css_conditional_io_interrupt(sch);
>      }
>  }
> diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
> index d1d0847..4221060 100644
> --- a/hw/sh4/r2d.c
> +++ b/hw/sh4/r2d.c
> @@ -318,8 +318,10 @@ static void r2d_init(MachineState *machine)
>          }
>  
>          /* initialization which should be done by firmware */
> -        stl_phys(&address_space_memory, SH7750_BCR1, 1<<3); /* cs3 SDRAM */
> -        stw_phys(&address_space_memory, SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
> +        address_space_stl(&address_space_memory, SH7750_BCR1, 1 << 3,
> +                          MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 SDRAM */
> +        address_space_stw(&address_space_memory, SH7750_BCR2, 3 << (3 * 2),
> +                          MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 32bit */
>          reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
>      }
>  
> diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
> index 78d86be..b6b8a20 100644
> --- a/hw/timer/hpet.c
> +++ b/hw/timer/hpet.c
> @@ -206,8 +206,9 @@ static void update_irq(struct HPETTimer *timer, int set)
>              }
>          }
>      } else if (timer_fsb_route(timer)) {
> -        stl_le_phys(&address_space_memory,
> -                    timer->fsb >> 32, timer->fsb & 0xffffffff);
> +        address_space_stl_le(&address_space_memory, timer->fsb >> 32,
> +                             timer->fsb & 0xffffffff, MEMTXATTRS_UNSPECIFIED,
> +                             NULL);
>      } else if (timer->config & HPET_TN_TYPE_LEVEL) {
>          s->isr |= mask;
>          /* fold the ICH PIRQ# pin's internal inversion logic into hpet */
> diff --git a/monitor.c b/monitor.c
> index 68873ec..c7a4db6 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -1385,7 +1385,8 @@ static void hmp_sum(Monitor *mon, const QDict *qdict)
>  
>      sum = 0;
>      for(addr = start; addr < (start + size); addr++) {
> -        uint8_t val = ldub_phys(&address_space_memory, addr);
> +        uint8_t val = address_space_ldub(&address_space_memory, addr,
> +                                         MEMTXATTRS_UNSPECIFIED, NULL);
>          /* BSD sum algorithm ('sum' Unix command) */
>          sum = (sum >> 1) | (sum << 15);
>          sum += val;
> diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
> index 2d35f63..01563fe 100644
> --- a/target-i386/arch_memory_mapping.c
> +++ b/target-i386/arch_memory_mapping.c
> @@ -27,7 +27,7 @@ static void walk_pte(MemoryMappingList *list, AddressSpace *as,
>  
>      for (i = 0; i < 512; i++) {
>          pte_addr = (pte_start_addr + i * 8) & a20_mask;
> -        pte = ldq_phys(as, pte_addr);
> +        pte = address_space_ldq(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
>          if (!(pte & PG_PRESENT_MASK)) {
>              /* not present */
>              continue;
> @@ -57,7 +57,7 @@ static void walk_pte2(MemoryMappingList *list, AddressSpace *as,
>  
>      for (i = 0; i < 1024; i++) {
>          pte_addr = (pte_start_addr + i * 4) & a20_mask;
> -        pte = ldl_phys(as, pte_addr);
> +        pte = address_space_ldl(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
>          if (!(pte & PG_PRESENT_MASK)) {
>              /* not present */
>              continue;
> @@ -89,7 +89,7 @@ static void walk_pde(MemoryMappingList *list, AddressSpace *as,
>  
>      for (i = 0; i < 512; i++) {
>          pde_addr = (pde_start_addr + i * 8) & a20_mask;
> -        pde = ldq_phys(as, pde_addr);
> +        pde = address_space_ldq(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
>          if (!(pde & PG_PRESENT_MASK)) {
>              /* not present */
>              continue;
> @@ -126,7 +126,7 @@ static void walk_pde2(MemoryMappingList *list, AddressSpace *as,
>  
>      for (i = 0; i < 1024; i++) {
>          pde_addr = (pde_start_addr + i * 4) & a20_mask;
> -        pde = ldl_phys(as, pde_addr);
> +        pde = address_space_ldl(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
>          if (!(pde & PG_PRESENT_MASK)) {
>              /* not present */
>              continue;
> @@ -167,7 +167,7 @@ static void walk_pdpe2(MemoryMappingList *list, AddressSpace *as,
>  
>      for (i = 0; i < 4; i++) {
>          pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
> -        pdpe = ldq_phys(as, pdpe_addr);
> +        pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
>          if (!(pdpe & PG_PRESENT_MASK)) {
>              /* not present */
>              continue;
> @@ -192,7 +192,7 @@ static void walk_pdpe(MemoryMappingList *list, AddressSpace *as,
>  
>      for (i = 0; i < 512; i++) {
>          pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
> -        pdpe = ldq_phys(as, pdpe_addr);
> +        pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
>          if (!(pdpe & PG_PRESENT_MASK)) {
>              /* not present */
>              continue;
> @@ -228,7 +228,8 @@ static void walk_pml4e(MemoryMappingList *list, AddressSpace *as,
>  
>      for (i = 0; i < 512; i++) {
>          pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
> -        pml4e = ldq_phys(as, pml4e_addr);
> +        pml4e = address_space_ldq(as, pml4e_addr, MEMTXATTRS_UNSPECIFIED,
> +                                  NULL);
>          if (!(pml4e & PG_PRESENT_MASK)) {
>              /* not present */
>              continue;
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 10/14] target-arm: Honour NS bits in page tables
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 10/14] target-arm: Honour NS bits in page tables Peter Maydell
@ 2015-04-09 11:23   ` Edgar E. Iglesias
  2015-04-09 14:14     ` Peter Maydell
  0 siblings, 1 reply; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09 11:23 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:56PM +0100, Peter Maydell wrote:
> Honour the NS bit in ARM page tables:
>  * when adding entries to the TLB, include the Secure/NonSecure
>    transaction attribute
>  * set the NS bit in the PAR when doing ATS operations
> 
> Note that we don't yet correctly use the NSTable bit to
> cause the page table walk itself to use the right attributes.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  include/exec/memattrs.h |  3 ++
>  target-arm/helper.c     | 83 ++++++++++++++++++++++++++++++++++++++++++-------
>  2 files changed, 74 insertions(+), 12 deletions(-)
> 
> diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
> index b8d7808..5df180e 100644
> --- a/include/exec/memattrs.h
> +++ b/include/exec/memattrs.h
> @@ -24,6 +24,9 @@
>   */
>  typedef uint64_t MemTxAttrs;
>  
> +/* ARM/AMBA TrustZone Secure access */
> +#define MEMTXATTRS_SECURE (1ULL << 0)
> +
>  /* Bus masters which don't specify any attributes will get this,
>   * which has all attribute bits clear except the topmost one
>   * (so that we can distinguish "all attributes deliberately clear"
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index d77c6de..c359d0c 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -14,7 +14,7 @@
>  #ifndef CONFIG_USER_ONLY
>  static inline int get_phys_addr(CPUARMState *env, target_ulong address,
>                                  int access_type, ARMMMUIdx mmu_idx,
> -                                hwaddr *phys_ptr, int *prot,
> +                                hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
>                                  target_ulong *page_size);
>  
>  /* Definitions for the PMCCNTR and PMCR registers */
> @@ -1466,9 +1466,10 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
>      int prot;
>      int ret;
>      uint64_t par64;
> +    MemTxAttrs attrs;
>  
>      ret = get_phys_addr(env, value, access_type, mmu_idx,
> -                        &phys_addr, &prot, &page_size);
> +                        &phys_addr, &attrs, &prot, &page_size);
>      if (extended_addresses_enabled(env)) {
>          /* ret is a DFSR/IFSR value for the long descriptor
>           * translation table format, but with WnR always clear.
> @@ -1477,6 +1478,9 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
>          par64 = (1 << 11); /* LPAE bit always set */
>          if (ret == 0) {
>              par64 |= phys_addr & ~0xfffULL;
> +            if (!(attrs & MEMTXATTRS_SECURE)) {
> +                par64 |= (1 << 9); /* NS */
> +            }
>              /* We don't set the ATTR or SH fields in the PAR. */
>          } else {
>              par64 |= 1; /* F */
> @@ -1499,6 +1503,9 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
>              } else {
>                  par64 = phys_addr & 0xfffff000;
>              }
> +            if (!(attrs & MEMTXATTRS_SECURE)) {
> +                par64 |= (1 << 9); /* NS */
> +            }
>          } else {
>              par64 = ((ret & (1 << 10)) >> 5) | ((ret & (1 << 12)) >> 6) |
>                      ((ret & 0xf) << 1) | 1;
> @@ -4858,6 +4865,26 @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
>      }
>  }
>  
> +/* Return true if this address translation regime is secure */
> +static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
> +{
> +    switch (mmu_idx) {
> +    case ARMMMUIdx_S12NSE0:
> +    case ARMMMUIdx_S12NSE1:
> +    case ARMMMUIdx_S1NSE0:
> +    case ARMMMUIdx_S1NSE1:
> +    case ARMMMUIdx_S1E2:
> +    case ARMMMUIdx_S2NS:
> +        return false;
> +    case ARMMMUIdx_S1E3:
> +    case ARMMMUIdx_S1SE0:
> +    case ARMMMUIdx_S1SE1:
> +        return true;
> +    default:
> +        g_assert_not_reached();
> +    }
> +}
> +
>  /* Return the SCTLR value which controls this address translation regime */
>  static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
>  {
> @@ -5210,6 +5237,7 @@ do_fault:
>  
>  static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
>                              ARMMMUIdx mmu_idx, hwaddr *phys_ptr,
> +                            MemTxAttrs *attrs,
>                              int *prot, target_ulong *page_size)
>  {
>      CPUState *cs = CPU(arm_env_get_cpu(env));
> @@ -5224,6 +5252,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
>      int domain_prot;
>      hwaddr phys_addr;
>      uint32_t dacr;
> +    bool ns;
>  
>      /* Pagetable walk.  */
>      /* Lookup l1 descriptor.  */
> @@ -5273,10 +5302,12 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
>          xn = desc & (1 << 4);
>          pxn = desc & 1;
>          code = 13;
> +        ns = extract32(desc, 19, 1);
>      } else {
>          if (arm_feature(env, ARM_FEATURE_PXN)) {
>              pxn = (desc >> 2) & 1;
>          }
> +        ns = extract32(desc, 3, 1);
>          /* Lookup l2 entry.  */
>          table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
>          desc = ldl_phys(cs->as, table);
> @@ -5330,6 +5361,13 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
>              goto do_fault;
>          }
>      }
> +    if (ns) {
> +        /* The NS bit will (as required by the architecture) have no effect if
> +         * the CPU doesn't support TZ or this is a non-secure translation
> +         * regime, because the attribute will already be non-secure.
> +         */
> +        *attrs &= ~MEMTXATTRS_SECURE;
> +    }
>      *phys_ptr = phys_addr;
>      return 0;
>  do_fault:
> @@ -5347,7 +5385,7 @@ typedef enum {
>  
>  static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
>                                int access_type, ARMMMUIdx mmu_idx,
> -                              hwaddr *phys_ptr, int *prot,
> +                              hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
>                                target_ulong *page_size_ptr)
>  {
>      CPUState *cs = CPU(arm_env_get_cpu(env));
> @@ -5552,6 +5590,13 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
>          goto do_fault;
>      }
>  
> +    if (ns) {
> +        /* The NS bit will (as required by the architecture) have no effect if
> +         * the CPU doesn't support TZ or this is a non-secure translation
> +         * regime, because the attribute will already be non-secure.
> +         */
> +        *txattrs &= ~MEMTXATTRS_SECURE;
> +    }
>      *phys_ptr = descaddr;
>      *page_size_ptr = page_size;
>      return 0;
> @@ -5635,8 +5680,8 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
>   * by doing a translation table walk on MMU based systems or using the
>   * MPU state on MPU based systems.
>   *
> - * Returns 0 if the translation was successful. Otherwise, phys_ptr,
> - * prot and page_size are not filled in, and the return value provides
> + * Returns 0 if the translation was successful. Otherwise, phys_ptr, attrs,
> + * prot and page_size may not be filled in, and the return value provides
>   * information on why the translation aborted, in the format of a
>   * DFSR/IFSR fault register, with the following caveats:
>   *  * we honour the short vs long DFSR format differences.
> @@ -5649,12 +5694,13 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
>   * @access_type: 0 for read, 1 for write, 2 for execute
>   * @mmu_idx: MMU index indicating required translation regime
>   * @phys_ptr: set to the physical address corresponding to the virtual address
> + * @attrs: set to the memory transaction attributes to use
>   * @prot: set to the permissions for the page containing phys_ptr
>   * @page_size: set to the size of the page containing phys_ptr
>   */
>  static inline int get_phys_addr(CPUARMState *env, target_ulong address,
>                                  int access_type, ARMMMUIdx mmu_idx,
> -                                hwaddr *phys_ptr, int *prot,
> +                                hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
>                                  target_ulong *page_size)
>  {
>      if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
> @@ -5667,6 +5713,16 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
>          mmu_idx += ARMMMUIdx_S1NSE0;
>      }
>  
> +    if (regime_is_secure(env, mmu_idx)) {
> +        /* The page table entries may downgrade this to non-secure, but
> +         * cannot upgrade an non-secure translation regime's attributes
> +         * to secure.
> +         */
> +        *attrs = MEMTXATTRS_SECURE;
> +    } else {
> +        *attrs = 0;
> +    }


Should this initialization maybe be done from some kind of secure and NS
per CPU attribute template?
What I'm trying to get to is that the machine description may want to
control some attributes like for example the master-id.

Or did you have another mechanism in mind for that?

In the hack I'm using, CPU code doesn't actually edit the attributes.
There are a set of attribute objects that board code sets up and the CPU
selects among them depending on it's state. Once the attributes hit
tlb_set_page_with_attrs a copy is made into the IOTLB so that
IOMMUs can modify the actual value in the IOTLB as they translate().

This makes it easy for board code to for example make a non TZ
capable CPU look as either secure or non-secure.

I'm not trying to claim that that approach is the best, just trying
to illustrate some use cases that I think are important..

Cheers,
Edgar




> +
>      /* Fast Context Switch Extension. This doesn't exist at all in v8.
>       * In v7 and earlier it affects all stage 1 translations.
>       */
> @@ -5695,10 +5751,10 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
>  
>      if (regime_using_lpae_format(env, mmu_idx)) {
>          return get_phys_addr_lpae(env, address, access_type, mmu_idx, phys_ptr,
> -                                  prot, page_size);
> +                                  attrs, prot, page_size);
>      } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
>          return get_phys_addr_v6(env, address, access_type, mmu_idx, phys_ptr,
> -                                prot, page_size);
> +                                attrs, prot, page_size);
>      } else {
>          return get_phys_addr_v5(env, address, access_type, mmu_idx, phys_ptr,
>                                  prot, page_size);
> @@ -5716,14 +5772,16 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
>      int ret;
>      uint32_t syn;
>      bool same_el = (arm_current_el(env) != 0);
> +    MemTxAttrs attrs;
>  
> -    ret = get_phys_addr(env, address, access_type, mmu_idx, &phys_addr, &prot,
> -                        &page_size);
> +    ret = get_phys_addr(env, address, access_type, mmu_idx, &phys_addr,
> +                        &attrs, &prot, &page_size);
>      if (ret == 0) {
>          /* Map a single [sub]page.  */
>          phys_addr &= TARGET_PAGE_MASK;
>          address &= TARGET_PAGE_MASK;
> -        tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size);
> +        tlb_set_page_with_attrs(cs, address, phys_addr, attrs,
> +                                prot, mmu_idx, page_size);
>          return 0;
>      }
>  
> @@ -5758,9 +5816,10 @@ hwaddr arm_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
>      target_ulong page_size;
>      int prot;
>      int ret;
> +    MemTxAttrs attrs;
>  
>      ret = get_phys_addr(env, addr, 0, cpu_mmu_index(env), &phys_addr,
> -                        &prot, &page_size);
> +                        &attrs, &prot, &page_size);
>  
>      if (ret != 0) {
>          return -1;
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 11/14] target-arm: Use correct memory attributes for page table walks
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 11/14] target-arm: Use correct memory attributes for page table walks Peter Maydell
@ 2015-04-09 11:34   ` Edgar E. Iglesias
  0 siblings, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09 11:34 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:57PM +0100, Peter Maydell wrote:
> Factor out the page table walk memory accesses into their own function,
> so that we can specify the correct S/NS memory attributes for them.
> This will also provide a place to use the correct endianness and
> handle the need for a stage-2 translation when virtualization is
> supported.

Nice!
The init of attrs question applies here too.

Anyway:
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target-arm/helper.c | 47 ++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 38 insertions(+), 9 deletions(-)
> 
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index c359d0c..fdeb2b7 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -5129,6 +5129,27 @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
>      return true;
>  }
>  
> +/* All loads done in the course of a page table walk go through here.
> + * TODO: rather than ignoring errors from physical memory reads (which
> + * are external aborts in ARM terminology) we should propagate this
> + * error out so that we can turn it into a Data Abort if this walk
> + * was being done for a CPU load/store or an address translation instruction
> + * (but not if it was for a debug access).
> + */
> +static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure)
> +{
> +    MemTxAttrs attrs = is_secure ? MEMTXATTRS_SECURE : 0;
> +
> +    return address_space_ldl(cs->as, addr, attrs, NULL);
> +}
> +
> +static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure)
> +{
> +    MemTxAttrs attrs = is_secure ? MEMTXATTRS_SECURE : 0;
> +
> +    return address_space_ldq(cs->as, addr, attrs, NULL);
> +}
> +
>  static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
>                              ARMMMUIdx mmu_idx, hwaddr *phys_ptr,
>                              int *prot, target_ulong *page_size)
> @@ -5151,7 +5172,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
>          code = 5;
>          goto do_fault;
>      }
> -    desc = ldl_phys(cs->as, table);
> +    desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
>      type = (desc & 3);
>      domain = (desc >> 5) & 0x0f;
>      if (regime_el(env, mmu_idx) == 1) {
> @@ -5187,7 +5208,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
>              /* Fine pagetable.  */
>              table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
>          }
> -        desc = ldl_phys(cs->as, table);
> +        desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
>          switch (desc & 3) {
>          case 0: /* Page translation fault.  */
>              code = 7;
> @@ -5261,7 +5282,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
>          code = 5;
>          goto do_fault;
>      }
> -    desc = ldl_phys(cs->as, table);
> +    desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
>      type = (desc & 3);
>      if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
>          /* Section translation fault, or attempt to use the encoding
> @@ -5310,7 +5331,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
>          ns = extract32(desc, 3, 1);
>          /* Lookup l2 entry.  */
>          table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
> -        desc = ldl_phys(cs->as, table);
> +        desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
>          ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
>          switch (desc & 3) {
>          case 0: /* Page translation fault.  */
> @@ -5525,13 +5546,20 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
>      descaddr = extract64(ttbr, 0, 48);
>      descaddr &= ~((1ULL << (va_size - tsz - (granule_sz * (4 - level)))) - 1);
>  
> -    tableattrs = 0;
> +    /* Secure accesses start with the page table in secure memory and
> +     * can be downgraded to non-secure at any step. Non-secure accesses
> +     * remain non-secure. We implement this by just ORing in the NSTable/NS
> +     * bits at each step.
> +     */
> +    tableattrs = regime_is_secure(env, mmu_idx) ? 0 : (1 << 4);
>      for (;;) {
>          uint64_t descriptor;
> +        bool nstable;
>  
>          descaddr |= (address >> (granule_sz * (4 - level))) & descmask;
>          descaddr &= ~7ULL;
> -        descriptor = ldq_phys(cs->as, descaddr);
> +        nstable = extract32(tableattrs, 4, 1);
> +        descriptor = arm_ldq_ptw(cs, descaddr, !nstable);
>          if (!(descriptor & 1) ||
>              (!(descriptor & 2) && (level == 3))) {
>              /* Invalid, or the Reserved level 3 encoding */
> @@ -5566,7 +5594,7 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
>          if (extract32(tableattrs, 2, 1)) {
>              attrs &= ~(1 << 4);
>          }
> -        attrs |= extract32(tableattrs, 4, 1) << 3; /* NS */
> +        attrs |= nstable << 3; /* NS */
>          break;
>      }
>      /* Here descaddr is the final physical address, and attributes
> @@ -5705,8 +5733,9 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
>  {
>      if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
>          /* TODO: when we support EL2 we should here call ourselves recursively
> -         * to do the stage 1 and then stage 2 translations. The ldl_phys
> -         * calls for stage 1 will also need changing.
> +         * to do the stage 1 and then stage 2 translations. The arm_ld*_ptw
> +         * functions will also need changing to perform ARMMMUIdx_S2NS loads
> +         * rather than direct physical memory loads when appropriate.
>           * For non-EL2 CPUs a stage1+stage2 translation is just stage 1.
>           */
>          assert(!arm_feature(env, ARM_FEATURE_EL2));
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 13/14] target-arm: Use attribute info to handle user-only watchpoints
  2015-04-07 20:09 ` [Qemu-devel] [PATCH 13/14] target-arm: Use attribute info to handle user-only watchpoints Peter Maydell
@ 2015-04-09 11:37   ` Edgar E. Iglesias
  0 siblings, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09 11:37 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:09:59PM +0100, Peter Maydell wrote:
> Now that we have memory access attribute information in the watchpoint
> checking code, we can correctly implement handling of watchpoints
> which should match only on userspace accesses, where LDRT/STRT/LDT/STT
> from EL1 are treated as userspace accesses.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> ---
>  target-arm/op_helper.c | 23 ++++++++++++-----------
>  1 file changed, 12 insertions(+), 11 deletions(-)
> 
> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
> index 7713022..ce09ab3 100644
> --- a/target-arm/op_helper.c
> +++ b/target-arm/op_helper.c
> @@ -602,13 +602,22 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
>      int pac, hmc, ssc, wt, lbn;
>      /* TODO: check against CPU security state when we implement TrustZone */
>      bool is_secure = false;
> +    int access_el = arm_current_el(env);
>  
>      if (is_wp) {
> -        if (!env->cpu_watchpoint[n]
> -            || !(env->cpu_watchpoint[n]->flags & BP_WATCHPOINT_HIT)) {
> +        CPUWatchpoint *wp = env->cpu_watchpoint[n];
> +
> +        if (!wp || !(wp->flags & BP_WATCHPOINT_HIT)) {
>              return false;
>          }
>          cr = env->cp15.dbgwcr[n];
> +        if (wp->hitattrs & MEMTXATTRS_USER) {
> +            /* The LDRT/STRT/LDT/STT "unprivileged access" instructions should
> +             * match watchpoints as if they were accesses done at EL0, even if
> +             * the CPU is at EL1 or higher.
> +             */
> +            access_el = 0;
> +        }
>      } else {
>          uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
>  
> @@ -649,15 +658,7 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
>          break;
>      }
>  
> -    /* TODO: this is not strictly correct because the LDRT/STRT/LDT/STT
> -     * "unprivileged access" instructions should match watchpoints as if
> -     * they were accesses done at EL0, even if the CPU is at EL1 or higher.
> -     * Implementing this would require reworking the core watchpoint code
> -     * to plumb the mmu_idx through to this point. Luckily Linux does not
> -     * rely on this behaviour currently.
> -     * For breakpoints we do want to use the current CPU state.
> -     */
> -    switch (arm_current_el(env)) {
> +    switch (access_el) {
>      case 3:
>      case 2:
>          if (!hmc) {
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 14/14] target-arm: Check watchpoints against CPU security state
  2015-04-07 20:10 ` [Qemu-devel] [PATCH 14/14] target-arm: Check watchpoints against CPU security state Peter Maydell
@ 2015-04-09 11:38   ` Edgar E. Iglesias
  0 siblings, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09 11:38 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, patches, qemu-devel, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Tue, Apr 07, 2015 at 09:10:00PM +0100, Peter Maydell wrote:
> Fix a TODO in bp_wp_matches() now that we have a function for
> testing whether the CPU is currently in Secure mode or not.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>


> ---
>  target-arm/op_helper.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
> index ce09ab3..d8a1054 100644
> --- a/target-arm/op_helper.c
> +++ b/target-arm/op_helper.c
> @@ -600,8 +600,10 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
>      CPUARMState *env = &cpu->env;
>      uint64_t cr;
>      int pac, hmc, ssc, wt, lbn;
> -    /* TODO: check against CPU security state when we implement TrustZone */
> -    bool is_secure = false;
> +    /* Note that for watchpoints the check is against the CPU security
> +     * state, not the S/NS attribute on the offending data access.
> +     */
> +    bool is_secure = arm_is_secure(env);
>      int access_el = arm_current_el(env);
>  
>      if (is_wp) {
> -- 
> 1.9.1
> 

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes
  2015-04-09 10:43         ` Peter Maydell
@ 2015-04-09 11:40           ` Paolo Bonzini
  2015-04-09 11:43             ` Peter Maydell
  0 siblings, 1 reply; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-09 11:40 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Edgar E. Iglesias, Alex Bennée, Richard Henderson



On 09/04/2015 12:43, Peter Maydell wrote:
> > At this point, some memory barriers, basically.
>
> So what distinguishes a device that needs the memory barriers
> and does its accesses via dma_* from a device that doesn't and
> uses address_space_* or ld/st*_phys ? (Or for that matter a
> non-device that does memory accesses...)

I don't know exactly, I didn't follow the discussion very much back
then.  The memory barriers were fixing PPC bugs; PCI devices definitely
need them.

Paolo

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes
  2015-04-09 11:40           ` Paolo Bonzini
@ 2015-04-09 11:43             ` Peter Maydell
  0 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2015-04-09 11:43 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Edgar E. Iglesias, Alex Bennée, Richard Henderson

On 9 April 2015 at 12:40, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 09/04/2015 12:43, Peter Maydell wrote:
>> > At this point, some memory barriers, basically.
>>
>> So what distinguishes a device that needs the memory barriers
>> and does its accesses via dma_* from a device that doesn't and
>> uses address_space_* or ld/st*_phys ? (Or for that matter a
>> non-device that does memory accesses...)
>
> I don't know exactly, I didn't follow the discussion very much back
> then.  The memory barriers were fixing PPC bugs; PCI devices definitely
> need them.

I suspect that actually we need barriers in a lot more places
and there shouldn't really be a separate set of APIs here;
it's just that nobody's tried using the wider set of devices
in PPC KVM systems.

-- PMM

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions
  2015-04-08 11:03   ` Paolo Bonzini
@ 2015-04-09 11:49     ` Peter Maydell
  2015-04-09 12:00       ` Paolo Bonzini
  0 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-09 11:49 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Edgar E. Iglesias, Alex Bennée, Richard Henderson

On 8 April 2015 at 12:03, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 07/04/2015 22:09, Peter Maydell wrote:
>> +#ifdef NEED_CPU_H
>> +uint32_t address_space_lduw(AddressSpace *as, hwaddr addr,
>> +                            MemTxAttrs attrs, MemTxResult *result);
>> +uint32_t address_space_ldl(AddressSpace *as, hwaddr addr,
>> +                            MemTxAttrs attrs, MemTxResult *result);
>> +uint64_t address_space_ldq(AddressSpace *as, hwaddr addr,
>> +                            MemTxAttrs attrs, MemTxResult *result);
>> +void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
>> +                            MemTxAttrs attrs, MemTxResult *result);
>> +void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val,
>> +                            MemTxAttrs attrs, MemTxResult *result);
>> +void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
>> +                            MemTxAttrs attrs, MemTxResult *result);
>> +void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
>> +                            MemTxAttrs attrs, MemTxResult *result);
>> +#endif
>
> I think we do not want to expose these at all (or at least, all users
> should really be CPUs and hence use *_phys functions).
>
> S390 is always big-endian, and watch_mem_read/write can use the same
> buffer trick as subpages (and in fact should probably use memattrs as well).
>
> So, please at least add a comment that these functions are deprecated,
> and check if watch_mem_read/write should be handled like subpages.

I looked at the subpages code, and it seems to me that it's the
other way around -- the subpages code should use these new functions.
At the moment the subpage handlers use address_space_read/write
to pull the data into a buffer, and then use the ldl_p/stl_p functions
to do "read data from target-CPU order buffer into host variable".
It would be better for them to just directly be able to say "do
a ld/st in target-CPU order into this host variable", which is
the purpose of these new functions. Indirecting via a buffer seems
like an ugly workaround for not having the direct operation.

-- PMM

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions
  2015-04-09 11:49     ` Peter Maydell
@ 2015-04-09 12:00       ` Paolo Bonzini
  2015-04-09 12:38         ` Peter Maydell
  0 siblings, 1 reply; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-09 12:00 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Edgar E. Iglesias, Alex Bennée, Richard Henderson



On 09/04/2015 13:49, Peter Maydell wrote:
>> > I think we do not want to expose these at all (or at least, all users
>> > should really be CPUs and hence use *_phys functions).
>> >
>> > S390 is always big-endian, and watch_mem_read/write can use the same
>> > buffer trick as subpages (and in fact should probably use memattrs as well).
>> >
>> > So, please at least add a comment that these functions are deprecated,
>> > and check if watch_mem_read/write should be handled like subpages.
> I looked at the subpages code, and it seems to me that it's the
> other way around -- the subpages code should use these new functions.
> At the moment the subpage handlers use address_space_read/write
> to pull the data into a buffer, and then use the ldl_p/stl_p functions
> to do "read data from target-CPU order buffer into host variable".
> It would be better for them to just directly be able to say "do
> a ld/st in target-CPU order into this host variable", which is
> the purpose of these new functions. Indirecting via a buffer seems
> like an ugly workaround for not having the direct operation.

Using them in subpage code is fine, but then the subpage code is in
exec.c and can use the _internal version directly (and pass
DEVICE_NATIVE_ENDIAN).  Still, usage of these outside exec.c is probably
suspicious.  It's at least worth pulling these in cpu-all.h; the whole
contents of cpu-common.h look like a sundry of functions that either are
deprecated or should be declared elsewhere.

Paolo

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions
  2015-04-09 12:00       ` Paolo Bonzini
@ 2015-04-09 12:38         ` Peter Maydell
  2015-04-09 12:42           ` Paolo Bonzini
  0 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-09 12:38 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Edgar E. Iglesias, Alex Bennée, Richard Henderson

On 9 April 2015 at 13:00, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 09/04/2015 13:49, Peter Maydell wrote:
>>> > I think we do not want to expose these at all (or at least, all users
>>> > should really be CPUs and hence use *_phys functions).
>>> >
>>> > S390 is always big-endian, and watch_mem_read/write can use the same
>>> > buffer trick as subpages (and in fact should probably use memattrs as well).
>>> >
>>> > So, please at least add a comment that these functions are deprecated,
>>> > and check if watch_mem_read/write should be handled like subpages.
>> I looked at the subpages code, and it seems to me that it's the
>> other way around -- the subpages code should use these new functions.
>> At the moment the subpage handlers use address_space_read/write
>> to pull the data into a buffer, and then use the ldl_p/stl_p functions
>> to do "read data from target-CPU order buffer into host variable".
>> It would be better for them to just directly be able to say "do
>> a ld/st in target-CPU order into this host variable", which is
>> the purpose of these new functions. Indirecting via a buffer seems
>> like an ugly workaround for not having the direct operation.
>
> Using them in subpage code is fine, but then the subpage code is in
> exec.c and can use the _internal version directly (and pass
> DEVICE_NATIVE_ENDIAN).  Still, usage of these outside exec.c is probably
> suspicious.

I use them (later in the series) in target-arm/ as well, when I
want a CPU-target-endian access which lets me specify memory
attributes.

> It's at least worth pulling these in cpu-all.h; the whole
> contents of cpu-common.h look like a sundry of functions that either are
> deprecated or should be declared elsewhere.

They need to be in memory.h because cpu-all.h doesn't have
all the typedefs. Also, memory.h seems to me clearly the
best place, since it's where we declare the MemoryRegion
and AddressSpace related functions.

It's certainly true that using target-cpu-endian functions
in a device is somewhat suspicious, but that's generally
true of all those functions, not just these new
address_space_* ones.

So I think I'm happy to add a comment that the functions
are deprecated for use outside target-*/, but I think they
are still necessary.

-- PMM

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions
  2015-04-09 12:38         ` Peter Maydell
@ 2015-04-09 12:42           ` Paolo Bonzini
  0 siblings, 0 replies; 56+ messages in thread
From: Paolo Bonzini @ 2015-04-09 12:42 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Edgar E. Iglesias, Alex Bennée, Richard Henderson



On 09/04/2015 14:38, Peter Maydell wrote:
> They need to be in memory.h because cpu-all.h doesn't have
> all the typedefs. Also, memory.h seems to me clearly the
> best place, since it's where we declare the MemoryRegion
> and AddressSpace related functions.
> 
> It's certainly true that using target-cpu-endian functions
> in a device is somewhat suspicious, but that's generally
> true of all those functions, not just these new
> address_space_* ones.
> 
> So I think I'm happy to add a comment that the functions
> are deprecated for use outside target-*/, but I think they
> are still necessary.

Fair enough, that will do.

Paolo

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 10/14] target-arm: Honour NS bits in page tables
  2015-04-09 11:23   ` Edgar E. Iglesias
@ 2015-04-09 14:14     ` Peter Maydell
  2015-04-09 14:23       ` Edgar E. Iglesias
  0 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-09 14:14 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On 9 April 2015 at 12:23, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> On Tue, Apr 07, 2015 at 09:09:56PM +0100, Peter Maydell wrote:
>>
>> +    if (regime_is_secure(env, mmu_idx)) {
>> +        /* The page table entries may downgrade this to non-secure, but
>> +         * cannot upgrade an non-secure translation regime's attributes
>> +         * to secure.
>> +         */
>> +        *attrs = MEMTXATTRS_SECURE;
>> +    } else {
>> +        *attrs = 0;
>> +    }
>
>
> Should this initialization maybe be done from some kind of secure and NS
> per CPU attribute template?
> What I'm trying to get to is that the machine description may want to
> control some attributes like for example the master-id.
>
> Or did you have another mechanism in mind for that?

I wasn't sure whether we should be adding the tx master ID
in target-specific code or if there was a place to OR it in
in generic code. So I left it out for the moment, since I
don't have an immediate use case for it, and I wanted to
keep the series from ballooning in size too much. If we
end up deciding to do it here then it would be a pretty
simple change to make later.

> In the hack I'm using, CPU code doesn't actually edit the attributes.
> There are a set of attribute objects that board code sets up and the CPU
> selects among them depending on it's state. Once the attributes hit
> tlb_set_page_with_attrs a copy is made into the IOTLB so that
> IOMMUs can modify the actual value in the IOTLB as they translate().
>
> This makes it easy for board code to for example make a non TZ
> capable CPU look as either secure or non-secure.

I think we should probably do this sort of thing using CPU
QOM properties that the board can set appropriately on CPU
creation to influence CPU behaviour (eg a property to set
a tx master ID value, with default being the cpu number).

thanks
-- PMM

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 10/14] target-arm: Honour NS bits in page tables
  2015-04-09 14:14     ` Peter Maydell
@ 2015-04-09 14:23       ` Edgar E. Iglesias
  0 siblings, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-09 14:23 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Thu, Apr 09, 2015 at 03:14:58PM +0100, Peter Maydell wrote:
> On 9 April 2015 at 12:23, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> > On Tue, Apr 07, 2015 at 09:09:56PM +0100, Peter Maydell wrote:
> >>
> >> +    if (regime_is_secure(env, mmu_idx)) {
> >> +        /* The page table entries may downgrade this to non-secure, but
> >> +         * cannot upgrade an non-secure translation regime's attributes
> >> +         * to secure.
> >> +         */
> >> +        *attrs = MEMTXATTRS_SECURE;
> >> +    } else {
> >> +        *attrs = 0;
> >> +    }
> >
> >
> > Should this initialization maybe be done from some kind of secure and NS
> > per CPU attribute template?
> > What I'm trying to get to is that the machine description may want to
> > control some attributes like for example the master-id.
> >
> > Or did you have another mechanism in mind for that?
> 
> I wasn't sure whether we should be adding the tx master ID
> in target-specific code or if there was a place to OR it in
> in generic code. So I left it out for the moment, since I
> don't have an immediate use case for it, and I wanted to
> keep the series from ballooning in size too much. If we
> end up deciding to do it here then it would be a pretty
> simple change to make later.

Yes, that makes sense.

> 
> > In the hack I'm using, CPU code doesn't actually edit the attributes.
> > There are a set of attribute objects that board code sets up and the CPU
> > selects among them depending on it's state. Once the attributes hit
> > tlb_set_page_with_attrs a copy is made into the IOTLB so that
> > IOMMUs can modify the actual value in the IOTLB as they translate().
> >
> > This makes it easy for board code to for example make a non TZ
> > capable CPU look as either secure or non-secure.
> 
> I think we should probably do this sort of thing using CPU
> QOM properties that the board can set appropriately on CPU
> creation to influence CPU behaviour (eg a property to set
> a tx master ID value, with default being the cpu number).

Yes, that's one way.
It would be nice if we could end up with an interface that looks similar 
for CPUs as for DMA devices. Can be naming conventions or maybe QOMifying
the mem-attribute templates so they can be set as links or props.

Cheers,
Edgar

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status
  2015-04-09  9:21       ` Paolo Bonzini
@ 2015-04-10  2:07         ` Edgar E. Iglesias
  2015-04-10 14:51           ` Peter Maydell
  0 siblings, 1 reply; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-10  2:07 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Maydell, Peter Crosthwaite, Patch Tracking,
	QEMU Developers, Greg Bellows, Alex Bennée,
	Richard Henderson

On Thu, Apr 09, 2015 at 11:21:26AM +0200, Paolo Bonzini wrote:
> 
> 
> On 09/04/2015 11:04, Peter Maydell wrote:
> > We discussed this last time round, I think. Whether structs get
> > passed in registers depends on the host CPU ABI/calling convention.
> 
> Because of C++, structs up to pointer size are in practice always passed
> in registers.  64-bit structs may or may not.
> 
> The main advantage of structs is that it's impossible to mismatch the
> parameter order.  That even trumps readability in my opinion.
> 
> I'm ambivalent, but I wouldn't mind at all using structs.

Thanks for clarifying that Paolo.

Yes, the manual bit masking and shifting is easier to get wrong.
The struct also has stronger type checking in a way, as you cant OR in literals
that are out of bounds. (IIRC GCC will even warn you for free).
The struct is also easy to extend if we ever run out of bits in the uint64_t.

Peter, would you consider switching to struct or are you still convinced
of the pure uint64_t approach?

Cheers,
Edgar

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status
  2015-04-10  2:07         ` Edgar E. Iglesias
@ 2015-04-10 14:51           ` Peter Maydell
  2015-04-11 10:27             ` Edgar E. Iglesias
  0 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2015-04-10 14:51 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On 10 April 2015 at 03:07, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> On Thu, Apr 09, 2015 at 11:21:26AM +0200, Paolo Bonzini wrote:
>> On 09/04/2015 11:04, Peter Maydell wrote:
>> > We discussed this last time round, I think. Whether structs get
>> > passed in registers depends on the host CPU ABI/calling convention.
>>
>> Because of C++, structs up to pointer size are in practice always passed
>> in registers.  64-bit structs may or may not.
>>
>> The main advantage of structs is that it's impossible to mismatch the
>> parameter order.  That even trumps readability in my opinion.
>>
>> I'm ambivalent, but I wouldn't mind at all using structs.
>
> Thanks for clarifying that Paolo.
>
> Yes, the manual bit masking and shifting is easier to get wrong.
> The struct also has stronger type checking in a way, as you cant OR in literals
> that are out of bounds. (IIRC GCC will even warn you for free).
> The struct is also easy to extend if we ever run out of bits in the uint64_t.
>
> Peter, would you consider switching to struct or are you still convinced
> of the pure uint64_t approach?

OK, having thought about this I'm willing to take the struct-and-bitfields
approach. My preferences are somewhat based on habit and also on some
of Linus' rants about bitfields for kernel use [eg
http://yarchive.net/comp/linux/bitfields.html], but I think we are
not going to hit any of the problem cases (notably, we don't care
about the arrangement of the bitfields within the word, we aren't
trying to have bitfields and locks/volatile/atomic info shared in
one struct, and we don't have a particular need to test multiple
bits at once).

I'll change over to structs for v2.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status
  2015-04-10 14:51           ` Peter Maydell
@ 2015-04-11 10:27             ` Edgar E. Iglesias
  0 siblings, 0 replies; 56+ messages in thread
From: Edgar E. Iglesias @ 2015-04-11 10:27 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Peter Crosthwaite, Patch Tracking, QEMU Developers, Greg Bellows,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Fri, Apr 10, 2015 at 03:51:07PM +0100, Peter Maydell wrote:
> On 10 April 2015 at 03:07, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> > On Thu, Apr 09, 2015 at 11:21:26AM +0200, Paolo Bonzini wrote:
> >> On 09/04/2015 11:04, Peter Maydell wrote:
> >> > We discussed this last time round, I think. Whether structs get
> >> > passed in registers depends on the host CPU ABI/calling convention.
> >>
> >> Because of C++, structs up to pointer size are in practice always passed
> >> in registers.  64-bit structs may or may not.
> >>
> >> The main advantage of structs is that it's impossible to mismatch the
> >> parameter order.  That even trumps readability in my opinion.
> >>
> >> I'm ambivalent, but I wouldn't mind at all using structs.
> >
> > Thanks for clarifying that Paolo.
> >
> > Yes, the manual bit masking and shifting is easier to get wrong.
> > The struct also has stronger type checking in a way, as you cant OR in literals
> > that are out of bounds. (IIRC GCC will even warn you for free).
> > The struct is also easy to extend if we ever run out of bits in the uint64_t.
> >
> > Peter, would you consider switching to struct or are you still convinced
> > of the pure uint64_t approach?
> 
> OK, having thought about this I'm willing to take the struct-and-bitfields
> approach. My preferences are somewhat based on habit and also on some
> of Linus' rants about bitfields for kernel use [eg
> http://yarchive.net/comp/linux/bitfields.html], but I think we are
> not going to hit any of the problem cases (notably, we don't care
> about the arrangement of the bitfields within the word, we aren't
> trying to have bitfields and locks/volatile/atomic info shared in
> one struct, and we don't have a particular need to test multiple
> bits at once).
> 
> I'll change over to structs for v2.

Awesome, thanks!

^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2015-04-11 10:27 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-07 20:09 [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Peter Maydell
2015-04-07 20:09 ` [Qemu-devel] [PATCH 01/14] memory: Define API for MemoryRegionOps to take attrs and return status Peter Maydell
2015-04-08 10:49   ` Paolo Bonzini
2015-04-09  8:55   ` Edgar E. Iglesias
2015-04-09  9:04     ` Peter Maydell
2015-04-09  9:21       ` Paolo Bonzini
2015-04-10  2:07         ` Edgar E. Iglesias
2015-04-10 14:51           ` Peter Maydell
2015-04-11 10:27             ` Edgar E. Iglesias
2015-04-09  9:32       ` Edgar E. Iglesias
2015-04-07 20:09 ` [Qemu-devel] [PATCH 02/14] memory: Add MemTxAttrs, MemTxResult to io_mem_read and io_mem_write Peter Maydell
2015-04-08 10:51   ` Paolo Bonzini
2015-04-08 10:59     ` Peter Maydell
2015-04-08 11:13       ` Paolo Bonzini
2015-04-09  8:59   ` Edgar E. Iglesias
2015-04-07 20:09 ` [Qemu-devel] [PATCH 03/14] Make CPU iotlb a structure rather than a plain hwaddr Peter Maydell
2015-04-08 10:52   ` Paolo Bonzini
2015-04-09  9:02   ` Edgar E. Iglesias
2015-04-07 20:09 ` [Qemu-devel] [PATCH 04/14] Add MemTxAttrs to the IOTLB Peter Maydell
2015-04-08 10:53   ` Paolo Bonzini
2015-04-09  9:04   ` Edgar E. Iglesias
2015-04-07 20:09 ` [Qemu-devel] [PATCH 05/14] exec.c: Convert subpage memory ops to _with_attrs Peter Maydell
2015-04-08 10:54   ` Paolo Bonzini
2015-04-09  9:07   ` Edgar E. Iglesias
2015-04-07 20:09 ` [Qemu-devel] [PATCH 06/14] exec.c: Make address_space_rw take transaction attributes Peter Maydell
2015-04-08 12:55   ` Paolo Bonzini
2015-04-09  9:59   ` Edgar E. Iglesias
2015-04-09 10:14     ` Peter Maydell
2015-04-09 10:21       ` Paolo Bonzini
2015-04-09 10:43         ` Peter Maydell
2015-04-09 11:40           ` Paolo Bonzini
2015-04-09 11:43             ` Peter Maydell
2015-04-07 20:09 ` [Qemu-devel] [PATCH 07/14] exec.c: Add new address_space_ld*/st* functions Peter Maydell
2015-04-08 11:03   ` Paolo Bonzini
2015-04-09 11:49     ` Peter Maydell
2015-04-09 12:00       ` Paolo Bonzini
2015-04-09 12:38         ` Peter Maydell
2015-04-09 12:42           ` Paolo Bonzini
2015-04-09 10:34   ` Edgar E. Iglesias
2015-04-07 20:09 ` [Qemu-devel] [PATCH 08/14] Switch non-CPU callers from ld/st*_phys to address_space_ld/st* Peter Maydell
2015-04-09 10:44   ` Edgar E. Iglesias
2015-04-07 20:09 ` [Qemu-devel] [PATCH 09/14] exec.c: Capture the memory attributes for a watchpoint hit Peter Maydell
2015-04-08 11:04   ` Paolo Bonzini
2015-04-08 11:14     ` Peter Maydell
2015-04-07 20:09 ` [Qemu-devel] [PATCH 10/14] target-arm: Honour NS bits in page tables Peter Maydell
2015-04-09 11:23   ` Edgar E. Iglesias
2015-04-09 14:14     ` Peter Maydell
2015-04-09 14:23       ` Edgar E. Iglesias
2015-04-07 20:09 ` [Qemu-devel] [PATCH 11/14] target-arm: Use correct memory attributes for page table walks Peter Maydell
2015-04-09 11:34   ` Edgar E. Iglesias
2015-04-07 20:09 ` [Qemu-devel] [PATCH 12/14] target-arm: Add user-mode transaction attribute Peter Maydell
2015-04-07 20:09 ` [Qemu-devel] [PATCH 13/14] target-arm: Use attribute info to handle user-only watchpoints Peter Maydell
2015-04-09 11:37   ` Edgar E. Iglesias
2015-04-07 20:10 ` [Qemu-devel] [PATCH 14/14] target-arm: Check watchpoints against CPU security state Peter Maydell
2015-04-09 11:38   ` Edgar E. Iglesias
2015-04-09  9:37 ` [Qemu-devel] [PATCH 00/14] Add memory attributes and use them in ARM Edgar E. Iglesias

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.