All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API
@ 2013-05-21 10:57 Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 01/30] exec: remove obsolete comment Paolo Bonzini
                   ` (30 more replies)
  0 siblings, 31 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

This is part 1 of the memory API updates for 1.6.  (Part 2 is the
introduction of get/set_owner, part 3 is the introduction of the
RCU-style flatview).

Compared to the first submissions, there are a few extra cleanup
patches, and address_space_rw/read/write grew a return value so
that the existing DMAContext API doesn't need to change.

Paolo

Alexey Kardashevskiy (1):
  memory: give name to every AddressSpace

Avi Kivity (5):
  memory: fix address space initialization/destruction
  memory: limit sections in the radix tree to the actual address space size
  memory: iommu support
  vfio: abort if an emulated iommu is used
  pci: use memory core for iommu support

David Gibson (1):
  memory: Add iommu map/unmap notifiers

Jan Kiszka (3):
  memory: Replace open-coded memory_region_is_romd
  memory: Rename readable flag to romd_mode
  memory: Introduce address_space_lookup_region

Paolo Bonzini (20):
  exec: remove obsolete comment
  exec: eliminate qemu_put_ram_ptr
  exec: make qemu_get_ram_ptr private
  exec: eliminate stq_phys_notdirty
  memory: assert that PhysPageEntry's ptr does not overflow
  memory: allow memory_region_find() to run on non-root memory regions
  memory: do not duplicate memory_region_destructor_none
  memory: make memory_global_sync_dirty_bitmap take an AddressSpace
  s390x: reduce TARGET_PHYS_ADDR_SPACE_BITS to 62
  memory: create FlatView for new address spaces
  memory: add address_space_valid
  memory: clean up phys_page_find
  memory: add address_space_translate
  memory: add return value to address_space_rw/read/write
  spapr: convert TCE API to use an opaque type
  spapr: make IOMMU translation go through IOMMUTLBEntry
  spapr: use memory core for iommu support
  dma: eliminate old-style IOMMU support
  spapr_vio: take care of creating our own AddressSpace/DMAContext
  dma: eliminate DMAContext

 arch_init.c                    |   2 +-
 cputlb.c                       |  20 +--
 dma-helpers.c                  | 185 ++---------------------
 exec.c                         | 332 ++++++++++++++++++++++-------------------
 hw/block/pflash_cfi01.c        |   6 +-
 hw/block/pflash_cfi02.c        |   2 +-
 hw/dma/pl330.c                 |   8 +-
 hw/ide/ahci.c                  |  18 +--
 hw/ide/ahci.h                  |   4 +-
 hw/ide/ich.c                   |   2 +-
 hw/ide/macio.c                 |   4 +-
 hw/misc/vfio.c                 |   2 +
 hw/pci/pci.c                   |  46 +++---
 hw/ppc/spapr_iommu.c           | 117 +++++++--------
 hw/ppc/spapr_pci.c             |  15 +-
 hw/ppc/spapr_vio.c             |  13 +-
 hw/scsi/megasas.c              |   5 +-
 hw/scsi/virtio-scsi.c          |   2 +-
 hw/scsi/vmw_pvscsi.c           |   2 +-
 hw/sd/sdhci.c                  |  22 +--
 hw/usb/hcd-ehci-pci.c          |   4 +-
 hw/usb/hcd-ehci-sysbus.c       |   2 +-
 hw/usb/hcd-ehci.c              |  12 +-
 hw/usb/hcd-ehci.h              |   2 +-
 hw/usb/hcd-ohci.c              |  30 ++--
 hw/usb/libhw.c                 |   4 +-
 include/exec/cpu-common.h      |   4 -
 include/exec/cputlb.h          |  12 +-
 include/exec/memory-internal.h |   1 +
 include/exec/memory.h          | 172 +++++++++++++++------
 include/exec/poison.h          |   1 -
 include/hw/pci-host/spapr.h    |   3 +-
 include/hw/pci/pci.h           |  21 ++-
 include/hw/pci/pci_bus.h       |   4 +-
 include/hw/ppc/spapr.h         |  12 +-
 include/hw/ppc/spapr_vio.h     |  21 +--
 include/sysemu/dma.h           | 143 +++++-------------
 memory.c                       | 111 ++++++++++----
 target-s390x/cpu.h             |   5 +-
 trace-events                   |   3 -
 translate-all.c                |   8 +-
 41 files changed, 654 insertions(+), 728 deletions(-)

-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 01/30] exec: remove obsolete comment
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 11:36   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 02/30] exec: eliminate qemu_put_ram_ptr Paolo Bonzini
                   ` (29 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

See how we call memory_region_section_addr two lines below to
convert a physical address to a base address in the region.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/exec.c b/exec.c
index aec65c5..197625c 100644
--- a/exec.c
+++ b/exec.c
@@ -639,12 +639,6 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
             iotlb |= phys_section_rom;
         }
     } else {
-        /* IO handlers are currently passed a physical address.
-           It would be nice to pass an offset from the base address
-           of that region.  This would avoid having to special case RAM,
-           and avoid full address decoding in every device.
-           We can't use the high bits of pd for this because
-           IO_MEM_ROMD uses these as a ram address.  */
         iotlb = section - phys_sections;
         iotlb += memory_region_section_addr(section, paddr);
     }
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 02/30] exec: eliminate qemu_put_ram_ptr
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 01/30] exec: remove obsolete comment Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 11:38   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 03/30] exec: make qemu_get_ram_ptr private Paolo Bonzini
                   ` (28 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c                    | 8 --------
 hw/pci/pci.c              | 2 --
 hw/scsi/megasas.c         | 1 -
 include/exec/cpu-common.h | 1 -
 trace-events              | 3 ---
 5 files changed, 15 deletions(-)

diff --git a/exec.c b/exec.c
index 197625c..fa5f9c3 100644
--- a/exec.c
+++ b/exec.c
@@ -1334,11 +1334,6 @@ static void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size)
     }
 }
 
-void qemu_put_ram_ptr(void *addr)
-{
-    trace_qemu_put_ram_ptr(addr);
-}
-
 int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
 {
     RAMBlock *block;
@@ -1928,7 +1923,6 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                 ptr = qemu_get_ram_ptr(addr1);
                 memcpy(ptr, buf, l);
                 invalidate_and_set_dirty(addr1, l);
-                qemu_put_ram_ptr(ptr);
             }
         } else {
             if (!(memory_region_is_ram(section->mr) ||
@@ -1958,7 +1952,6 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                                        + memory_region_section_addr(section,
                                                                     addr));
                 memcpy(buf, ptr, l);
-                qemu_put_ram_ptr(ptr);
             }
         }
         len -= l;
@@ -2020,7 +2013,6 @@ void cpu_physical_memory_write_rom(hwaddr addr,
             ptr = qemu_get_ram_ptr(addr1);
             memcpy(ptr, buf, l);
             invalidate_and_set_dirty(addr1, l);
-            qemu_put_ram_ptr(ptr);
         }
         len -= l;
         buf += l;
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index d5257ed..bb3879b 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1959,8 +1959,6 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
         pci_patch_ids(pdev, ptr, size);
     }
 
-    qemu_put_ram_ptr(ptr);
-
     pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom);
 
     return 0;
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 4934a81..fe6550c 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -711,7 +711,6 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
 
         ptr = memory_region_get_ram_ptr(&s->dev.rom);
         memcpy(biosver, ptr + 0x41, 31);
-        qemu_put_ram_ptr(ptr);
         memcpy(info.image_component[1].name, "BIOS", 4);
         memcpy(info.image_component[1].version, biosver,
                strlen((const char *)biosver));
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 2e5f11f..cafc3c2 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -51,7 +51,6 @@ typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr);
 void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
 /* This should only be used for ram local to a device.  */
 void *qemu_get_ram_ptr(ram_addr_t addr);
-void qemu_put_ram_ptr(void *addr);
 /* This should not be used by devices.  */
 int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
 ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
diff --git a/trace-events b/trace-events
index 9c73931..b123b0f 100644
--- a/trace-events
+++ b/trace-events
@@ -813,9 +813,6 @@ xen_map_cache_return(void* ptr) "%p"
 xen_map_block(uint64_t phys_addr, uint64_t size) "%#"PRIx64", size %#"PRIx64
 xen_unmap_block(void* addr, unsigned long size) "%p, size %#lx"
 
-# exec.c
-qemu_put_ram_ptr(void* addr) "%p"
-
 # hw/xen_platform.c
 xen_platform_log(char *s) "xen platform: %s"
 
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 03/30] exec: make qemu_get_ram_ptr private
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 01/30] exec: remove obsolete comment Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 02/30] exec: eliminate qemu_put_ram_ptr Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 11:38   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 04/30] exec: eliminate stq_phys_notdirty Paolo Bonzini
                   ` (27 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

It is a private interface between exec.c and memory.c.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/exec/cpu-common.h      | 2 --
 include/exec/memory-internal.h | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index cafc3c2..af851aa 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -49,8 +49,6 @@ typedef void CPUWriteMemoryFunc(void *opaque, hwaddr addr, uint32_t value);
 typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr);
 
 void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
-/* This should only be used for ram local to a device.  */
-void *qemu_get_ram_ptr(ram_addr_t addr);
 /* This should not be used by devices.  */
 int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
 ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 1b156fd..8d15f90 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -46,6 +46,7 @@ void address_space_destroy_dispatch(AddressSpace *as);
 ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
                                    MemoryRegion *mr);
 ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);
+void *qemu_get_ram_ptr(ram_addr_t addr);
 void qemu_ram_free(ram_addr_t addr);
 void qemu_ram_free_from_ptr(ram_addr_t addr);
 
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 04/30] exec: eliminate stq_phys_notdirty
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (2 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 03/30] exec: make qemu_get_ram_ptr private Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 17:32   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 05/30] memory: assert that PhysPageEntry's ptr does not overflow Paolo Bonzini
                   ` (26 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

It is not used anywhere.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c                    | 27 ---------------------------
 include/exec/cpu-common.h |  1 -
 include/exec/poison.h     |  1 -
 3 files changed, 29 deletions(-)

diff --git a/exec.c b/exec.c
index fa5f9c3..1355661 100644
--- a/exec.c
+++ b/exec.c
@@ -2390,33 +2390,6 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val)
     }
 }
 
-void stq_phys_notdirty(hwaddr addr, uint64_t val)
-{
-    uint8_t *ptr;
-    MemoryRegionSection *section;
-
-    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
-
-    if (!memory_region_is_ram(section->mr) || section->readonly) {
-        addr = memory_region_section_addr(section, addr);
-        if (memory_region_is_ram(section->mr)) {
-            section = &phys_sections[phys_section_rom];
-        }
-#ifdef TARGET_WORDS_BIGENDIAN
-        io_mem_write(section->mr, addr, val >> 32, 4);
-        io_mem_write(section->mr, addr + 4, (uint32_t)val, 4);
-#else
-        io_mem_write(section->mr, addr, (uint32_t)val, 4);
-        io_mem_write(section->mr, addr + 4, val >> 32, 4);
-#endif
-    } else {
-        ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
-                                & TARGET_PAGE_MASK)
-                               + memory_region_section_addr(section, addr));
-        stq_p(ptr, val);
-    }
-}
-
 /* warning: addr must be aligned */
 static inline void stl_phys_internal(hwaddr addr, uint32_t val,
                                      enum device_endian endian)
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index af851aa..af5258d 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -102,7 +102,6 @@ uint32_t lduw_phys(hwaddr addr);
 uint32_t ldl_phys(hwaddr addr);
 uint64_t ldq_phys(hwaddr addr);
 void stl_phys_notdirty(hwaddr addr, uint32_t val);
-void stq_phys_notdirty(hwaddr addr, uint64_t val);
 void stw_phys(hwaddr addr, uint32_t val);
 void stl_phys(hwaddr addr, uint32_t val);
 void stq_phys(hwaddr addr, uint64_t val);
diff --git a/include/exec/poison.h b/include/exec/poison.h
index 7d7b23b..2341a75 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -42,7 +42,6 @@
 #pragma GCC poison ldl_phys
 #pragma GCC poison ldq_phys
 #pragma GCC poison stl_phys_notdirty
-#pragma GCC poison stq_phys_notdirty
 #pragma GCC poison stw_phys
 #pragma GCC poison stl_phys
 #pragma GCC poison stq_phys
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 05/30] memory: assert that PhysPageEntry's ptr does not overflow
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (3 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 04/30] exec: eliminate stq_phys_notdirty Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 17:36   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 06/30] memory: allow memory_region_find() to run on non-root memory regions Paolo Bonzini
                   ` (25 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

While sized to 15 bits in PhysPageEntry, the ptr field is ORed into the
iotlb entries together with a page-aligned pointer.  The ptr field must
not overflow into this page-aligned value, assert that it is smaller than
the page size.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/exec.c b/exec.c
index 1355661..380245f 100644
--- a/exec.c
+++ b/exec.c
@@ -713,6 +713,8 @@ static void destroy_all_mappings(AddressSpaceDispatch *d)
 
 static uint16_t phys_section_add(MemoryRegionSection *section)
 {
+    assert(phys_sections_nb < TARGET_PAGE_SIZE);
+
     if (phys_sections_nb == phys_sections_nb_alloc) {
         phys_sections_nb_alloc = MAX(phys_sections_nb_alloc * 2, 16);
         phys_sections = g_renew(MemoryRegionSection, phys_sections,
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 06/30] memory: allow memory_region_find() to run on non-root memory regions
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (4 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 05/30] memory: assert that PhysPageEntry's ptr does not overflow Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 17:52   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 07/30] memory: Replace open-coded memory_region_is_romd Paolo Bonzini
                   ` (24 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

memory_region_find() is similar to registering a MemoryListener and
checking for the MemoryRegionSections that come from a particular
region.  There is no reason for this to be limited to a root memory
region.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/exec/memory.h | 13 +++++++------
 memory.c              | 20 +++++++++++++++-----
 2 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 9e88320..efe210b 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -725,17 +725,18 @@ void memory_region_set_alias_offset(MemoryRegion *mr,
  *
  * Returns a #MemoryRegionSection that describes a contiguous overlap.
  * It will have the following characteristics:
- *    .@offset_within_address_space >= @addr
- *    .@offset_within_address_space + .@size <= @addr + @size
  *    .@size = 0 iff no overlap was found
  *    .@mr is non-%NULL iff an overlap was found
  *
- * @address_space: a top-level (i.e. parentless) region that contains
- *       the region to be found
- * @addr: start of the area within @address_space to be searched
+ * If @mr has no parent, @addr is an absolute address in an AddressSpace, hence:
+ *    .@offset_within_address_space >= @addr
+ *    .@offset_within_address_space + .@size <= @addr + @size
+ *
+ * @mr: a MemoryRegion within which @addr is a relative address
+ * @addr: start of the area within @as to be searched
  * @size: size of the area to be searched
  */
-MemoryRegionSection memory_region_find(MemoryRegion *address_space,
+MemoryRegionSection memory_region_find(MemoryRegion *mr,
                                        hwaddr addr, uint64_t size);
 
 /**
diff --git a/memory.c b/memory.c
index 75ca281..34bfb13 100644
--- a/memory.c
+++ b/memory.c
@@ -1451,15 +1451,24 @@ static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr)
                    sizeof(FlatRange), cmp_flatrange_addr);
 }
 
-MemoryRegionSection memory_region_find(MemoryRegion *address_space,
+MemoryRegionSection memory_region_find(MemoryRegion *mr,
                                        hwaddr addr, uint64_t size)
 {
-    AddressSpace *as = memory_region_to_address_space(address_space);
-    AddrRange range = addrrange_make(int128_make64(addr),
-                                     int128_make64(size));
-    FlatRange *fr = address_space_lookup(as, range);
     MemoryRegionSection ret = { .mr = NULL, .size = 0 };
+    MemoryRegion *root;
+    AddressSpace *as;
+    AddrRange range;
+    FlatRange *fr;
+
+    addr += mr->addr;
+    for (root = mr; root->parent; ) {
+        root = root->parent;
+        addr += root->addr;
+    }
 
+    as = memory_region_to_address_space(root);
+    range = addrrange_make(int128_make64(addr), int128_make64(size));
+    fr = address_space_lookup(as, range);
     if (!fr) {
         return ret;
     }
@@ -1470,6 +1479,7 @@ MemoryRegionSection memory_region_find(MemoryRegion *address_space,
     }
 
     ret.mr = fr->mr;
+    ret.address_space = as;
     range = addrrange_intersection(range, fr->addr);
     ret.offset_within_region = fr->offset_in_region;
     ret.offset_within_region += int128_get64(int128_sub(range.start,
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 07/30] memory: Replace open-coded memory_region_is_romd
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (5 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 06/30] memory: allow memory_region_find() to run on non-root memory regions Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 11:54   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 08/30] memory: Rename readable flag to romd_mode Paolo Bonzini
                   ` (23 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, Jan Kiszka, David Gibson

From: Jan Kiszka <jan.kiszka@siemens.com>

Improves readability.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 translate-all.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/translate-all.c b/translate-all.c
index da93608..0d84b0d 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1359,7 +1359,7 @@ void tb_invalidate_phys_addr(hwaddr addr)
     section = phys_page_find(address_space_memory.dispatch,
                              addr >> TARGET_PAGE_BITS);
     if (!(memory_region_is_ram(section->mr)
-          || (section->mr->rom_device && section->mr->readable))) {
+          || memory_region_is_romd(section->mr))) {
         return;
     }
     ram_addr = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 08/30] memory: Rename readable flag to romd_mode
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (6 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 07/30] memory: Replace open-coded memory_region_is_romd Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 09/30] memory: do not duplicate memory_region_destructor_none Paolo Bonzini
                   ` (22 subsequent siblings)
  30 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, Jan Kiszka, David Gibson

From: Jan Kiszka <jan.kiszka@siemens.com>

"Readable" is a very unfortunate name for this flag because even a
rom_device region will always be readable from the guest POV. What
differs is the mapping, just like the comments had to explain already.
Also, readable could currently be understood as being a generic region
flag, but it only applies to rom_device regions.

So rename the flag and the function to modify it after the original term
"ROMD" which could also be interpreted as "ROM direct", i.e. ROM mode
with direct access. In any case, the scope of the flag is clearer now.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/block/pflash_cfi01.c |  6 +++---
 hw/block/pflash_cfi02.c |  2 +-
 include/exec/memory.h   | 22 +++++++++++-----------
 memory.c                | 30 +++++++++++++++---------------
 4 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 3ff20e0..63d7c99 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -105,7 +105,7 @@ static void pflash_timer (void *opaque)
     DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);
     /* Reset flash */
     pfl->status ^= 0x80;
-    memory_region_rom_device_set_readable(&pfl->mem, true);
+    memory_region_rom_device_set_romd(&pfl->mem, true);
     pfl->wcycle = 0;
     pfl->cmd = 0;
 }
@@ -281,7 +281,7 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
 
     if (!pfl->wcycle) {
         /* Set the device in I/O access mode */
-        memory_region_rom_device_set_readable(&pfl->mem, false);
+        memory_region_rom_device_set_romd(&pfl->mem, false);
     }
 
     switch (pfl->wcycle) {
@@ -458,7 +458,7 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
                   "\n", __func__, offset, pfl->wcycle, pfl->cmd, value);
 
  reset_flash:
-    memory_region_rom_device_set_readable(&pfl->mem, true);
+    memory_region_rom_device_set_romd(&pfl->mem, true);
 
     pfl->wcycle = 0;
     pfl->cmd = 0;
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 9a7fa70..5f25246 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -111,7 +111,7 @@ static void pflash_setup_mappings(pflash_t *pfl)
 
 static void pflash_register_memory(pflash_t *pfl, int rom_mode)
 {
-    memory_region_rom_device_set_readable(&pfl->orig_mem, rom_mode);
+    memory_region_rom_device_set_romd(&pfl->orig_mem, rom_mode);
     pfl->rom_mode = rom_mode;
 }
 
diff --git a/include/exec/memory.h b/include/exec/memory.h
index efe210b..0409180 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -126,7 +126,7 @@ struct MemoryRegion {
     ram_addr_t ram_addr;
     bool subpage;
     bool terminates;
-    bool readable;
+    bool romd_mode;
     bool ram;
     bool readonly; /* For RAM regions */
     bool enabled;
@@ -355,16 +355,16 @@ uint64_t memory_region_size(MemoryRegion *mr);
 bool memory_region_is_ram(MemoryRegion *mr);
 
 /**
- * memory_region_is_romd: check whether a memory region is ROMD
+ * memory_region_is_romd: check whether a memory region is in ROMD mode
  *
- * Returns %true is a memory region is ROMD and currently set to allow
+ * Returns %true if a memory region is a ROM device and currently set to allow
  * direct reads.
  *
  * @mr: the memory region being queried
  */
 static inline bool memory_region_is_romd(MemoryRegion *mr)
 {
-    return mr->rom_device && mr->readable;
+    return mr->rom_device && mr->romd_mode;
 }
 
 /**
@@ -502,18 +502,18 @@ void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr,
 void memory_region_set_readonly(MemoryRegion *mr, bool readonly);
 
 /**
- * memory_region_rom_device_set_readable: enable/disable ROM readability
+ * memory_region_rom_device_set_romd: enable/disable ROMD mode
  *
  * Allows a ROM device (initialized with memory_region_init_rom_device() to
- * to be marked as readable (default) or not readable.  When it is readable,
- * the device is mapped to guest memory.  When not readable, reads are
- * forwarded to the #MemoryRegion.read function.
+ * set to ROMD mode (default) or MMIO mode.  When it is in ROMD mode, the
+ * device is mapped to guest memory and satisfies read access directly.
+ * When in MMIO mode, reads are forwarded to the #MemoryRegion.read function.
+ * Writes are always handled by the #MemoryRegion.write function.
  *
  * @mr: the memory region to be updated
- * @readable: whether reads are satisified directly (%true) or via callbacks
- *            (%false)
+ * @romd_mode: %true to put the region into ROMD mode
  */
-void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable);
+void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode);
 
 /**
  * memory_region_set_coalescing: Enable memory coalescing for the region.
diff --git a/memory.c b/memory.c
index 34bfb13..013464b 100644
--- a/memory.c
+++ b/memory.c
@@ -213,7 +213,7 @@ struct FlatRange {
     hwaddr offset_in_region;
     AddrRange addr;
     uint8_t dirty_log_mask;
-    bool readable;
+    bool romd_mode;
     bool readonly;
 };
 
@@ -236,7 +236,7 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b)
     return a->mr == b->mr
         && addrrange_equal(a->addr, b->addr)
         && a->offset_in_region == b->offset_in_region
-        && a->readable == b->readable
+        && a->romd_mode == b->romd_mode
         && a->readonly == b->readonly;
 }
 
@@ -276,7 +276,7 @@ static bool can_merge(FlatRange *r1, FlatRange *r2)
                                 r1->addr.size),
                      int128_make64(r2->offset_in_region))
         && r1->dirty_log_mask == r2->dirty_log_mask
-        && r1->readable == r2->readable
+        && r1->romd_mode == r2->romd_mode
         && r1->readonly == r2->readonly;
 }
 
@@ -532,7 +532,7 @@ static void render_memory_region(FlatView *view,
             fr.offset_in_region = offset_in_region;
             fr.addr = addrrange_make(base, now);
             fr.dirty_log_mask = mr->dirty_log_mask;
-            fr.readable = mr->readable;
+            fr.romd_mode = mr->romd_mode;
             fr.readonly = readonly;
             flatview_insert(view, i, &fr);
             ++i;
@@ -552,7 +552,7 @@ static void render_memory_region(FlatView *view,
         fr.offset_in_region = offset_in_region;
         fr.addr = addrrange_make(base, remain);
         fr.dirty_log_mask = mr->dirty_log_mask;
-        fr.readable = mr->readable;
+        fr.romd_mode = mr->romd_mode;
         fr.readonly = readonly;
         flatview_insert(view, i, &fr);
     }
@@ -801,7 +801,7 @@ void memory_region_init(MemoryRegion *mr,
     mr->enabled = true;
     mr->terminates = false;
     mr->ram = false;
-    mr->readable = true;
+    mr->romd_mode = true;
     mr->readonly = false;
     mr->rom_device = false;
     mr->destructor = memory_region_destructor_none;
@@ -1121,11 +1121,11 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
     }
 }
 
-void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable)
+void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode)
 {
-    if (mr->readable != readable) {
+    if (mr->romd_mode != romd_mode) {
         memory_region_transaction_begin();
-        mr->readable = readable;
+        mr->romd_mode = romd_mode;
         memory_region_update_pending |= mr->enabled;
         memory_region_transaction_commit();
     }
@@ -1659,9 +1659,9 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
                    base + mr->addr
                    + (hwaddr)int128_get64(mr->size) - 1,
                    mr->priority,
-                   mr->readable ? 'R' : '-',
-                   !mr->readonly && !(mr->rom_device && mr->readable) ? 'W'
-                                                                      : '-',
+                   mr->romd_mode ? 'R' : '-',
+                   !mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W'
+                                                                       : '-',
                    mr->name,
                    mr->alias->name,
                    mr->alias_offset,
@@ -1674,9 +1674,9 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
                    base + mr->addr
                    + (hwaddr)int128_get64(mr->size) - 1,
                    mr->priority,
-                   mr->readable ? 'R' : '-',
-                   !mr->readonly && !(mr->rom_device && mr->readable) ? 'W'
-                                                                      : '-',
+                   mr->romd_mode ? 'R' : '-',
+                   !mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W'
+                                                                       : '-',
                    mr->name);
     }
 
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 09/30] memory: do not duplicate memory_region_destructor_none
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (7 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 08/30] memory: Rename readable flag to romd_mode Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 11:55   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 10/30] memory: make memory_global_sync_dirty_bitmap take an AddressSpace Paolo Bonzini
                   ` (21 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 memory.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/memory.c b/memory.c
index 013464b..5431463 100644
--- a/memory.c
+++ b/memory.c
@@ -768,10 +768,6 @@ static void memory_region_destructor_ram_from_ptr(MemoryRegion *mr)
     qemu_ram_free_from_ptr(mr->ram_addr);
 }
 
-static void memory_region_destructor_iomem(MemoryRegion *mr)
-{
-}
-
 static void memory_region_destructor_rom_device(MemoryRegion *mr)
 {
     qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
@@ -929,7 +925,6 @@ void memory_region_init_io(MemoryRegion *mr,
     mr->ops = ops;
     mr->opaque = opaque;
     mr->terminates = true;
-    mr->destructor = memory_region_destructor_iomem;
     mr->ram_addr = ~(ram_addr_t)0;
 }
 
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 10/30] memory: make memory_global_sync_dirty_bitmap take an AddressSpace
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (8 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 09/30] memory: do not duplicate memory_region_destructor_none Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 11:56   ` Peter Maydell
  2013-05-23  1:05   ` David Gibson
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 11/30] memory: fix address space initialization/destruction Paolo Bonzini
                   ` (20 subsequent siblings)
  30 siblings, 2 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch_init.c           | 2 +-
 include/exec/memory.h | 7 +++----
 memory.c              | 3 +--
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 49c5dc2..5d32ecf 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -386,7 +386,7 @@ static void migration_bitmap_sync(void)
     }
 
     trace_migration_bitmap_sync_start();
-    memory_global_sync_dirty_bitmap(get_system_memory());
+    address_space_sync_dirty_bitmap(&address_space_memory);
 
     QTAILQ_FOREACH(block, &ram_list.blocks, next) {
         for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 0409180..9fae89b 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -757,13 +757,12 @@ memory_region_section_addr(MemoryRegionSection *section,
 }
 
 /**
- * memory_global_sync_dirty_bitmap: synchronize the dirty log for all memory
+ * address_space_sync_dirty_bitmap: synchronize the dirty log for all memory
  *
  * Synchronizes the dirty page log for an entire address space.
- * @address_space: a top-level (i.e. parentless) region that contains the
- *       memory being synchronized
+ * @as: the address space that contains the memory being synchronized
  */
-void memory_global_sync_dirty_bitmap(MemoryRegion *address_space);
+void address_space_sync_dirty_bitmap(AddressSpace *as);
 
 /**
  * memory_region_transaction_begin: Start a transaction.
diff --git a/memory.c b/memory.c
index 5431463..11bbeb7 100644
--- a/memory.c
+++ b/memory.c
@@ -1485,9 +1485,8 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
     return ret;
 }
 
-void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
+void address_space_sync_dirty_bitmap(AddressSpace *as)
 {
-    AddressSpace *as = memory_region_to_address_space(address_space);
     FlatRange *fr;
 
     FOR_EACH_FLAT_RANGE(fr, as->current_map) {
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 11/30] memory: fix address space initialization/destruction
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (9 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 10/30] memory: make memory_global_sync_dirty_bitmap take an AddressSpace Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 11:58   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 12/30] s390x: reduce TARGET_PHYS_ADDR_SPACE_BITS to 62 Paolo Bonzini
                   ` (19 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, Avi Kivity, David Gibson

From: Avi Kivity <avi.kivity@gmail.com>

A couple of fields were left uninitialized.  This was not observed earlier
because all address spaces were statically allocated.  Also free allocation
for those fields.

Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 memory.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/memory.c b/memory.c
index 11bbeb7..9478f98 100644
--- a/memory.c
+++ b/memory.c
@@ -1572,6 +1572,8 @@ void address_space_init(AddressSpace *as, MemoryRegion *root)
     as->root = root;
     as->current_map = g_new(FlatView, 1);
     flatview_init(as->current_map);
+    as->ioeventfd_nb = 0;
+    as->ioeventfds = NULL;
     QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
     as->name = NULL;
     memory_region_transaction_commit();
@@ -1588,6 +1590,7 @@ void address_space_destroy(AddressSpace *as)
     address_space_destroy_dispatch(as);
     flatview_destroy(as->current_map);
     g_free(as->current_map);
+    g_free(as->ioeventfds);
 }
 
 uint64_t io_mem_read(MemoryRegion *mr, hwaddr addr, unsigned size)
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 12/30] s390x: reduce TARGET_PHYS_ADDR_SPACE_BITS to 62
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (10 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 11/30] memory: fix address space initialization/destruction Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 13/30] memory: limit sections in the radix tree to the actual address space size Paolo Bonzini
                   ` (18 subsequent siblings)
  30 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, Alexander Graf, David Gibson

With the next patch, the memory API will complain if the
TARGET_PHYS_ADDR_SPACE_BITS gets dangerously close to an
overflow.  s390x can handle up to 64 bit of physical address
space from its page tables, but we never use that much.  Just
decrease the value.

Cc: Alexander Graf <agraf@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-s390x/cpu.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 0ce82cf..6304c4d 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -34,7 +34,10 @@
 #include "exec/cpu-defs.h"
 #define TARGET_PAGE_BITS 12
 
-#define TARGET_PHYS_ADDR_SPACE_BITS 64
+/* Actually 64-bits, limited by the memory API to 62 bits.  We
+ * never use that much.
+ */
+#define TARGET_PHYS_ADDR_SPACE_BITS 62
 #define TARGET_VIRT_ADDR_SPACE_BITS 64
 
 #include "exec/cpu-all.h"
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 13/30] memory: limit sections in the radix tree to the actual address space size
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (11 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 12/30] s390x: reduce TARGET_PHYS_ADDR_SPACE_BITS to 62 Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 12:02   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 14/30] memory: create FlatView for new address spaces Paolo Bonzini
                   ` (17 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, Avi Kivity, David Gibson

From: Avi Kivity <avi.kivity@gmail.com>

The radix tree is statically sized to fit TARGET_PHYS_ADDR_SPACE_BITS.
If a larger memory region is registered, it will overflow.

Fix by limiting any section in the radix tree to the supported size.

This problem was not observed earlier since artificial regions (containers
and aliases) are eliminated by the memory core, leaving only device regions
which have reasonable sizes.  An IOMMU however cannot be eliminated by the
memory core, and may have an artificial size.

Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
[ Fail the build if TARGET_PHYS_ADDR_SPACE_BITS is too large - Paolo ]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c                | 13 ++++++++++++-
 include/exec/memory.h |  3 +++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/exec.c b/exec.c
index 380245f..8d91221 100644
--- a/exec.c
+++ b/exec.c
@@ -771,10 +771,21 @@ static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *sec
                   section_index);
 }
 
+QEMU_BUILD_BUG_ON(TARGET_PHYS_ADDR_SPACE_BITS > MAX_PHYS_ADDR_SPACE_BITS)
+
+static MemoryRegionSection limit(MemoryRegionSection section)
+{
+    section.size = MIN(section.offset_within_address_space + section.size,
+                       MAX_PHYS_ADDR + 1)
+                   - section.offset_within_address_space;
+
+    return section;
+}
+
 static void mem_add(MemoryListener *listener, MemoryRegionSection *section)
 {
     AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener);
-    MemoryRegionSection now = *section, remain = *section;
+    MemoryRegionSection now = limit(*section), remain = limit(*section);
 
     if ((now.offset_within_address_space & ~TARGET_PAGE_MASK)
         || (now.size < TARGET_PAGE_SIZE)) {
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 9fae89b..6ed593c 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -26,6 +26,9 @@
 #include "exec/ioport.h"
 #include "qemu/int128.h"
 
+#define MAX_PHYS_ADDR_SPACE_BITS 62
+#define MAX_PHYS_ADDR            (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
+
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegionPortio MemoryRegionPortio;
 typedef struct MemoryRegionMmio MemoryRegionMmio;
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 14/30] memory: create FlatView for new address spaces
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (12 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 13/30] memory: limit sections in the radix tree to the actual address space size Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 12:03   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 15/30] memory: add address_space_valid Paolo Bonzini
                   ` (16 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

Even a new address space might have a non-empty FlatView.  In order
to initialize it properly, address_space_init should (a) call
memory_region_transaction_commit after the address space is inserted
into the list; (b) force memory_region_transaction_commit to do something.

This bug was latent so far because all address spaces started empty, including
the PCI address space where the bus master region is initially disabled.
However, the target address space of an IOMMU is usually rooted at
get_system_memory(), which might not be empty at the time the IOMMU is created.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 memory.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/memory.c b/memory.c
index 9478f98..99f046d 100644
--- a/memory.c
+++ b/memory.c
@@ -1576,8 +1576,9 @@ void address_space_init(AddressSpace *as, MemoryRegion *root)
     as->ioeventfds = NULL;
     QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
     as->name = NULL;
-    memory_region_transaction_commit();
     address_space_init_dispatch(as);
+    memory_region_update_pending |= root->enabled;
+    memory_region_transaction_commit();
 }
 
 void address_space_destroy(AddressSpace *as)
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (13 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 14/30] memory: create FlatView for new address spaces Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 12:05   ` David Gibson
  2013-05-23 18:04   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 16/30] memory: clean up phys_page_find Paolo Bonzini
                   ` (15 subsequent siblings)
  30 siblings, 2 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

The old-style IOMMU lets you check whether an access is valid in a
given DMAContext.  There is no equivalent for AddressSpace in the
memory API, implement it with a lookup of the dispatch tree.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 dma-helpers.c         |  5 +++++
 exec.c                | 25 +++++++++++++++++++++++++
 include/exec/memory.h | 14 ++++++++++++++
 include/sysemu/dma.h  |  3 ++-
 4 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/dma-helpers.c b/dma-helpers.c
index 272632f..2962b69 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -298,6 +298,11 @@ bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len,
             plen = len;
         }
 
+        if (!address_space_valid(dma->as, paddr, len,
+                                 dir == DMA_DIRECTION_FROM_DEVICE)) {
+            return false;
+        }
+
         len -= plen;
         addr += plen;
     }
diff --git a/exec.c b/exec.c
index 8d91221..8f1b507 100644
--- a/exec.c
+++ b/exec.c
@@ -2079,6 +2079,31 @@ static void cpu_notify_map_clients(void)
     }
 }
 
+bool address_space_valid(AddressSpace *as, hwaddr addr, int len, bool is_write)
+{
+    AddressSpaceDispatch *d = as->dispatch;
+    MemoryRegionSection *section;
+    int l;
+    hwaddr page;
+
+    while (len > 0) {
+        page = addr & TARGET_PAGE_MASK;
+        l = (page + TARGET_PAGE_SIZE) - addr;
+        if (l > len) {
+            l = len;
+        }
+        section = phys_page_find(d, addr >> TARGET_PAGE_BITS);
+        if (section->mr == &io_mem_unassigned ||
+            (is_write && section->mr->readonly)) {
+            return false;
+        }
+
+        len -= l;
+        addr += l;
+    }
+    return true;
+}
+
 /* Map a physical memory region into a host virtual address.
  * May map a subset of the requested range, given by and returned in *plen.
  * May return NULL if resources needed to perform the mapping are exhausted.
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 6ed593c..2e5fd11 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -860,6 +860,20 @@ void address_space_write(AddressSpace *as, hwaddr addr,
  */
 void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
 
+/* address_space_valid: check for validity of an address space range
+ *
+ * Check whether memory is assigned to the given address space range.
+ *
+ * For now, addr and len should be aligned to a page size.  This limitation
+ * will be lifted in the future.
+ *
+ * @as: #AddressSpace to be accessed
+ * @addr: address within that address space
+ * @len: length of the area to be checked
+ * @is_write: indicates the transfer direction
+ */
+bool address_space_valid(AddressSpace *as, hwaddr addr, int len, bool is_write);
+
 /* address_space_map: map a physical memory region into a host virtual address
  *
  * May map a subset of the requested range, given by and returned in @plen.
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
index a52c93a..2e239dc 100644
--- a/include/sysemu/dma.h
+++ b/include/sysemu/dma.h
@@ -113,7 +113,8 @@ static inline bool dma_memory_valid(DMAContext *dma,
                                     DMADirection dir)
 {
     if (!dma_has_iommu(dma)) {
-        return true;
+        return address_space_valid(dma->as, addr, len,
+                                   dir == DMA_DIRECTION_FROM_DEVICE);
     } else {
         return iommu_dma_memory_valid(dma, addr, len, dir);
     }
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 16/30] memory: clean up phys_page_find
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (14 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 15/30] memory: add address_space_valid Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 18:06   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 17/30] memory: add address_space_translate Paolo Bonzini
                   ` (14 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

Remove the goto.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/exec.c b/exec.c
index 8f1b507..82da067 100644
--- a/exec.c
+++ b/exec.c
@@ -187,19 +187,15 @@ MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
     PhysPageEntry lp = d->phys_map;
     PhysPageEntry *p;
     int i;
-    uint16_t s_index = phys_section_unassigned;
 
     for (i = P_L2_LEVELS - 1; i >= 0 && !lp.is_leaf; i--) {
         if (lp.ptr == PHYS_MAP_NODE_NIL) {
-            goto not_found;
+            return &phys_sections[phys_section_unassigned];
         }
         p = phys_map_nodes[lp.ptr];
         lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)];
     }
-
-    s_index = lp.ptr;
-not_found:
-    return &phys_sections[s_index];
+    return &phys_sections[lp.ptr];
 }
 
 bool memory_region_is_unassigned(MemoryRegion *mr)
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (15 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 16/30] memory: clean up phys_page_find Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23  7:09   ` liu ping fan
                     ` (2 more replies)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 18/30] memory: add return value to address_space_rw/read/write Paolo Bonzini
                   ` (13 subsequent siblings)
  30 siblings, 3 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

Using phys_page_find to translate an AddressSpace to a MemoryRegionSection
is unwieldy.  It requires to pass the page index rather than the address,
and later memory_region_section_addr has to be called.  Replace
memory_region_section_addr with a function that does all of it: call
phys_page_find, compute the offset within the region, and check how
big the current mapping is.  This way, a large flat region can be written
with a single lookup rather than a page at a time.

address_space_translate will also provide a single point where IOMMU
forwarding is implemented.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 cputlb.c              |  20 ++---
 exec.c                | 201 +++++++++++++++++++++++++++-----------------------
 include/exec/cputlb.h |  12 ++-
 include/exec/memory.h |  31 ++++----
 translate-all.c       |   6 +-
 5 files changed, 143 insertions(+), 127 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index aba7e44..1f85da0 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -248,13 +248,18 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
     target_ulong code_address;
     uintptr_t addend;
     CPUTLBEntry *te;
-    hwaddr iotlb;
+    hwaddr iotlb, xlat, sz;
 
     assert(size >= TARGET_PAGE_SIZE);
     if (size != TARGET_PAGE_SIZE) {
         tlb_add_large_page(env, vaddr, size);
     }
-    section = phys_page_find(address_space_memory.dispatch, paddr >> TARGET_PAGE_BITS);
+
+    sz = size;
+    section = address_space_translate(&address_space_memory, paddr, &xlat, &sz,
+                                      false);
+    assert(sz >= TARGET_PAGE_SIZE);
+
 #if defined(DEBUG_TLB)
     printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
            " prot=%x idx=%d pd=0x%08lx\n",
@@ -269,15 +274,14 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
     }
     if (memory_region_is_ram(section->mr) ||
         memory_region_is_romd(section->mr)) {
-        addend = (uintptr_t)memory_region_get_ram_ptr(section->mr)
-        + memory_region_section_addr(section, paddr);
+        addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
     } else {
         addend = 0;
     }
 
     code_address = address;
-    iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, prot,
-                                            &address);
+    iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, xlat,
+                                            prot, &address);
 
     index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     env->iotlb[mmu_idx][index] = iotlb - vaddr;
@@ -300,9 +304,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
             /* Write access calls the I/O callback.  */
             te->addr_write = address | TLB_MMIO;
         } else if (memory_region_is_ram(section->mr)
-                   && !cpu_physical_memory_is_dirty(
-                           section->mr->ram_addr
-                           + memory_region_section_addr(section, paddr))) {
+                   && !cpu_physical_memory_is_dirty(section->mr->ram_addr + xlat)) {
             te->addr_write = address | TLB_NOTDIRTY;
         } else {
             te->addr_write = address;
diff --git a/exec.c b/exec.c
index 82da067..e5ee8ff 100644
--- a/exec.c
+++ b/exec.c
@@ -182,7 +182,7 @@ static void phys_page_set(AddressSpaceDispatch *d,
     phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
 }
 
-MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
+static MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
 {
     PhysPageEntry lp = d->phys_map;
     PhysPageEntry *p;
@@ -198,6 +198,22 @@ MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
     return &phys_sections[lp.ptr];
 }
 
+MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
+                                             hwaddr *xlat, hwaddr *plen,
+                                             bool is_write)
+{
+    MemoryRegionSection *section;
+
+    section = phys_page_find(as->dispatch, addr >> TARGET_PAGE_BITS);
+    /* Compute offset within MemoryRegionSection */
+    addr -= section->offset_within_address_space;
+    *plen = MIN(section->size - addr, *plen);
+
+    /* Compute offset within MemoryRegion */
+    *xlat = addr + section->offset_within_region;
+    return section;
+}
+
 bool memory_region_is_unassigned(MemoryRegion *mr)
 {
     return mr != &io_mem_ram && mr != &io_mem_rom
@@ -616,11 +632,11 @@ static int cpu_physical_memory_set_dirty_tracking(int enable)
 }
 
 hwaddr memory_region_section_get_iotlb(CPUArchState *env,
-                                                   MemoryRegionSection *section,
-                                                   target_ulong vaddr,
-                                                   hwaddr paddr,
-                                                   int prot,
-                                                   target_ulong *address)
+                                       MemoryRegionSection *section,
+                                       target_ulong vaddr,
+                                       hwaddr paddr, hwaddr xlat,
+                                       int prot,
+                                       target_ulong *address)
 {
     hwaddr iotlb;
     CPUWatchpoint *wp;
@@ -628,7 +644,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
     if (memory_region_is_ram(section->mr)) {
         /* Normal RAM.  */
         iotlb = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
-            + memory_region_section_addr(section, paddr);
+            + xlat;
         if (!section->readonly) {
             iotlb |= phys_section_notdirty;
         } else {
@@ -636,7 +652,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
         }
     } else {
         iotlb = section - phys_sections;
-        iotlb += memory_region_section_addr(section, paddr);
+        iotlb += xlat;
     }
 
     /* Make accesses to pages with watchpoints go via the
@@ -1888,24 +1904,18 @@ static void invalidate_and_set_dirty(hwaddr addr,
 void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                       int len, bool is_write)
 {
-    AddressSpaceDispatch *d = as->dispatch;
-    int l;
+    hwaddr l;
     uint8_t *ptr;
     uint32_t val;
-    hwaddr page;
+    hwaddr addr1;
     MemoryRegionSection *section;
 
     while (len > 0) {
-        page = addr & TARGET_PAGE_MASK;
-        l = (page + TARGET_PAGE_SIZE) - addr;
-        if (l > len)
-            l = len;
-        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
+        l = len;
+        section = address_space_translate(as, addr, &addr1, &l, is_write);
 
         if (is_write) {
             if (!memory_region_is_ram(section->mr)) {
-                hwaddr addr1;
-                addr1 = memory_region_section_addr(section, addr);
                 /* XXX: could force cpu_single_env to NULL to avoid
                    potential bugs */
                 if (l >= 4 && ((addr1 & 3) == 0)) {
@@ -1925,9 +1935,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                     l = 1;
                 }
             } else if (!section->readonly) {
-                ram_addr_t addr1;
-                addr1 = memory_region_get_ram_addr(section->mr)
-                    + memory_region_section_addr(section, addr);
+                addr1 += memory_region_get_ram_addr(section->mr);
                 /* RAM case */
                 ptr = qemu_get_ram_ptr(addr1);
                 memcpy(ptr, buf, l);
@@ -1936,9 +1944,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
         } else {
             if (!(memory_region_is_ram(section->mr) ||
                   memory_region_is_romd(section->mr))) {
-                hwaddr addr1;
                 /* I/O case */
-                addr1 = memory_region_section_addr(section, addr);
                 if (l >= 4 && ((addr1 & 3) == 0)) {
                     /* 32 bit read access */
                     val = io_mem_read(section->mr, addr1, 4);
@@ -1957,9 +1963,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                 }
             } else {
                 /* RAM case */
-                ptr = qemu_get_ram_ptr(section->mr->ram_addr
-                                       + memory_region_section_addr(section,
-                                                                    addr));
+                ptr = qemu_get_ram_ptr(section->mr->ram_addr + addr1);
                 memcpy(buf, ptr, l);
             }
         }
@@ -1998,26 +2002,21 @@ void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
 void cpu_physical_memory_write_rom(hwaddr addr,
                                    const uint8_t *buf, int len)
 {
-    AddressSpaceDispatch *d = address_space_memory.dispatch;
-    int l;
+    hwaddr l;
     uint8_t *ptr;
-    hwaddr page;
+    hwaddr addr1;
     MemoryRegionSection *section;
 
     while (len > 0) {
-        page = addr & TARGET_PAGE_MASK;
-        l = (page + TARGET_PAGE_SIZE) - addr;
-        if (l > len)
-            l = len;
-        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
+        l = len;
+        section = address_space_translate(&address_space_memory,
+                                          addr, &addr1, &l, true);
 
         if (!(memory_region_is_ram(section->mr) ||
               memory_region_is_romd(section->mr))) {
             /* do nothing */
         } else {
-            unsigned long addr1;
-            addr1 = memory_region_get_ram_addr(section->mr)
-                + memory_region_section_addr(section, addr);
+            addr1 += memory_region_get_ram_addr(section->mr);
             /* ROM/RAM case */
             ptr = qemu_get_ram_ptr(addr1);
             memcpy(ptr, buf, l);
@@ -2077,18 +2076,12 @@ static void cpu_notify_map_clients(void)
 
 bool address_space_valid(AddressSpace *as, hwaddr addr, int len, bool is_write)
 {
-    AddressSpaceDispatch *d = as->dispatch;
     MemoryRegionSection *section;
-    int l;
-    hwaddr page;
+    hwaddr l, xlat;
 
     while (len > 0) {
-        page = addr & TARGET_PAGE_MASK;
-        l = (page + TARGET_PAGE_SIZE) - addr;
-        if (l > len) {
-            l = len;
-        }
-        section = phys_page_find(d, addr >> TARGET_PAGE_BITS);
+        l = len;
+        section = address_space_translate(as, addr, &xlat, &l, is_write);
         if (section->mr == &io_mem_unassigned ||
             (is_write && section->mr->readonly)) {
             return false;
@@ -2112,22 +2105,17 @@ void *address_space_map(AddressSpace *as,
                         hwaddr *plen,
                         bool is_write)
 {
-    AddressSpaceDispatch *d = as->dispatch;
     hwaddr len = *plen;
     hwaddr todo = 0;
-    int l;
-    hwaddr page;
+    hwaddr l, xlat;
     MemoryRegionSection *section;
     ram_addr_t raddr = RAM_ADDR_MAX;
     ram_addr_t rlen;
     void *ret;
 
     while (len > 0) {
-        page = addr & TARGET_PAGE_MASK;
-        l = (page + TARGET_PAGE_SIZE) - addr;
-        if (l > len)
-            l = len;
-        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
+        l = len;
+        section = address_space_translate(as, addr, &xlat, &l, is_write);
 
         if (!(memory_region_is_ram(section->mr) && !section->readonly)) {
             if (todo || bounce.buffer) {
@@ -2144,8 +2132,11 @@ void *address_space_map(AddressSpace *as,
             return bounce.buffer;
         }
         if (!todo) {
-            raddr = memory_region_get_ram_addr(section->mr)
-                + memory_region_section_addr(section, addr);
+            raddr = memory_region_get_ram_addr(section->mr) + xlat;
+        } else {
+            if (memory_region_get_ram_addr(section->mr) + xlat != raddr + todo) {
+                break;
+            }
         }
 
         len -= l;
@@ -2211,14 +2202,19 @@ static inline uint32_t ldl_phys_internal(hwaddr addr,
     uint8_t *ptr;
     uint32_t val;
     MemoryRegionSection *section;
+    hwaddr l = 4;
+    hwaddr addr1;
 
-    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
+    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
+                                      false);
+    if (l < 4) {
+        return unassigned_mem_read(NULL, addr, 4);
+    }
 
     if (!(memory_region_is_ram(section->mr) ||
           memory_region_is_romd(section->mr))) {
         /* I/O case */
-        addr = memory_region_section_addr(section, addr);
-        val = io_mem_read(section->mr, addr, 4);
+        val = io_mem_read(section->mr, addr1, 4);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap32(val);
@@ -2232,7 +2228,7 @@ static inline uint32_t ldl_phys_internal(hwaddr addr,
         /* RAM case */
         ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
                                 & TARGET_PAGE_MASK)
-                               + memory_region_section_addr(section, addr));
+                               + addr1);
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
             val = ldl_le_p(ptr);
@@ -2270,28 +2266,33 @@ static inline uint64_t ldq_phys_internal(hwaddr addr,
     uint8_t *ptr;
     uint64_t val;
     MemoryRegionSection *section;
+    hwaddr l = 8;
+    hwaddr addr1;
 
-    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
+    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
+                                      false);
+    if (l < 8) {
+        return unassigned_mem_read(NULL, addr, 8);
+    }
 
     if (!(memory_region_is_ram(section->mr) ||
           memory_region_is_romd(section->mr))) {
         /* I/O case */
-        addr = memory_region_section_addr(section, addr);
 
         /* XXX This is broken when device endian != cpu endian.
                Fix and add "endian" variable check */
 #ifdef TARGET_WORDS_BIGENDIAN
-        val = io_mem_read(section->mr, addr, 4) << 32;
-        val |= io_mem_read(section->mr, addr + 4, 4);
+        val = io_mem_read(section->mr, addr1, 4) << 32;
+        val |= io_mem_read(section->mr, addr1 + 4, 4);
 #else
-        val = io_mem_read(section->mr, addr, 4);
-        val |= io_mem_read(section->mr, addr + 4, 4) << 32;
+        val = io_mem_read(section->mr, addr1, 4);
+        val |= io_mem_read(section->mr, addr1 + 4, 4) << 32;
 #endif
     } else {
         /* RAM case */
         ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
                                 & TARGET_PAGE_MASK)
-                               + memory_region_section_addr(section, addr));
+                               + addr1);
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
             val = ldq_le_p(ptr);
@@ -2337,14 +2338,19 @@ static inline uint32_t lduw_phys_internal(hwaddr addr,
     uint8_t *ptr;
     uint64_t val;
     MemoryRegionSection *section;
+    hwaddr l = 2;
+    hwaddr addr1;
 
-    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
+    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
+                                      false);
+    if (l < 2) {
+        return unassigned_mem_read(NULL, addr, 2);
+    }
 
     if (!(memory_region_is_ram(section->mr) ||
           memory_region_is_romd(section->mr))) {
         /* I/O case */
-        addr = memory_region_section_addr(section, addr);
-        val = io_mem_read(section->mr, addr, 2);
+        val = io_mem_read(section->mr, addr1, 2);
 #if defined(TARGET_WORDS_BIGENDIAN)
         if (endian == DEVICE_LITTLE_ENDIAN) {
             val = bswap16(val);
@@ -2358,7 +2364,7 @@ static inline uint32_t lduw_phys_internal(hwaddr addr,
         /* RAM case */
         ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
                                 & TARGET_PAGE_MASK)
-                               + memory_region_section_addr(section, addr));
+                               + addr1);
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
             val = lduw_le_p(ptr);
@@ -2396,19 +2402,23 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val)
 {
     uint8_t *ptr;
     MemoryRegionSection *section;
+    hwaddr l = 4;
+    hwaddr addr1;
 
-    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
+    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
+                                      true);
+    if (l < 4) {
+        unassigned_mem_write(NULL, addr, val, 4);
+        return;
+    }
 
     if (!memory_region_is_ram(section->mr) || section->readonly) {
-        addr = memory_region_section_addr(section, addr);
         if (memory_region_is_ram(section->mr)) {
             section = &phys_sections[phys_section_rom];
         }
-        io_mem_write(section->mr, addr, val, 4);
+        io_mem_write(section->mr, addr1, val, 4);
     } else {
-        unsigned long addr1 = (memory_region_get_ram_addr(section->mr)
-                               & TARGET_PAGE_MASK)
-            + memory_region_section_addr(section, addr);
+        addr1 += memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK;
         ptr = qemu_get_ram_ptr(addr1);
         stl_p(ptr, val);
 
@@ -2430,11 +2440,17 @@ static inline void stl_phys_internal(hwaddr addr, uint32_t val,
 {
     uint8_t *ptr;
     MemoryRegionSection *section;
+    hwaddr l = 4;
+    hwaddr addr1;
 
-    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
+    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
+                                      true);
+    if (l < 4) {
+        unassigned_mem_write(NULL, addr, val, 4);
+        return;
+    }
 
     if (!memory_region_is_ram(section->mr) || section->readonly) {
-        addr = memory_region_section_addr(section, addr);
         if (memory_region_is_ram(section->mr)) {
             section = &phys_sections[phys_section_rom];
         }
@@ -2447,12 +2463,10 @@ static inline void stl_phys_internal(hwaddr addr, uint32_t val,
             val = bswap32(val);
         }
 #endif
-        io_mem_write(section->mr, addr, val, 4);
+        io_mem_write(section->mr, addr1, val, 4);
     } else {
-        unsigned long addr1;
-        addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
-            + memory_region_section_addr(section, addr);
         /* RAM case */
+        addr1 += memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK;
         ptr = qemu_get_ram_ptr(addr1);
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
@@ -2497,11 +2511,17 @@ static inline void stw_phys_internal(hwaddr addr, uint32_t val,
 {
     uint8_t *ptr;
     MemoryRegionSection *section;
+    hwaddr l = 2;
+    hwaddr addr1;
 
-    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
+    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
+                                      true);
+    if (l < 2) {
+        unassigned_mem_write(NULL, addr, val, 2);
+        return;
+    }
 
     if (!memory_region_is_ram(section->mr) || section->readonly) {
-        addr = memory_region_section_addr(section, addr);
         if (memory_region_is_ram(section->mr)) {
             section = &phys_sections[phys_section_rom];
         }
@@ -2514,12 +2534,10 @@ static inline void stw_phys_internal(hwaddr addr, uint32_t val,
             val = bswap16(val);
         }
 #endif
-        io_mem_write(section->mr, addr, val, 2);
+        io_mem_write(section->mr, addr1, val, 2);
     } else {
-        unsigned long addr1;
-        addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
-            + memory_region_section_addr(section, addr);
         /* RAM case */
+        addr1 += memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK;
         ptr = qemu_get_ram_ptr(addr1);
         switch (endian) {
         case DEVICE_LITTLE_ENDIAN:
@@ -2622,9 +2640,10 @@ bool virtio_is_big_endian(void)
 bool cpu_physical_memory_is_io(hwaddr phys_addr)
 {
     MemoryRegionSection *section;
+    hwaddr l = 1;
 
-    section = phys_page_find(address_space_memory.dispatch,
-                             phys_addr >> TARGET_PAGE_BITS);
+    section = address_space_translate(&address_space_memory,
+                                      phys_addr, &phys_addr, &l, false);
 
     return !(memory_region_is_ram(section->mr) ||
              memory_region_is_romd(section->mr));
diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h
index 733c885..e821660 100644
--- a/include/exec/cputlb.h
+++ b/include/exec/cputlb.h
@@ -26,8 +26,6 @@ void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
                              target_ulong vaddr);
 void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start,
                            uintptr_t length);
-MemoryRegionSection *phys_page_find(struct AddressSpaceDispatch *d,
-                                    hwaddr index);
 void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length);
 void tlb_set_dirty(CPUArchState *env, target_ulong vaddr);
 extern int tlb_flush_count;
@@ -35,11 +33,11 @@ extern int tlb_flush_count;
 /* exec.c */
 void tb_flush_jmp_cache(CPUArchState *env, target_ulong addr);
 hwaddr memory_region_section_get_iotlb(CPUArchState *env,
-                                                   MemoryRegionSection *section,
-                                                   target_ulong vaddr,
-                                                   hwaddr paddr,
-                                                   int prot,
-                                                   target_ulong *address);
+                                       MemoryRegionSection *section,
+                                       target_ulong vaddr,
+                                       hwaddr paddr, hwaddr xlat,
+                                       int prot,
+                                       target_ulong *address);
 bool memory_region_is_unassigned(MemoryRegion *mr);
 
 #endif
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 2e5fd11..809a958 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -743,23 +743,6 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
                                        hwaddr addr, uint64_t size);
 
 /**
- * memory_region_section_addr: get offset within MemoryRegionSection
- *
- * Returns offset within MemoryRegionSection
- *
- * @section: the memory region section being queried
- * @addr: address in address space
- */
-static inline hwaddr
-memory_region_section_addr(MemoryRegionSection *section,
-                           hwaddr addr)
-{
-    addr -= section->offset_within_address_space;
-    addr += section->offset_within_region;
-    return addr;
-}
-
-/**
  * address_space_sync_dirty_bitmap: synchronize the dirty log for all memory
  *
  * Synchronizes the dirty page log for an entire address space.
@@ -860,6 +843,20 @@ void address_space_write(AddressSpace *as, hwaddr addr,
  */
 void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
 
+/* address_space_translate: translate an address range into an address space
+ * into a MemoryRegionSection and an address range into that section
+ *
+ * @as: #AddressSpace to be accessed
+ * @addr: address within that address space
+ * @xlat: pointer to address within the returned memory region section's
+ * #MemoryRegion.
+ * @len: pointer to length
+ * @is_write: indicates the transfer direction
+ */
+MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
+                                             hwaddr *xlat, hwaddr *len,
+                                             bool is_write);
+
 /* address_space_valid: check for validity of an address space range
  *
  * Check whether memory is assigned to the given address space range.
diff --git a/translate-all.c b/translate-all.c
index 0d84b0d..7a7d537 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1355,15 +1355,15 @@ void tb_invalidate_phys_addr(hwaddr addr)
 {
     ram_addr_t ram_addr;
     MemoryRegionSection *section;
+    hwaddr l = 1;
 
-    section = phys_page_find(address_space_memory.dispatch,
-                             addr >> TARGET_PAGE_BITS);
+    section = address_space_translate(&address_space_memory, addr, &addr, &l, false);
     if (!(memory_region_is_ram(section->mr)
           || memory_region_is_romd(section->mr))) {
         return;
     }
     ram_addr = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
-        + memory_region_section_addr(section, addr);
+        + addr;
     tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
 }
 #endif /* TARGET_HAS_ICE && !defined(CONFIG_USER_ONLY) */
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 18/30] memory: add return value to address_space_rw/read/write
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (16 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 17/30] memory: add address_space_translate Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 18:18   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 19/30] memory: Introduce address_space_lookup_region Paolo Bonzini
                   ` (12 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c                | 23 ++++++++++-------------
 include/exec/memory.h | 12 +++++++++---
 2 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/exec.c b/exec.c
index e5ee8ff..4cc5ecb 100644
--- a/exec.c
+++ b/exec.c
@@ -1901,7 +1901,7 @@ static void invalidate_and_set_dirty(hwaddr addr,
     xen_modified_memory(addr, length);
 }
 
-void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
+bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                       int len, bool is_write)
 {
     hwaddr l;
@@ -1909,10 +1909,12 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
     uint32_t val;
     hwaddr addr1;
     MemoryRegionSection *section;
+    bool error = false;
 
     while (len > 0) {
         l = len;
         section = address_space_translate(as, addr, &addr1, &l, is_write);
+        error |= (section == &phys_sections[phys_section_unassigned]);
 
         if (is_write) {
             if (!memory_region_is_ram(section->mr)) {
@@ -1971,31 +1973,26 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
         buf += l;
         addr += l;
     }
+
+    return error;
 }
 
-void address_space_write(AddressSpace *as, hwaddr addr,
+bool address_space_write(AddressSpace *as, hwaddr addr,
                          const uint8_t *buf, int len)
 {
-    address_space_rw(as, addr, (uint8_t *)buf, len, true);
+    return address_space_rw(as, addr, (uint8_t *)buf, len, true);
 }
 
-/**
- * address_space_read: read from an address space.
- *
- * @as: #AddressSpace to be accessed
- * @addr: address within that address space
- * @buf: buffer with the data transferred
- */
-void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len)
+bool address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len)
 {
-    address_space_rw(as, addr, buf, len, false);
+    return address_space_rw(as, addr, buf, len, false);
 }
 
 
 void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
                             int len, int is_write)
 {
-    return address_space_rw(&address_space_memory, addr, buf, len, is_write);
+    address_space_rw(&address_space_memory, addr, buf, len, is_write);
 }
 
 /* used for ROM loading : can write in RAM and ROM */
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 809a958..94709d1 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -816,32 +816,38 @@ 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.
+ *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
  * @buf: buffer with the data transferred
  * @is_write: indicates the transfer direction
  */
-void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
+bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
                       int len, bool is_write);
 
 /**
  * address_space_write: write to address space.
  *
+ * Return true if the operation hit any unassigned memory.
+ *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
  * @buf: buffer with the data transferred
  */
-void address_space_write(AddressSpace *as, hwaddr addr,
+bool address_space_write(AddressSpace *as, hwaddr addr,
                          const uint8_t *buf, int len);
 
 /**
  * address_space_read: read from an address space.
  *
+ * Return true if the operation hit any unassigned memory.
+ *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
  * @buf: buffer with the data transferred
  */
-void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
+bool address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
 
 /* address_space_translate: translate an address range into an address space
  * into a MemoryRegionSection and an address range into that section
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 19/30] memory: Introduce address_space_lookup_region
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (17 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 18/30] memory: add return value to address_space_rw/read/write Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 18:19   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 20/30] memory: iommu support Paolo Bonzini
                   ` (11 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, Jan Kiszka, David Gibson

From: Jan Kiszka <jan.kiszka@siemens.com>

This introduces a wrapper for phys_page_find (before we complicate
address_space_translate with IOMMU translation).  This function will
also encapsulate locking and reference counting when we introduce
BQL-free dispatching.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/exec.c b/exec.c
index 4cc5ecb..a29dec5 100644
--- a/exec.c
+++ b/exec.c
@@ -198,13 +198,19 @@ static MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index
     return &phys_sections[lp.ptr];
 }
 
+static MemoryRegionSection *address_space_lookup_region(AddressSpace *as,
+                                                        hwaddr addr)
+{
+    return phys_page_find(as->dispatch, addr >> TARGET_PAGE_BITS);
+}
+
 MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
                                              hwaddr *xlat, hwaddr *plen,
                                              bool is_write)
 {
     MemoryRegionSection *section;
 
-    section = phys_page_find(as->dispatch, addr >> TARGET_PAGE_BITS);
+    section = address_space_lookup_region(as, addr);
     /* Compute offset within MemoryRegionSection */
     addr -= section->offset_within_address_space;
     *plen = MIN(section->size - addr, *plen);
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 20/30] memory: iommu support
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (18 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 19/30] memory: Introduce address_space_lookup_region Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 18:24   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 21/30] memory: Add iommu map/unmap notifiers Paolo Bonzini
                   ` (10 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, Avi Kivity, David Gibson

From: Avi Kivity <avi.kivity@gmail.com>

Add a new memory region type that translates addresses it is given,
then forwards them to a target address space.  This is similar to
an alias, except that the mapping is more flexible than a linear
translation and trucation, and also less efficient since the
translation happens at runtime.

The implementation uses an AddressSpace mapping the target region to
avoid hierarchical dispatch all the way to the resolved region; only
iommu regions are looked up dynamically.

Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
[Modified to put translation in address_space_translate - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c                | 35 ++++++++++++++++++++++-----
 include/exec/memory.h | 66 +++++++++++++++++++++++++++++++++++++++++++++++----
 memory.c              | 21 ++++++++++++++++
 3 files changed, 112 insertions(+), 10 deletions(-)

diff --git a/exec.c b/exec.c
index a29dec5..b7266c8 100644
--- a/exec.c
+++ b/exec.c
@@ -208,15 +208,38 @@ MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
                                              hwaddr *xlat, hwaddr *plen,
                                              bool is_write)
 {
+    IOMMUTLBEntry iotlb;
     MemoryRegionSection *section;
+    hwaddr len = *plen;
 
-    section = address_space_lookup_region(as, addr);
-    /* Compute offset within MemoryRegionSection */
-    addr -= section->offset_within_address_space;
-    *plen = MIN(section->size - addr, *plen);
+    for (;;) {
+        section = address_space_lookup_region(as, addr);
+
+        /* Compute offset within MemoryRegionSection */
+        addr -= section->offset_within_address_space;
+        len = MIN(section->size - addr, len);
+
+        /* Compute offset within MemoryRegion */
+        addr += section->offset_within_region;
+
+        if (!section->mr->iommu_ops) {
+            break;
+        }
+
+        iotlb = section->mr->iommu_ops->translate(section->mr, addr);
+        addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
+                | (addr & iotlb.addr_mask));
+        len = MIN(len, (addr | iotlb.addr_mask) - addr + 1);
+        if (!(iotlb.perm & (1 << is_write))) {
+            section = &phys_sections[phys_section_unassigned];
+            break;
+        }
+
+        as = section->mr->iommu_target_as;
+    }
 
-    /* Compute offset within MemoryRegion */
-    *xlat = addr + section->offset_within_region;
+    *plen = len;
+    *xlat = addr;
     return section;
 }
 
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 94709d1..e5cad03 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -115,12 +115,36 @@ struct MemoryRegionOps {
     const MemoryRegionMmio old_mmio;
 };
 
+typedef struct IOMMUTLBEntry IOMMUTLBEntry;
+typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;
+
+/* See address_space_translate: bit 0 is read, bit 1 is write.  */
+typedef enum {
+    IOMMU_NONE = 0,
+    IOMMU_RO   = 1,
+    IOMMU_WO   = 2,
+    IOMMU_RW   = 3,
+} IOMMUAccessFlags;
+
+struct IOMMUTLBEntry {
+    hwaddr           iova;
+    hwaddr           translated_addr;
+    hwaddr           addr_mask;  /* 0xfff = 4k translation */
+    IOMMUAccessFlags perm;
+};
+
+struct MemoryRegionIOMMUOps {
+    /* Returns a TLB entry that contains a given address. */
+    IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr);
+};
+
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
 typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
 
 struct MemoryRegion {
     /* All fields are private - violators will be prosecuted */
     const MemoryRegionOps *ops;
+    const MemoryRegionIOMMUOps *iommu_ops;
     void *opaque;
     MemoryRegion *parent;
     Int128 size;
@@ -147,6 +171,7 @@ struct MemoryRegion {
     uint8_t dirty_log_mask;
     unsigned ioeventfd_nb;
     MemoryRegionIoeventfd *ioeventfds;
+    struct AddressSpace *iommu_target_as;
 };
 
 struct MemoryRegionPortio {
@@ -332,6 +357,25 @@ void memory_region_init_rom_device(MemoryRegion *mr,
 void memory_region_init_reservation(MemoryRegion *mr,
                                     const char *name,
                                     uint64_t size);
+
+/**
+ * memory_region_init_iommu: Initialize a memory region that translates addresses
+ *
+ * An IOMMU region translates addresses and forwards accesses to a target memory region.
+ *
+ * @mr: the #MemoryRegion to be initialized
+ * @ops: a function that translates addresses into the @target region
+ * @target_as: the #AddressSpace that will be used to satisfy accesses to translated
+ *          addresses
+ * @name: used for debugging; not visible to the user or ABI
+ * @size: size of the region.
+ */
+void memory_region_init_iommu(MemoryRegion *mr,
+                              MemoryRegionIOMMUOps *ops,
+                              AddressSpace *target_as,
+                              const char *name,
+                              uint64_t size);
+
 /**
  * memory_region_destroy: Destroy a memory region and reclaim all resources.
  *
@@ -371,6 +415,15 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
 }
 
 /**
+ * memory_region_is_iommu: check whether a memory region is an iommu
+ *
+ * Returns %true is a memory region is an iommu.
+ *
+ * @mr: the memory region being queried
+ */
+bool memory_region_is_iommu(MemoryRegion *mr);
+
+/**
  * memory_region_name: get a memory region's name
  *
  * Returns the string that was used to initialize the memory region.
@@ -816,7 +869,8 @@ 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.
+ * Return true if the operation hit any unassigned memory or encountered an
+ * IOMMU fault.
  *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
@@ -829,7 +883,8 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
 /**
  * address_space_write: write to address space.
  *
- * Return true if the operation hit any unassigned memory.
+ * Return true if the operation hit any unassigned memory or encountered an
+ * IOMMU fault.
  *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
@@ -841,7 +896,8 @@ bool address_space_write(AddressSpace *as, hwaddr addr,
 /**
  * address_space_read: read from an address space.
  *
- * Return true if the operation hit any unassigned memory.
+ * Return true if the operation hit any unassigned memory or encountered an
+ * IOMMU fault.
  *
  * @as: #AddressSpace to be accessed
  * @addr: address within that address space
@@ -865,7 +921,9 @@ MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
 
 /* address_space_valid: check for validity of an address space range
  *
- * Check whether memory is assigned to the given address space range.
+ * Check whether memory is assigned to the given address space range, and
+ * access is permitted by any IOMMU regions that are active for the address
+ * space.
  *
  * For now, addr and len should be aligned to a page size.  This limitation
  * will be lifted in the future.
diff --git a/memory.c b/memory.c
index 99f046d..b25d21d 100644
--- a/memory.c
+++ b/memory.c
@@ -787,6 +787,7 @@ void memory_region_init(MemoryRegion *mr,
                         uint64_t size)
 {
     mr->ops = NULL;
+    mr->iommu_ops = NULL;
     mr->parent = NULL;
     mr->size = int128_make64(size);
     if (size == UINT64_MAX) {
@@ -977,6 +978,21 @@ void memory_region_init_rom_device(MemoryRegion *mr,
     mr->ram_addr = qemu_ram_alloc(size, mr);
 }
 
+void memory_region_init_iommu(MemoryRegion *mr,
+                              MemoryRegionIOMMUOps *ops,
+                              AddressSpace *target_as,
+                              const char *name,
+                              uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->ops = NULL;
+    mr->iommu_ops = ops,
+    mr->opaque = mr;
+    mr->terminates = true;  /* then re-forwards */
+    mr->destructor = memory_region_destructor_none;
+    mr->iommu_target_as = target_as;
+}
+
 static uint64_t invalid_read(void *opaque, hwaddr addr,
                              unsigned size)
 {
@@ -1051,6 +1067,11 @@ bool memory_region_is_rom(MemoryRegion *mr)
     return mr->ram && mr->readonly;
 }
 
+bool memory_region_is_iommu(MemoryRegion *mr)
+{
+    return mr->iommu_ops;
+}
+
 void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 {
     uint8_t mask = 1 << client;
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 21/30] memory: Add iommu map/unmap notifiers
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (19 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 20/30] memory: iommu support Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 18:27   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 22/30] vfio: abort if an emulated iommu is used Paolo Bonzini
                   ` (9 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

From: David Gibson <david@gibson.dropbear.id.au>

This patch adds a NotifierList to MemoryRegions which represent IOMMUs
allowing other parts of the code to register interest in mappings or
unmappings from the IOMMU.  All IOMMU implementations will need to call
memory_region_notify_iommu() to inform those waiting on the notifier list,
whenever an IOMMU mapping is made or removed.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 include/exec/memory.h |  7 +++++++
 memory.c              | 18 ++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/include/exec/memory.h b/include/exec/memory.h
index e5cad03..05b9bb2 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -25,6 +25,7 @@
 #include "exec/iorange.h"
 #include "exec/ioport.h"
 #include "qemu/int128.h"
+#include "qemu/notify.h"
 
 #define MAX_PHYS_ADDR_SPACE_BITS 62
 #define MAX_PHYS_ADDR            (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
@@ -172,6 +173,7 @@ struct MemoryRegion {
     unsigned ioeventfd_nb;
     MemoryRegionIoeventfd *ioeventfds;
     struct AddressSpace *iommu_target_as;
+    NotifierList iommu_notify;
 };
 
 struct MemoryRegionPortio {
@@ -423,6 +425,11 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
  */
 bool memory_region_is_iommu(MemoryRegion *mr);
 
+void memory_region_notify_iommu(MemoryRegion *mr,
+                                IOMMUTLBEntry entry);
+void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n);
+void memory_region_unregister_iommu_notifier(Notifier *n);
+
 /**
  * memory_region_name: get a memory region's name
  *
diff --git a/memory.c b/memory.c
index b25d21d..e3970bf 100644
--- a/memory.c
+++ b/memory.c
@@ -991,6 +991,7 @@ void memory_region_init_iommu(MemoryRegion *mr,
     mr->terminates = true;  /* then re-forwards */
     mr->destructor = memory_region_destructor_none;
     mr->iommu_target_as = target_as;
+    notifier_list_init(&mr->iommu_notify);
 }
 
 static uint64_t invalid_read(void *opaque, hwaddr addr,
@@ -1072,6 +1073,23 @@ bool memory_region_is_iommu(MemoryRegion *mr)
     return mr->iommu_ops;
 }
 
+void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n)
+{
+    notifier_list_add(&mr->iommu_notify, n);
+}
+
+void memory_region_unregister_iommu_notifier(Notifier *n)
+{
+    notifier_remove(n);
+}
+
+void memory_region_notify_iommu(MemoryRegion *mr,
+                                IOMMUTLBEntry entry)
+{
+    assert(memory_region_is_iommu(mr));
+    notifier_list_notify(&mr->iommu_notify, &entry);
+}
+
 void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 {
     uint8_t mask = 1 << client;
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 22/30] vfio: abort if an emulated iommu is used
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (20 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 21/30] memory: Add iommu map/unmap notifiers Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 23/30] spapr: convert TCE API to use an opaque type Paolo Bonzini
                   ` (8 subsequent siblings)
  30 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, Avi Kivity, David Gibson

From: Avi Kivity <avi.kivity@gmail.com>

vfio doesn't support guest iommus yet, indicate it to the user
by gently depositing a core on their disk.

Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/misc/vfio.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 693a9ff..178dd11 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -1939,6 +1939,8 @@ static void vfio_listener_region_add(MemoryListener *listener,
     void *vaddr;
     int ret;
 
+    assert(!memory_region_is_iommu(section->mr));
+
     if (vfio_listener_skipped_section(section)) {
         DPRINTF("SKIPPING region_add %"HWADDR_PRIx" - %"PRIx64"\n",
                 section->offset_within_address_space,
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 23/30] spapr: convert TCE API to use an opaque type
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (21 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 22/30] vfio: abort if an emulated iommu is used Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 24/30] spapr: make IOMMU translation go through IOMMUTLBEntry Paolo Bonzini
                   ` (7 subsequent siblings)
  30 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

The TCE table is currently returned as a DMAContext, and non-type-safe
APIs are called later passing back the DMAContext.  Since we want to move
away from DMAContext, use an opaque type instead, and add an accessor
to retrieve the DMAContext from it.

Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ppc/spapr_iommu.c        | 54 ++++++++++++++++++---------------------------
 hw/ppc/spapr_pci.c          |  8 +++----
 hw/ppc/spapr_vio.c          | 13 ++++++-----
 include/hw/pci-host/spapr.h |  2 +-
 include/hw/ppc/spapr.h      | 12 +++++-----
 include/hw/ppc/spapr_vio.h  |  1 +
 6 files changed, 42 insertions(+), 48 deletions(-)

diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index e1fe941..7a507e0 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -36,8 +36,6 @@ enum sPAPRTCEAccess {
     SPAPR_TCE_RW = 3,
 };
 
-typedef struct sPAPRTCETable sPAPRTCETable;
-
 struct sPAPRTCETable {
     DMAContext dma;
     uint32_t liobn;
@@ -122,7 +120,7 @@ static int spapr_tce_translate(DMAContext *dma,
     return 0;
 }
 
-DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size)
+sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size)
 {
     sPAPRTCETable *tcet;
 
@@ -155,43 +153,40 @@ DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size)
     }
 
 #ifdef DEBUG_TCE
-    fprintf(stderr, "spapr_iommu: New TCE table, liobn=0x%x, context @ %p, "
-            "table @ %p, fd=%d\n", liobn, &tcet->dma, tcet->table, tcet->fd);
+    fprintf(stderr, "spapr_iommu: New TCE table @ %p, liobn=0x%x, "
+            "table @ %p, fd=%d\n", tcet, liobn, tcet->table, tcet->fd);
 #endif
 
     QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
 
-    return &tcet->dma;
+    return tcet;
 }
 
-void spapr_tce_free(DMAContext *dma)
+void spapr_tce_free(sPAPRTCETable *tcet)
 {
+    QLIST_REMOVE(tcet, list);
 
-    if (dma) {
-        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-
-        QLIST_REMOVE(tcet, list);
-
-        if (!kvm_enabled() ||
-            (kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
-                                     tcet->window_size) != 0)) {
-            g_free(tcet->table);
-        }
-
-        g_free(tcet);
+    if (!kvm_enabled() ||
+        (kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
+                                 tcet->window_size) != 0)) {
+        g_free(tcet->table);
     }
+
+    g_free(tcet);
 }
 
-void spapr_tce_set_bypass(DMAContext *dma, bool bypass)
+DMAContext *spapr_tce_get_dma(sPAPRTCETable *tcet)
 {
-    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+    return &tcet->dma;
+}
 
+void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass)
+{
     tcet->bypass = bypass;
 }
 
-void spapr_tce_reset(DMAContext *dma)
+void spapr_tce_reset(sPAPRTCETable *tcet)
 {
-    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
     size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
         * sizeof(sPAPRTCE);
 
@@ -277,17 +272,12 @@ int spapr_dma_dt(void *fdt, int node_off, const char *propname,
 }
 
 int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
-                      DMAContext *iommu)
+                      sPAPRTCETable *tcet)
 {
-    if (!iommu) {
+    if (!tcet) {
         return 0;
     }
 
-    if (iommu->translate == spapr_tce_translate) {
-        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, iommu);
-        return spapr_dma_dt(fdt, node_off, propname,
-                tcet->liobn, 0, tcet->window_size);
-    }
-
-    return -1;
+    return spapr_dma_dt(fdt, node_off, propname,
+                        tcet->liobn, 0, tcet->window_size);
 }
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 62ff323..eb64a8f 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -511,7 +511,7 @@ static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque,
 {
     sPAPRPHBState *phb = opaque;
 
-    return phb->dma;
+    return spapr_tce_get_dma(phb->tcet);
 }
 
 static int spapr_phb_init(SysBusDevice *s)
@@ -646,8 +646,8 @@ static int spapr_phb_init(SysBusDevice *s)
 
     sphb->dma_window_start = 0;
     sphb->dma_window_size = 0x40000000;
-    sphb->dma = spapr_tce_new_dma_context(sphb->dma_liobn, sphb->dma_window_size);
-    if (!sphb->dma) {
+    sphb->tcet = spapr_tce_new_table(sphb->dma_liobn, sphb->dma_window_size);
+    if (!sphb->tcet) {
         fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
         return -1;
     }
@@ -676,7 +676,7 @@ static void spapr_phb_reset(DeviceState *qdev)
     sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
 
     /* Reset the IOMMU state */
-    spapr_tce_reset(sphb->dma);
+    spapr_tce_reset(sphb->tcet);
 }
 
 static Property spapr_phb_properties[] = {
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 1405c32..a06ac94 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -145,7 +145,7 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
         }
     }
 
-    ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma);
+    ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->tcet);
     if (ret < 0) {
         return ret;
     }
@@ -319,8 +319,8 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
 
 static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
 {
-    if (dev->dma) {
-        spapr_tce_reset(dev->dma);
+    if (dev->tcet) {
+        spapr_tce_reset(dev->tcet);
     }
     free_crq(dev);
 }
@@ -345,12 +345,12 @@ static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
         return;
     }
 
-    if (!dev->dma) {
+    if (!dev->tcet) {
         rtas_st(rets, 0, -3);
         return;
     }
 
-    spapr_tce_set_bypass(dev->dma, !!enable);
+    spapr_tce_set_bypass(dev->tcet, !!enable);
 
     rtas_st(rets, 0, 0);
 }
@@ -457,7 +457,8 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
 
     if (pc->rtce_window_size) {
         uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
-        dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
+        dev->tcet = spapr_tce_new_table(liobn, pc->rtce_window_size);
+        dev->dma = spapr_tce_get_dma(dev->tcet);
     }
 
     return pc->init(dev);
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index b21080c..653dd40 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -49,7 +49,7 @@ typedef struct sPAPRPHBState {
     uint32_t dma_liobn;
     uint64_t dma_window_start;
     uint64_t dma_window_size;
-    DMAContext *dma;
+    sPAPRTCETable *tcet;
 
     struct {
         uint32_t irq;
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 864bee9..e8d617b 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -342,17 +342,19 @@ typedef struct sPAPRTCE {
 
 #define RTAS_ERROR_LOG_MAX      2048
 
+typedef struct sPAPRTCETable sPAPRTCETable;
 
 void spapr_iommu_init(void);
 void spapr_events_init(sPAPREnvironment *spapr);
 void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
-DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size);
-void spapr_tce_free(DMAContext *dma);
-void spapr_tce_reset(DMAContext *dma);
-void spapr_tce_set_bypass(DMAContext *dma, bool bypass);
+sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size);
+DMAContext *spapr_tce_get_dma(sPAPRTCETable *tcet);
+void spapr_tce_free(sPAPRTCETable *tcet);
+void spapr_tce_reset(sPAPRTCETable *tcet);
+void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass);
 int spapr_dma_dt(void *fdt, int node_off, const char *propname,
                  uint32_t liobn, uint64_t window, uint32_t size);
 int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
-                      DMAContext *dma);
+                      sPAPRTCETable *tcet);
 
 #endif /* !defined (__HW_SPAPR_H__) */
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
index f98ec0a..56f2821 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -63,6 +63,7 @@ struct VIOsPAPRDevice {
     uint32_t irq;
     target_ulong signal_state;
     VIOsPAPR_CRQ crq;
+    sPAPRTCETable *tcet;
     DMAContext *dma;
 };
 
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 24/30] spapr: make IOMMU translation go through IOMMUTLBEntry
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (22 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 23/30] spapr: convert TCE API to use an opaque type Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 25/30] spapr: use memory core for iommu support Paolo Bonzini
                   ` (6 subsequent siblings)
  30 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

The next step is to introduce the translation code that will be used for
IOMMU MemoryRegions, but still do the actual translation in a DMAContext.

Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ppc/spapr_iommu.c | 59 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 34 insertions(+), 25 deletions(-)

diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 7a507e0..f6d74fe 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -68,15 +68,8 @@ static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
     return NULL;
 }
 
-static int spapr_tce_translate(DMAContext *dma,
-                               dma_addr_t addr,
-                               hwaddr *paddr,
-                               hwaddr *len,
-                               DMADirection dir)
+static IOMMUTLBEntry spapr_tce_translate_iommu(sPAPRTCETable *tcet, hwaddr addr)
 {
-    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-    enum sPAPRTCEAccess access = (dir == DMA_DIRECTION_FROM_DEVICE)
-        ? SPAPR_TCE_WO : SPAPR_TCE_RO;
     uint64_t tce;
 
 #ifdef DEBUG_TCE
@@ -85,9 +78,12 @@ static int spapr_tce_translate(DMAContext *dma,
 #endif
 
     if (tcet->bypass) {
-        *paddr = addr;
-        *len = (hwaddr)-1;
-        return 0;
+        return (IOMMUTLBEntry) {
+            .iova = 0,
+            .translated_addr = 0,
+            .addr_mask = ~(hwaddr)0,
+            .perm = IOMMU_RW,
+        };
     }
 
     /* Check if we are in bound */
@@ -95,28 +91,41 @@ static int spapr_tce_translate(DMAContext *dma,
 #ifdef DEBUG_TCE
         fprintf(stderr, "spapr_tce_translate out of bounds\n");
 #endif
-        return -EFAULT;
+        return (IOMMUTLBEntry) { .perm = IOMMU_NONE };
     }
 
     tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT].tce;
 
-    /* Check TCE */
-    if (!(tce & access)) {
-        return -EPERM;
-    }
+#ifdef DEBUG_TCE
+    fprintf(stderr, " ->  *paddr=0x%llx, *len=0x%llx\n",
+            (tce & ~SPAPR_TCE_PAGE_MASK), SPAPR_TCE_PAGE_MASK + 1);
+#endif
 
-    /* How much til end of page ? */
-    *len = ((~addr) & SPAPR_TCE_PAGE_MASK) + 1;
+    return (IOMMUTLBEntry) {
+        .iova = addr & ~SPAPR_TCE_PAGE_MASK,
+        .translated_addr = tce & ~SPAPR_TCE_PAGE_MASK,
+        .addr_mask = SPAPR_TCE_PAGE_MASK,
+        .perm = tce,
+    };
+}
 
-    /* Translate */
-    *paddr = (tce & ~SPAPR_TCE_PAGE_MASK) |
-        (addr & SPAPR_TCE_PAGE_MASK);
+static int spapr_tce_translate(DMAContext *dma,
+                               dma_addr_t addr,
+                               hwaddr *paddr,
+                               hwaddr *len,
+                               DMADirection dir)
+ {
+    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+    bool is_write = (dir == DMA_DIRECTION_FROM_DEVICE);
+    IOMMUTLBEntry entry = spapr_tce_translate_iommu(tcet, addr);
 
-#ifdef DEBUG_TCE
-    fprintf(stderr, " ->  *paddr=0x" TARGET_FMT_plx ", *len=0x"
-            TARGET_FMT_plx "\n", *paddr, *len);
-#endif
+    if (!(entry.perm & (1 << is_write))) {
+        return -EPERM;
+    }
 
+    /* Translate */
+    *paddr = entry.translated_addr | (addr & entry.addr_mask);
+    *len = (addr | entry.addr_mask) - addr + 1;
     return 0;
 }
 
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 25/30] spapr: use memory core for iommu support
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (23 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 24/30] spapr: make IOMMU translation go through IOMMUTLBEntry Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 26/30] dma: eliminate old-style IOMMU support Paolo Bonzini
                   ` (5 subsequent siblings)
  30 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

Now we can stop using a "translating" DMAContext, but we do not yet modify
the sPAPRTCETable users to get an AddressSpace; they keep using the table
via a DMAContext.

Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ppc/spapr_iommu.c   | 49 +++++++++++++++++++++++++++----------------------
 include/hw/ppc/spapr.h |  1 +
 2 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index f6d74fe..f7b1b18 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -37,12 +37,16 @@ enum sPAPRTCEAccess {
 };
 
 struct sPAPRTCETable {
+    /* temporary until everyone has its own AddressSpace */
     DMAContext dma;
+    AddressSpace as;
+
     uint32_t liobn;
     uint32_t window_size;
     sPAPRTCE *table;
     bool bypass;
     int fd;
+    MemoryRegion iommu;
     QLIST_ENTRY(sPAPRTCETable) list;
 };
 
@@ -68,8 +72,9 @@ static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
     return NULL;
 }
 
-static IOMMUTLBEntry spapr_tce_translate_iommu(sPAPRTCETable *tcet, hwaddr addr)
+static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr)
 {
+    sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
     uint64_t tce;
 
 #ifdef DEBUG_TCE
@@ -109,25 +114,9 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(sPAPRTCETable *tcet, hwaddr addr)
     };
 }
 
-static int spapr_tce_translate(DMAContext *dma,
-                               dma_addr_t addr,
-                               hwaddr *paddr,
-                               hwaddr *len,
-                               DMADirection dir)
- {
-    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-    bool is_write = (dir == DMA_DIRECTION_FROM_DEVICE);
-    IOMMUTLBEntry entry = spapr_tce_translate_iommu(tcet, addr);
-
-    if (!(entry.perm & (1 << is_write))) {
-        return -EPERM;
-    }
-
-    /* Translate */
-    *paddr = entry.translated_addr | (addr & entry.addr_mask);
-    *len = (addr | entry.addr_mask) - addr + 1;
-    return 0;
-}
+static MemoryRegionIOMMUOps spapr_iommu_ops = {
+    .translate = spapr_tce_translate_iommu,
+};
 
 sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size)
 {
@@ -144,8 +133,6 @@ sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size)
     }
 
     tcet = g_malloc0(sizeof(*tcet));
-    dma_context_init(&tcet->dma, &address_space_memory, spapr_tce_translate, NULL, NULL);
-
     tcet->liobn = liobn;
     tcet->window_size = window_size;
 
@@ -166,6 +153,12 @@ sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size)
             "table @ %p, fd=%d\n", tcet, liobn, tcet->table, tcet->fd);
 #endif
 
+    memory_region_init_iommu(&tcet->iommu, &spapr_iommu_ops,
+                             &address_space_memory,
+                             "iommu-spapr", INT64_MAX);
+    address_space_init(&tcet->as, &tcet->iommu);
+    dma_context_init(&tcet->dma, &tcet->as, NULL, NULL, NULL);
+
     QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
 
     return tcet;
@@ -189,6 +182,11 @@ DMAContext *spapr_tce_get_dma(sPAPRTCETable *tcet)
     return &tcet->dma;
 }
 
+MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)
+{
+    return &tcet->iommu;
+}
+
 void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass)
 {
     tcet->bypass = bypass;
@@ -207,6 +205,7 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
                                 target_ulong tce)
 {
     sPAPRTCE *tcep;
+    IOMMUTLBEntry entry;
 
     if (ioba >= tcet->window_size) {
         hcall_dprintf("spapr_vio_put_tce on out-of-bounds IOBA 0x"
@@ -217,6 +216,12 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
     tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT);
     tcep->tce = tce;
 
+    entry.iova = ioba & ~SPAPR_TCE_PAGE_MASK;
+    entry.translated_addr = tce & ~SPAPR_TCE_PAGE_MASK;
+    entry.addr_mask = SPAPR_TCE_PAGE_MASK;
+    entry.perm = tce;
+    memory_region_notify_iommu(&tcet->iommu, entry);
+
     return H_SUCCESS;
 }
 
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index e8d617b..142abb7 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -349,6 +349,7 @@ void spapr_events_init(sPAPREnvironment *spapr);
 void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
 sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size);
 DMAContext *spapr_tce_get_dma(sPAPRTCETable *tcet);
+MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
 void spapr_tce_free(sPAPRTCETable *tcet);
 void spapr_tce_reset(sPAPRTCETable *tcet);
 void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass);
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 26/30] dma: eliminate old-style IOMMU support
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (24 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 25/30] spapr: use memory core for iommu support Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 18:31   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 27/30] pci: use memory core for iommu support Paolo Bonzini
                   ` (4 subsequent siblings)
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

The translate function in the DMAContext is now always NULL.
Remove every reference to it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 dma-helpers.c        | 178 +++------------------------------------------------
 exec.c               |   3 +-
 hw/pci/pci.c         |   3 +-
 hw/ppc/spapr_iommu.c |   2 +-
 include/sysemu/dma.h |  79 ++++-------------------
 5 files changed, 26 insertions(+), 239 deletions(-)

diff --git a/dma-helpers.c b/dma-helpers.c
index 2962b69..c53705a 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -14,32 +14,26 @@
 
 /* #define DEBUG_IOMMU */
 
-static void do_dma_memory_set(AddressSpace *as,
-                              dma_addr_t addr, uint8_t c, dma_addr_t len)
+int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len)
 {
+    AddressSpace *as = dma->as;
+
+    dma_barrier(dma, DMA_DIRECTION_FROM_DEVICE);
+
 #define FILLBUF_SIZE 512
     uint8_t fillbuf[FILLBUF_SIZE];
     int l;
+    bool error = false;
 
     memset(fillbuf, c, FILLBUF_SIZE);
     while (len > 0) {
         l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
-        address_space_rw(as, addr, fillbuf, l, true);
+        error |= address_space_rw(as, addr, fillbuf, l, true);
         len -= l;
         addr += l;
     }
-}
 
-int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len)
-{
-    dma_barrier(dma, DMA_DIRECTION_FROM_DEVICE);
-
-    if (dma_has_iommu(dma)) {
-        return iommu_dma_memory_set(dma, addr, c, len);
-    }
-    do_dma_memory_set(dma->as, addr, c, len);
-
-    return 0;
+    return error;
 }
 
 void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, DMAContext *dma)
@@ -278,162 +272,10 @@ void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
     bdrv_acct_start(bs, cookie, sg->size, type);
 }
 
-bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len,
-                            DMADirection dir)
+void dma_context_init(DMAContext *dma, AddressSpace *as)
 {
-    hwaddr paddr, plen;
-
 #ifdef DEBUG_IOMMU
-    fprintf(stderr, "dma_memory_check context=%p addr=0x" DMA_ADDR_FMT
-            " len=0x" DMA_ADDR_FMT " dir=%d\n", dma, addr, len, dir);
-#endif
-
-    while (len) {
-        if (dma->translate(dma, addr, &paddr, &plen, dir) != 0) {
-            return false;
-        }
-
-        /* The translation might be valid for larger regions. */
-        if (plen > len) {
-            plen = len;
-        }
-
-        if (!address_space_valid(dma->as, paddr, len,
-                                 dir == DMA_DIRECTION_FROM_DEVICE)) {
-            return false;
-        }
-
-        len -= plen;
-        addr += plen;
-    }
-
-    return true;
-}
-
-int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr,
-                        void *buf, dma_addr_t len, DMADirection dir)
-{
-    hwaddr paddr, plen;
-    int err;
-
-#ifdef DEBUG_IOMMU
-    fprintf(stderr, "dma_memory_rw context=%p addr=0x" DMA_ADDR_FMT " len=0x"
-            DMA_ADDR_FMT " dir=%d\n", dma, addr, len, dir);
-#endif
-
-    while (len) {
-        err = dma->translate(dma, addr, &paddr, &plen, dir);
-        if (err) {
-	    /*
-             * In case of failure on reads from the guest, we clean the
-             * destination buffer so that a device that doesn't test
-             * for errors will not expose qemu internal memory.
-	     */
-	    memset(buf, 0, len);
-            return -1;
-        }
-
-        /* The translation might be valid for larger regions. */
-        if (plen > len) {
-            plen = len;
-        }
-
-        address_space_rw(dma->as, paddr, buf, plen, dir == DMA_DIRECTION_FROM_DEVICE);
-
-        len -= plen;
-        addr += plen;
-        buf += plen;
-    }
-
-    return 0;
-}
-
-int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c,
-                         dma_addr_t len)
-{
-    hwaddr paddr, plen;
-    int err;
-
-#ifdef DEBUG_IOMMU
-    fprintf(stderr, "dma_memory_set context=%p addr=0x" DMA_ADDR_FMT
-            " len=0x" DMA_ADDR_FMT "\n", dma, addr, len);
-#endif
-
-    while (len) {
-        err = dma->translate(dma, addr, &paddr, &plen,
-                             DMA_DIRECTION_FROM_DEVICE);
-        if (err) {
-            return err;
-        }
-
-        /* The translation might be valid for larger regions. */
-        if (plen > len) {
-            plen = len;
-        }
-
-        do_dma_memory_set(dma->as, paddr, c, plen);
-
-        len -= plen;
-        addr += plen;
-    }
-
-    return 0;
-}
-
-void dma_context_init(DMAContext *dma, AddressSpace *as, DMATranslateFunc translate,
-                      DMAMapFunc map, DMAUnmapFunc unmap)
-{
-#ifdef DEBUG_IOMMU
-    fprintf(stderr, "dma_context_init(%p, %p, %p, %p)\n",
-            dma, translate, map, unmap);
+    fprintf(stderr, "dma_context_init(%p -> %p)\n", dma, as);
 #endif
     dma->as = as;
-    dma->translate = translate;
-    dma->map = map;
-    dma->unmap = unmap;
-}
-
-void *iommu_dma_memory_map(DMAContext *dma, dma_addr_t addr, dma_addr_t *len,
-                           DMADirection dir)
-{
-    int err;
-    hwaddr paddr, plen;
-    void *buf;
-
-    if (dma->map) {
-        return dma->map(dma, addr, len, dir);
-    }
-
-    plen = *len;
-    err = dma->translate(dma, addr, &paddr, &plen, dir);
-    if (err) {
-        return NULL;
-    }
-
-    /*
-     * If this is true, the virtual region is contiguous,
-     * but the translated physical region isn't. We just
-     * clamp *len, much like address_space_map() does.
-     */
-    if (plen < *len) {
-        *len = plen;
-    }
-
-    buf = address_space_map(dma->as, paddr, &plen, dir == DMA_DIRECTION_FROM_DEVICE);
-    *len = plen;
-
-    return buf;
-}
-
-void iommu_dma_memory_unmap(DMAContext *dma, void *buffer, dma_addr_t len,
-                            DMADirection dir, dma_addr_t access_len)
-{
-    if (dma->unmap) {
-        dma->unmap(dma, buffer, len, dir, access_len);
-        return;
-    }
-
-    address_space_unmap(dma->as, buffer, len, dir == DMA_DIRECTION_FROM_DEVICE,
-                        access_len);
-
 }
diff --git a/exec.c b/exec.c
index b7266c8..4c43fdd 100644
--- a/exec.c
+++ b/exec.c
@@ -1859,8 +1859,7 @@ static void memory_map_init(void)
     memory_listener_register(&io_memory_listener, &address_space_io);
     memory_listener_register(&tcg_memory_listener, &address_space_memory);
 
-    dma_context_init(&dma_context_memory, &address_space_memory,
-                     NULL, NULL, NULL);
+    dma_context_init(&dma_context_memory, &address_space_memory);
 }
 
 MemoryRegion *get_system_memory(void)
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index bb3879b..c9d585c 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -814,8 +814,9 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
         memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
         address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
         pci_dev->dma = g_new(DMAContext, 1);
-        dma_context_init(pci_dev->dma, &pci_dev->bus_master_as, NULL, NULL, NULL);
+        dma_context_init(pci_dev->dma, &pci_dev->bus_master_as);
     }
+
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
     pci_dev->irq_state = 0;
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index f7b1b18..8971d72 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -157,7 +157,7 @@ sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size)
                              &address_space_memory,
                              "iommu-spapr", INT64_MAX);
     address_space_init(&tcet->as, &tcet->iommu);
-    dma_context_init(&tcet->dma, &tcet->as, NULL, NULL, NULL);
+    dma_context_init(&tcet->dma, &tcet->as);
 
     QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
 
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
index 2e239dc..3ed621b 100644
--- a/include/sysemu/dma.h
+++ b/include/sysemu/dma.h
@@ -46,26 +46,8 @@ typedef uint64_t dma_addr_t;
 #define DMA_ADDR_BITS 64
 #define DMA_ADDR_FMT "%" PRIx64
 
-typedef int DMATranslateFunc(DMAContext *dma,
-                             dma_addr_t addr,
-                             hwaddr *paddr,
-                             hwaddr *len,
-                             DMADirection dir);
-typedef void* DMAMapFunc(DMAContext *dma,
-                         dma_addr_t addr,
-                         dma_addr_t *len,
-                         DMADirection dir);
-typedef void DMAUnmapFunc(DMAContext *dma,
-                          void *buffer,
-                          dma_addr_t len,
-                          DMADirection dir,
-                          dma_addr_t access_len);
-
 struct DMAContext {
     AddressSpace *as;
-    DMATranslateFunc *translate;
-    DMAMapFunc *map;
-    DMAUnmapFunc *unmap;
 };
 
 /* A global DMA context corresponding to the address_space_memory
@@ -98,41 +80,22 @@ static inline void dma_barrier(DMAContext *dma, DMADirection dir)
     }
 }
 
-static inline bool dma_has_iommu(DMAContext *dma)
-{
-    return dma && dma->translate;
-}
-
 /* Checks that the given range of addresses is valid for DMA.  This is
  * useful for certain cases, but usually you should just use
  * dma_memory_{read,write}() and check for errors */
-bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len,
-                            DMADirection dir);
 static inline bool dma_memory_valid(DMAContext *dma,
                                     dma_addr_t addr, dma_addr_t len,
                                     DMADirection dir)
 {
-    if (!dma_has_iommu(dma)) {
-        return address_space_valid(dma->as, addr, len,
-                                   dir == DMA_DIRECTION_FROM_DEVICE);
-    } else {
-        return iommu_dma_memory_valid(dma, addr, len, dir);
-    }
+    return address_space_valid(dma->as, addr, len,
+                               dir == DMA_DIRECTION_FROM_DEVICE);
 }
 
-int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr,
-                        void *buf, dma_addr_t len, DMADirection dir);
 static inline int dma_memory_rw_relaxed(DMAContext *dma, dma_addr_t addr,
                                         void *buf, dma_addr_t len,
                                         DMADirection dir)
 {
-    if (!dma_has_iommu(dma)) {
-        /* Fast-path for no IOMMU */
-        address_space_rw(dma->as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
-        return 0;
-    } else {
-        return iommu_dma_memory_rw(dma, addr, buf, len, dir);
-    }
+    return address_space_rw(dma->as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
 }
 
 static inline int dma_memory_read_relaxed(DMAContext *dma, dma_addr_t addr,
@@ -170,43 +133,26 @@ static inline int dma_memory_write(DMAContext *dma, dma_addr_t addr,
                          DMA_DIRECTION_FROM_DEVICE);
 }
 
-int iommu_dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c,
-			 dma_addr_t len);
-
 int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len);
 
-void *iommu_dma_memory_map(DMAContext *dma,
-                           dma_addr_t addr, dma_addr_t *len,
-                           DMADirection dir);
 static inline void *dma_memory_map(DMAContext *dma,
                                    dma_addr_t addr, dma_addr_t *len,
                                    DMADirection dir)
 {
-    if (!dma_has_iommu(dma)) {
-        hwaddr xlen = *len;
-        void *p;
-
-        p = address_space_map(dma->as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE);
-        *len = xlen;
-        return p;
-    } else {
-        return iommu_dma_memory_map(dma, addr, len, dir);
-    }
+    hwaddr xlen = *len;
+    void *p;
+
+    p = address_space_map(dma->as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE);
+    *len = xlen;
+    return p;
 }
 
-void iommu_dma_memory_unmap(DMAContext *dma,
-                            void *buffer, dma_addr_t len,
-                            DMADirection dir, dma_addr_t access_len);
 static inline void dma_memory_unmap(DMAContext *dma,
                                     void *buffer, dma_addr_t len,
                                     DMADirection dir, dma_addr_t access_len)
 {
-    if (!dma_has_iommu(dma)) {
-        address_space_unmap(dma->as, buffer, (hwaddr)len,
-                            dir == DMA_DIRECTION_FROM_DEVICE, access_len);
-    } else {
-        iommu_dma_memory_unmap(dma, buffer, len, dir, access_len);
-    }
+    address_space_unmap(dma->as, buffer, (hwaddr)len,
+                        dir == DMA_DIRECTION_FROM_DEVICE, access_len);
 }
 
 #define DEFINE_LDST_DMA(_lname, _sname, _bits, _end) \
@@ -247,8 +193,7 @@ DEFINE_LDST_DMA(q, q, 64, be);
 
 #undef DEFINE_LDST_DMA
 
-void dma_context_init(DMAContext *dma, AddressSpace *as, DMATranslateFunc translate,
-                      DMAMapFunc map, DMAUnmapFunc unmap);
+void dma_context_init(DMAContext *dma, AddressSpace *as);
 
 struct ScatterGatherEntry {
     dma_addr_t base;
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 27/30] pci: use memory core for iommu support
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (25 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 26/30] dma: eliminate old-style IOMMU support Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 18:36   ` Peter Maydell
  2013-05-23 21:22   ` Michael S. Tsirkin
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 28/30] spapr_vio: take care of creating our own AddressSpace/DMAContext Paolo Bonzini
                   ` (3 subsequent siblings)
  30 siblings, 2 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, jan.kiszka, Michael S. Tsirkin, Avi Kivity, David Gibson

From: Avi Kivity <avi.kivity@gmail.com>

Use the new iommu support in the memory core for iommu support.  The only
user, spapr, is also converted, but it still provides a DMAContext
interface until the non-PCI bits switch to AddressSpace.

Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
[ Do not calls memory_region_del_subregion() on the device's
  bus_master_enable_region, it is an alias; return an AddressSpace
  from the IOMMU hook and remove the destructor hook. - David Gibson ]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/pci/pci.c                | 46 ++++++++++++++++++++++-----------------------
 hw/ppc/spapr_pci.c          |  9 +++++----
 include/hw/pci-host/spapr.h |  1 +
 include/hw/pci/pci.h        |  4 ++--
 include/hw/pci/pci_bus.h    |  4 ++--
 5 files changed, 33 insertions(+), 31 deletions(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index c9d585c..9e6bd77 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -279,6 +279,12 @@ int pci_find_domain(const PCIBus *bus)
     return -1;
 }
 
+static AddressSpace *pci_default_address_space(PCIBus *bus, void *opaque, int devfn)
+{
+    /* FIXME: inherit memory region from bus creator */
+    return &address_space_memory;
+}
+
 static void pci_bus_init(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
@@ -289,6 +295,7 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent,
     bus->devfn_min = devfn_min;
     bus->address_space_mem = address_space_mem;
     bus->address_space_io = address_space_io;
+    pci_setup_iommu(bus, pci_default_address_space, NULL);
 
     /* host bridge */
     QLIST_INIT(&bus->child);
@@ -786,6 +793,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
     PCIConfigReadFunc *config_read = pc->config_read;
     PCIConfigWriteFunc *config_write = pc->config_write;
+    AddressSpace *dma_as;
 
     if (devfn < 0) {
         for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);
@@ -801,21 +809,15 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                      PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name);
         return NULL;
     }
+
     pci_dev->bus = bus;
-    if (bus->dma_context_fn) {
-        pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, devfn);
-    } else {
-        /* FIXME: Make dma_context_fn use MemoryRegions instead, so this path is
-         * taken unconditionally */
-        /* FIXME: inherit memory region from bus creator */
-        memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master",
-                                 get_system_memory(), 0,
-                                 memory_region_size(get_system_memory()));
-        memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
-        address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
-        pci_dev->dma = g_new(DMAContext, 1);
-        dma_context_init(pci_dev->dma, &pci_dev->bus_master_as);
-    }
+    dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
+    memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master",
+                             dma_as->root, 0, memory_region_size(dma_as->root));
+    memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
+    address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
+    pci_dev->dma = g_new(DMAContext, 1);
+    dma_context_init(pci_dev->dma, &pci_dev->bus_master_as);
 
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
@@ -870,12 +872,10 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
     pci_dev->bus->devices[pci_dev->devfn] = NULL;
     pci_config_free(pci_dev);
 
-    if (!pci_dev->bus->dma_context_fn) {
-        address_space_destroy(&pci_dev->bus_master_as);
-        memory_region_destroy(&pci_dev->bus_master_enable_region);
-        g_free(pci_dev->dma);
-        pci_dev->dma = NULL;
-    }
+    address_space_destroy(&pci_dev->bus_master_as);
+    memory_region_destroy(&pci_dev->bus_master_enable_region);
+    g_free(pci_dev->dma);
+    pci_dev->dma = NULL;
 }
 
 static void pci_unregister_io_regions(PCIDevice *pci_dev)
@@ -2232,10 +2232,10 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
     k->props = pci_props;
 }
 
-void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque)
+void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
 {
-    bus->dma_context_fn = fn;
-    bus->dma_context_opaque = opaque;
+    bus->iommu_fn = fn;
+    bus->iommu_opaque = opaque;
 }
 
 static const TypeInfo pci_device_type_info = {
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index eb64a8f..762db62 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -506,12 +506,11 @@ static const MemoryRegionOps spapr_msi_ops = {
 /*
  * PHB PCI device
  */
-static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque,
-                                            int devfn)
+static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
 {
     sPAPRPHBState *phb = opaque;
 
-    return spapr_tce_get_dma(phb->tcet);
+    return &phb->iommu_as;
 }
 
 static int spapr_phb_init(SysBusDevice *s)
@@ -651,7 +650,9 @@ static int spapr_phb_init(SysBusDevice *s)
         fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
         return -1;
     }
-    pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb);
+    address_space_init(&sphb->iommu_as, spapr_tce_get_iommu(sphb->tcet),
+                       sphb->dtbusname);
+    pci_setup_iommu(bus, spapr_pci_dma_iommu, sphb);
 
     QLIST_INSERT_HEAD(&spapr->phbs, sphb, list);
 
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 653dd40..1e23dbf 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -50,6 +50,7 @@ typedef struct sPAPRPHBState {
     uint64_t dma_window_start;
     uint64_t dma_window_size;
     sPAPRTCETable *tcet;
+    AddressSpace iommu_as;
 
     struct {
         uint32_t irq;
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 8d075ab..3a85bce 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -401,9 +401,9 @@ int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
 
 void pci_device_deassert_intx(PCIDevice *dev);
 
-typedef DMAContext *(*PCIDMAContextFunc)(PCIBus *, void *, int);
+typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int);
 
-void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque);
+void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque);
 
 static inline void
 pci_set_byte(uint8_t *config, uint8_t val)
diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h
index 6ee443c..66762f6 100644
--- a/include/hw/pci/pci_bus.h
+++ b/include/hw/pci/pci_bus.h
@@ -10,8 +10,8 @@
 
 struct PCIBus {
     BusState qbus;
-    PCIDMAContextFunc dma_context_fn;
-    void *dma_context_opaque;
+    PCIIOMMUFunc iommu_fn;
+    void *iommu_opaque;
     uint8_t devfn_min;
     pci_set_irq_fn set_irq;
     pci_map_irq_fn map_irq;
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 28/30] spapr_vio: take care of creating our own AddressSpace/DMAContext
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (26 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 27/30] pci: use memory core for iommu support Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 29/30] dma: eliminate DMAContext Paolo Bonzini
                   ` (2 subsequent siblings)
  30 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

Fetch the root region from the sPAPRTCETable, and use it to build
an AddressSpace and DMAContext.

Now, everywhere we have a DMAContext we also have access to the
corresponding AddressSpace (either because we create it just before
the DMAContext, or because dma_context_memory's AddressSpace is
trivially address_space_memory).

Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ppc/spapr_iommu.c       | 11 -----------
 hw/ppc/spapr_vio.c         |  3 ++-
 include/hw/ppc/spapr.h     |  1 -
 include/hw/ppc/spapr_vio.h | 21 +++++++++++----------
 4 files changed, 13 insertions(+), 23 deletions(-)

diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 8971d72..1d11e28 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -37,10 +37,6 @@ enum sPAPRTCEAccess {
 };
 
 struct sPAPRTCETable {
-    /* temporary until everyone has its own AddressSpace */
-    DMAContext dma;
-    AddressSpace as;
-
     uint32_t liobn;
     uint32_t window_size;
     sPAPRTCE *table;
@@ -156,8 +152,6 @@ sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size)
     memory_region_init_iommu(&tcet->iommu, &spapr_iommu_ops,
                              &address_space_memory,
                              "iommu-spapr", INT64_MAX);
-    address_space_init(&tcet->as, &tcet->iommu);
-    dma_context_init(&tcet->dma, &tcet->as);
 
     QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
 
@@ -177,11 +171,6 @@ void spapr_tce_free(sPAPRTCETable *tcet)
     g_free(tcet);
 }
 
-DMAContext *spapr_tce_get_dma(sPAPRTCETable *tcet)
-{
-    return &tcet->dma;
-}
-
 MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)
 {
     return &tcet->iommu;
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index a06ac94..8d77a36 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -458,7 +458,8 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
     if (pc->rtce_window_size) {
         uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
         dev->tcet = spapr_tce_new_table(liobn, pc->rtce_window_size);
-        dev->dma = spapr_tce_get_dma(dev->tcet);
+        address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet));
+        dma_context_init(&dev->dma, &dev->as);
     }
 
     return pc->init(dev);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 142abb7..a83720e 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -348,7 +348,6 @@ void spapr_iommu_init(void);
 void spapr_events_init(sPAPREnvironment *spapr);
 void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
 sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size);
-DMAContext *spapr_tce_get_dma(sPAPRTCETable *tcet);
 MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
 void spapr_tce_free(sPAPRTCETable *tcet);
 void spapr_tce_reset(sPAPRTCETable *tcet);
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
index 56f2821..2de58f1 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -63,8 +63,9 @@ struct VIOsPAPRDevice {
     uint32_t irq;
     target_ulong signal_state;
     VIOsPAPR_CRQ crq;
+    AddressSpace as;
+    DMAContext dma;
     sPAPRTCETable *tcet;
-    DMAContext *dma;
 };
 
 #define DEFINE_SPAPR_PROPERTIES(type, field)           \
@@ -92,35 +93,35 @@ static inline qemu_irq spapr_vio_qirq(VIOsPAPRDevice *dev)
 static inline bool spapr_vio_dma_valid(VIOsPAPRDevice *dev, uint64_t taddr,
                                        uint32_t size, DMADirection dir)
 {
-    return dma_memory_valid(dev->dma, taddr, size, dir);
+    return dma_memory_valid(&dev->dma, taddr, size, dir);
 }
 
 static inline int spapr_vio_dma_read(VIOsPAPRDevice *dev, uint64_t taddr,
                                      void *buf, uint32_t size)
 {
-    return (dma_memory_read(dev->dma, taddr, buf, size) != 0) ?
+    return (dma_memory_read(&dev->dma, taddr, buf, size) != 0) ?
         H_DEST_PARM : H_SUCCESS;
 }
 
 static inline int spapr_vio_dma_write(VIOsPAPRDevice *dev, uint64_t taddr,
                                       const void *buf, uint32_t size)
 {
-    return (dma_memory_write(dev->dma, taddr, buf, size) != 0) ?
+    return (dma_memory_write(&dev->dma, taddr, buf, size) != 0) ?
         H_DEST_PARM : H_SUCCESS;
 }
 
 static inline int spapr_vio_dma_set(VIOsPAPRDevice *dev, uint64_t taddr,
                                     uint8_t c, uint32_t size)
 {
-    return (dma_memory_set(dev->dma, taddr, c, size) != 0) ?
+    return (dma_memory_set(&dev->dma, taddr, c, size) != 0) ?
         H_DEST_PARM : H_SUCCESS;
 }
 
-#define vio_stb(_dev, _addr, _val) (stb_dma((_dev)->dma, (_addr), (_val)))
-#define vio_sth(_dev, _addr, _val) (stw_be_dma((_dev)->dma, (_addr), (_val)))
-#define vio_stl(_dev, _addr, _val) (stl_be_dma((_dev)->dma, (_addr), (_val)))
-#define vio_stq(_dev, _addr, _val) (stq_be_dma((_dev)->dma, (_addr), (_val)))
-#define vio_ldq(_dev, _addr) (ldq_be_dma((_dev)->dma, (_addr)))
+#define vio_stb(_dev, _addr, _val) (stb_dma(&(_dev)->dma, (_addr), (_val)))
+#define vio_sth(_dev, _addr, _val) (stw_be_dma(&(_dev)->dma, (_addr), (_val)))
+#define vio_stl(_dev, _addr, _val) (stl_be_dma(&(_dev)->dma, (_addr), (_val)))
+#define vio_stq(_dev, _addr, _val) (stq_be_dma(&(_dev)->dma, (_addr), (_val)))
+#define vio_ldq(_dev, _addr) (ldq_be_dma(&(_dev)->dma, (_addr)))
 
 int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
 
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 29/30] dma: eliminate DMAContext
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (27 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 28/30] spapr_vio: take care of creating our own AddressSpace/DMAContext Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 18:40   ` Peter Maydell
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 30/30] memory: give name to every AddressSpace Paolo Bonzini
  2013-05-22  2:30 ` [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Alexey Kardashevskiy
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, jan.kiszka, David Gibson

The DMAContext is a simple pointer to an AddressSpace that is now always
already available.  Make everyone hold the address space directly,
and clean up the DMA API to use the AddressSpace directly.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 dma-helpers.c              | 24 +++++----------
 exec.c                     |  3 --
 hw/dma/pl330.c             |  8 ++---
 hw/ide/ahci.c              | 18 +++++------
 hw/ide/ahci.h              |  4 +--
 hw/ide/ich.c               |  2 +-
 hw/ide/macio.c             |  4 +--
 hw/pci/pci.c               |  4 ---
 hw/ppc/spapr_vio.c         |  1 -
 hw/scsi/megasas.c          |  4 +--
 hw/scsi/virtio-scsi.c      |  2 +-
 hw/scsi/vmw_pvscsi.c       |  2 +-
 hw/sd/sdhci.c              | 22 +++++++-------
 hw/usb/hcd-ehci-pci.c      |  4 +--
 hw/usb/hcd-ehci-sysbus.c   |  2 +-
 hw/usb/hcd-ehci.c          | 12 ++++----
 hw/usb/hcd-ehci.h          |  2 +-
 hw/usb/hcd-ohci.c          | 30 +++++++++----------
 hw/usb/libhw.c             |  4 +--
 include/hw/pci/pci.h       | 17 +++++------
 include/hw/ppc/spapr_vio.h | 19 ++++++------
 include/sysemu/dma.h       | 75 ++++++++++++++++++++--------------------------
 22 files changed, 116 insertions(+), 147 deletions(-)

diff --git a/dma-helpers.c b/dma-helpers.c
index c53705a..5afba47 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -14,11 +14,9 @@
 
 /* #define DEBUG_IOMMU */
 
-int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len)
+int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len)
 {
-    AddressSpace *as = dma->as;
-
-    dma_barrier(dma, DMA_DIRECTION_FROM_DEVICE);
+    dma_barrier(as, DMA_DIRECTION_FROM_DEVICE);
 
 #define FILLBUF_SIZE 512
     uint8_t fillbuf[FILLBUF_SIZE];
@@ -36,13 +34,13 @@ int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len)
     return error;
 }
 
-void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, DMAContext *dma)
+void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, AddressSpace *as)
 {
     qsg->sg = g_malloc(alloc_hint * sizeof(ScatterGatherEntry));
     qsg->nsg = 0;
     qsg->nalloc = alloc_hint;
     qsg->size = 0;
-    qsg->dma = dma;
+    qsg->as = as;
 }
 
 void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len)
@@ -102,7 +100,7 @@ static void dma_bdrv_unmap(DMAAIOCB *dbs)
     int i;
 
     for (i = 0; i < dbs->iov.niov; ++i) {
-        dma_memory_unmap(dbs->sg->dma, dbs->iov.iov[i].iov_base,
+        dma_memory_unmap(dbs->sg->as, dbs->iov.iov[i].iov_base,
                          dbs->iov.iov[i].iov_len, dbs->dir,
                          dbs->iov.iov[i].iov_len);
     }
@@ -150,7 +148,7 @@ static void dma_bdrv_cb(void *opaque, int ret)
     while (dbs->sg_cur_index < dbs->sg->nsg) {
         cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte;
         cur_len = dbs->sg->sg[dbs->sg_cur_index].len - dbs->sg_cur_byte;
-        mem = dma_memory_map(dbs->sg->dma, cur_addr, &cur_len, dbs->dir);
+        mem = dma_memory_map(dbs->sg->as, cur_addr, &cur_len, dbs->dir);
         if (!mem)
             break;
         qemu_iovec_add(&dbs->iov, mem, cur_len);
@@ -247,7 +245,7 @@ static uint64_t dma_buf_rw(uint8_t *ptr, int32_t len, QEMUSGList *sg,
     while (len > 0) {
         ScatterGatherEntry entry = sg->sg[sg_cur_index++];
         int32_t xfer = MIN(len, entry.len);
-        dma_memory_rw(sg->dma, entry.base, ptr, xfer, dir);
+        dma_memory_rw(sg->as, entry.base, ptr, xfer, dir);
         ptr += xfer;
         len -= xfer;
         resid -= xfer;
@@ -271,11 +269,3 @@ void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
 {
     bdrv_acct_start(bs, cookie, sg->size, type);
 }
-
-void dma_context_init(DMAContext *dma, AddressSpace *as)
-{
-#ifdef DEBUG_IOMMU
-    fprintf(stderr, "dma_context_init(%p -> %p)\n", dma, as);
-#endif
-    dma->as = as;
-}
diff --git a/exec.c b/exec.c
index 4c43fdd..f508a59 100644
--- a/exec.c
+++ b/exec.c
@@ -64,7 +64,6 @@ static MemoryRegion *system_io;
 
 AddressSpace address_space_io;
 AddressSpace address_space_memory;
-DMAContext dma_context_memory;
 
 MemoryRegion io_mem_ram, io_mem_rom, io_mem_unassigned, io_mem_notdirty;
 static MemoryRegion io_mem_subpage_ram;
@@ -1858,8 +1857,6 @@ static void memory_map_init(void)
     memory_listener_register(&core_memory_listener, &address_space_memory);
     memory_listener_register(&io_memory_listener, &address_space_io);
     memory_listener_register(&tcg_memory_listener, &address_space_memory);
-
-    dma_context_init(&dma_context_memory, &address_space_memory);
 }
 
 MemoryRegion *get_system_memory(void)
diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c
index 60f5299..044c087 100644
--- a/hw/dma/pl330.c
+++ b/hw/dma/pl330.c
@@ -1074,7 +1074,7 @@ static inline const PL330InsnDesc *pl330_fetch_insn(PL330Chan *ch)
     uint8_t opcode;
     int i;
 
-    dma_memory_read(&dma_context_memory, ch->pc, &opcode, 1);
+    dma_memory_read(&address_space_memory, ch->pc, &opcode, 1);
     for (i = 0; insn_desc[i].size; i++) {
         if ((opcode & insn_desc[i].opmask) == insn_desc[i].opcode) {
             return &insn_desc[i];
@@ -1088,7 +1088,7 @@ static inline void pl330_exec_insn(PL330Chan *ch, const PL330InsnDesc *insn)
     uint8_t buf[PL330_INSN_MAXSIZE];
 
     assert(insn->size <= PL330_INSN_MAXSIZE);
-    dma_memory_read(&dma_context_memory, ch->pc, buf, insn->size);
+    dma_memory_read(&address_space_memory, ch->pc, buf, insn->size);
     insn->exec(ch, buf[0], &buf[1], insn->size - 1);
 }
 
@@ -1153,7 +1153,7 @@ static int pl330_exec_cycle(PL330Chan *channel)
     if (q != NULL && q->len <= pl330_fifo_num_free(&s->fifo)) {
         int len = q->len - (q->addr & (q->len - 1));
 
-        dma_memory_read(&dma_context_memory, q->addr, buf, len);
+        dma_memory_read(&address_space_memory, q->addr, buf, len);
         if (PL330_ERR_DEBUG > 1) {
             DB_PRINT("PL330 read from memory @%08x (size = %08x):\n",
                       q->addr, len);
@@ -1185,7 +1185,7 @@ static int pl330_exec_cycle(PL330Chan *channel)
             fifo_res = pl330_fifo_get(&s->fifo, buf, len, q->tag);
         }
         if (fifo_res == PL330_FIFO_OK || q->z) {
-            dma_memory_write(&dma_context_memory, q->addr, buf, len);
+            dma_memory_write(&address_space_memory, q->addr, buf, len);
             if (PL330_ERR_DEBUG > 1) {
                 DB_PRINT("PL330 read from memory @%08x (size = %08x):\n",
                          q->addr, len);
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index eab6096..1adfa0b 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -597,7 +597,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis)
     if (!cmd_fis) {
         /* map cmd_fis */
         uint64_t tbl_addr = le64_to_cpu(ad->cur_cmd->tbl_addr);
-        cmd_fis = dma_memory_map(ad->hba->dma, tbl_addr, &cmd_len,
+        cmd_fis = dma_memory_map(ad->hba->as, tbl_addr, &cmd_len,
                                  DMA_DIRECTION_TO_DEVICE);
         cmd_mapped = 1;
     }
@@ -630,7 +630,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis)
     ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS);
 
     if (cmd_mapped) {
-        dma_memory_unmap(ad->hba->dma, cmd_fis, cmd_len,
+        dma_memory_unmap(ad->hba->as, cmd_fis, cmd_len,
                          DMA_DIRECTION_TO_DEVICE, cmd_len);
     }
 }
@@ -657,7 +657,7 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
     }
 
     /* map PRDT */
-    if (!(prdt = dma_memory_map(ad->hba->dma, prdt_addr, &prdt_len,
+    if (!(prdt = dma_memory_map(ad->hba->as, prdt_addr, &prdt_len,
                                 DMA_DIRECTION_TO_DEVICE))){
         DPRINTF(ad->port_no, "map failed\n");
         return -1;
@@ -691,7 +691,7 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
             goto out;
         }
 
-        qemu_sglist_init(sglist, (sglist_alloc_hint - off_idx), ad->hba->dma);
+        qemu_sglist_init(sglist, (sglist_alloc_hint - off_idx), ad->hba->as);
         qemu_sglist_add(sglist, le64_to_cpu(tbl[off_idx].addr + off_pos),
                         le32_to_cpu(tbl[off_idx].flags_size) + 1 - off_pos);
 
@@ -703,7 +703,7 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset)
     }
 
 out:
-    dma_memory_unmap(ad->hba->dma, prdt, prdt_len,
+    dma_memory_unmap(ad->hba->as, prdt, prdt_len,
                      DMA_DIRECTION_TO_DEVICE, prdt_len);
     return r;
 }
@@ -836,7 +836,7 @@ static int handle_cmd(AHCIState *s, int port, int slot)
     tbl_addr = le64_to_cpu(cmd->tbl_addr);
 
     cmd_len = 0x80;
-    cmd_fis = dma_memory_map(s->dma, tbl_addr, &cmd_len,
+    cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len,
                              DMA_DIRECTION_FROM_DEVICE);
 
     if (!cmd_fis) {
@@ -963,7 +963,7 @@ static int handle_cmd(AHCIState *s, int port, int slot)
     }
 
 out:
-    dma_memory_unmap(s->dma, cmd_fis, cmd_len, DMA_DIRECTION_FROM_DEVICE,
+    dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_FROM_DEVICE,
                      cmd_len);
 
     if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) {
@@ -1145,12 +1145,12 @@ static const IDEDMAOps ahci_dma_ops = {
     .reset = ahci_dma_reset,
 };
 
-void ahci_init(AHCIState *s, DeviceState *qdev, DMAContext *dma, int ports)
+void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports)
 {
     qemu_irq *irqs;
     int i;
 
-    s->dma = dma;
+    s->as = as;
     s->ports = ports;
     s->dev = g_malloc0(sizeof(AHCIDevice) * ports);
     ahci_reg_init(s);
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index 85f37fe..341a571 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -297,7 +297,7 @@ typedef struct AHCIState {
     uint32_t idp_index;     /* Current IDP index */
     int32_t ports;
     qemu_irq irq;
-    DMAContext *dma;
+    AddressSpace *as;
 } AHCIState;
 
 typedef struct AHCIPCIState {
@@ -338,7 +338,7 @@ typedef struct NCQFrame {
     uint8_t reserved10;
 } QEMU_PACKED NCQFrame;
 
-void ahci_init(AHCIState *s, DeviceState *qdev, DMAContext *dma, int ports);
+void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports);
 void ahci_uninit(AHCIState *s);
 
 void ahci_reset(AHCIState *s);
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index ed1f1a2..6c0c0c2 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -104,7 +104,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
     uint8_t *sata_cap;
     d = DO_UPCAST(struct AHCIPCIState, card, dev);
 
-    ahci_init(&d->ahci, &dev->qdev, pci_dma_context(dev), 6);
+    ahci_init(&d->ahci, &dev->qdev, pci_get_address_space(dev), 6);
 
     pci_config_set_prog_interface(d->card.config, AHCI_PROGMODE_MAJOR_REV_1);
 
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index e1e4f41..a1952b0 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -71,7 +71,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
     s->io_buffer_size = io->len;
 
     qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
-                     &dma_context_memory);
+                     &address_space_memory);
     qemu_sglist_add(&s->sg, io->addr, io->len);
     io->addr += io->len;
     io->len = 0;
@@ -128,7 +128,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
     s->io_buffer_size = io->len;
 
     qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
-                     &dma_context_memory);
+                     &address_space_memory);
     qemu_sglist_add(&s->sg, io->addr, io->len);
     io->addr += io->len;
     io->len = 0;
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 9e6bd77..2b1bc6d 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -816,8 +816,6 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
                              dma_as->root, 0, memory_region_size(dma_as->root));
     memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
     address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
-    pci_dev->dma = g_new(DMAContext, 1);
-    dma_context_init(pci_dev->dma, &pci_dev->bus_master_as);
 
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
@@ -874,8 +872,6 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
 
     address_space_destroy(&pci_dev->bus_master_as);
     memory_region_destroy(&pci_dev->bus_master_enable_region);
-    g_free(pci_dev->dma);
-    pci_dev->dma = NULL;
 }
 
 static void pci_unregister_io_regions(PCIDevice *pci_dev)
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 8d77a36..5e72f1b 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -459,7 +459,6 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
         uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
         dev->tcet = spapr_tce_new_table(liobn, pc->rtce_window_size);
         address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet));
-        dma_context_init(&dev->dma, &dev->as);
     }
 
     return pc->init(dev);
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index fe6550c..7ee7d97 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -232,7 +232,7 @@ static int megasas_map_sgl(MegasasState *s, MegasasCmd *cmd, union mfi_sgl *sgl)
                                          MEGASAS_MAX_SGE);
         return iov_count;
     }
-    qemu_sglist_init(&cmd->qsg, iov_count, pci_dma_context(&s->dev));
+    qemu_sglist_init(&cmd->qsg, iov_count, pci_get_address_space(&s->dev));
     for (i = 0; i < iov_count; i++) {
         dma_addr_t iov_pa, iov_size_p;
 
@@ -628,7 +628,7 @@ static int megasas_map_dcmd(MegasasState *s, MegasasCmd *cmd)
     }
     iov_pa = megasas_sgl_get_addr(cmd, &cmd->frame->dcmd.sgl);
     iov_size = megasas_sgl_get_len(cmd, &cmd->frame->dcmd.sgl);
-    qemu_sglist_init(&cmd->qsg, 1, pci_dma_context(&s->dev));
+    qemu_sglist_init(&cmd->qsg, 1, pci_get_address_space(&s->dev));
     qemu_sglist_add(&cmd->qsg, iov_pa, iov_size);
     cmd->iov_size = iov_size;
     return cmd->iov_size;
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 08dd3f3..b8a0abf 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -80,7 +80,7 @@ static void virtio_scsi_bad_req(void)
 static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg,
                                    hwaddr *addr, int num)
 {
-    qemu_sglist_init(qsgl, num, &dma_context_memory);
+    qemu_sglist_init(qsgl, num, &address_space_memory);
     while (num--) {
         qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len);
     }
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 48d12f4..eb2270f 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -617,7 +617,7 @@ pvscsi_build_sglist(PVSCSIState *s, PVSCSIRequest *r)
 {
     PCIDevice *d = PCI_DEVICE(s);
 
-    qemu_sglist_init(&r->sgl, 1, pci_dma_context(d));
+    pci_dma_sglist_init(&r->sgl, d, 1);
     if (r->req.flags & PVSCSI_FLAG_CMD_WITH_SG_LIST) {
         pvscsi_convert_sglist(r);
     } else {
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 91dc9b0..5d9247a 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -496,7 +496,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
                     s->blkcnt--;
                 }
             }
-            dma_memory_write(&dma_context_memory, s->sdmasysad,
+            dma_memory_write(&address_space_memory, s->sdmasysad,
                              &s->fifo_buffer[begin], s->data_count - begin);
             s->sdmasysad += s->data_count - begin;
             if (s->data_count == block_size) {
@@ -518,7 +518,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
                 s->data_count = block_size;
                 boundary_count -= block_size - begin;
             }
-            dma_memory_read(&dma_context_memory, s->sdmasysad,
+            dma_memory_read(&address_space_memory, s->sdmasysad,
                             &s->fifo_buffer[begin], s->data_count);
             s->sdmasysad += s->data_count - begin;
             if (s->data_count == block_size) {
@@ -557,10 +557,10 @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s)
         for (n = 0; n < datacnt; n++) {
             s->fifo_buffer[n] = sd_read_data(s->card);
         }
-        dma_memory_write(&dma_context_memory, s->sdmasysad, s->fifo_buffer,
+        dma_memory_write(&address_space_memory, s->sdmasysad, s->fifo_buffer,
                          datacnt);
     } else {
-        dma_memory_read(&dma_context_memory, s->sdmasysad, s->fifo_buffer,
+        dma_memory_read(&address_space_memory, s->sdmasysad, s->fifo_buffer,
                         datacnt);
         for (n = 0; n < datacnt; n++) {
             sd_write_data(s->card, s->fifo_buffer[n]);
@@ -588,7 +588,7 @@ static void get_adma_description(SDHCIState *s, ADMADescr *dscr)
     hwaddr entry_addr = (hwaddr)s->admasysaddr;
     switch (SDHC_DMA_TYPE(s->hostctl)) {
     case SDHC_CTRL_ADMA2_32:
-        dma_memory_read(&dma_context_memory, entry_addr, (uint8_t *)&adma2,
+        dma_memory_read(&address_space_memory, entry_addr, (uint8_t *)&adma2,
                         sizeof(adma2));
         adma2 = le64_to_cpu(adma2);
         /* The spec does not specify endianness of descriptor table.
@@ -600,7 +600,7 @@ static void get_adma_description(SDHCIState *s, ADMADescr *dscr)
         dscr->incr = 8;
         break;
     case SDHC_CTRL_ADMA1_32:
-        dma_memory_read(&dma_context_memory, entry_addr, (uint8_t *)&adma1,
+        dma_memory_read(&address_space_memory, entry_addr, (uint8_t *)&adma1,
                         sizeof(adma1));
         adma1 = le32_to_cpu(adma1);
         dscr->addr = (hwaddr)(adma1 & 0xFFFFF000);
@@ -613,12 +613,12 @@ static void get_adma_description(SDHCIState *s, ADMADescr *dscr)
         }
         break;
     case SDHC_CTRL_ADMA2_64:
-        dma_memory_read(&dma_context_memory, entry_addr,
+        dma_memory_read(&address_space_memory, entry_addr,
                         (uint8_t *)(&dscr->attr), 1);
-        dma_memory_read(&dma_context_memory, entry_addr + 2,
+        dma_memory_read(&address_space_memory, entry_addr + 2,
                         (uint8_t *)(&dscr->length), 2);
         dscr->length = le16_to_cpu(dscr->length);
-        dma_memory_read(&dma_context_memory, entry_addr + 4,
+        dma_memory_read(&address_space_memory, entry_addr + 4,
                         (uint8_t *)(&dscr->addr), 8);
         dscr->attr = le64_to_cpu(dscr->attr);
         dscr->attr &= 0xfffffff8;
@@ -678,7 +678,7 @@ static void sdhci_do_adma(SDHCIState *s)
                         s->data_count = block_size;
                         length -= block_size - begin;
                     }
-                    dma_memory_write(&dma_context_memory, dscr.addr,
+                    dma_memory_write(&address_space_memory, dscr.addr,
                                      &s->fifo_buffer[begin],
                                      s->data_count - begin);
                     dscr.addr += s->data_count - begin;
@@ -702,7 +702,7 @@ static void sdhci_do_adma(SDHCIState *s)
                         s->data_count = block_size;
                         length -= block_size - begin;
                     }
-                    dma_memory_read(&dma_context_memory, dscr.addr,
+                    dma_memory_read(&address_space_memory, dscr.addr,
                                     &s->fifo_buffer[begin], s->data_count);
                     dscr.addr += s->data_count - begin;
                     if (s->data_count == block_size) {
diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index 0eb7826..f1b5f5d 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -63,7 +63,7 @@ static int usb_ehci_pci_initfn(PCIDevice *dev)
     s->caps[0x09] = 0x68;        /* EECP */
 
     s->irq = dev->irq[3];
-    s->dma = pci_dma_context(dev);
+    s->as = pci_get_address_space(dev);
 
     s->capsbase = 0x00;
     s->opregbase = 0x20;
@@ -86,7 +86,7 @@ static void usb_ehci_pci_write_config(PCIDevice *dev, uint32_t addr,
         return;
     }
     busmaster = pci_get_word(dev->config + PCI_COMMAND) & PCI_COMMAND_MASTER;
-    i->ehci.dma = busmaster ? pci_dma_context(dev) : NULL;
+    i->ehci.as = busmaster ? pci_get_address_space(dev) : &address_space_memory;
 }
 
 static Property ehci_pci_properties[] = {
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
index b68a66a..f9e4fd3 100644
--- a/hw/usb/hcd-ehci-sysbus.c
+++ b/hw/usb/hcd-ehci-sysbus.c
@@ -40,7 +40,7 @@ static int usb_ehci_sysbus_initfn(SysBusDevice *dev)
 
     s->capsbase = sec->capsbase;
     s->opregbase = sec->opregbase;
-    s->dma = &dma_context_memory;
+    s->as = &address_space_memory;
 
     usb_ehci_initfn(s, DEVICE(dev));
     sysbus_init_irq(dev, &s->irq);
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 0d3799d..1ad2159 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -446,7 +446,7 @@ static inline int get_dwords(EHCIState *ehci, uint32_t addr,
 {
     int i;
 
-    if (!ehci->dma) {
+    if (!ehci->as) {
         ehci_raise_irq(ehci, USBSTS_HSE);
         ehci->usbcmd &= ~USBCMD_RUNSTOP;
         trace_usb_ehci_dma_error();
@@ -454,7 +454,7 @@ static inline int get_dwords(EHCIState *ehci, uint32_t addr,
     }
 
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        dma_memory_read(ehci->dma, addr, buf, sizeof(*buf));
+        dma_memory_read(ehci->as, addr, buf, sizeof(*buf));
         *buf = le32_to_cpu(*buf);
     }
 
@@ -467,7 +467,7 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr,
 {
     int i;
 
-    if (!ehci->dma) {
+    if (!ehci->as) {
         ehci_raise_irq(ehci, USBSTS_HSE);
         ehci->usbcmd &= ~USBCMD_RUNSTOP;
         trace_usb_ehci_dma_error();
@@ -476,7 +476,7 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr,
 
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         uint32_t tmp = cpu_to_le32(*buf);
-        dma_memory_write(ehci->dma, addr, &tmp, sizeof(tmp));
+        dma_memory_write(ehci->as, addr, &tmp, sizeof(tmp));
     }
 
     return num;
@@ -1245,7 +1245,7 @@ static int ehci_init_transfer(EHCIPacket *p)
     cpage  = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
     bytes  = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
     offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
-    qemu_sglist_init(&p->sgl, 5, p->queue->ehci->dma);
+    qemu_sglist_init(&p->sgl, 5, p->queue->ehci->as);
 
     while (bytes > 0) {
         if (cpage > 4) {
@@ -1484,7 +1484,7 @@ static int ehci_process_itd(EHCIState *ehci,
                 return -1;
             }
 
-            qemu_sglist_init(&ehci->isgl, 2, ehci->dma);
+            qemu_sglist_init(&ehci->isgl, 2, ehci->as);
             if (off + len > 4096) {
                 /* transfer crosses page border */
                 uint32_t len2 = off + len - 4096;
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index e95bb7e..2fcb92f 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -261,7 +261,7 @@ struct EHCIState {
     USBBus bus;
     qemu_irq irq;
     MemoryRegion mem;
-    DMAContext *dma;
+    AddressSpace *as;
     MemoryRegion mem_caps;
     MemoryRegion mem_opreg;
     MemoryRegion mem_ports;
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 51241cd..5513924 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -62,7 +62,7 @@ typedef struct {
     USBBus bus;
     qemu_irq irq;
     MemoryRegion mem;
-    DMAContext *dma;
+    AddressSpace *as;
     int num_ports;
     const char *name;
 
@@ -508,7 +508,7 @@ static inline int get_dwords(OHCIState *ohci,
     addr += ohci->localmem_base;
 
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        dma_memory_read(ohci->dma, addr, buf, sizeof(*buf));
+        dma_memory_read(ohci->as, addr, buf, sizeof(*buf));
         *buf = le32_to_cpu(*buf);
     }
 
@@ -525,7 +525,7 @@ static inline int put_dwords(OHCIState *ohci,
 
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         uint32_t tmp = cpu_to_le32(*buf);
-        dma_memory_write(ohci->dma, addr, &tmp, sizeof(tmp));
+        dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp));
     }
 
     return 1;
@@ -540,7 +540,7 @@ static inline int get_words(OHCIState *ohci,
     addr += ohci->localmem_base;
 
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
-        dma_memory_read(ohci->dma, addr, buf, sizeof(*buf));
+        dma_memory_read(ohci->as, addr, buf, sizeof(*buf));
         *buf = le16_to_cpu(*buf);
     }
 
@@ -557,7 +557,7 @@ static inline int put_words(OHCIState *ohci,
 
     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
         uint16_t tmp = cpu_to_le16(*buf);
-        dma_memory_write(ohci->dma, addr, &tmp, sizeof(tmp));
+        dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp));
     }
 
     return 1;
@@ -585,7 +585,7 @@ static inline int ohci_read_iso_td(OHCIState *ohci,
 static inline int ohci_read_hcca(OHCIState *ohci,
                                  dma_addr_t addr, struct ohci_hcca *hcca)
 {
-    dma_memory_read(ohci->dma, addr + ohci->localmem_base, hcca, sizeof(*hcca));
+    dma_memory_read(ohci->as, addr + ohci->localmem_base, hcca, sizeof(*hcca));
     return 1;
 }
 
@@ -617,7 +617,7 @@ static inline int ohci_put_iso_td(OHCIState *ohci,
 static inline int ohci_put_hcca(OHCIState *ohci,
                                 dma_addr_t addr, struct ohci_hcca *hcca)
 {
-    dma_memory_write(ohci->dma,
+    dma_memory_write(ohci->as,
                      addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
                      (char *)hcca + HCCA_WRITEBACK_OFFSET,
                      HCCA_WRITEBACK_SIZE);
@@ -634,12 +634,12 @@ static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
     n = 0x1000 - (ptr & 0xfff);
     if (n > len)
         n = len;
-    dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, n, dir);
+    dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir);
     if (n == len)
         return;
     ptr = td->be & ~0xfffu;
     buf += n;
-    dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, len - n, dir);
+    dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, len - n, dir);
 }
 
 /* Read/Write the contents of an ISO TD from/to main memory.  */
@@ -653,12 +653,12 @@ static void ohci_copy_iso_td(OHCIState *ohci,
     n = 0x1000 - (ptr & 0xfff);
     if (n > len)
         n = len;
-    dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, n, dir);
+    dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir);
     if (n == len)
         return;
     ptr = end_addr & ~0xfffu;
     buf += n;
-    dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, len - n, dir);
+    dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, len - n, dir);
 }
 
 static void ohci_process_lists(OHCIState *ohci, int completion);
@@ -1788,11 +1788,11 @@ static USBBusOps ohci_bus_ops = {
 static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
                          int num_ports, dma_addr_t localmem_base,
                          char *masterbus, uint32_t firstport,
-                         DMAContext *dma)
+                         AddressSpace *as)
 {
     int i;
 
-    ohci->dma = dma;
+    ohci->as = as;
 
     if (usb_frame_time == 0) {
 #ifdef OHCI_TIME_WARP
@@ -1859,7 +1859,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
 
     if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0,
                       ohci->masterbus, ohci->firstport,
-                      pci_dma_context(dev)) != 0) {
+                      pci_get_address_space(dev)) != 0) {
         return -1;
     }
     ohci->state.irq = ohci->pci_dev.irq[0];
@@ -1882,7 +1882,7 @@ static int ohci_init_pxa(SysBusDevice *dev)
 
     /* Cannot fail as we pass NULL for masterbus */
     usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0,
-                  &dma_context_memory);
+                  &address_space_memory);
     sysbus_init_irq(dev, &s->ohci.irq);
     sysbus_init_mmio(dev, &s->ohci.mem);
 
diff --git a/hw/usb/libhw.c b/hw/usb/libhw.c
index d2d4b51..8df11c4 100644
--- a/hw/usb/libhw.c
+++ b/hw/usb/libhw.c
@@ -37,7 +37,7 @@ int usb_packet_map(USBPacket *p, QEMUSGList *sgl)
 
         while (len) {
             dma_addr_t xlen = len;
-            mem = dma_memory_map(sgl->dma, base, &xlen, dir);
+            mem = dma_memory_map(sgl->as, base, &xlen, dir);
             if (!mem) {
                 goto err;
             }
@@ -63,7 +63,7 @@ void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl)
     int i;
 
     for (i = 0; i < p->iov.niov; i++) {
-        dma_memory_unmap(sgl->dma, p->iov.iov[i].iov_base,
+        dma_memory_unmap(sgl->as, p->iov.iov[i].iov_base,
                          p->iov.iov[i].iov_len, dir,
                          p->iov.iov[i].iov_len);
     }
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 3a85bce..6ef1f97 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -242,7 +242,6 @@ struct PCIDevice {
     PCIIORegion io_regions[PCI_NUM_REGIONS];
     AddressSpace bus_master_as;
     MemoryRegion bus_master_enable_region;
-    DMAContext *dma;
 
     /* do not access the following fields */
     PCIConfigReadFunc *config_read;
@@ -639,15 +638,15 @@ static inline uint32_t pci_config_size(const PCIDevice *d)
 }
 
 /* DMA access functions */
-static inline DMAContext *pci_dma_context(PCIDevice *dev)
+static inline AddressSpace *pci_get_address_space(PCIDevice *dev)
 {
-    return dev->dma;
+    return &dev->bus_master_as;
 }
 
 static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr,
                              void *buf, dma_addr_t len, DMADirection dir)
 {
-    dma_memory_rw(pci_dma_context(dev), addr, buf, len, dir);
+    dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir);
     return 0;
 }
 
@@ -667,12 +666,12 @@ static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr,
     static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev,      \
                                                    dma_addr_t addr)     \
     {                                                                   \
-        return ld##_l##_dma(pci_dma_context(dev), addr);                \
+        return ld##_l##_dma(pci_get_address_space(dev), addr);          \
     }                                                                   \
     static inline void st##_s##_pci_dma(PCIDevice *dev,                 \
                                         dma_addr_t addr, uint##_bits##_t val) \
     {                                                                   \
-        st##_s##_dma(pci_dma_context(dev), addr, val);                  \
+        st##_s##_dma(pci_get_address_space(dev), addr, val);            \
     }
 
 PCI_DMA_DEFINE_LDST(ub, b, 8);
@@ -690,20 +689,20 @@ static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr,
 {
     void *buf;
 
-    buf = dma_memory_map(pci_dma_context(dev), addr, plen, dir);
+    buf = dma_memory_map(pci_get_address_space(dev), addr, plen, dir);
     return buf;
 }
 
 static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len,
                                  DMADirection dir, dma_addr_t access_len)
 {
-    dma_memory_unmap(pci_dma_context(dev), buffer, len, dir, access_len);
+    dma_memory_unmap(pci_get_address_space(dev), buffer, len, dir, access_len);
 }
 
 static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev,
                                        int alloc_hint)
 {
-    qemu_sglist_init(qsg, alloc_hint, pci_dma_context(dev));
+    qemu_sglist_init(qsg, alloc_hint, pci_get_address_space(dev));
 }
 
 extern const VMStateDescription vmstate_pci_device;
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
index 2de58f1..3609327 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -64,7 +64,6 @@ struct VIOsPAPRDevice {
     target_ulong signal_state;
     VIOsPAPR_CRQ crq;
     AddressSpace as;
-    DMAContext dma;
     sPAPRTCETable *tcet;
 };
 
@@ -93,35 +92,35 @@ static inline qemu_irq spapr_vio_qirq(VIOsPAPRDevice *dev)
 static inline bool spapr_vio_dma_valid(VIOsPAPRDevice *dev, uint64_t taddr,
                                        uint32_t size, DMADirection dir)
 {
-    return dma_memory_valid(&dev->dma, taddr, size, dir);
+    return dma_memory_valid(&dev->as, taddr, size, dir);
 }
 
 static inline int spapr_vio_dma_read(VIOsPAPRDevice *dev, uint64_t taddr,
                                      void *buf, uint32_t size)
 {
-    return (dma_memory_read(&dev->dma, taddr, buf, size) != 0) ?
+    return (dma_memory_read(&dev->as, taddr, buf, size) != 0) ?
         H_DEST_PARM : H_SUCCESS;
 }
 
 static inline int spapr_vio_dma_write(VIOsPAPRDevice *dev, uint64_t taddr,
                                       const void *buf, uint32_t size)
 {
-    return (dma_memory_write(&dev->dma, taddr, buf, size) != 0) ?
+    return (dma_memory_write(&dev->as, taddr, buf, size) != 0) ?
         H_DEST_PARM : H_SUCCESS;
 }
 
 static inline int spapr_vio_dma_set(VIOsPAPRDevice *dev, uint64_t taddr,
                                     uint8_t c, uint32_t size)
 {
-    return (dma_memory_set(&dev->dma, taddr, c, size) != 0) ?
+    return (dma_memory_set(&dev->as, taddr, c, size) != 0) ?
         H_DEST_PARM : H_SUCCESS;
 }
 
-#define vio_stb(_dev, _addr, _val) (stb_dma(&(_dev)->dma, (_addr), (_val)))
-#define vio_sth(_dev, _addr, _val) (stw_be_dma(&(_dev)->dma, (_addr), (_val)))
-#define vio_stl(_dev, _addr, _val) (stl_be_dma(&(_dev)->dma, (_addr), (_val)))
-#define vio_stq(_dev, _addr, _val) (stq_be_dma(&(_dev)->dma, (_addr), (_val)))
-#define vio_ldq(_dev, _addr) (ldq_be_dma(&(_dev)->dma, (_addr)))
+#define vio_stb(_dev, _addr, _val) (stb_dma(&(_dev)->as, (_addr), (_val)))
+#define vio_sth(_dev, _addr, _val) (stw_be_dma(&(_dev)->as, (_addr), (_val)))
+#define vio_stl(_dev, _addr, _val) (stl_be_dma(&(_dev)->as, (_addr), (_val)))
+#define vio_stq(_dev, _addr, _val) (stq_be_dma(&(_dev)->as, (_addr), (_val)))
+#define vio_ldq(_dev, _addr) (ldq_be_dma(&(_dev)->as, (_addr)))
 
 int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
 
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
index 3ed621b..e315364 100644
--- a/include/sysemu/dma.h
+++ b/include/sysemu/dma.h
@@ -12,11 +12,11 @@
 
 #include <stdio.h>
 #include "exec/memory.h"
+#include "exec/address-spaces.h"
 #include "hw/hw.h"
 #include "block/block.h"
 #include "sysemu/kvm.h"
 
-typedef struct DMAContext DMAContext;
 typedef struct ScatterGatherEntry ScatterGatherEntry;
 
 typedef enum {
@@ -29,7 +29,7 @@ struct QEMUSGList {
     int nsg;
     int nalloc;
     size_t size;
-    DMAContext *dma;
+    AddressSpace *as;
 };
 
 #ifndef CONFIG_USER_ONLY
@@ -46,16 +46,7 @@ typedef uint64_t dma_addr_t;
 #define DMA_ADDR_BITS 64
 #define DMA_ADDR_FMT "%" PRIx64
 
-struct DMAContext {
-    AddressSpace *as;
-};
-
-/* A global DMA context corresponding to the address_space_memory
- * AddressSpace, for sysbus devices which do DMA.
- */
-extern DMAContext dma_context_memory;
-
-static inline void dma_barrier(DMAContext *dma, DMADirection dir)
+static inline void dma_barrier(AddressSpace *as, DMADirection dir)
 {
     /*
      * This is called before DMA read and write operations
@@ -83,105 +74,105 @@ static inline void dma_barrier(DMAContext *dma, DMADirection dir)
 /* Checks that the given range of addresses is valid for DMA.  This is
  * useful for certain cases, but usually you should just use
  * dma_memory_{read,write}() and check for errors */
-static inline bool dma_memory_valid(DMAContext *dma,
+static inline bool dma_memory_valid(AddressSpace *as,
                                     dma_addr_t addr, dma_addr_t len,
                                     DMADirection dir)
 {
-    return address_space_valid(dma->as, addr, len,
+    return address_space_valid(as, addr, len,
                                dir == DMA_DIRECTION_FROM_DEVICE);
 }
 
-static inline int dma_memory_rw_relaxed(DMAContext *dma, dma_addr_t addr,
+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(dma->as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
+    return address_space_rw(as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
 }
 
-static inline int dma_memory_read_relaxed(DMAContext *dma, dma_addr_t addr,
+static inline int dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr,
                                           void *buf, dma_addr_t len)
 {
-    return dma_memory_rw_relaxed(dma, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
+    return dma_memory_rw_relaxed(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
 }
 
-static inline int dma_memory_write_relaxed(DMAContext *dma, dma_addr_t addr,
+static inline int dma_memory_write_relaxed(AddressSpace *as, dma_addr_t addr,
                                            const void *buf, dma_addr_t len)
 {
-    return dma_memory_rw_relaxed(dma, addr, (void *)buf, len,
+    return dma_memory_rw_relaxed(as, addr, (void *)buf, len,
                                  DMA_DIRECTION_FROM_DEVICE);
 }
 
-static inline int dma_memory_rw(DMAContext *dma, dma_addr_t addr,
+static inline int dma_memory_rw(AddressSpace *as, dma_addr_t addr,
                                 void *buf, dma_addr_t len,
                                 DMADirection dir)
 {
-    dma_barrier(dma, dir);
+    dma_barrier(as, dir);
 
-    return dma_memory_rw_relaxed(dma, addr, buf, len, dir);
+    return dma_memory_rw_relaxed(as, addr, buf, len, dir);
 }
 
-static inline int dma_memory_read(DMAContext *dma, dma_addr_t addr,
+static inline int dma_memory_read(AddressSpace *as, dma_addr_t addr,
                                   void *buf, dma_addr_t len)
 {
-    return dma_memory_rw(dma, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
+    return dma_memory_rw(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
 }
 
-static inline int dma_memory_write(DMAContext *dma, dma_addr_t addr,
+static inline int dma_memory_write(AddressSpace *as, dma_addr_t addr,
                                    const void *buf, dma_addr_t len)
 {
-    return dma_memory_rw(dma, addr, (void *)buf, len,
+    return dma_memory_rw(as, addr, (void *)buf, len,
                          DMA_DIRECTION_FROM_DEVICE);
 }
 
-int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t len);
+int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len);
 
-static inline void *dma_memory_map(DMAContext *dma,
+static inline void *dma_memory_map(AddressSpace *as,
                                    dma_addr_t addr, dma_addr_t *len,
                                    DMADirection dir)
 {
     hwaddr xlen = *len;
     void *p;
 
-    p = address_space_map(dma->as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE);
+    p = address_space_map(as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE);
     *len = xlen;
     return p;
 }
 
-static inline void dma_memory_unmap(DMAContext *dma,
+static inline void dma_memory_unmap(AddressSpace *as,
                                     void *buffer, dma_addr_t len,
                                     DMADirection dir, dma_addr_t access_len)
 {
-    address_space_unmap(dma->as, buffer, (hwaddr)len,
+    address_space_unmap(as, buffer, (hwaddr)len,
                         dir == DMA_DIRECTION_FROM_DEVICE, access_len);
 }
 
 #define DEFINE_LDST_DMA(_lname, _sname, _bits, _end) \
-    static inline uint##_bits##_t ld##_lname##_##_end##_dma(DMAContext *dma, \
+    static inline uint##_bits##_t ld##_lname##_##_end##_dma(AddressSpace *as, \
                                                             dma_addr_t addr) \
     {                                                                   \
         uint##_bits##_t val;                                            \
-        dma_memory_read(dma, addr, &val, (_bits) / 8);                  \
+        dma_memory_read(as, addr, &val, (_bits) / 8);                   \
         return _end##_bits##_to_cpu(val);                               \
     }                                                                   \
-    static inline void st##_sname##_##_end##_dma(DMAContext *dma,       \
+    static inline void st##_sname##_##_end##_dma(AddressSpace *as,      \
                                                  dma_addr_t addr,       \
                                                  uint##_bits##_t val)   \
     {                                                                   \
         val = cpu_to_##_end##_bits(val);                                \
-        dma_memory_write(dma, addr, &val, (_bits) / 8);                 \
+        dma_memory_write(as, addr, &val, (_bits) / 8);                  \
     }
 
-static inline uint8_t ldub_dma(DMAContext *dma, dma_addr_t addr)
+static inline uint8_t ldub_dma(AddressSpace *as, dma_addr_t addr)
 {
     uint8_t val;
 
-    dma_memory_read(dma, addr, &val, 1);
+    dma_memory_read(as, addr, &val, 1);
     return val;
 }
 
-static inline void stb_dma(DMAContext *dma, dma_addr_t addr, uint8_t val)
+static inline void stb_dma(AddressSpace *as, dma_addr_t addr, uint8_t val)
 {
-    dma_memory_write(dma, addr, &val, 1);
+    dma_memory_write(as, addr, &val, 1);
 }
 
 DEFINE_LDST_DMA(uw, w, 16, le);
@@ -193,14 +184,12 @@ DEFINE_LDST_DMA(q, q, 64, be);
 
 #undef DEFINE_LDST_DMA
 
-void dma_context_init(DMAContext *dma, AddressSpace *as);
-
 struct ScatterGatherEntry {
     dma_addr_t base;
     dma_addr_t len;
 };
 
-void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, DMAContext *dma);
+void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, AddressSpace *as);
 void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
 void qemu_sglist_destroy(QEMUSGList *qsg);
 #endif
-- 
1.8.1.4

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

* [Qemu-devel] [PATCH 30/30] memory: give name to every AddressSpace
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (28 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 29/30] dma: eliminate DMAContext Paolo Bonzini
@ 2013-05-21 10:57 ` Paolo Bonzini
  2013-05-23 18:46   ` Peter Maydell
  2013-05-22  2:30 ` [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Alexey Kardashevskiy
  30 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-21 10:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alexey Kardashevskiy, peter.maydell, jan.kiszka, David Gibson

From: Alexey Kardashevskiy <aik@ozlabs.ru>

The "info mtree" command in QEMU console prints only "memory" and "I/O"
address spaces while there are actually a lot more other AddressSpace
structs created by PCI and VIO devices. Those devices do not normally
have names and therefore not present in "info mtree" output.

The patch fixes this.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 exec.c                | 6 ++----
 hw/pci/pci.c          | 3 ++-
 hw/ppc/spapr_vio.c    | 2 +-
 include/exec/memory.h | 5 +++--
 memory.c              | 8 +++-----
 5 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/exec.c b/exec.c
index f508a59..1610604 100644
--- a/exec.c
+++ b/exec.c
@@ -1846,13 +1846,11 @@ static void memory_map_init(void)
 {
     system_memory = g_malloc(sizeof(*system_memory));
     memory_region_init(system_memory, "system", INT64_MAX);
-    address_space_init(&address_space_memory, system_memory);
-    address_space_memory.name = "memory";
+    address_space_init(&address_space_memory, system_memory, "memory");
 
     system_io = g_malloc(sizeof(*system_io));
     memory_region_init(system_io, "io", 65536);
-    address_space_init(&address_space_io, system_io);
-    address_space_io.name = "I/O";
+    address_space_init(&address_space_io, system_io, "I/O");
 
     memory_listener_register(&core_memory_listener, &address_space_memory);
     memory_listener_register(&io_memory_listener, &address_space_io);
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 2b1bc6d..fa30110 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -815,7 +815,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
     memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master",
                              dma_as->root, 0, memory_region_size(dma_as->root));
     memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
-    address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
+    address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region,
+                       name);
 
     pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 5e72f1b..3cfa326 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -458,7 +458,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
     if (pc->rtce_window_size) {
         uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
         dev->tcet = spapr_tce_new_table(liobn, pc->rtce_window_size);
-        address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet));
+        address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet), qdev->id);
     }
 
     return pc->init(dev);
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 05b9bb2..01b70ed 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -191,7 +191,7 @@ struct MemoryRegionPortio {
  */
 struct AddressSpace {
     /* All fields are private. */
-    const char *name;
+    char *name;
     MemoryRegion *root;
     struct FlatView *current_map;
     int ioeventfd_nb;
@@ -858,8 +858,9 @@ void mtree_info(fprintf_function mon_printf, void *f);
  *
  * @as: an uninitialized #AddressSpace
  * @root: a #MemoryRegion that routes addesses for the address space
+ * @name: an address space name
  */
-void address_space_init(AddressSpace *as, MemoryRegion *root);
+void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name);
 
 
 /**
diff --git a/memory.c b/memory.c
index e3970bf..66258e2 100644
--- a/memory.c
+++ b/memory.c
@@ -1605,7 +1605,7 @@ void memory_listener_unregister(MemoryListener *listener)
     QTAILQ_REMOVE(&memory_listeners, listener, link);
 }
 
-void address_space_init(AddressSpace *as, MemoryRegion *root)
+void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 {
     memory_region_transaction_begin();
     as->root = root;
@@ -1614,7 +1614,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root)
     as->ioeventfd_nb = 0;
     as->ioeventfds = NULL;
     QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
-    as->name = NULL;
+    as->name = g_strdup(name?name:"anonymous");
     address_space_init_dispatch(as);
     memory_region_update_pending |= root->enabled;
     memory_region_transaction_commit();
@@ -1629,6 +1629,7 @@ void address_space_destroy(AddressSpace *as)
     QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
     address_space_destroy_dispatch(as);
     flatview_destroy(as->current_map);
+    g_free(as->name);
     g_free(as->current_map);
     g_free(as->ioeventfds);
 }
@@ -1755,9 +1756,6 @@ void mtree_info(fprintf_function mon_printf, void *f)
     QTAILQ_INIT(&ml_head);
 
     QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
-        if (!as->name) {
-            continue;
-        }
         mon_printf(f, "%s\n", as->name);
         mtree_print_mr(mon_printf, f, as->root, 0, 0, &ml_head);
     }
-- 
1.8.1.4

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

* Re: [Qemu-devel] [PATCH 01/30] exec: remove obsolete comment
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 01/30] exec: remove obsolete comment Paolo Bonzini
@ 2013-05-21 11:36   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-21 11:36 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> See how we call memory_region_section_addr two lines below to
> convert a physical address to a base address in the region.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

(I'm sure I've reviewed this patch already in a previous version)

-- PMM

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

* Re: [Qemu-devel] [PATCH 02/30] exec: eliminate qemu_put_ram_ptr
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 02/30] exec: eliminate qemu_put_ram_ptr Paolo Bonzini
@ 2013-05-21 11:38   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-21 11:38 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 03/30] exec: make qemu_get_ram_ptr private
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 03/30] exec: make qemu_get_ram_ptr private Paolo Bonzini
@ 2013-05-21 11:38   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-21 11:38 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> It is a private interface between exec.c and memory.c.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 07/30] memory: Replace open-coded memory_region_is_romd
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 07/30] memory: Replace open-coded memory_region_is_romd Paolo Bonzini
@ 2013-05-21 11:54   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-21 11:54 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Jan Kiszka, jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> From: Jan Kiszka <jan.kiszka@siemens.com>
>
> Improves readability.
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
for about the third time.

-- PMM

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

* Re: [Qemu-devel] [PATCH 09/30] memory: do not duplicate memory_region_destructor_none
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 09/30] memory: do not duplicate memory_region_destructor_none Paolo Bonzini
@ 2013-05-21 11:55   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-21 11:55 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 10/30] memory: make memory_global_sync_dirty_bitmap take an AddressSpace
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 10/30] memory: make memory_global_sync_dirty_bitmap take an AddressSpace Paolo Bonzini
@ 2013-05-21 11:56   ` Peter Maydell
  2013-05-23  1:05   ` David Gibson
  1 sibling, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-21 11:56 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Suggested-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 11/30] memory: fix address space initialization/destruction
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 11/30] memory: fix address space initialization/destruction Paolo Bonzini
@ 2013-05-21 11:58   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-21 11:58 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, Avi Kivity, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> From: Avi Kivity <avi.kivity@gmail.com>
>
> A couple of fields were left uninitialized.  This was not observed earlier
> because all address spaces were statically allocated.  Also free allocation
> for those fields.
>
> Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 13/30] memory: limit sections in the radix tree to the actual address space size
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 13/30] memory: limit sections in the radix tree to the actual address space size Paolo Bonzini
@ 2013-05-21 12:02   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-21 12:02 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, Avi Kivity, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> From: Avi Kivity <avi.kivity@gmail.com>
>
> The radix tree is statically sized to fit TARGET_PHYS_ADDR_SPACE_BITS.
> If a larger memory region is registered, it will overflow.
>
> Fix by limiting any section in the radix tree to the supported size.
>
> This problem was not observed earlier since artificial regions (containers
> and aliases) are eliminated by the memory core, leaving only device regions
> which have reasonable sizes.  An IOMMU however cannot be eliminated by the
> memory core, and may have an artificial size.
>
> Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
> [ Fail the build if TARGET_PHYS_ADDR_SPACE_BITS is too large - Paolo ]
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 14/30] memory: create FlatView for new address spaces
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 14/30] memory: create FlatView for new address spaces Paolo Bonzini
@ 2013-05-21 12:03   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-21 12:03 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Even a new address space might have a non-empty FlatView.  In order
> to initialize it properly, address_space_init should (a) call
> memory_region_transaction_commit after the address space is inserted
> into the list; (b) force memory_region_transaction_commit to do something.
>
> This bug was latent so far because all address spaces started empty, including
> the PCI address space where the bus master region is initially disabled.
> However, the target address space of an IOMMU is usually rooted at
> get_system_memory(), which might not be empty at the time the IOMMU is created.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

The patch title should probably be "populate FlatView for new address
spaces", not "create". Given that,

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API
  2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
                   ` (29 preceding siblings ...)
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 30/30] memory: give name to every AddressSpace Paolo Bonzini
@ 2013-05-22  2:30 ` Alexey Kardashevskiy
  2013-05-22  9:24   ` Paolo Bonzini
  30 siblings, 1 reply; 106+ messages in thread
From: Alexey Kardashevskiy @ 2013-05-22  2:30 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, David Gibson, qemu-devel, jan.kiszka

On 05/21/2013 08:57 PM, Paolo Bonzini wrote:
> This is part 1 of the memory API updates for 1.6.  (Part 2 is the
> introduction of get/set_owner, part 3 is the introduction of the
> RCU-style flatview).
> 
> Compared to the first submissions, there are a few extra cleanup
> patches, and address_space_rw/read/write grew a return value so
> that the existing DMAContext API doesn't need to change.
> 

Is this series much different from the one in
https://github.com/bonzini/qemu/tree/iommu (hope it is the same :) )?


-- 
Alexey

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

* Re: [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API
  2013-05-22  2:30 ` [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Alexey Kardashevskiy
@ 2013-05-22  9:24   ` Paolo Bonzini
  2013-05-23 17:08     ` Paolo Bonzini
  0 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-22  9:24 UTC (permalink / raw)
  To: Alexey Kardashevskiy; +Cc: peter.maydell, David Gibson, qemu-devel, jan.kiszka

Il 22/05/2013 04:30, Alexey Kardashevskiy ha scritto:
> On 05/21/2013 08:57 PM, Paolo Bonzini wrote:
>> This is part 1 of the memory API updates for 1.6.  (Part 2 is the
>> introduction of get/set_owner, part 3 is the introduction of the
>> RCU-style flatview).
>>
>> Compared to the first submissions, there are a few extra cleanup
>> patches, and address_space_rw/read/write grew a return value so
>> that the existing DMAContext API doesn't need to change.
>>
> 
> Is this series much different from the one in
> https://github.com/bonzini/qemu/tree/iommu (hope it is the same :) )?

Not much, I've updated the branch now.

Paolo

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

* Re: [Qemu-devel] [PATCH 10/30] memory: make memory_global_sync_dirty_bitmap take an AddressSpace
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 10/30] memory: make memory_global_sync_dirty_bitmap take an AddressSpace Paolo Bonzini
  2013-05-21 11:56   ` Peter Maydell
@ 2013-05-23  1:05   ` David Gibson
  1 sibling, 0 replies; 106+ messages in thread
From: David Gibson @ 2013-05-23  1:05 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, qemu-devel, jan.kiszka

[-- Attachment #1: Type: text/plain, Size: 446 bytes --]

On Tue, May 21, 2013 at 12:57:11PM +0200, Paolo Bonzini wrote:
> Suggested-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Hrm.  This could surely do with some sort of rationale in the comment.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 17/30] memory: add address_space_translate Paolo Bonzini
@ 2013-05-23  7:09   ` liu ping fan
  2013-05-23  9:59     ` Paolo Bonzini
  2013-05-23 18:15   ` Peter Maydell
  2013-05-25  6:40   ` Jan Kiszka
  2 siblings, 1 reply; 106+ messages in thread
From: liu ping fan @ 2013-05-23  7:09 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, David Gibson, qemu-devel, jan.kiszka

On Tue, May 21, 2013 at 6:57 PM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Using phys_page_find to translate an AddressSpace to a MemoryRegionSection
> is unwieldy.  It requires to pass the page index rather than the address,
> and later memory_region_section_addr has to be called.  Replace
> memory_region_section_addr with a function that does all of it: call
> phys_page_find, compute the offset within the region, and check how
> big the current mapping is.  This way, a large flat region can be written
> with a single lookup rather than a page at a time.
>
> address_space_translate will also provide a single point where IOMMU
> forwarding is implemented.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  cputlb.c              |  20 ++---
>  exec.c                | 201 +++++++++++++++++++++++++++-----------------------
>  include/exec/cputlb.h |  12 ++-
>  include/exec/memory.h |  31 ++++----
>  translate-all.c       |   6 +-
>  5 files changed, 143 insertions(+), 127 deletions(-)
>
> diff --git a/cputlb.c b/cputlb.c
> index aba7e44..1f85da0 100644
> --- a/cputlb.c
> +++ b/cputlb.c
> @@ -248,13 +248,18 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
>      target_ulong code_address;
>      uintptr_t addend;
>      CPUTLBEntry *te;
> -    hwaddr iotlb;
> +    hwaddr iotlb, xlat, sz;
>
>      assert(size >= TARGET_PAGE_SIZE);
>      if (size != TARGET_PAGE_SIZE) {
>          tlb_add_large_page(env, vaddr, size);
>      }
> -    section = phys_page_find(address_space_memory.dispatch, paddr >> TARGET_PAGE_BITS);
> +
> +    sz = size;
> +    section = address_space_translate(&address_space_memory, paddr, &xlat, &sz,
> +                                      false);
> +    assert(sz >= TARGET_PAGE_SIZE);
> +
>  #if defined(DEBUG_TLB)
>      printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
>             " prot=%x idx=%d pd=0x%08lx\n",
> @@ -269,15 +274,14 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
>      }
>      if (memory_region_is_ram(section->mr) ||
>          memory_region_is_romd(section->mr)) {
> -        addend = (uintptr_t)memory_region_get_ram_ptr(section->mr)
> -        + memory_region_section_addr(section, paddr);
> +        addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
>      } else {
>          addend = 0;
>      }
>
>      code_address = address;
> -    iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, prot,
> -                                            &address);
> +    iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, xlat,
> +                                            prot, &address);
>
>      index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
>      env->iotlb[mmu_idx][index] = iotlb - vaddr;
> @@ -300,9 +304,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
>              /* Write access calls the I/O callback.  */
>              te->addr_write = address | TLB_MMIO;
>          } else if (memory_region_is_ram(section->mr)
> -                   && !cpu_physical_memory_is_dirty(
> -                           section->mr->ram_addr
> -                           + memory_region_section_addr(section, paddr))) {
> +                   && !cpu_physical_memory_is_dirty(section->mr->ram_addr + xlat)) {
>              te->addr_write = address | TLB_NOTDIRTY;
>          } else {
>              te->addr_write = address;
> diff --git a/exec.c b/exec.c
> index 82da067..e5ee8ff 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -182,7 +182,7 @@ static void phys_page_set(AddressSpaceDispatch *d,
>      phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
>  }
>
> -MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
> +static MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
>  {
>      PhysPageEntry lp = d->phys_map;
>      PhysPageEntry *p;
> @@ -198,6 +198,22 @@ MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
>      return &phys_sections[lp.ptr];
>  }
>
> +MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
> +                                             hwaddr *xlat, hwaddr *plen,
> +                                             bool is_write)
> +{
> +    MemoryRegionSection *section;
> +
> +    section = phys_page_find(as->dispatch, addr >> TARGET_PAGE_BITS);
> +    /* Compute offset within MemoryRegionSection */
> +    addr -= section->offset_within_address_space;
> +    *plen = MIN(section->size - addr, *plen);
> +
> +    /* Compute offset within MemoryRegion */
> +    *xlat = addr + section->offset_within_region;
> +    return section;
> +}
> +
>  bool memory_region_is_unassigned(MemoryRegion *mr)
>  {
>      return mr != &io_mem_ram && mr != &io_mem_rom
> @@ -616,11 +632,11 @@ static int cpu_physical_memory_set_dirty_tracking(int enable)
>  }
>
>  hwaddr memory_region_section_get_iotlb(CPUArchState *env,
> -                                                   MemoryRegionSection *section,
> -                                                   target_ulong vaddr,
> -                                                   hwaddr paddr,
> -                                                   int prot,
> -                                                   target_ulong *address)
> +                                       MemoryRegionSection *section,
> +                                       target_ulong vaddr,
> +                                       hwaddr paddr, hwaddr xlat,
> +                                       int prot,
> +                                       target_ulong *address)
>  {
>      hwaddr iotlb;
>      CPUWatchpoint *wp;
> @@ -628,7 +644,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
>      if (memory_region_is_ram(section->mr)) {
>          /* Normal RAM.  */
>          iotlb = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
> -            + memory_region_section_addr(section, paddr);
> +            + xlat;
>          if (!section->readonly) {
>              iotlb |= phys_section_notdirty;
>          } else {
> @@ -636,7 +652,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env,
>          }
>      } else {
>          iotlb = section - phys_sections;
> -        iotlb += memory_region_section_addr(section, paddr);
> +        iotlb += xlat;
>      }
>
>      /* Make accesses to pages with watchpoints go via the
> @@ -1888,24 +1904,18 @@ static void invalidate_and_set_dirty(hwaddr addr,
>  void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>                        int len, bool is_write)
>  {
> -    AddressSpaceDispatch *d = as->dispatch;
> -    int l;
> +    hwaddr l;
>      uint8_t *ptr;
>      uint32_t val;
> -    hwaddr page;
> +    hwaddr addr1;
>      MemoryRegionSection *section;
>
>      while (len > 0) {
> -        page = addr & TARGET_PAGE_MASK;
> -        l = (page + TARGET_PAGE_SIZE) - addr;
> -        if (l > len)
> -            l = len;
> -        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
> +        l = len;
> +        section = address_space_translate(as, addr, &addr1, &l, is_write);
>
Jan's "Rework sub-page handling" patch broke the tlb_set_page
(anything else?)  But I think we still need a function based on
address_space_translate to wrap the subpage logic inside and ease the
incoming RCU style.

Regards,
Pingfan
>          if (is_write) {
>              if (!memory_region_is_ram(section->mr)) {
> -                hwaddr addr1;
> -                addr1 = memory_region_section_addr(section, addr);
>                  /* XXX: could force cpu_single_env to NULL to avoid
>                     potential bugs */
>                  if (l >= 4 && ((addr1 & 3) == 0)) {
> @@ -1925,9 +1935,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>                      l = 1;
>                  }
>              } else if (!section->readonly) {
> -                ram_addr_t addr1;
> -                addr1 = memory_region_get_ram_addr(section->mr)
> -                    + memory_region_section_addr(section, addr);
> +                addr1 += memory_region_get_ram_addr(section->mr);
>                  /* RAM case */
>                  ptr = qemu_get_ram_ptr(addr1);
>                  memcpy(ptr, buf, l);
> @@ -1936,9 +1944,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>          } else {
>              if (!(memory_region_is_ram(section->mr) ||
>                    memory_region_is_romd(section->mr))) {
> -                hwaddr addr1;
>                  /* I/O case */
> -                addr1 = memory_region_section_addr(section, addr);
>                  if (l >= 4 && ((addr1 & 3) == 0)) {
>                      /* 32 bit read access */
>                      val = io_mem_read(section->mr, addr1, 4);
> @@ -1957,9 +1963,7 @@ void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>                  }
>              } else {
>                  /* RAM case */
> -                ptr = qemu_get_ram_ptr(section->mr->ram_addr
> -                                       + memory_region_section_addr(section,
> -                                                                    addr));
> +                ptr = qemu_get_ram_ptr(section->mr->ram_addr + addr1);
>                  memcpy(buf, ptr, l);
>              }
>          }
> @@ -1998,26 +2002,21 @@ void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
>  void cpu_physical_memory_write_rom(hwaddr addr,
>                                     const uint8_t *buf, int len)
>  {
> -    AddressSpaceDispatch *d = address_space_memory.dispatch;
> -    int l;
> +    hwaddr l;
>      uint8_t *ptr;
> -    hwaddr page;
> +    hwaddr addr1;
>      MemoryRegionSection *section;
>
>      while (len > 0) {
> -        page = addr & TARGET_PAGE_MASK;
> -        l = (page + TARGET_PAGE_SIZE) - addr;
> -        if (l > len)
> -            l = len;
> -        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
> +        l = len;
> +        section = address_space_translate(&address_space_memory,
> +                                          addr, &addr1, &l, true);
>
>          if (!(memory_region_is_ram(section->mr) ||
>                memory_region_is_romd(section->mr))) {
>              /* do nothing */
>          } else {
> -            unsigned long addr1;
> -            addr1 = memory_region_get_ram_addr(section->mr)
> -                + memory_region_section_addr(section, addr);
> +            addr1 += memory_region_get_ram_addr(section->mr);
>              /* ROM/RAM case */
>              ptr = qemu_get_ram_ptr(addr1);
>              memcpy(ptr, buf, l);
> @@ -2077,18 +2076,12 @@ static void cpu_notify_map_clients(void)
>
>  bool address_space_valid(AddressSpace *as, hwaddr addr, int len, bool is_write)
>  {
> -    AddressSpaceDispatch *d = as->dispatch;
>      MemoryRegionSection *section;
> -    int l;
> -    hwaddr page;
> +    hwaddr l, xlat;
>
>      while (len > 0) {
> -        page = addr & TARGET_PAGE_MASK;
> -        l = (page + TARGET_PAGE_SIZE) - addr;
> -        if (l > len) {
> -            l = len;
> -        }
> -        section = phys_page_find(d, addr >> TARGET_PAGE_BITS);
> +        l = len;
> +        section = address_space_translate(as, addr, &xlat, &l, is_write);
>          if (section->mr == &io_mem_unassigned ||
>              (is_write && section->mr->readonly)) {
>              return false;
> @@ -2112,22 +2105,17 @@ void *address_space_map(AddressSpace *as,
>                          hwaddr *plen,
>                          bool is_write)
>  {
> -    AddressSpaceDispatch *d = as->dispatch;
>      hwaddr len = *plen;
>      hwaddr todo = 0;
> -    int l;
> -    hwaddr page;
> +    hwaddr l, xlat;
>      MemoryRegionSection *section;
>      ram_addr_t raddr = RAM_ADDR_MAX;
>      ram_addr_t rlen;
>      void *ret;
>
>      while (len > 0) {
> -        page = addr & TARGET_PAGE_MASK;
> -        l = (page + TARGET_PAGE_SIZE) - addr;
> -        if (l > len)
> -            l = len;
> -        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
> +        l = len;
> +        section = address_space_translate(as, addr, &xlat, &l, is_write);
>
>          if (!(memory_region_is_ram(section->mr) && !section->readonly)) {
>              if (todo || bounce.buffer) {
> @@ -2144,8 +2132,11 @@ void *address_space_map(AddressSpace *as,
>              return bounce.buffer;
>          }
>          if (!todo) {
> -            raddr = memory_region_get_ram_addr(section->mr)
> -                + memory_region_section_addr(section, addr);
> +            raddr = memory_region_get_ram_addr(section->mr) + xlat;
> +        } else {
> +            if (memory_region_get_ram_addr(section->mr) + xlat != raddr + todo) {
> +                break;
> +            }
>          }
>
>          len -= l;
> @@ -2211,14 +2202,19 @@ static inline uint32_t ldl_phys_internal(hwaddr addr,
>      uint8_t *ptr;
>      uint32_t val;
>      MemoryRegionSection *section;
> +    hwaddr l = 4;
> +    hwaddr addr1;
>
> -    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
> +    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
> +                                      false);
> +    if (l < 4) {
> +        return unassigned_mem_read(NULL, addr, 4);
> +    }
>
>      if (!(memory_region_is_ram(section->mr) ||
>            memory_region_is_romd(section->mr))) {
>          /* I/O case */
> -        addr = memory_region_section_addr(section, addr);
> -        val = io_mem_read(section->mr, addr, 4);
> +        val = io_mem_read(section->mr, addr1, 4);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap32(val);
> @@ -2232,7 +2228,7 @@ static inline uint32_t ldl_phys_internal(hwaddr addr,
>          /* RAM case */
>          ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
>                                  & TARGET_PAGE_MASK)
> -                               + memory_region_section_addr(section, addr));
> +                               + addr1);
>          switch (endian) {
>          case DEVICE_LITTLE_ENDIAN:
>              val = ldl_le_p(ptr);
> @@ -2270,28 +2266,33 @@ static inline uint64_t ldq_phys_internal(hwaddr addr,
>      uint8_t *ptr;
>      uint64_t val;
>      MemoryRegionSection *section;
> +    hwaddr l = 8;
> +    hwaddr addr1;
>
> -    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
> +    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
> +                                      false);
> +    if (l < 8) {
> +        return unassigned_mem_read(NULL, addr, 8);
> +    }
>
>      if (!(memory_region_is_ram(section->mr) ||
>            memory_region_is_romd(section->mr))) {
>          /* I/O case */
> -        addr = memory_region_section_addr(section, addr);
>
>          /* XXX This is broken when device endian != cpu endian.
>                 Fix and add "endian" variable check */
>  #ifdef TARGET_WORDS_BIGENDIAN
> -        val = io_mem_read(section->mr, addr, 4) << 32;
> -        val |= io_mem_read(section->mr, addr + 4, 4);
> +        val = io_mem_read(section->mr, addr1, 4) << 32;
> +        val |= io_mem_read(section->mr, addr1 + 4, 4);
>  #else
> -        val = io_mem_read(section->mr, addr, 4);
> -        val |= io_mem_read(section->mr, addr + 4, 4) << 32;
> +        val = io_mem_read(section->mr, addr1, 4);
> +        val |= io_mem_read(section->mr, addr1 + 4, 4) << 32;
>  #endif
>      } else {
>          /* RAM case */
>          ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
>                                  & TARGET_PAGE_MASK)
> -                               + memory_region_section_addr(section, addr));
> +                               + addr1);
>          switch (endian) {
>          case DEVICE_LITTLE_ENDIAN:
>              val = ldq_le_p(ptr);
> @@ -2337,14 +2338,19 @@ static inline uint32_t lduw_phys_internal(hwaddr addr,
>      uint8_t *ptr;
>      uint64_t val;
>      MemoryRegionSection *section;
> +    hwaddr l = 2;
> +    hwaddr addr1;
>
> -    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
> +    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
> +                                      false);
> +    if (l < 2) {
> +        return unassigned_mem_read(NULL, addr, 2);
> +    }
>
>      if (!(memory_region_is_ram(section->mr) ||
>            memory_region_is_romd(section->mr))) {
>          /* I/O case */
> -        addr = memory_region_section_addr(section, addr);
> -        val = io_mem_read(section->mr, addr, 2);
> +        val = io_mem_read(section->mr, addr1, 2);
>  #if defined(TARGET_WORDS_BIGENDIAN)
>          if (endian == DEVICE_LITTLE_ENDIAN) {
>              val = bswap16(val);
> @@ -2358,7 +2364,7 @@ static inline uint32_t lduw_phys_internal(hwaddr addr,
>          /* RAM case */
>          ptr = qemu_get_ram_ptr((memory_region_get_ram_addr(section->mr)
>                                  & TARGET_PAGE_MASK)
> -                               + memory_region_section_addr(section, addr));
> +                               + addr1);
>          switch (endian) {
>          case DEVICE_LITTLE_ENDIAN:
>              val = lduw_le_p(ptr);
> @@ -2396,19 +2402,23 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val)
>  {
>      uint8_t *ptr;
>      MemoryRegionSection *section;
> +    hwaddr l = 4;
> +    hwaddr addr1;
>
> -    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
> +    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
> +                                      true);
> +    if (l < 4) {
> +        unassigned_mem_write(NULL, addr, val, 4);
> +        return;
> +    }
>
>      if (!memory_region_is_ram(section->mr) || section->readonly) {
> -        addr = memory_region_section_addr(section, addr);
>          if (memory_region_is_ram(section->mr)) {
>              section = &phys_sections[phys_section_rom];
>          }
> -        io_mem_write(section->mr, addr, val, 4);
> +        io_mem_write(section->mr, addr1, val, 4);
>      } else {
> -        unsigned long addr1 = (memory_region_get_ram_addr(section->mr)
> -                               & TARGET_PAGE_MASK)
> -            + memory_region_section_addr(section, addr);
> +        addr1 += memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK;
>          ptr = qemu_get_ram_ptr(addr1);
>          stl_p(ptr, val);
>
> @@ -2430,11 +2440,17 @@ static inline void stl_phys_internal(hwaddr addr, uint32_t val,
>  {
>      uint8_t *ptr;
>      MemoryRegionSection *section;
> +    hwaddr l = 4;
> +    hwaddr addr1;
>
> -    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
> +    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
> +                                      true);
> +    if (l < 4) {
> +        unassigned_mem_write(NULL, addr, val, 4);
> +        return;
> +    }
>
>      if (!memory_region_is_ram(section->mr) || section->readonly) {
> -        addr = memory_region_section_addr(section, addr);
>          if (memory_region_is_ram(section->mr)) {
>              section = &phys_sections[phys_section_rom];
>          }
> @@ -2447,12 +2463,10 @@ static inline void stl_phys_internal(hwaddr addr, uint32_t val,
>              val = bswap32(val);
>          }
>  #endif
> -        io_mem_write(section->mr, addr, val, 4);
> +        io_mem_write(section->mr, addr1, val, 4);
>      } else {
> -        unsigned long addr1;
> -        addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
> -            + memory_region_section_addr(section, addr);
>          /* RAM case */
> +        addr1 += memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK;
>          ptr = qemu_get_ram_ptr(addr1);
>          switch (endian) {
>          case DEVICE_LITTLE_ENDIAN:
> @@ -2497,11 +2511,17 @@ static inline void stw_phys_internal(hwaddr addr, uint32_t val,
>  {
>      uint8_t *ptr;
>      MemoryRegionSection *section;
> +    hwaddr l = 2;
> +    hwaddr addr1;
>
> -    section = phys_page_find(address_space_memory.dispatch, addr >> TARGET_PAGE_BITS);
> +    section = address_space_translate(&address_space_memory, addr, &addr1, &l,
> +                                      true);
> +    if (l < 2) {
> +        unassigned_mem_write(NULL, addr, val, 2);
> +        return;
> +    }
>
>      if (!memory_region_is_ram(section->mr) || section->readonly) {
> -        addr = memory_region_section_addr(section, addr);
>          if (memory_region_is_ram(section->mr)) {
>              section = &phys_sections[phys_section_rom];
>          }
> @@ -2514,12 +2534,10 @@ static inline void stw_phys_internal(hwaddr addr, uint32_t val,
>              val = bswap16(val);
>          }
>  #endif
> -        io_mem_write(section->mr, addr, val, 2);
> +        io_mem_write(section->mr, addr1, val, 2);
>      } else {
> -        unsigned long addr1;
> -        addr1 = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
> -            + memory_region_section_addr(section, addr);
>          /* RAM case */
> +        addr1 += memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK;
>          ptr = qemu_get_ram_ptr(addr1);
>          switch (endian) {
>          case DEVICE_LITTLE_ENDIAN:
> @@ -2622,9 +2640,10 @@ bool virtio_is_big_endian(void)
>  bool cpu_physical_memory_is_io(hwaddr phys_addr)
>  {
>      MemoryRegionSection *section;
> +    hwaddr l = 1;
>
> -    section = phys_page_find(address_space_memory.dispatch,
> -                             phys_addr >> TARGET_PAGE_BITS);
> +    section = address_space_translate(&address_space_memory,
> +                                      phys_addr, &phys_addr, &l, false);
>
>      return !(memory_region_is_ram(section->mr) ||
>               memory_region_is_romd(section->mr));
> diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h
> index 733c885..e821660 100644
> --- a/include/exec/cputlb.h
> +++ b/include/exec/cputlb.h
> @@ -26,8 +26,6 @@ void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
>                               target_ulong vaddr);
>  void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start,
>                             uintptr_t length);
> -MemoryRegionSection *phys_page_find(struct AddressSpaceDispatch *d,
> -                                    hwaddr index);
>  void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length);
>  void tlb_set_dirty(CPUArchState *env, target_ulong vaddr);
>  extern int tlb_flush_count;
> @@ -35,11 +33,11 @@ extern int tlb_flush_count;
>  /* exec.c */
>  void tb_flush_jmp_cache(CPUArchState *env, target_ulong addr);
>  hwaddr memory_region_section_get_iotlb(CPUArchState *env,
> -                                                   MemoryRegionSection *section,
> -                                                   target_ulong vaddr,
> -                                                   hwaddr paddr,
> -                                                   int prot,
> -                                                   target_ulong *address);
> +                                       MemoryRegionSection *section,
> +                                       target_ulong vaddr,
> +                                       hwaddr paddr, hwaddr xlat,
> +                                       int prot,
> +                                       target_ulong *address);
>  bool memory_region_is_unassigned(MemoryRegion *mr);
>
>  #endif
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 2e5fd11..809a958 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -743,23 +743,6 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr,
>                                         hwaddr addr, uint64_t size);
>
>  /**
> - * memory_region_section_addr: get offset within MemoryRegionSection
> - *
> - * Returns offset within MemoryRegionSection
> - *
> - * @section: the memory region section being queried
> - * @addr: address in address space
> - */
> -static inline hwaddr
> -memory_region_section_addr(MemoryRegionSection *section,
> -                           hwaddr addr)
> -{
> -    addr -= section->offset_within_address_space;
> -    addr += section->offset_within_region;
> -    return addr;
> -}
> -
> -/**
>   * address_space_sync_dirty_bitmap: synchronize the dirty log for all memory
>   *
>   * Synchronizes the dirty page log for an entire address space.
> @@ -860,6 +843,20 @@ void address_space_write(AddressSpace *as, hwaddr addr,
>   */
>  void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
>
> +/* address_space_translate: translate an address range into an address space
> + * into a MemoryRegionSection and an address range into that section
> + *
> + * @as: #AddressSpace to be accessed
> + * @addr: address within that address space
> + * @xlat: pointer to address within the returned memory region section's
> + * #MemoryRegion.
> + * @len: pointer to length
> + * @is_write: indicates the transfer direction
> + */
> +MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
> +                                             hwaddr *xlat, hwaddr *len,
> +                                             bool is_write);
> +
>  /* address_space_valid: check for validity of an address space range
>   *
>   * Check whether memory is assigned to the given address space range.
> diff --git a/translate-all.c b/translate-all.c
> index 0d84b0d..7a7d537 100644
> --- a/translate-all.c
> +++ b/translate-all.c
> @@ -1355,15 +1355,15 @@ void tb_invalidate_phys_addr(hwaddr addr)
>  {
>      ram_addr_t ram_addr;
>      MemoryRegionSection *section;
> +    hwaddr l = 1;
>
> -    section = phys_page_find(address_space_memory.dispatch,
> -                             addr >> TARGET_PAGE_BITS);
> +    section = address_space_translate(&address_space_memory, addr, &addr, &l, false);
>      if (!(memory_region_is_ram(section->mr)
>            || memory_region_is_romd(section->mr))) {
>          return;
>      }
>      ram_addr = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK)
> -        + memory_region_section_addr(section, addr);
> +        + addr;
>      tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
>  }
>  #endif /* TARGET_HAS_ICE && !defined(CONFIG_USER_ONLY) */
> --
> 1.8.1.4
>
>
>

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-23  7:09   ` liu ping fan
@ 2013-05-23  9:59     ` Paolo Bonzini
  2013-05-23 13:06       ` liu ping fan
  0 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-23  9:59 UTC (permalink / raw)
  To: liu ping fan; +Cc: peter.maydell, David Gibson, qemu-devel, jan.kiszka

Il 23/05/2013 09:09, liu ping fan ha scritto:
>> >  void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>> >                        int len, bool is_write)
>> >  {
>> > -    AddressSpaceDispatch *d = as->dispatch;
>> > -    int l;
>> > +    hwaddr l;
>> >      uint8_t *ptr;
>> >      uint32_t val;
>> > -    hwaddr page;
>> > +    hwaddr addr1;
>> >      MemoryRegionSection *section;
>> >
>> >      while (len > 0) {
>> > -        page = addr & TARGET_PAGE_MASK;
>> > -        l = (page + TARGET_PAGE_SIZE) - addr;
>> > -        if (l > len)
>> > -            l = len;
>> > -        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
>> > +        l = len;
>> > +        section = address_space_translate(as, addr, &addr1, &l, is_write);
>> >
> Jan's "Rework sub-page handling" patch broke the tlb_set_page
> (anything else?)  But I think we still need a function based on
> address_space_translate to wrap the subpage logic inside and ease the
> incoming RCU style.

The idea is that address_space_translate gets a ref to the MemoryRegion,
and the ref is then released by the caller of address_space_translate.

That means that the actual memory accesses can run outside the RCU
critical section.

But I'm not sure how that is related to subpage logic.  Subpages are
simply MemoryRegions that only exist in the phys page map, rather than
within an AddressSpace.  Their destruction will be delayed anyway by
doing call_rcu on the old phys page map.

Paolo

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 15/30] memory: add address_space_valid Paolo Bonzini
@ 2013-05-23 12:05   ` David Gibson
  2013-05-23 14:22     ` Jan Kiszka
  2013-05-23 18:04   ` Peter Maydell
  1 sibling, 1 reply; 106+ messages in thread
From: David Gibson @ 2013-05-23 12:05 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, qemu-devel, jan.kiszka

[-- Attachment #1: Type: text/plain, Size: 4386 bytes --]

On Tue, May 21, 2013 at 12:57:16PM +0200, Paolo Bonzini wrote:
> The old-style IOMMU lets you check whether an access is valid in a
> given DMAContext.  There is no equivalent for AddressSpace in the
> memory API, implement it with a lookup of the dispatch tree.

I don't love the name - "address_space_valid" suggests to me it tests
the validity of the whole address space, not a specific range.  But
an obviously better name doesn't quickly occur to me.

Obviously I like the functionality, since I wrote that into the
DMAContext stuff specifically to support the spapr_llan driver :).


> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  dma-helpers.c         |  5 +++++
>  exec.c                | 25 +++++++++++++++++++++++++
>  include/exec/memory.h | 14 ++++++++++++++
>  include/sysemu/dma.h  |  3 ++-
>  4 files changed, 46 insertions(+), 1 deletion(-)
> 
> diff --git a/dma-helpers.c b/dma-helpers.c
> index 272632f..2962b69 100644
> --- a/dma-helpers.c
> +++ b/dma-helpers.c
> @@ -298,6 +298,11 @@ bool iommu_dma_memory_valid(DMAContext *dma, dma_addr_t addr, dma_addr_t len,
>              plen = len;
>          }
>  
> +        if (!address_space_valid(dma->as, paddr, len,
> +                                 dir == DMA_DIRECTION_FROM_DEVICE)) {
> +            return false;
> +        }
> +
>          len -= plen;
>          addr += plen;
>      }
> diff --git a/exec.c b/exec.c
> index 8d91221..8f1b507 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2079,6 +2079,31 @@ static void cpu_notify_map_clients(void)
>      }
>  }
>  
> +bool address_space_valid(AddressSpace *as, hwaddr addr, int len, bool is_write)
> +{
> +    AddressSpaceDispatch *d = as->dispatch;
> +    MemoryRegionSection *section;
> +    int l;
> +    hwaddr page;
> +
> +    while (len > 0) {
> +        page = addr & TARGET_PAGE_MASK;
> +        l = (page + TARGET_PAGE_SIZE) - addr;
> +        if (l > len) {
> +            l = len;
> +        }
> +        section = phys_page_find(d, addr >> TARGET_PAGE_BITS);
> +        if (section->mr == &io_mem_unassigned ||
> +            (is_write && section->mr->readonly)) {
> +            return false;
> +        }
> +
> +        len -= l;
> +        addr += l;
> +    }
> +    return true;
> +}
> +
>  /* Map a physical memory region into a host virtual address.
>   * May map a subset of the requested range, given by and returned in *plen.
>   * May return NULL if resources needed to perform the mapping are exhausted.
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 6ed593c..2e5fd11 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -860,6 +860,20 @@ void address_space_write(AddressSpace *as, hwaddr addr,
>   */
>  void address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
>  
> +/* address_space_valid: check for validity of an address space range
> + *
> + * Check whether memory is assigned to the given address space range.
> + *
> + * For now, addr and len should be aligned to a page size.  This limitation
> + * will be lifted in the future.
> + *
> + * @as: #AddressSpace to be accessed
> + * @addr: address within that address space
> + * @len: length of the area to be checked
> + * @is_write: indicates the transfer direction
> + */
> +bool address_space_valid(AddressSpace *as, hwaddr addr, int len, bool is_write);
> +
>  /* address_space_map: map a physical memory region into a host virtual address
>   *
>   * May map a subset of the requested range, given by and returned in @plen.
> diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
> index a52c93a..2e239dc 100644
> --- a/include/sysemu/dma.h
> +++ b/include/sysemu/dma.h
> @@ -113,7 +113,8 @@ static inline bool dma_memory_valid(DMAContext *dma,
>                                      DMADirection dir)
>  {
>      if (!dma_has_iommu(dma)) {
> -        return true;
> +        return address_space_valid(dma->as, addr, len,
> +                                   dir == DMA_DIRECTION_FROM_DEVICE);
>      } else {
>          return iommu_dma_memory_valid(dma, addr, len, dir);
>      }

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-23  9:59     ` Paolo Bonzini
@ 2013-05-23 13:06       ` liu ping fan
  2013-05-23 13:17         ` Paolo Bonzini
  0 siblings, 1 reply; 106+ messages in thread
From: liu ping fan @ 2013-05-23 13:06 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, David Gibson, qemu-devel, jan.kiszka

On Thu, May 23, 2013 at 5:59 PM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 23/05/2013 09:09, liu ping fan ha scritto:
>>> >  void address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
>>> >                        int len, bool is_write)
>>> >  {
>>> > -    AddressSpaceDispatch *d = as->dispatch;
>>> > -    int l;
>>> > +    hwaddr l;
>>> >      uint8_t *ptr;
>>> >      uint32_t val;
>>> > -    hwaddr page;
>>> > +    hwaddr addr1;
>>> >      MemoryRegionSection *section;
>>> >
>>> >      while (len > 0) {
>>> > -        page = addr & TARGET_PAGE_MASK;
>>> > -        l = (page + TARGET_PAGE_SIZE) - addr;
>>> > -        if (l > len)
>>> > -            l = len;
>>> > -        section = phys_page_find(d, page >> TARGET_PAGE_BITS);
>>> > +        l = len;
>>> > +        section = address_space_translate(as, addr, &addr1, &l, is_write);
>>> >
>> Jan's "Rework sub-page handling" patch broke the tlb_set_page
>> (anything else?)  But I think we still need a function based on
>> address_space_translate to wrap the subpage logic inside and ease the
>> incoming RCU style.
>
> The idea is that address_space_translate gets a ref to the MemoryRegion,
> and the ref is then released by the caller of address_space_translate.
>
This will require subpage hold a reference to real mr. But I think it
is needless. Maybe when later in your these series, we will see how to
resolve it.  BTW,  do you target URCU patches to 1.6

Regards,
Pingfan

> That means that the actual memory accesses can run outside the RCU
> critical section.
>
> But I'm not sure how that is related to subpage logic.  Subpages are
> simply MemoryRegions that only exist in the phys page map, rather than
> within an AddressSpace.  Their destruction will be delayed anyway by
> doing call_rcu on the old phys page map.
>
> Paolo

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-23 13:06       ` liu ping fan
@ 2013-05-23 13:17         ` Paolo Bonzini
  0 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-23 13:17 UTC (permalink / raw)
  To: liu ping fan; +Cc: peter.maydell, David Gibson, qemu-devel, jan.kiszka

Il 23/05/2013 15:06, liu ping fan ha scritto:
>> The idea is that address_space_translate gets a ref to the MemoryRegion,
>> and the ref is then released by the caller of address_space_translate.
>>
> This will require subpage hold a reference to real mr.

Hmm, that's right.  Jan, that could be a concern when you update your
PIO series.

> But I think it
> is needless. Maybe when later in your these series, we will see how to
> resolve it.  BTW,  do you target URCU patches to 1.6

Yes.

Paolo

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-23 12:05   ` David Gibson
@ 2013-05-23 14:22     ` Jan Kiszka
  2013-05-23 14:43       ` Paolo Bonzini
  0 siblings, 1 reply; 106+ messages in thread
From: Jan Kiszka @ 2013-05-23 14:22 UTC (permalink / raw)
  To: David Gibson; +Cc: Paolo Bonzini, qemu-devel, peter.maydell

On 2013-05-23 14:05, David Gibson wrote:
> On Tue, May 21, 2013 at 12:57:16PM +0200, Paolo Bonzini wrote:
>> The old-style IOMMU lets you check whether an access is valid in a
>> given DMAContext.  There is no equivalent for AddressSpace in the
>> memory API, implement it with a lookup of the dispatch tree.
> 
> I don't love the name - "address_space_valid" suggests to me it tests
> the validity of the whole address space, not a specific range.  But
> an obviously better name doesn't quickly occur to me.

Not sure ATM if someone else suggested this earlier already, but what
about something like address_space_access_valid?

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-23 14:22     ` Jan Kiszka
@ 2013-05-23 14:43       ` Paolo Bonzini
  0 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-23 14:43 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: peter.maydell, qemu-devel, David Gibson

Il 23/05/2013 16:22, Jan Kiszka ha scritto:
>>> >> The old-style IOMMU lets you check whether an access is valid in a
>>> >> given DMAContext.  There is no equivalent for AddressSpace in the
>>> >> memory API, implement it with a lookup of the dispatch tree.
>> > 
>> > I don't love the name - "address_space_valid" suggests to me it tests
>> > the validity of the whole address space, not a specific range.  But
>> > an obviously better name doesn't quickly occur to me.
> Not sure ATM if someone else suggested this earlier already, but what
> about something like address_space_access_valid?

Sure.

Paolo

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

* Re: [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API
  2013-05-22  9:24   ` Paolo Bonzini
@ 2013-05-23 17:08     ` Paolo Bonzini
  2013-05-23 17:25       ` Peter Maydell
  2013-05-24 14:12       ` Alexey Kardashevskiy
  0 siblings, 2 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-23 17:08 UTC (permalink / raw)
  Cc: Alexey Kardashevskiy, peter.maydell, jan.kiszka, qemu-devel,
	David Gibson

Il 22/05/2013 11:24, Paolo Bonzini ha scritto:
> Il 22/05/2013 04:30, Alexey Kardashevskiy ha scritto:
>> On 05/21/2013 08:57 PM, Paolo Bonzini wrote:
>>> This is part 1 of the memory API updates for 1.6.  (Part 2 is the
>>> introduction of get/set_owner, part 3 is the introduction of the
>>> RCU-style flatview).
>>>
>>> Compared to the first submissions, there are a few extra cleanup
>>> patches, and address_space_rw/read/write grew a return value so
>>> that the existing DMAContext API doesn't need to change.
>>>
>>
>> Is this series much different from the one in
>> https://github.com/bonzini/qemu/tree/iommu (hope it is the same :) )?
> 
> Not much, I've updated the branch now.

BTW, if you give me your Tested-by it would be good, since most comments
have been cosmetic.  I'd like to collect all of Peter's Reviewed-by from
the RFC and send a pull request next week.

Then we can proceed with the fun stuff. :)

Paolo

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

* Re: [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API
  2013-05-23 17:08     ` Paolo Bonzini
@ 2013-05-23 17:25       ` Peter Maydell
  2013-05-23 17:30         ` Paolo Bonzini
  2013-05-23 18:47         ` Peter Maydell
  2013-05-24 14:12       ` Alexey Kardashevskiy
  1 sibling, 2 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 17:25 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Alexey Kardashevskiy, jan.kiszka, qemu-devel, David Gibson

On 23 May 2013 18:08, Paolo Bonzini <pbonzini@redhat.com> wrote:
> BTW, if you give me your Tested-by it would be good, since most comments
> have been cosmetic.  I'd like to collect all of Peter's Reviewed-by from
> the RFC and send a pull request next week.

There's been at least one requested fix in code review, so you
need to send out another series version first before you can
do a pullreq.

I'll have a look at the remaining patches now.

-- PMM

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

* Re: [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API
  2013-05-23 17:25       ` Peter Maydell
@ 2013-05-23 17:30         ` Paolo Bonzini
  2013-05-23 18:47         ` Peter Maydell
  1 sibling, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-23 17:30 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Alexey Kardashevskiy, David Gibson, qemu-devel, jan.kiszka

Il 23/05/2013 19:25, Peter Maydell ha scritto:
>> > BTW, if you give me your Tested-by it would be good, since most comments
>> > have been cosmetic.  I'd like to collect all of Peter's Reviewed-by from
>> > the RFC and send a pull request next week.
> There's been at least one requested fix in code review, so you
> need to send out another series version first before you can
> do a pullreq.

The only fix is s/address_space_valid/address_space_access_valid/, right?

Paolo

> I'll have a look at the remaining patches now.

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

* Re: [Qemu-devel] [PATCH 04/30] exec: eliminate stq_phys_notdirty
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 04/30] exec: eliminate stq_phys_notdirty Paolo Bonzini
@ 2013-05-23 17:32   ` Peter Maydell
  2013-05-23 19:18     ` Anthony Liguori
  2013-05-23 19:22     ` Paolo Bonzini
  0 siblings, 2 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 17:32 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> It is not used anywhere.

So does this get deleted just because it's not used, or because
it gets in the way of patches later in the series. As far as I
can tell the st*_phys_notdirty() are for TCG to update page
table entries with accessed/modified bits, and I don't see
any reason we wouldn't have targets that need to update a
64 bit page table descriptor rather than just 32 bits of it.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 05/30] memory: assert that PhysPageEntry's ptr does not overflow
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 05/30] memory: assert that PhysPageEntry's ptr does not overflow Paolo Bonzini
@ 2013-05-23 17:36   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 17:36 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> While sized to 15 bits in PhysPageEntry, the ptr field is ORed into the
> iotlb entries together with a page-aligned pointer.  The ptr field must
> not overflow into this page-aligned value, assert that it is smaller than
> the page size.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  exec.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/exec.c b/exec.c
> index 1355661..380245f 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -713,6 +713,8 @@ static void destroy_all_mappings(AddressSpaceDispatch *d)
>
>  static uint16_t phys_section_add(MemoryRegionSection *section)
>  {

You might consider having the rationale for the assert in a comment
here as well as in the commit log.

> +    assert(phys_sections_nb < TARGET_PAGE_SIZE);
> +
>      if (phys_sections_nb == phys_sections_nb_alloc) {
>          phys_sections_nb_alloc = MAX(phys_sections_nb_alloc * 2, 16);
>          phys_sections = g_renew(MemoryRegionSection, phys_sections,


Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 06/30] memory: allow memory_region_find() to run on non-root memory regions
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 06/30] memory: allow memory_region_find() to run on non-root memory regions Paolo Bonzini
@ 2013-05-23 17:52   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 17:52 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> memory_region_find() is similar to registering a MemoryListener and
> checking for the MemoryRegionSections that come from a particular
> region.  There is no reason for this to be limited to a root memory
> region.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  include/exec/memory.h | 13 +++++++------
>  memory.c              | 20 +++++++++++++++-----
>  2 files changed, 22 insertions(+), 11 deletions(-)
>
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 9e88320..efe210b 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -725,17 +725,18 @@ void memory_region_set_alias_offset(MemoryRegion *mr,
>   *
>   * Returns a #MemoryRegionSection that describes a contiguous overlap.
>   * It will have the following characteristics:
> - *    .@offset_within_address_space >= @addr
> - *    .@offset_within_address_space + .@size <= @addr + @size
>   *    .@size = 0 iff no overlap was found
>   *    .@mr is non-%NULL iff an overlap was found
>   *
> - * @address_space: a top-level (i.e. parentless) region that contains
> - *       the region to be found
> - * @addr: start of the area within @address_space to be searched
> + * If @mr has no parent, @addr is an absolute address in an AddressSpace, hence:
> + *    .@offset_within_address_space >= @addr
> + *    .@offset_within_address_space + .@size <= @addr + @size
> + *
> + * @mr: a MemoryRegion within which @addr is a relative address
> + * @addr: start of the area within @as to be searched
>   * @size: size of the area to be searched
>   */

You need to change the first para of the doc comment, which
still says @address_space. In fact the entire doc comment is
pretty confusing now. The code looks OK but I forget what the
rationale for this change is; it would be nice if the comment
was informative enough to remind me :-)

-- PMM

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 15/30] memory: add address_space_valid Paolo Bonzini
  2013-05-23 12:05   ` David Gibson
@ 2013-05-23 18:04   ` Peter Maydell
  2013-05-24  6:13     ` Jan Kiszka
  2013-05-24  8:02     ` Paolo Bonzini
  1 sibling, 2 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:04 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> +bool address_space_valid(AddressSpace *as, hwaddr addr, int len, bool is_write)
> +{
> +    AddressSpaceDispatch *d = as->dispatch;
> +    MemoryRegionSection *section;
> +    int l;
> +    hwaddr page;
> +
> +    while (len > 0) {
> +        page = addr & TARGET_PAGE_MASK;
> +        l = (page + TARGET_PAGE_SIZE) - addr;
> +        if (l > len) {
> +            l = len;
> +        }
> +        section = phys_page_find(d, addr >> TARGET_PAGE_BITS);
> +        if (section->mr == &io_mem_unassigned ||
> +            (is_write && section->mr->readonly)) {

It's kind of bogus that io_mem_unassigned is the only MemoryRegion
that can be unreadable. Why is 'readonly' a MemoryRegion attribute
and 'writeonly' not? Shouldn't we be calling the MemoryRegionOps
accepts() callback here? What about access alignment constraints
and access size restrictions? What if the validity of the range
changes between the time you asked and when you actually do the
access?

The whole API is kind of unconvincing really, especially since
the only thing we seem to use it for is some parameter checking
in spapr_llan.c (via a huge pile of intermediate wrappers).

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 16/30] memory: clean up phys_page_find
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 16/30] memory: clean up phys_page_find Paolo Bonzini
@ 2013-05-23 18:06   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:06 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Remove the goto.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 17/30] memory: add address_space_translate Paolo Bonzini
  2013-05-23  7:09   ` liu ping fan
@ 2013-05-23 18:15   ` Peter Maydell
  2013-05-25  6:40   ` Jan Kiszka
  2 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:15 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Using phys_page_find to translate an AddressSpace to a MemoryRegionSection
> is unwieldy.  It requires to pass the page index rather than the address,
> and later memory_region_section_addr has to be called.  Replace
> memory_region_section_addr with a function that does all of it: call
> phys_page_find, compute the offset within the region, and check how
> big the current mapping is.  This way, a large flat region can be written
> with a single lookup rather than a page at a time.
>
> address_space_translate will also provide a single point where IOMMU
> forwarding is implemented.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

4 overlength lines in this patch. Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 18/30] memory: add return value to address_space_rw/read/write
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 18/30] memory: add return value to address_space_rw/read/write Paolo Bonzini
@ 2013-05-23 18:18   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:18 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 19/30] memory: Introduce address_space_lookup_region
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 19/30] memory: Introduce address_space_lookup_region Paolo Bonzini
@ 2013-05-23 18:19   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:19 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Jan Kiszka, jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> From: Jan Kiszka <jan.kiszka@siemens.com>
>
> This introduces a wrapper for phys_page_find (before we complicate
> address_space_translate with IOMMU translation).  This function will
> also encapsulate locking and reference counting when we introduce
> BQL-free dispatching.
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 20/30] memory: iommu support
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 20/30] memory: iommu support Paolo Bonzini
@ 2013-05-23 18:24   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:24 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, Avi Kivity, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> From: Avi Kivity <avi.kivity@gmail.com>
>
> Add a new memory region type that translates addresses it is given,
> then forwards them to a target address space.  This is similar to
> an alias, except that the mapping is more flexible than a linear
> translation and trucation, and also less efficient since the
> translation happens at runtime.
>
> The implementation uses an AddressSpace mapping the target region to
> avoid hierarchical dispatch all the way to the resolved region; only
> iommu regions are looked up dynamically.
>
> Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
> [Modified to put translation in address_space_translate - Paolo]
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

More overlong lines here, and these are in comments so trivial
to avoid.

>  /**
> + * memory_region_is_iommu: check whether a memory region is an iommu
> + *
> + * Returns %true is a memory region is an iommu.

"s/is/if/"

>
> +void memory_region_init_iommu(MemoryRegion *mr,
> +                              MemoryRegionIOMMUOps *ops,
> +                              AddressSpace *target_as,
> +                              const char *name,
> +                              uint64_t size)
> +{
> +    memory_region_init(mr, name, size);
> +    mr->ops = NULL;
> +    mr->iommu_ops = ops,
> +    mr->opaque = mr;
> +    mr->terminates = true;  /* then re-forwards */
> +    mr->destructor = memory_region_destructor_none;

destructor_none is the default, you don't need to set it again.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 21/30] memory: Add iommu map/unmap notifiers
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 21/30] memory: Add iommu map/unmap notifiers Paolo Bonzini
@ 2013-05-23 18:27   ` Peter Maydell
  2013-05-23 19:24     ` Paolo Bonzini
  0 siblings, 1 reply; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:27 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> From: David Gibson <david@gibson.dropbear.id.au>
>
> This patch adds a NotifierList to MemoryRegions which represent IOMMUs
> allowing other parts of the code to register interest in mappings or
> unmappings from the IOMMU.  All IOMMU implementations will need to call
> memory_region_notify_iommu() to inform those waiting on the notifier list,
> whenever an IOMMU mapping is made or removed.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> @@ -423,6 +425,11 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
>   */
>  bool memory_region_is_iommu(MemoryRegion *mr);
>
> +void memory_region_notify_iommu(MemoryRegion *mr,
> +                                IOMMUTLBEntry entry);
> +void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n);
> +void memory_region_unregister_iommu_notifier(Notifier *n);

These all need doc comments.

The code looks good.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 26/30] dma: eliminate old-style IOMMU support
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 26/30] dma: eliminate old-style IOMMU support Paolo Bonzini
@ 2013-05-23 18:31   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:31 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> The translate function in the DMAContext is now always NULL.
> Remove every reference to it.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

More long lines. Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 27/30] pci: use memory core for iommu support
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 27/30] pci: use memory core for iommu support Paolo Bonzini
@ 2013-05-23 18:36   ` Peter Maydell
  2013-05-23 21:22   ` Michael S. Tsirkin
  1 sibling, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:36 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: jan.kiszka, Michael S. Tsirkin, qemu-devel, Avi Kivity, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> From: Avi Kivity <avi.kivity@gmail.com>
>
> Use the new iommu support in the memory core for iommu support.  The only
> user, spapr, is also converted, but it still provides a DMAContext
> interface until the non-PCI bits switch to AddressSpace.
>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
> [ Do not calls memory_region_del_subregion() on the device's
>   bus_master_enable_region, it is an alias; return an AddressSpace
>   from the IOMMU hook and remove the destructor hook. - David Gibson ]
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

More >80column excesses. Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 29/30] dma: eliminate DMAContext
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 29/30] dma: eliminate DMAContext Paolo Bonzini
@ 2013-05-23 18:40   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:40 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> The DMAContext is a simple pointer to an AddressSpace that is now always
> already available.  Make everyone hold the address space directly,
> and clean up the DMA API to use the AddressSpace directly.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Hey look, checkpatch is complaining again. Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

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

* Re: [Qemu-devel] [PATCH 30/30] memory: give name to every AddressSpace
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 30/30] memory: give name to every AddressSpace Paolo Bonzini
@ 2013-05-23 18:46   ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:46 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Alexey Kardashevskiy, jan.kiszka, qemu-devel, David Gibson

On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> From: Alexey Kardashevskiy <aik@ozlabs.ru>
>
> The "info mtree" command in QEMU console prints only "memory" and "I/O"
> address spaces while there are actually a lot more other AddressSpace
> structs created by PCI and VIO devices. Those devices do not normally
> have names and therefore not present in "info mtree" output.

> @@ -815,7 +815,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>      memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master",
>                               dma_as->root, 0, memory_region_size(dma_as->root));
>      memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
> -    address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
> +    address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region,
> +                       name);

Overlong line.

> @@ -858,8 +858,9 @@ void mtree_info(fprintf_function mon_printf, void *f);
>   *
>   * @as: an uninitialized #AddressSpace
>   * @root: a #MemoryRegion that routes addesses for the address space
> + * @name: an address space name

Does this need to be a unique name? Does it matter if it changes?
(compare/contrast the documentation of memory_region_init()'s name param)

>   */
> -void address_space_init(AddressSpace *as, MemoryRegion *root);
> +void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name);
>
>
>  /**
> diff --git a/memory.c b/memory.c
> index e3970bf..66258e2 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -1605,7 +1605,7 @@ void memory_listener_unregister(MemoryListener *listener)
>      QTAILQ_REMOVE(&memory_listeners, listener, link);
>  }
>
> -void address_space_init(AddressSpace *as, MemoryRegion *root)
> +void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
>  {
>      memory_region_transaction_begin();
>      as->root = root;
> @@ -1614,7 +1614,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root)
>      as->ioeventfd_nb = 0;
>      as->ioeventfds = NULL;
>      QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
> -    as->name = NULL;
> +    as->name = g_strdup(name?name:"anonymous");

This needs spaces round the ? and :.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API
  2013-05-23 17:25       ` Peter Maydell
  2013-05-23 17:30         ` Paolo Bonzini
@ 2013-05-23 18:47         ` Peter Maydell
  1 sibling, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 18:47 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Alexey Kardashevskiy, jan.kiszka, qemu-devel, David Gibson

On 23 May 2013 18:25, Peter Maydell <peter.maydell@linaro.org> wrote:
> I'll have a look at the remaining patches now.

...and done. I haven't reviewed the spapr specific stuff,
on the assumption that somebody familiar with that h/w
will do so.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 04/30] exec: eliminate stq_phys_notdirty
  2013-05-23 17:32   ` Peter Maydell
@ 2013-05-23 19:18     ` Anthony Liguori
  2013-05-23 19:22     ` Paolo Bonzini
  1 sibling, 0 replies; 106+ messages in thread
From: Anthony Liguori @ 2013-05-23 19:18 UTC (permalink / raw)
  To: Peter Maydell, Paolo Bonzini; +Cc: David Gibson, qemu-devel, jan.kiszka

Peter Maydell <peter.maydell@linaro.org> writes:

> On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> It is not used anywhere.
>
> So does this get deleted just because it's not used, or because
> it gets in the way of patches later in the series. As far as I
> can tell the st*_phys_notdirty() are for TCG to update page
> table entries with accessed/modified bits, and I don't see
> any reason we wouldn't have targets that need to update a
> 64 bit page table descriptor rather than just 32 bits of it.

Unused code is untested code.  Untested code is broken code.

Someone can add it back later if it's ever needed.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori


>
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH 04/30] exec: eliminate stq_phys_notdirty
  2013-05-23 17:32   ` Peter Maydell
  2013-05-23 19:18     ` Anthony Liguori
@ 2013-05-23 19:22     ` Paolo Bonzini
  2013-05-23 23:14       ` Peter Maydell
  1 sibling, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-23 19:22 UTC (permalink / raw)
  To: Peter Maydell; +Cc: David Gibson, qemu-devel, jan.kiszka

Il 23/05/2013 19:32, Peter Maydell ha scritto:
> On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> > It is not used anywhere.
> So does this get deleted just because it's not used, or because
> it gets in the way of patches later in the series. 

No, it doesn't get in the way, I just preferred to kill it rather than
have an untested conversion.

Paolo

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

* Re: [Qemu-devel] [PATCH 21/30] memory: Add iommu map/unmap notifiers
  2013-05-23 18:27   ` Peter Maydell
@ 2013-05-23 19:24     ` Paolo Bonzini
  2013-05-29  4:08       ` David Gibson
  0 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-23 19:24 UTC (permalink / raw)
  To: Peter Maydell; +Cc: David Gibson, qemu-devel, jan.kiszka

Il 23/05/2013 20:27, Peter Maydell ha scritto:
> On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> From: David Gibson <david@gibson.dropbear.id.au>
>>
>> This patch adds a NotifierList to MemoryRegions which represent IOMMUs
>> allowing other parts of the code to register interest in mappings or
>> unmappings from the IOMMU.  All IOMMU implementations will need to call
>> memory_region_notify_iommu() to inform those waiting on the notifier list,
>> whenever an IOMMU mapping is made or removed.
>>
>> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>> @@ -423,6 +425,11 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
>>   */
>>  bool memory_region_is_iommu(MemoryRegion *mr);
>>
>> +void memory_region_notify_iommu(MemoryRegion *mr,
>> +                                IOMMUTLBEntry entry);
>> +void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n);
>> +void memory_region_unregister_iommu_notifier(Notifier *n);
> 
> These all need doc comments.

David, can you provide them?  (If not as a patch, just an inline reply
to this email will do).

Paolo

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

* Re: [Qemu-devel] [PATCH 27/30] pci: use memory core for iommu support
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 27/30] pci: use memory core for iommu support Paolo Bonzini
  2013-05-23 18:36   ` Peter Maydell
@ 2013-05-23 21:22   ` Michael S. Tsirkin
  1 sibling, 0 replies; 106+ messages in thread
From: Michael S. Tsirkin @ 2013-05-23 21:22 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: peter.maydell, jan.kiszka, qemu-devel, Avi Kivity, David Gibson

On Tue, May 21, 2013 at 12:57:28PM +0200, Paolo Bonzini wrote:
> From: Avi Kivity <avi.kivity@gmail.com>
> 
> Use the new iommu support in the memory core for iommu support.  The only
> user, spapr, is also converted, but it still provides a DMAContext
> interface until the non-PCI bits switch to AddressSpace.
> 
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Avi Kivity <avi.kivity@gmail.com>
> [ Do not calls memory_region_del_subregion() on the device's
>   bus_master_enable_region, it is an alias; return an AddressSpace
>   from the IOMMU hook and remove the destructor hook. - David Gibson ]
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Looks good to me.
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  hw/pci/pci.c                | 46 ++++++++++++++++++++++-----------------------
>  hw/ppc/spapr_pci.c          |  9 +++++----
>  include/hw/pci-host/spapr.h |  1 +
>  include/hw/pci/pci.h        |  4 ++--
>  include/hw/pci/pci_bus.h    |  4 ++--
>  5 files changed, 33 insertions(+), 31 deletions(-)
> 
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index c9d585c..9e6bd77 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -279,6 +279,12 @@ int pci_find_domain(const PCIBus *bus)
>      return -1;
>  }
>  
> +static AddressSpace *pci_default_address_space(PCIBus *bus, void *opaque, int devfn)
> +{
> +    /* FIXME: inherit memory region from bus creator */
> +    return &address_space_memory;
> +}
> +
>  static void pci_bus_init(PCIBus *bus, DeviceState *parent,
>                           const char *name,
>                           MemoryRegion *address_space_mem,
> @@ -289,6 +295,7 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent,
>      bus->devfn_min = devfn_min;
>      bus->address_space_mem = address_space_mem;
>      bus->address_space_io = address_space_io;
> +    pci_setup_iommu(bus, pci_default_address_space, NULL);
>  
>      /* host bridge */
>      QLIST_INIT(&bus->child);
> @@ -786,6 +793,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>      PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
>      PCIConfigReadFunc *config_read = pc->config_read;
>      PCIConfigWriteFunc *config_write = pc->config_write;
> +    AddressSpace *dma_as;
>  
>      if (devfn < 0) {
>          for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);
> @@ -801,21 +809,15 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
>                       PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name);
>          return NULL;
>      }
> +
>      pci_dev->bus = bus;
> -    if (bus->dma_context_fn) {
> -        pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, devfn);
> -    } else {
> -        /* FIXME: Make dma_context_fn use MemoryRegions instead, so this path is
> -         * taken unconditionally */
> -        /* FIXME: inherit memory region from bus creator */
> -        memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master",
> -                                 get_system_memory(), 0,
> -                                 memory_region_size(get_system_memory()));
> -        memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
> -        address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
> -        pci_dev->dma = g_new(DMAContext, 1);
> -        dma_context_init(pci_dev->dma, &pci_dev->bus_master_as);
> -    }
> +    dma_as = bus->iommu_fn(bus, bus->iommu_opaque, devfn);
> +    memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master",
> +                             dma_as->root, 0, memory_region_size(dma_as->root));
> +    memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);
> +    address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region);
> +    pci_dev->dma = g_new(DMAContext, 1);
> +    dma_context_init(pci_dev->dma, &pci_dev->bus_master_as);
>  
>      pci_dev->devfn = devfn;
>      pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
> @@ -870,12 +872,10 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
>      pci_dev->bus->devices[pci_dev->devfn] = NULL;
>      pci_config_free(pci_dev);
>  
> -    if (!pci_dev->bus->dma_context_fn) {
> -        address_space_destroy(&pci_dev->bus_master_as);
> -        memory_region_destroy(&pci_dev->bus_master_enable_region);
> -        g_free(pci_dev->dma);
> -        pci_dev->dma = NULL;
> -    }
> +    address_space_destroy(&pci_dev->bus_master_as);
> +    memory_region_destroy(&pci_dev->bus_master_enable_region);
> +    g_free(pci_dev->dma);
> +    pci_dev->dma = NULL;
>  }
>  
>  static void pci_unregister_io_regions(PCIDevice *pci_dev)
> @@ -2232,10 +2232,10 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
>      k->props = pci_props;
>  }
>  
> -void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque)
> +void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
>  {
> -    bus->dma_context_fn = fn;
> -    bus->dma_context_opaque = opaque;
> +    bus->iommu_fn = fn;
> +    bus->iommu_opaque = opaque;
>  }
>  
>  static const TypeInfo pci_device_type_info = {
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index eb64a8f..762db62 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -506,12 +506,11 @@ static const MemoryRegionOps spapr_msi_ops = {
>  /*
>   * PHB PCI device
>   */
> -static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque,
> -                                            int devfn)
> +static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>  {
>      sPAPRPHBState *phb = opaque;
>  
> -    return spapr_tce_get_dma(phb->tcet);
> +    return &phb->iommu_as;
>  }
>  
>  static int spapr_phb_init(SysBusDevice *s)
> @@ -651,7 +650,9 @@ static int spapr_phb_init(SysBusDevice *s)
>          fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
>          return -1;
>      }
> -    pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb);
> +    address_space_init(&sphb->iommu_as, spapr_tce_get_iommu(sphb->tcet),
> +                       sphb->dtbusname);
> +    pci_setup_iommu(bus, spapr_pci_dma_iommu, sphb);
>  
>      QLIST_INSERT_HEAD(&spapr->phbs, sphb, list);
>  
> diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
> index 653dd40..1e23dbf 100644
> --- a/include/hw/pci-host/spapr.h
> +++ b/include/hw/pci-host/spapr.h
> @@ -50,6 +50,7 @@ typedef struct sPAPRPHBState {
>      uint64_t dma_window_start;
>      uint64_t dma_window_size;
>      sPAPRTCETable *tcet;
> +    AddressSpace iommu_as;
>  
>      struct {
>          uint32_t irq;
> diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
> index 8d075ab..3a85bce 100644
> --- a/include/hw/pci/pci.h
> +++ b/include/hw/pci/pci.h
> @@ -401,9 +401,9 @@ int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
>  
>  void pci_device_deassert_intx(PCIDevice *dev);
>  
> -typedef DMAContext *(*PCIDMAContextFunc)(PCIBus *, void *, int);
> +typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int);
>  
> -void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque);
> +void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque);
>  
>  static inline void
>  pci_set_byte(uint8_t *config, uint8_t val)
> diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h
> index 6ee443c..66762f6 100644
> --- a/include/hw/pci/pci_bus.h
> +++ b/include/hw/pci/pci_bus.h
> @@ -10,8 +10,8 @@
>  
>  struct PCIBus {
>      BusState qbus;
> -    PCIDMAContextFunc dma_context_fn;
> -    void *dma_context_opaque;
> +    PCIIOMMUFunc iommu_fn;
> +    void *iommu_opaque;
>      uint8_t devfn_min;
>      pci_set_irq_fn set_irq;
>      pci_map_irq_fn map_irq;
> -- 
> 1.8.1.4
> 

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

* Re: [Qemu-devel] [PATCH 04/30] exec: eliminate stq_phys_notdirty
  2013-05-23 19:22     ` Paolo Bonzini
@ 2013-05-23 23:14       ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-23 23:14 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: David Gibson, qemu-devel, jan.kiszka

On 23 May 2013 20:22, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 23/05/2013 19:32, Peter Maydell ha scritto:
>> On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>> > It is not used anywhere.
>> So does this get deleted just because it's not used, or because
>> it gets in the way of patches later in the series.
>
> No, it doesn't get in the way, I just preferred to kill it rather than
> have an untested conversion.

Fair enough -- we can always put it back again if we need it.

-- PMM

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-23 18:04   ` Peter Maydell
@ 2013-05-24  6:13     ` Jan Kiszka
  2013-05-24 10:28       ` Jan Kiszka
  2013-05-24 10:50       ` Peter Maydell
  2013-05-24  8:02     ` Paolo Bonzini
  1 sibling, 2 replies; 106+ messages in thread
From: Jan Kiszka @ 2013-05-24  6:13 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Paolo Bonzini, qemu-devel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 1405 bytes --]

On 2013-05-23 20:04, Peter Maydell wrote:
> On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> +bool address_space_valid(AddressSpace *as, hwaddr addr, int len, bool is_write)
>> +{
>> +    AddressSpaceDispatch *d = as->dispatch;
>> +    MemoryRegionSection *section;
>> +    int l;
>> +    hwaddr page;
>> +
>> +    while (len > 0) {
>> +        page = addr & TARGET_PAGE_MASK;
>> +        l = (page + TARGET_PAGE_SIZE) - addr;
>> +        if (l > len) {
>> +            l = len;
>> +        }
>> +        section = phys_page_find(d, addr >> TARGET_PAGE_BITS);
>> +        if (section->mr == &io_mem_unassigned ||
>> +            (is_write && section->mr->readonly)) {
> 
> It's kind of bogus that io_mem_unassigned is the only MemoryRegion
> that can be unreadable. Why is 'readonly' a MemoryRegion attribute
> and 'writeonly' not? Shouldn't we be calling the MemoryRegionOps
> accepts() callback here? What about access alignment constraints
> and access size restrictions? What if the validity of the range
> changes between the time you asked and when you actually do the
> access?
> 
> The whole API is kind of unconvincing really, especially since
> the only thing we seem to use it for is some parameter checking
> in spapr_llan.c (via a huge pile of intermediate wrappers).

I'll also have a use for it: replace isa_is_ioport_assigned.

Jan



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-23 18:04   ` Peter Maydell
  2013-05-24  6:13     ` Jan Kiszka
@ 2013-05-24  8:02     ` Paolo Bonzini
  2013-05-24 10:52       ` Peter Maydell
  1 sibling, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-24  8:02 UTC (permalink / raw)
  To: Peter Maydell; +Cc: David Gibson, qemu-devel, jan.kiszka

Il 23/05/2013 20:04, Peter Maydell ha scritto:
> Shouldn't we be calling the MemoryRegionOps
> accepts() callback here? What about access alignment constraints
> and access size restrictions?

Yes, we should.

> What if the validity of the range
> changes between the time you asked and when you actually do the
> access?

If that's a concern, you shouldn't use this API, you should just do the
access and rely on the return value of address_space_rw & friends.

(Or, at least for the foreseeable future, do the checks under the BQL).

Paolo

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-24  6:13     ` Jan Kiszka
@ 2013-05-24 10:28       ` Jan Kiszka
  2013-05-24 10:50       ` Peter Maydell
  1 sibling, 0 replies; 106+ messages in thread
From: Jan Kiszka @ 2013-05-24 10:28 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Peter Maydell, qemu-devel, David Gibson

On 2013-05-24 08:13, Jan Kiszka wrote:
> On 2013-05-23 20:04, Peter Maydell wrote:
>> On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>> +bool address_space_valid(AddressSpace *as, hwaddr addr, int len, bool is_write)
>>> +{
>>> +    AddressSpaceDispatch *d = as->dispatch;
>>> +    MemoryRegionSection *section;
>>> +    int l;
>>> +    hwaddr page;
>>> +
>>> +    while (len > 0) {
>>> +        page = addr & TARGET_PAGE_MASK;
>>> +        l = (page + TARGET_PAGE_SIZE) - addr;
>>> +        if (l > len) {
>>> +            l = len;
>>> +        }
>>> +        section = phys_page_find(d, addr >> TARGET_PAGE_BITS);
>>> +        if (section->mr == &io_mem_unassigned ||
>>> +            (is_write && section->mr->readonly)) {
>>
>> It's kind of bogus that io_mem_unassigned is the only MemoryRegion
>> that can be unreadable. Why is 'readonly' a MemoryRegion attribute
>> and 'writeonly' not? Shouldn't we be calling the MemoryRegionOps
>> accepts() callback here? What about access alignment constraints
>> and access size restrictions? What if the validity of the range
>> changes between the time you asked and when you actually do the
>> access?
>>
>> The whole API is kind of unconvincing really, especially since
>> the only thing we seem to use it for is some parameter checking
>> in spapr_llan.c (via a huge pile of intermediate wrappers).
> 
> I'll also have a use for it: replace isa_is_ioport_assigned.

But for this use case, something like
memory_region_access_valid(MemoryRegion *, ...) would be more helpful
because pci_address_space_io returns a memory region, not an address
space. Can we change it? dma_memory_valid could simply pass the address
space's root region.

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-24  6:13     ` Jan Kiszka
  2013-05-24 10:28       ` Jan Kiszka
@ 2013-05-24 10:50       ` Peter Maydell
  2013-05-24 11:02         ` Jan Kiszka
  1 sibling, 1 reply; 106+ messages in thread
From: Peter Maydell @ 2013-05-24 10:50 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Paolo Bonzini, qemu-devel, David Gibson

On 24 May 2013 07:13, Jan Kiszka <jan.kiszka@web.de> wrote:
> I'll also have a use for it: replace isa_is_ioport_assigned.

That seems like it's something different: it's asking
"has some other bit of QEMU registered a handler for
this ioport?", not "at this moment in time if I make
an I/O access will it succeed?" (which in principle
should actually go all the way through and call a
registered ioport handler which might then say "no,
for this specific access we will fail").

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-24  8:02     ` Paolo Bonzini
@ 2013-05-24 10:52       ` Peter Maydell
  2013-05-24 12:58         ` Paolo Bonzini
  2013-05-25  3:44         ` David Gibson
  0 siblings, 2 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-24 10:52 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: David Gibson, qemu-devel, jan.kiszka

On 24 May 2013 09:02, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 23/05/2013 20:04, Peter Maydell ha scritto:
>> Shouldn't we be calling the MemoryRegionOps
>> accepts() callback here? What about access alignment constraints
>> and access size restrictions?
>
> Yes, we should.
>
>> What if the validity of the range
>> changes between the time you asked and when you actually do the
>> access?
>
> If that's a concern, you shouldn't use this API, you should just do the
> access and rely on the return value of address_space_rw & friends.

So when *is* it a good idea to use this API? In real
hardware you don't usually get a "tell me whether this
access would succeed if I did it" bus operation -- you
just do the operation and the memory transaction either
succeeds or it doesn't. Are we modelling something that
really exists in hardware on spapr here?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-24 10:50       ` Peter Maydell
@ 2013-05-24 11:02         ` Jan Kiszka
  0 siblings, 0 replies; 106+ messages in thread
From: Jan Kiszka @ 2013-05-24 11:02 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Paolo Bonzini, qemu-devel, David Gibson

On 2013-05-24 12:50, Peter Maydell wrote:
> On 24 May 2013 07:13, Jan Kiszka <jan.kiszka@web.de> wrote:
>> I'll also have a use for it: replace isa_is_ioport_assigned.
> 
> That seems like it's something different: it's asking
> "has some other bit of QEMU registered a handler for
> this ioport?", not "at this moment in time if I make
> an I/O access will it succeed?" (which in principle
> should actually go all the way through and call a
> registered ioport handler which might then say "no,
> for this specific access we will fail").

Hmm... Paolo suggested to use it. But given the current arguments I
guess it's better to stick with memory_region_find for that purpose.

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-24 10:52       ` Peter Maydell
@ 2013-05-24 12:58         ` Paolo Bonzini
  2013-05-24 13:27           ` Peter Maydell
  2013-05-25  3:44         ` David Gibson
  1 sibling, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-24 12:58 UTC (permalink / raw)
  To: Peter Maydell; +Cc: David Gibson, qemu-devel, jan.kiszka

Il 24/05/2013 12:52, Peter Maydell ha scritto:
> On 24 May 2013 09:02, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> Il 23/05/2013 20:04, Peter Maydell ha scritto:
>>> Shouldn't we be calling the MemoryRegionOps
>>> accepts() callback here? What about access alignment constraints
>>> and access size restrictions?
>>
>> Yes, we should.
>>
>>> What if the validity of the range
>>> changes between the time you asked and when you actually do the
>>> access?
>>
>> If that's a concern, you shouldn't use this API, you should just do the
>> access and rely on the return value of address_space_rw & friends.
> 
> So when *is* it a good idea to use this API? In real
> hardware you don't usually get a "tell me whether this
> access would succeed if I did it" bus operation -- you
> just do the operation and the memory transaction either
> succeeds or it doesn't. Are we modelling something that
> really exists in hardware on spapr here?

Well, sPAPR is not hardware. :)  It is a paravirtualized interface.

Anyhow, I can eliminate all the references to unassigned and basically
do this:

bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_write)
{
    MemoryRegionSection *section;
    hwaddr l, xlat;

    while (len > 0) {
        l = len;
        section = address_space_translate(as, addr, &xlat, &l, is_write);
        if (!memory_access_is_direct(section->mr, is_write)) {
            l = memory_access_size(l, addr);
            if (!memory_region_access_valid(section->mr, addr1, l) {
                return false;
            }
        }

        len -= l;
        addr += l;
    }
    return true;
}

It requires some more changes however.  I'll drop this patch.  If it's okay
for you, I'll send a pull request up to "memory: clean up phys_page_find"
and go on with the next series.

Paolo

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-24 12:58         ` Paolo Bonzini
@ 2013-05-24 13:27           ` Peter Maydell
  2013-05-24 13:33             ` Paolo Bonzini
  0 siblings, 1 reply; 106+ messages in thread
From: Peter Maydell @ 2013-05-24 13:27 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: David Gibson, qemu-devel, jan.kiszka

On 24 May 2013 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
> If it's okay
> for you, I'll send a pull request up to "memory: clean up phys_page_find"
> and go on with the next series.

That's fine with me, but please don't forget to fix up
the doc comment for memory_region_find() (see comments on
patch 6/30). You can do that in a patch in the next series,
though, I guess.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-24 13:27           ` Peter Maydell
@ 2013-05-24 13:33             ` Paolo Bonzini
  2013-05-24 13:38               ` Peter Maydell
  0 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-24 13:33 UTC (permalink / raw)
  To: Peter Maydell; +Cc: David Gibson, qemu-devel, jan.kiszka

Il 24/05/2013 15:27, Peter Maydell ha scritto:
> On 24 May 2013 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> If it's okay
>> for you, I'll send a pull request up to "memory: clean up phys_page_find"
>> and go on with the next series.
> 
> That's fine with me, but please don't forget to fix up
> the doc comment for memory_region_find() (see comments on
> patch 6/30). You can do that in a patch in the next series,
> though, I guess.

What about this:

/**
 * memory_region_find: translate an address/size relative to a
 * MemoryRegion into a #MemoryRegionSection.
 *
 * Locates the first #MemoryRegion within @mr that overlaps the range
 * given by @addr and @size.
 *
 * Returns a #MemoryRegionSection that describes a contiguous overlap.
 * It will have the following characteristics:
 *    .@size = 0 iff no overlap was found
 *    .@mr is non-%NULL iff an overlap was found
 *
 * Remember that in the return value the @offset_within_region is
 * relative to the returned region (in the .@mr field), not to the
 * @mr argument.
 *
 * Similarly, the .@offset_within_address_space is relative to the
 * address space that contains both regions, the passed and the
 * returned one.  However, in the special case where the @mr argument
 * has no parent (and thus is the root of the address space), the
 * following will hold:
 *    .@offset_within_address_space >= @addr
 *    .@offset_within_address_space + .@size <= @addr + @size
 *
 * @mr: a MemoryRegion within which @addr is a relative address
 * @addr: start of the area within @as to be searched
 * @size: size of the area to be searched
 */

?
Paolo

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-24 13:33             ` Paolo Bonzini
@ 2013-05-24 13:38               ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-24 13:38 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: David Gibson, qemu-devel, jan.kiszka

On 24 May 2013 14:33, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 24/05/2013 15:27, Peter Maydell ha scritto:
>> On 24 May 2013 13:58, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>> If it's okay
>>> for you, I'll send a pull request up to "memory: clean up phys_page_find"
>>> and go on with the next series.
>>
>> That's fine with me, but please don't forget to fix up
>> the doc comment for memory_region_find() (see comments on
>> patch 6/30). You can do that in a patch in the next series,
>> though, I guess.
>
> What about this:
>
> /**
>  * memory_region_find: translate an address/size relative to a
>  * MemoryRegion into a #MemoryRegionSection.
>  *
>  * Locates the first #MemoryRegion within @mr that overlaps the range
>  * given by @addr and @size.
>  *
>  * Returns a #MemoryRegionSection that describes a contiguous overlap.
>  * It will have the following characteristics:
>  *    .@size = 0 iff no overlap was found
>  *    .@mr is non-%NULL iff an overlap was found
>  *
>  * Remember that in the return value the @offset_within_region is
>  * relative to the returned region (in the .@mr field), not to the
>  * @mr argument.
>  *
>  * Similarly, the .@offset_within_address_space is relative to the
>  * address space that contains both regions, the passed and the
>  * returned one.  However, in the special case where the @mr argument
>  * has no parent (and thus is the root of the address space), the
>  * following will hold:
>  *    .@offset_within_address_space >= @addr
>  *    .@offset_within_address_space + .@size <= @addr + @size
>  *
>  * @mr: a MemoryRegion within which @addr is a relative address
>  * @addr: start of the area within @as to be searched
>  * @size: size of the area to be searched
>  */

Yes, that looks OK to me.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API
  2013-05-23 17:08     ` Paolo Bonzini
  2013-05-23 17:25       ` Peter Maydell
@ 2013-05-24 14:12       ` Alexey Kardashevskiy
  2013-05-24 14:20         ` Paolo Bonzini
  1 sibling, 1 reply; 106+ messages in thread
From: Alexey Kardashevskiy @ 2013-05-24 14:12 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, jan.kiszka, qemu-devel, David Gibson

On 05/24/2013 03:08 AM, Paolo Bonzini wrote:
> Il 22/05/2013 11:24, Paolo Bonzini ha scritto:
>> Il 22/05/2013 04:30, Alexey Kardashevskiy ha scritto:
>>> On 05/21/2013 08:57 PM, Paolo Bonzini wrote:
>>>> This is part 1 of the memory API updates for 1.6.  (Part 2 is the
>>>> introduction of get/set_owner, part 3 is the introduction of the
>>>> RCU-style flatview).
>>>>
>>>> Compared to the first submissions, there are a few extra cleanup
>>>> patches, and address_space_rw/read/write grew a return value so
>>>> that the existing DMAContext API doesn't need to change.
>>>>
>>>
>>> Is this series much different from the one in
>>> https://github.com/bonzini/qemu/tree/iommu (hope it is the same :) )?
>>
>> Not much, I've updated the branch now.

Does the memory region ref/unref patch go to series#2?

> BTW, if you give me your Tested-by it would be good, since most comments
> have been cosmetic.  I'd like to collect all of Peter's Reviewed-by from
> the RFC and send a pull request next week.


With all the stuff I got now (qemu.org/master + your set + David's PCI
patches + David's VFIO patches + my VFIO patches), it works for me. Tried
for emulated PCI, VFIO, emulated IBM VIO (and in full emulaiton as well),
have not found any problem so far.


> Then we can proceed with the fun stuff. :)

Go ahead :)


-- 
Alexey

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

* Re: [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API
  2013-05-24 14:12       ` Alexey Kardashevskiy
@ 2013-05-24 14:20         ` Paolo Bonzini
  0 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-24 14:20 UTC (permalink / raw)
  To: Alexey Kardashevskiy; +Cc: peter.maydell, jan.kiszka, qemu-devel, David Gibson

Il 24/05/2013 16:12, Alexey Kardashevskiy ha scritto:
> On 05/24/2013 03:08 AM, Paolo Bonzini wrote:
>> Il 22/05/2013 11:24, Paolo Bonzini ha scritto:
>>> Il 22/05/2013 04:30, Alexey Kardashevskiy ha scritto:
>>>> On 05/21/2013 08:57 PM, Paolo Bonzini wrote:
>>>>> This is part 1 of the memory API updates for 1.6.  (Part 2 is the
>>>>> introduction of get/set_owner, part 3 is the introduction of the
>>>>> RCU-style flatview).
>>>>>
>>>>> Compared to the first submissions, there are a few extra cleanup
>>>>> patches, and address_space_rw/read/write grew a return value so
>>>>> that the existing DMAContext API doesn't need to change.
>>>>>
>>>>
>>>> Is this series much different from the one in
>>>> https://github.com/bonzini/qemu/tree/iommu (hope it is the same :) )?
>>>
>>> Not much, I've updated the branch now.
> 
> Does the memory region ref/unref patch go to series#2?

Now it will be #3, since the first pull request won't have the iommu
stuff. :)

> With all the stuff I got now (qemu.org/master + your set + David's PCI
> patches + David's VFIO patches + my VFIO patches), it works for me. Tried
> for emulated PCI, VFIO, emulated IBM VIO (and in full emulaiton as well),
> have not found any problem so far.

Good.

Paolo

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-24 10:52       ` Peter Maydell
  2013-05-24 12:58         ` Paolo Bonzini
@ 2013-05-25  3:44         ` David Gibson
  2013-05-25  9:23           ` Peter Maydell
  1 sibling, 1 reply; 106+ messages in thread
From: David Gibson @ 2013-05-25  3:44 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Paolo Bonzini, qemu-devel, jan.kiszka

[-- Attachment #1: Type: text/plain, Size: 1986 bytes --]

On Fri, May 24, 2013 at 11:52:17AM +0100, Peter Maydell wrote:
> On 24 May 2013 09:02, Paolo Bonzini <pbonzini@redhat.com> wrote:
> > Il 23/05/2013 20:04, Peter Maydell ha scritto:
> >> Shouldn't we be calling the MemoryRegionOps
> >> accepts() callback here? What about access alignment constraints
> >> and access size restrictions?
> >
> > Yes, we should.
> >
> >> What if the validity of the range
> >> changes between the time you asked and when you actually do the
> >> access?
> >
> > If that's a concern, you shouldn't use this API, you should just do the
> > access and rely on the return value of address_space_rw & friends.
> 
> So when *is* it a good idea to use this API? In real
> hardware you don't usually get a "tell me whether this
> access would succeed if I did it" bus operation -- you
> just do the operation and the memory transaction either
> succeeds or it doesn't. Are we modelling something that
> really exists in hardware on spapr here?

So, as a general rule, you should just attempt the access and handle
failures - this is a bad interface.  The reason I added it, however,
is that the PAPR specification mandates that the virtual LAN pre-check
various buffers when they're registered, and return specific errors if
they're not mapped to valid memory.  Since we have nothing to read or
write at that point, adding this interface was the only way I could
see to implement that requirement.

Or... a bit more charitably: You should always handle failures at the
point of read or write, but using this interface can give you an
earlier, and therefore potentially easier to analyze, error in the
more common failure cases, even if there are more complex cases where
the pre-check succeeds but the read/write still fails later.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-21 10:57 ` [Qemu-devel] [PATCH 17/30] memory: add address_space_translate Paolo Bonzini
  2013-05-23  7:09   ` liu ping fan
  2013-05-23 18:15   ` Peter Maydell
@ 2013-05-25  6:40   ` Jan Kiszka
  2013-05-25  7:47     ` Paolo Bonzini
  2 siblings, 1 reply; 106+ messages in thread
From: Jan Kiszka @ 2013-05-25  6:40 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, qemu-devel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 5515 bytes --]

On 2013-05-21 12:57, Paolo Bonzini wrote:
> Using phys_page_find to translate an AddressSpace to a MemoryRegionSection
> is unwieldy.  It requires to pass the page index rather than the address,
> and later memory_region_section_addr has to be called.  Replace
> memory_region_section_addr with a function that does all of it: call
> phys_page_find, compute the offset within the region, and check how
> big the current mapping is.  This way, a large flat region can be written
> with a single lookup rather than a page at a time.
> 
> address_space_translate will also provide a single point where IOMMU
> forwarding is implemented.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  cputlb.c              |  20 ++---
>  exec.c                | 201 +++++++++++++++++++++++++++-----------------------
>  include/exec/cputlb.h |  12 ++-
>  include/exec/memory.h |  31 ++++----
>  translate-all.c       |   6 +-
>  5 files changed, 143 insertions(+), 127 deletions(-)
> 
> diff --git a/cputlb.c b/cputlb.c
> index aba7e44..1f85da0 100644
> --- a/cputlb.c
> +++ b/cputlb.c
> @@ -248,13 +248,18 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
>      target_ulong code_address;
>      uintptr_t addend;
>      CPUTLBEntry *te;
> -    hwaddr iotlb;
> +    hwaddr iotlb, xlat, sz;
>  
>      assert(size >= TARGET_PAGE_SIZE);
>      if (size != TARGET_PAGE_SIZE) {
>          tlb_add_large_page(env, vaddr, size);
>      }
> -    section = phys_page_find(address_space_memory.dispatch, paddr >> TARGET_PAGE_BITS);
> +
> +    sz = size;
> +    section = address_space_translate(&address_space_memory, paddr, &xlat, &sz,
> +                                      false);
> +    assert(sz >= TARGET_PAGE_SIZE);
> +
>  #if defined(DEBUG_TLB)
>      printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
>             " prot=%x idx=%d pd=0x%08lx\n",
> @@ -269,15 +274,14 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
>      }
>      if (memory_region_is_ram(section->mr) ||
>          memory_region_is_romd(section->mr)) {
> -        addend = (uintptr_t)memory_region_get_ram_ptr(section->mr)
> -        + memory_region_section_addr(section, paddr);
> +        addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
>      } else {
>          addend = 0;
>      }
>  
>      code_address = address;
> -    iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, prot,
> -                                            &address);
> +    iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, xlat,
> +                                            prot, &address);
>  
>      index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
>      env->iotlb[mmu_idx][index] = iotlb - vaddr;
> @@ -300,9 +304,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
>              /* Write access calls the I/O callback.  */
>              te->addr_write = address | TLB_MMIO;
>          } else if (memory_region_is_ram(section->mr)
> -                   && !cpu_physical_memory_is_dirty(
> -                           section->mr->ram_addr
> -                           + memory_region_section_addr(section, paddr))) {
> +                   && !cpu_physical_memory_is_dirty(section->mr->ram_addr + xlat)) {
>              te->addr_write = address | TLB_NOTDIRTY;
>          } else {
>              te->addr_write = address;
> diff --git a/exec.c b/exec.c
> index 82da067..e5ee8ff 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -182,7 +182,7 @@ static void phys_page_set(AddressSpaceDispatch *d,
>      phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1);
>  }
>  
> -MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
> +static MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
>  {
>      PhysPageEntry lp = d->phys_map;
>      PhysPageEntry *p;
> @@ -198,6 +198,22 @@ MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index)
>      return &phys_sections[lp.ptr];
>  }
>  
> +MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
> +                                             hwaddr *xlat, hwaddr *plen,
> +                                             bool is_write)
> +{
> +    MemoryRegionSection *section;
> +
> +    section = phys_page_find(as->dispatch, addr >> TARGET_PAGE_BITS);
> +    /* Compute offset within MemoryRegionSection */
> +    addr -= section->offset_within_address_space;
> +    *plen = MIN(section->size - addr, *plen);

This limitation causes problems. Consider two overlapping memory regions
A and B. A handles 4-byte accesses and is at least 4 bytes long, B only
deals with a single byte. They overlap like this:

B (prio 1):   X
A (prio 0): XXXX...
            ^access here with 4 bytes length

Now if an access happens at the marked position, it is split into one
2-byte access to A, followed by a one-byte access to B and another
one-byte access to A. But the right access emulation would be 4-bytes to
A, no?

I think we need to check against the length of the target mr here
instead, but I'm not totally sure yet.

A concrete scenario where this breaks popped up while reworking PIO
dispatching. PCI accesses to 0xcf8 no longer worked:

  0000000000000cf8-0000000000000cfb (prio 0, RW): pci-conf-idx
  0000000000000cf9-0000000000000cf9 (prio 1, RW): piix3-reset-control

Jan



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-25  6:40   ` Jan Kiszka
@ 2013-05-25  7:47     ` Paolo Bonzini
  2013-05-25 10:19       ` Jan Kiszka
  0 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-25  7:47 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: peter.maydell, qemu-devel, David Gibson

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Il 25/05/2013 08:40, Jan Kiszka ha scritto:
> On 2013-05-21 12:57, Paolo Bonzini wrote:
>> Using phys_page_find to translate an AddressSpace to a
>> MemoryRegionSection is unwieldy.  It requires to pass the page
>> index rather than the address, and later
>> memory_region_section_addr has to be called.  Replace 
>> memory_region_section_addr with a function that does all of it:
>> call phys_page_find, compute the offset within the region, and
>> check how big the current mapping is.  This way, a large flat
>> region can be written with a single lookup rather than a page at
>> a time.
>> 
>> address_space_translate will also provide a single point where
>> IOMMU forwarding is implemented.
>> 
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- cputlb.c
>> |  20 ++--- exec.c                | 201
>> +++++++++++++++++++++++++++----------------------- 
>> include/exec/cputlb.h |  12 ++- include/exec/memory.h |  31
>> ++++---- translate-all.c       |   6 +- 5 files changed, 143
>> insertions(+), 127 deletions(-)
>> 
>> diff --git a/cputlb.c b/cputlb.c index aba7e44..1f85da0 100644 
>> --- a/cputlb.c +++ b/cputlb.c @@ -248,13 +248,18 @@ void
>> tlb_set_page(CPUArchState *env, target_ulong vaddr, target_ulong
>> code_address; uintptr_t addend; CPUTLBEntry *te; -    hwaddr
>> iotlb; +    hwaddr iotlb, xlat, sz;
>> 
>> assert(size >= TARGET_PAGE_SIZE); if (size != TARGET_PAGE_SIZE)
>> { tlb_add_large_page(env, vaddr, size); } -    section =
>> phys_page_find(address_space_memory.dispatch, paddr >>
>> TARGET_PAGE_BITS); + +    sz = size; +    section =
>> address_space_translate(&address_space_memory, paddr, &xlat,
>> &sz, +                                      false); +
>> assert(sz >= TARGET_PAGE_SIZE); + #if defined(DEBUG_TLB) 
>> printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x"
>> TARGET_FMT_plx " prot=%x idx=%d pd=0x%08lx\n", @@ -269,15 +274,14
>> @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, } if
>> (memory_region_is_ram(section->mr) || 
>> memory_region_is_romd(section->mr)) { -        addend =
>> (uintptr_t)memory_region_get_ram_ptr(section->mr) -        +
>> memory_region_section_addr(section, paddr); +        addend =
>> (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat; } else
>> { addend = 0; }
>> 
>> code_address = address; -    iotlb =
>> memory_region_section_get_iotlb(env, section, vaddr, paddr,
>> prot, -                                            &address); +
>> iotlb = memory_region_section_get_iotlb(env, section, vaddr,
>> paddr, xlat, +                                            prot,
>> &address);
>> 
>> index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); 
>> env->iotlb[mmu_idx][index] = iotlb - vaddr; @@ -300,9 +304,7 @@
>> void tlb_set_page(CPUArchState *env, target_ulong vaddr, /* Write
>> access calls the I/O callback.  */ te->addr_write = address |
>> TLB_MMIO; } else if (memory_region_is_ram(section->mr) -
>> && !cpu_physical_memory_is_dirty( -
>> section->mr->ram_addr -                           +
>> memory_region_section_addr(section, paddr))) { +
>> && !cpu_physical_memory_is_dirty(section->mr->ram_addr + xlat))
>> { te->addr_write = address | TLB_NOTDIRTY; } else { 
>> te->addr_write = address; diff --git a/exec.c b/exec.c index
>> 82da067..e5ee8ff 100644 --- a/exec.c +++ b/exec.c @@ -182,7
>> +182,7 @@ static void phys_page_set(AddressSpaceDispatch *d, 
>> phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS
>> - 1); }
>> 
>> -MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d,
>> hwaddr index) +static MemoryRegionSection
>> *phys_page_find(AddressSpaceDispatch *d, hwaddr index) { 
>> PhysPageEntry lp = d->phys_map; PhysPageEntry *p; @@ -198,6
>> +198,22 @@ MemoryRegionSection
>> *phys_page_find(AddressSpaceDispatch *d, hwaddr index) return
>> &phys_sections[lp.ptr]; }
>> 
>> +MemoryRegionSection *address_space_translate(AddressSpace *as,
>> hwaddr addr, +                                             hwaddr
>> *xlat, hwaddr *plen, +
>> bool is_write) +{ +    MemoryRegionSection *section; + +
>> section = phys_page_find(as->dispatch, addr >>
>> TARGET_PAGE_BITS); +    /* Compute offset within
>> MemoryRegionSection */ +    addr -=
>> section->offset_within_address_space; +    *plen =
>> MIN(section->size - addr, *plen);
> 
> This limitation causes problems. Consider two overlapping memory
> regions A and B. A handles 4-byte accesses and is at least 4 bytes
> long, B only deals with a single byte. They overlap like this:
> 
> B (prio 1):   X A (prio 0): XXXX... ^access here with 4 bytes
> length
> 
> Now if an access happens at the marked position, it is split into
> one 2-byte access to A, followed by a one-byte access to B and
> another one-byte access to A. But the right access emulation would
> be 4-bytes to A, no?

I guess it depends on the width of the bus.  On a 16-bit computer the
right thing to do would be to split the write in two, one two-byte
access to A and one two-byte access to B.  But as a first
approximation the fix you suggest is the right one.  Implementing bus
width in TCG is tricky, so we should get by with the simple fix.

This patch is not in the pull request I sent, so there is time to make
it work.  Is it simply

- -    *plen = MIN(section->size - addr, *plen);
+    addr += section->offset_within_memory_region;
+    *plen = MIN(section->mr->size - addr, *plen);

or something like that?  If you post it as a diff I can squash it in.

> I think we need to check against the length of the target mr here 
> instead, but I'm not totally sure yet.
> 
> A concrete scenario where this breaks popped up while reworking
> PIO dispatching. PCI accesses to 0xcf8 no longer worked:
> 
> 0000000000000cf8-0000000000000cfb (prio 0, RW): pci-conf-idx 
> 0000000000000cf9-0000000000000cf9 (prio 1, RW):
> piix3-reset-control

Paolo

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJRoGybAAoJEBvWZb6bTYbyELUP/09bPNSKl39Tog0uyV+VJ3BR
IGDsWfKHnIm6T2hC0S4BhVRaBkDyDAC6c8hJ7iy9084/pw61Cra1RrNMdSOzNHqo
x4pC+Zw6hD9lK0ncRsB21w1n398yen7nk+RN4zf2LxxAnIiXrUuaG6SL5q3qSibz
lXj1fKP+hG2yoxS7frMAJVjBEFIhBj/EY5u3pmd6+qREGxYaLBKkuXSnbjHdfG3s
Q8OLJZ8bRH7o3c034yt+LvJ776PfhjzaggUmrYri7fZ2kU+SmUzqnkW9If2ekQsf
MQ3ZQRVrVc5AaHLdQLyjSaSpzPcON5w4VpqU9SCisKi9rFdDOW6qHuZc6ZTbUpch
wAbGeI0h1PA01o41milx0LU+Y7Qfl6wRzbB3CZEpgp8fFSR95LySwD1Zldt1Ft6E
Zv8Mh0NVV4qvVEtp+HrTTh91kVz5W9OXnqFOz+wYrBlaVBRUxBLWSzQvuScnYv2B
Rv51bcsq07bOZFR2BabC9zuRnHlCC9LqQAvP5i8AdvC1FsxIGPtK+FLc3QDeD+c7
Ndz5mZq6jgAeg0BQrBv7H++P6I2dw/lJkrb4zwGY68ckJ+Yo67NGbYvhM0/W1WF5
XVebDnb1F3+qWsVtSJWWoOHtW0HRFS+3il87/u4MKJc1BF+ceONrSJLBQyvSJDNf
9sPb/mhfVloOj7tWqWAk
=Y4yR
-----END PGP SIGNATURE-----

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-25  3:44         ` David Gibson
@ 2013-05-25  9:23           ` Peter Maydell
  2013-05-26 13:02             ` David Gibson
  0 siblings, 1 reply; 106+ messages in thread
From: Peter Maydell @ 2013-05-25  9:23 UTC (permalink / raw)
  To: David Gibson; +Cc: Paolo Bonzini, qemu-devel, jan.kiszka

On 25 May 2013 04:44, David Gibson <david@gibson.dropbear.id.au> wrote:
> On Fri, May 24, 2013 at 11:52:17AM +0100, Peter Maydell wrote:
>> So when *is* it a good idea to use this API? In real
>> hardware you don't usually get a "tell me whether this
>> access would succeed if I did it" bus operation -- you
>> just do the operation and the memory transaction either
>> succeeds or it doesn't. Are we modelling something that
>> really exists in hardware on spapr here?
>
> So, as a general rule, you should just attempt the access and handle
> failures - this is a bad interface.  The reason I added it, however,
> is that the PAPR specification mandates that the virtual LAN pre-check
> various buffers when they're registered, and return specific errors if
> they're not mapped to valid memory.  Since we have nothing to read or
> write at that point, adding this interface was the only way I could
> see to implement that requirement.

Would it work to just read and throw away the result of the read?

> Or... a bit more charitably: You should always handle failures at the
> point of read or write, but using this interface can give you an
> earlier, and therefore potentially easier to analyze, error in the
> more common failure cases, even if there are more complex cases where
> the pre-check succeeds but the read/write still fails later.

There's also the converse case where the pre-check fails but
doing the operation at the proper time would succeed, in
which case where we're modelling real hardware we would
be doing it wrong. So the set of cases where it's OK to
pre-check seems a bit limited.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-25  7:47     ` Paolo Bonzini
@ 2013-05-25 10:19       ` Jan Kiszka
  2013-05-25 11:20         ` Paolo Bonzini
  0 siblings, 1 reply; 106+ messages in thread
From: Jan Kiszka @ 2013-05-25 10:19 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, qemu-devel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 6501 bytes --]

On 2013-05-25 09:47, Paolo Bonzini wrote:
> Il 25/05/2013 08:40, Jan Kiszka ha scritto:
>> On 2013-05-21 12:57, Paolo Bonzini wrote:
>>> Using phys_page_find to translate an AddressSpace to a
>>> MemoryRegionSection is unwieldy.  It requires to pass the page
>>> index rather than the address, and later
>>> memory_region_section_addr has to be called.  Replace 
>>> memory_region_section_addr with a function that does all of it:
>>> call phys_page_find, compute the offset within the region, and
>>> check how big the current mapping is.  This way, a large flat
>>> region can be written with a single lookup rather than a page at
>>> a time.
>>>
>>> address_space_translate will also provide a single point where
>>> IOMMU forwarding is implemented.
>>>
>>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- cputlb.c
>>> |  20 ++--- exec.c                | 201
>>> +++++++++++++++++++++++++++----------------------- 
>>> include/exec/cputlb.h |  12 ++- include/exec/memory.h |  31
>>> ++++---- translate-all.c       |   6 +- 5 files changed, 143
>>> insertions(+), 127 deletions(-)
>>>
>>> diff --git a/cputlb.c b/cputlb.c index aba7e44..1f85da0 100644 
>>> --- a/cputlb.c +++ b/cputlb.c @@ -248,13 +248,18 @@ void
>>> tlb_set_page(CPUArchState *env, target_ulong vaddr, target_ulong
>>> code_address; uintptr_t addend; CPUTLBEntry *te; -    hwaddr
>>> iotlb; +    hwaddr iotlb, xlat, sz;
>>>
>>> assert(size >= TARGET_PAGE_SIZE); if (size != TARGET_PAGE_SIZE)
>>> { tlb_add_large_page(env, vaddr, size); } -    section =
>>> phys_page_find(address_space_memory.dispatch, paddr >>
>>> TARGET_PAGE_BITS); + +    sz = size; +    section =
>>> address_space_translate(&address_space_memory, paddr, &xlat,
>>> &sz, +                                      false); +
>>> assert(sz >= TARGET_PAGE_SIZE); + #if defined(DEBUG_TLB) 
>>> printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x"
>>> TARGET_FMT_plx " prot=%x idx=%d pd=0x%08lx\n", @@ -269,15 +274,14
>>> @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, } if
>>> (memory_region_is_ram(section->mr) || 
>>> memory_region_is_romd(section->mr)) { -        addend =
>>> (uintptr_t)memory_region_get_ram_ptr(section->mr) -        +
>>> memory_region_section_addr(section, paddr); +        addend =
>>> (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat; } else
>>> { addend = 0; }
>>>
>>> code_address = address; -    iotlb =
>>> memory_region_section_get_iotlb(env, section, vaddr, paddr,
>>> prot, -                                            &address); +
>>> iotlb = memory_region_section_get_iotlb(env, section, vaddr,
>>> paddr, xlat, +                                            prot,
>>> &address);
>>>
>>> index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); 
>>> env->iotlb[mmu_idx][index] = iotlb - vaddr; @@ -300,9 +304,7 @@
>>> void tlb_set_page(CPUArchState *env, target_ulong vaddr, /* Write
>>> access calls the I/O callback.  */ te->addr_write = address |
>>> TLB_MMIO; } else if (memory_region_is_ram(section->mr) -
>>> && !cpu_physical_memory_is_dirty( -
>>> section->mr->ram_addr -                           +
>>> memory_region_section_addr(section, paddr))) { +
>>> && !cpu_physical_memory_is_dirty(section->mr->ram_addr + xlat))
>>> { te->addr_write = address | TLB_NOTDIRTY; } else { 
>>> te->addr_write = address; diff --git a/exec.c b/exec.c index
>>> 82da067..e5ee8ff 100644 --- a/exec.c +++ b/exec.c @@ -182,7
>>> +182,7 @@ static void phys_page_set(AddressSpaceDispatch *d, 
>>> phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS
>>> - 1); }
>>>
>>> -MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d,
>>> hwaddr index) +static MemoryRegionSection
>>> *phys_page_find(AddressSpaceDispatch *d, hwaddr index) { 
>>> PhysPageEntry lp = d->phys_map; PhysPageEntry *p; @@ -198,6
>>> +198,22 @@ MemoryRegionSection
>>> *phys_page_find(AddressSpaceDispatch *d, hwaddr index) return
>>> &phys_sections[lp.ptr]; }
>>>
>>> +MemoryRegionSection *address_space_translate(AddressSpace *as,
>>> hwaddr addr, +                                             hwaddr
>>> *xlat, hwaddr *plen, +
>>> bool is_write) +{ +    MemoryRegionSection *section; + +
>>> section = phys_page_find(as->dispatch, addr >>
>>> TARGET_PAGE_BITS); +    /* Compute offset within
>>> MemoryRegionSection */ +    addr -=
>>> section->offset_within_address_space; +    *plen =
>>> MIN(section->size - addr, *plen);
> 
>> This limitation causes problems. Consider two overlapping memory
>> regions A and B. A handles 4-byte accesses and is at least 4 bytes
>> long, B only deals with a single byte. They overlap like this:
> 
>> B (prio 1):   X A (prio 0): XXXX... ^access here with 4 bytes
>> length
> 
>> Now if an access happens at the marked position, it is split into
>> one 2-byte access to A, followed by a one-byte access to B and
>> another one-byte access to A. But the right access emulation would
>> be 4-bytes to A, no?
> 
> I guess it depends on the width of the bus.  On a 16-bit computer the
> right thing to do would be to split the write in two, one two-byte
> access to A and one two-byte access to B.  But as a first
> approximation the fix you suggest is the right one.  Implementing bus
> width in TCG is tricky, so we should get by with the simple fix.
> 
> This patch is not in the pull request I sent, so there is time to make
> it work.  Is it simply
> 
> -    *plen = MIN(section->size - addr, *plen);
> +    addr += section->offset_within_memory_region;
> +    *plen = MIN(section->mr->size - addr, *plen);
> 
> or something like that?  If you post it as a diff I can squash it in.

This works for me now:

diff --git a/exec.c b/exec.c
index 1610604..3d36bc7 100644
--- a/exec.c
+++ b/exec.c
@@ -210,13 +210,15 @@ MemoryRegionSection *address_space_translate(AddressSpace *as, hwaddr addr,
     IOMMUTLBEntry iotlb;
     MemoryRegionSection *section;
     hwaddr len = *plen;
+    Int128 diff;
 
     for (;;) {
         section = address_space_lookup_region(as, addr);
 
         /* Compute offset within MemoryRegionSection */
         addr -= section->offset_within_address_space;
-        len = MIN(section->size - addr, len);
+        diff = int128_sub(section->mr->size, int128_make64(addr));
+        len = MIN(int128_get64(diff), len);
 
         /* Compute offset within MemoryRegion */
         addr += section->offset_within_region;

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-25 10:19       ` Jan Kiszka
@ 2013-05-25 11:20         ` Paolo Bonzini
  2013-05-25 11:30           ` Jan Kiszka
  0 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-25 11:20 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: peter.maydell, qemu-devel, David Gibson

Il 25/05/2013 12:19, Jan Kiszka ha scritto:
>          addr -= section->offset_within_address_space;
> -        len = MIN(section->size - addr, len);
                     ^^^^^^^^^^^^^   ^^^^

This is the size of a section minus an offset in the section.

> +        diff = int128_sub(section->mr->size, int128_make64(addr));
                             ^^^^^^^^^^^^^^^^^                ^^^^

This is the size of a region minus the same offset in the section.

> +        len = MIN(int128_get64(diff), len);
>  
>          /* Compute offset within MemoryRegion */
>          addr += section->offset_within_region;

So this has to be moved above.  Do you have a branch pushed somewhere
that I can test against?

Paolo

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-25 11:20         ` Paolo Bonzini
@ 2013-05-25 11:30           ` Jan Kiszka
  2013-05-26  8:56             ` Paolo Bonzini
  2013-05-26  9:01             ` Paolo Bonzini
  0 siblings, 2 replies; 106+ messages in thread
From: Jan Kiszka @ 2013-05-25 11:30 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, qemu-devel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 884 bytes --]

On 2013-05-25 13:20, Paolo Bonzini wrote:
> Il 25/05/2013 12:19, Jan Kiszka ha scritto:
>>          addr -= section->offset_within_address_space;
>> -        len = MIN(section->size - addr, len);
>                      ^^^^^^^^^^^^^   ^^^^
> 
> This is the size of a section minus an offset in the section.
> 
>> +        diff = int128_sub(section->mr->size, int128_make64(addr));
>                              ^^^^^^^^^^^^^^^^^                ^^^^
> 
> This is the size of a region minus the same offset in the section.
> 
>> +        len = MIN(int128_get64(diff), len);
>>  
>>          /* Compute offset within MemoryRegion */
>>          addr += section->offset_within_region;
> 
> So this has to be moved above.

Right, fixed.

>  Do you have a branch pushed somewhere
> that I can test against?

git://git.kiszka.org/qemu.git queues/ioport

Jan



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-25 11:30           ` Jan Kiszka
@ 2013-05-26  8:56             ` Paolo Bonzini
  2013-05-26  9:02               ` Jan Kiszka
  2013-05-26  9:01             ` Paolo Bonzini
  1 sibling, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-26  8:56 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: peter.maydell, qemu-devel, David Gibson

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Il 25/05/2013 13:30, Jan Kiszka ha scritto:
> On 2013-05-25 13:20, Paolo Bonzini wrote:
>> Il 25/05/2013 12:19, Jan Kiszka ha scritto:
>>> addr -= section->offset_within_address_space; -        len =
>>> MIN(section->size - addr, len);
>> ^^^^^^^^^^^^^   ^^^^
>> 
>> This is the size of a section minus an offset in the section.
>> 
>>> +        diff = int128_sub(section->mr->size,
>>> int128_make64(addr));
>> ^^^^^^^^^^^^^^^^^                ^^^^
>> 
>> This is the size of a region minus the same offset in the
>> section.
>> 
>>> +        len = MIN(int128_get64(diff), len);
>>> 
>>> /* Compute offset within MemoryRegion */ addr +=
>>> section->offset_within_region;
>> 
>> So this has to be moved above.
> 
> Right, fixed.
> 
>> Do you have a branch pushed somewhere that I can test against?
> 
> git://git.kiszka.org/qemu.git queues/ioport

Nice patches.  Only one thing, how is .impl.unaligned different from
the existing .valid.unaligned?

Paolo
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJRoc4vAAoJEBvWZb6bTYby7UEP/0l5Stow6nrKirryCNuds3ky
L3FTjqEhLZ+aKha4rdbYNKhwbvY92rfR/Wo8hMckkFv6wwcieHD+nYQltuIDW3y2
xV7FmCPJd1M1pajIQ5Nk+Ssqf7Qhv7jRX5Kg2L6ksNf5srb5485J9oH4M9hIO6CH
XFHO9GeKmynbeeZmSNFF9mNlQd0leHx6h6IbJxYov/eD0zxp5cxoN7xM6+V5hCP/
UjBa2Zn07AI94BS/64YSHSa155BLxIOS5jJi25PNOWti29wHE8Nhw2KF5pMD/JYM
hPblsTIpFf6zg53FMHmrY/B990Ol+IjNogQhRh3tSfNf/48XWA4l+anLdaMweQf6
TuCEOoDqgNphz6c5lOPjzQB/CJZFUCQzxaUjok499ZQyPY5SpIgjKmzl7Vszos8I
wnYmJJ3xVLyJujvx61rg7qiW3ckyVx0sPHZXt/DWEDUNDHTW+HdqAcrZ8TgJrIni
gQF1VEKNplxdgauIv17RGxnVOXwb8PcoNwXE9Gn6XJ/KKQLh9KukmdufCSBmOARV
iiAo8N4rUK8FaCFXDwrZ3S8OIiyWCSdnud/4wZPcsI+r5gM/rrtlrZoQExyx5meO
9RzLBtL5hwFaQ9erE8ce+GDKbo+nie593z3UiN5NKLuH5KjWig2OYQxV6ylg4Vx7
RscCNjGvppk+2I3PAv9R
=pCeD
-----END PGP SIGNATURE-----

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-25 11:30           ` Jan Kiszka
  2013-05-26  8:56             ` Paolo Bonzini
@ 2013-05-26  9:01             ` Paolo Bonzini
  2013-05-26  9:12               ` Jan Kiszka
  1 sibling, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-26  9:01 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: peter.maydell, qemu-devel, David Gibson

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Il 25/05/2013 13:30, Jan Kiszka ha scritto:
> On 2013-05-25 13:20, Paolo Bonzini wrote:
>> Il 25/05/2013 12:19, Jan Kiszka ha scritto:
>>> addr -= section->offset_within_address_space; -        len =
>>> MIN(section->size - addr, len);
>> ^^^^^^^^^^^^^   ^^^^
>> 
>> This is the size of a section minus an offset in the section.
>> 
>>> +        diff = int128_sub(section->mr->size,
>>> int128_make64(addr));
>> ^^^^^^^^^^^^^^^^^                ^^^^
>> 
>> This is the size of a region minus the same offset in the
>> section.
>> 
>>> +        len = MIN(int128_get64(diff), len);
>>> 
>>> /* Compute offset within MemoryRegion */ addr +=
>>> section->offset_within_region;
>> 
>> So this has to be moved above.
> 
> Right, fixed.
> 
>> Do you have a branch pushed somewhere that I can test against?
> 
> git://git.kiszka.org/qemu.git queues/ioport

And another thing... in "ioport: Switch dispatching to memory core
layer", could you put memory_region_iorange_read/write in
mr->ops->read/write instead of adding an "if" in the dispatch routines?

Paolo

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJRoc9MAAoJEBvWZb6bTYbya6IP/Rso0r/qUrRttOZYyC0GX1IL
xBXZEyCDrbV49pQw9O85Lpb2BRzbUOy38RZ/gvrUfGzg9iYo+88nxoA4qiTXSKil
IBxC/Nu5QCcV01zTWLE7dsjAGVVP6td2UWqtI/41T7H1OmhmN9BR2hD0hHhDT6aO
f1KAhzkrdD2aOJHCyWjtehriZFH+J638QuAem8zMIC6kFGOBm475iYBI5l4haXaN
k2Rx66EaOuJRFzZVscHnTw3Ohrk2QZEe8EpBScQIf3hxAlDv4wPDzXYjADUmCGhH
u5dHXSDMgD3+ll5/XLAq3dX/lZPn6nJCzAqV2DPboAxhjpe5+gt0i50r91Di8T+3
Rn8ycEi5hy7Pck++ijwTDs4JGU1vGvT6xpnCmsTwiU3Tw5Yd8lNEQJyOQAMsdsrH
GX+Tsqiowoq8LKVACHSOHouffUB4TM5XdUN0dPGKdohPGyDSlRlkE58mFPeBmMRT
SIhaCPkykpRguNFnkxx5iLl66yUsi5Jb0qeXslffKKx6wCr6N5d3jOeb2jqjG/LT
AAlQ4U5GdKbKU6rDWmcB8GeV2HZh9+ivIUwC4Q4+s+inlaXXh5V4hnNKQ8aHc2MX
wBfq07Zit8bbCUvB+tYf+ORAWHUV1BFWjFRkE4sZ08ouCs45TN7Ug67334GyPvxe
K5Zz+3M9ZKkvnK4kNINg
=71ln
-----END PGP SIGNATURE-----

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-26  8:56             ` Paolo Bonzini
@ 2013-05-26  9:02               ` Jan Kiszka
  2013-05-27  7:20                 ` Paolo Bonzini
  0 siblings, 1 reply; 106+ messages in thread
From: Jan Kiszka @ 2013-05-26  9:02 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, qemu-devel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 1221 bytes --]

On 2013-05-26 10:56, Paolo Bonzini wrote:
> Il 25/05/2013 13:30, Jan Kiszka ha scritto:
>> On 2013-05-25 13:20, Paolo Bonzini wrote:
>>> Il 25/05/2013 12:19, Jan Kiszka ha scritto:
>>>> addr -= section->offset_within_address_space; -        len =
>>>> MIN(section->size - addr, len);
>>> ^^^^^^^^^^^^^   ^^^^
>>>
>>> This is the size of a section minus an offset in the section.
>>>
>>>> +        diff = int128_sub(section->mr->size,
>>>> int128_make64(addr));
>>> ^^^^^^^^^^^^^^^^^                ^^^^
>>>
>>> This is the size of a region minus the same offset in the
>>> section.
>>>
>>>> +        len = MIN(int128_get64(diff), len);
>>>>
>>>> /* Compute offset within MemoryRegion */ addr +=
>>>> section->offset_within_region;
>>>
>>> So this has to be moved above.
> 
>> Right, fixed.
> 
>>> Do you have a branch pushed somewhere that I can test against?
> 
>> git://git.kiszka.org/qemu.git queues/ioport
> 
> Nice patches.  Only one thing, how is .impl.unaligned different from
> the existing .valid.unaligned?

See memory.h: valid controls is an unaligned access traps or gets
processed, impl manages if it is passed as-is to the device or broken up
and aligned first.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-26  9:01             ` Paolo Bonzini
@ 2013-05-26  9:12               ` Jan Kiszka
  2013-05-26 18:23                 ` Paolo Bonzini
  0 siblings, 1 reply; 106+ messages in thread
From: Jan Kiszka @ 2013-05-26  9:12 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, qemu-devel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 1359 bytes --]

On 2013-05-26 11:01, Paolo Bonzini wrote:
> Il 25/05/2013 13:30, Jan Kiszka ha scritto:
>> On 2013-05-25 13:20, Paolo Bonzini wrote:
>>> Il 25/05/2013 12:19, Jan Kiszka ha scritto:
>>>> addr -= section->offset_within_address_space; -        len =
>>>> MIN(section->size - addr, len);
>>> ^^^^^^^^^^^^^   ^^^^
>>>
>>> This is the size of a section minus an offset in the section.
>>>
>>>> +        diff = int128_sub(section->mr->size,
>>>> int128_make64(addr));
>>> ^^^^^^^^^^^^^^^^^                ^^^^
>>>
>>> This is the size of a region minus the same offset in the
>>> section.
>>>
>>>> +        len = MIN(int128_get64(diff), len);
>>>>
>>>> /* Compute offset within MemoryRegion */ addr +=
>>>> section->offset_within_region;
>>>
>>> So this has to be moved above.
> 
>> Right, fixed.
> 
>>> Do you have a branch pushed somewhere that I can test against?
> 
>> git://git.kiszka.org/qemu.git queues/ioport
> 
> And another thing... in "ioport: Switch dispatching to memory core
> layer", could you put memory_region_iorange_read/write in
> mr->ops->read/write instead of adding an "if" in the dispatch routines?

Not trivially because mr->opaque is passed to the read/write handler,
but memory_region_iorange_read/write needs the region. Can add more data
structures to handles this, but what does it buy us?

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

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

* Re: [Qemu-devel] [PATCH 15/30] memory: add address_space_valid
  2013-05-25  9:23           ` Peter Maydell
@ 2013-05-26 13:02             ` David Gibson
  0 siblings, 0 replies; 106+ messages in thread
From: David Gibson @ 2013-05-26 13:02 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Paolo Bonzini, qemu-devel, jan.kiszka

[-- Attachment #1: Type: text/plain, Size: 3130 bytes --]

On Sat, May 25, 2013 at 10:23:32AM +0100, Peter Maydell wrote:
> On 25 May 2013 04:44, David Gibson <david@gibson.dropbear.id.au> wrote:
> > On Fri, May 24, 2013 at 11:52:17AM +0100, Peter Maydell wrote:
> >> So when *is* it a good idea to use this API? In real
> >> hardware you don't usually get a "tell me whether this
> >> access would succeed if I did it" bus operation -- you
> >> just do the operation and the memory transaction either
> >> succeeds or it doesn't. Are we modelling something that
> >> really exists in hardware on spapr here?
> >
> > So, as a general rule, you should just attempt the access and handle
> > failures - this is a bad interface.  The reason I added it, however,
> > is that the PAPR specification mandates that the virtual LAN pre-check
> > various buffers when they're registered, and return specific errors if
> > they're not mapped to valid memory.  Since we have nothing to read or
> > write at that point, adding this interface was the only way I could
> > see to implement that requirement.
> 
> Would it work to just read and throw away the result of the read?

Not when checking for writability.

> > Or... a bit more charitably: You should always handle failures at the
> > point of read or write, but using this interface can give you an
> > earlier, and therefore potentially easier to analyze, error in the
> > more common failure cases, even if there are more complex cases where
> > the pre-check succeeds but the read/write still fails later.
> 
> There's also the converse case where the pre-check fails but
> doing the operation at the proper time would succeed, in
> which case where we're modelling real hardware we would
> be doing it wrong. So the set of cases where it's OK to
> pre-check seems a bit limited.

Whether originally real or otherwise, this is a question of faithfully
implementing what the hardware is supposed to do.  In the case of the
PAPR llan, the (virtual) hardware specification says that the buffer
accessibility is checked at buffer add time, and the driver won't work
if it only makes the buffers accessible between that point and the
actual buffer access.  It would be entirely possible to design real
hardware with similar behaviour (probe buffer accessibility when a
descriptor is added to a pool, say), although it's not the sort of
thing hardware people generally do.

So, certainly qemu should not go using this pre-check when the
hardware it's emulating does not do such a check.  Designing hardware
that does do a pre-check is not, IMO, a good idea on balance, but the
point is that there is a reason (albeit, not a great one) you might
want to design the (possibly virtual) hardware that way.

As an aside, when you consider devices with embedded firmware - which
is practically everything these days - the distinction between "real"
hardware and virtual hardware can get kind of blurry.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-26  9:12               ` Jan Kiszka
@ 2013-05-26 18:23                 ` Paolo Bonzini
  0 siblings, 0 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-26 18:23 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: peter.maydell, qemu-devel, David Gibson

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Il 26/05/2013 11:12, Jan Kiszka ha scritto:
> On 2013-05-26 11:01, Paolo Bonzini wrote:
>> Il 25/05/2013 13:30, Jan Kiszka ha scritto:
>>> On 2013-05-25 13:20, Paolo Bonzini wrote:
>>>> Il 25/05/2013 12:19, Jan Kiszka ha scritto:
>>>>> addr -= section->offset_within_address_space; -        len
>>>>> = MIN(section->size - addr, len);
>>>> ^^^^^^^^^^^^^   ^^^^
>>>> 
>>>> This is the size of a section minus an offset in the
>>>> section.
>>>> 
>>>>> +        diff = int128_sub(section->mr->size, 
>>>>> int128_make64(addr));
>>>> ^^^^^^^^^^^^^^^^^                ^^^^
>>>> 
>>>> This is the size of a region minus the same offset in the 
>>>> section.
>>>> 
>>>>> +        len = MIN(int128_get64(diff), len);
>>>>> 
>>>>> /* Compute offset within MemoryRegion */ addr += 
>>>>> section->offset_within_region;
>>>> 
>>>> So this has to be moved above.
>> 
>>> Right, fixed.
>> 
>>>> Do you have a branch pushed somewhere that I can test
>>>> against?
>> 
>>> git://git.kiszka.org/qemu.git queues/ioport
>> 
>> And another thing... in "ioport: Switch dispatching to memory
>> core layer", could you put memory_region_iorange_read/write in 
>> mr->ops->read/write instead of adding an "if" in the dispatch
>> routines?
> 
> Not trivially because mr->opaque is passed to the read/write
> handler, but memory_region_iorange_read/write needs the region. Can
> add more data structures to handles this, but what does it buy us?

It's simpler, and I think it lets us remove ops->old_portio too.  We
can have something like

typedef MemoryRegionPortioList {
    MemoryRegion mr;
    void *piolist_opaque;
    MemoryRegionPortio pio[];
}

then you can set mr->opaque == mr.  It's more similar to how other
regions are implemented, e.g. subpages.

Paolo
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJRolMGAAoJEBvWZb6bTYbym5wP/izYQtpCSLhiAe6LiyN5cSVj
wMe+gSqhqyvi8Ho/GewilHlp1L0UKXQs18KhKqZbEtVETFdvKYoU+sJCPqWbRThW
Gj62dfo1Zn814gnv/CxiebslcI5fiU2UrHtpW1oXBKCZWmLJrfZSJqT5K7o1Z8Y3
qRDcR2sIISIQgAxM/n2EbuJWq/v50BUCDOXgpT3eUrq3rvdQHbh/Ym+y8Zd74sXl
VhK3UmP17ro0YPLtImForhrFutgavtgKuKCVvMTkD04ZLrWrW+QdXJmGl+LuCp+M
L/ib7jaR/4uPJ1RiDPbZexKc956yRsA5gzvJo9kHE0B6IipM+uqVCbrfk96kWrAC
Cg3qGn26cT/bc4zNF7NudJxAErVaHf220iJecoqFXNi6OwZTM6IgHlVH58l+yrRE
swQlxqQHQoYEzm4ZzsuK9C9Y50Y4C6G0LzkEWeyvYi5UdbOxt/hl1yh0pdSnhSSx
47Hw28nZgceDpcySv/Deb3zBzw/Pxx1Z3wkTxMhVpZ6t3Bot/T9hmkGQyuFqvXWF
cdrJEdYmJ2CEkmY2uwKUWCZeMzNtR+qfij+QlcI9RjFoVlmlOySJmBwR55Y7yu5m
H4wRZjeQ8PtfpZH/NmmwkNPOxaghDTaUn9k9/rEQzCDM9b17ddovvDI8JYqo9oaa
K1di55883LPNfkvycya3
=dJkN
-----END PGP SIGNATURE-----

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-26  9:02               ` Jan Kiszka
@ 2013-05-27  7:20                 ` Paolo Bonzini
  2013-05-27  7:23                   ` Jan Kiszka
  0 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-27  7:20 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: peter.maydell, qemu-devel, David Gibson

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Il 26/05/2013 11:02, Jan Kiszka ha scritto:
>>> 
>>> Nice patches.  Only one thing, how is .impl.unaligned different
>>> from the existing .valid.unaligned?
> See memory.h: valid controls is an unaligned access traps or gets 
> processed, impl manages if it is passed as-is to the device or
> broken up and aligned first.

I took the following patches:

    exec: Allow unaligned address_space_rw
    exec: Resolve subpages in one step except for IOTLB fills
    exec: Implement subpage_read/write via address_space_rw

to limit the conflicts and because I realized that TCG should never
encounter an IOMMU.  Thus I removed the is_write argument from
address_space_translate_internal and moved the IOMMU handling to
address_space_translate.  I'll push to my iommu branch after some more
testing.  If you reorganize the old_portio handling along the lines I
suggested in my previous email you should have no conflicts when rebasing.

Paolo
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJRowkzAAoJEBvWZb6bTYbybiQP/i4S4tUisfJVPlnKosEwxUxk
LY0I6oyeXIQznv/2VC+CkKuNFRpQyPgOoD+Nc4mVdVSEgexdJdNHvT3qQeewkRBB
Kk074LS/tMdtyRFyhf+ZuhYFBFgCV4LINyJ3iZV9E913LqV/cM6CXnvYcOWwNspu
2ZPGLCueG5y0iHcHHFo2ZXRf/OqUKiKIzMMKPzS57+7o7rUqav8wSnQV1Qox/L0G
xeeUZ4BO9a59ULIb63bwhrjcUHS77vddvAcPDe5LifAo1OZqZWXsWvzdj/3VKY0A
Deyt+q02QA9erYPR0K16nLr3j+8z44McPugHWNNmAzQzMXjFIVE1g7kBmqzBLAst
tStrog73ol1xgor5xl1wIqEfGQNGOroNuPEpdlU7NQf4c6aFJ7cWFMJnaOtfZuNB
7eTtQV32lQkqns7ho3wJFsv7k2sWjpBrjrXCNnii+LH/MUUm8KsAQ+w2JVCRHEDK
AEmnniEoCSLMbwZFOiKGT0J5291dZgeK6dbH2NVJ8jYhTWaDGuIldXtGyMvBkvpi
+YZF4Z3vvOPFeT+zl0DPh0xHsaXcblfZbe3pe4aDDlgjmsUAbyNIsTsAIn/+eq0y
WwjuEj76bR8Y+RbJgkQ1VP6mCDqQLaOAiKWniZZ1wjZMBmE3vCwsmi3CNEVMxJOD
XOnhQIEOw5kautUlcnQ3
=1nFS
-----END PGP SIGNATURE-----

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-27  7:20                 ` Paolo Bonzini
@ 2013-05-27  7:23                   ` Jan Kiszka
  2013-05-27  8:19                     ` Paolo Bonzini
  0 siblings, 1 reply; 106+ messages in thread
From: Jan Kiszka @ 2013-05-27  7:23 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, qemu-devel, David Gibson

On 2013-05-27 09:20, Paolo Bonzini wrote:
> Il 26/05/2013 11:02, Jan Kiszka ha scritto:
>>>>
>>>> Nice patches.  Only one thing, how is .impl.unaligned different
>>>> from the existing .valid.unaligned?
>> See memory.h: valid controls is an unaligned access traps or gets
>> processed, impl manages if it is passed as-is to the device or
>> broken up and aligned first.
> 
> I took the following patches:
> 
>     exec: Allow unaligned address_space_rw
>     exec: Resolve subpages in one step except for IOTLB fills
>     exec: Implement subpage_read/write via address_space_rw
> 
> to limit the conflicts and because I realized that TCG should never
> encounter an IOMMU.

Err, why? Will we emulate IOMMUs for TCG differently?

>  Thus I removed the is_write argument from
> address_space_translate_internal and moved the IOMMU handling to
> address_space_translate.  I'll push to my iommu branch after some more
> testing.  If you reorganize the old_portio handling along the lines I
> suggested in my previous email you should have no conflicts when rebasing.

old_portio should rather be eliminated on the long run. But that's a
future story.

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-27  7:23                   ` Jan Kiszka
@ 2013-05-27  8:19                     ` Paolo Bonzini
  2013-05-27  8:37                       ` Jan Kiszka
  2013-05-27 10:33                       ` Peter Maydell
  0 siblings, 2 replies; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-27  8:19 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: peter.maydell, qemu-devel, David Gibson

Il 27/05/2013 09:23, Jan Kiszka ha scritto:
> On 2013-05-27 09:20, Paolo Bonzini wrote:
>> Il 26/05/2013 11:02, Jan Kiszka ha scritto:
>>>>>
>>>>> Nice patches.  Only one thing, how is .impl.unaligned different
>>>>> from the existing .valid.unaligned?
>>> See memory.h: valid controls is an unaligned access traps or gets
>>> processed, impl manages if it is passed as-is to the device or
>>> broken up and aligned first.
>>
>> I took the following patches:
>>
>>     exec: Allow unaligned address_space_rw
>>     exec: Resolve subpages in one step except for IOTLB fills
>>     exec: Implement subpage_read/write via address_space_rw
>>
>> to limit the conflicts and because I realized that TCG should never
>> encounter an IOMMU.
> 
> Err, why? Will we emulate IOMMUs for TCG differently?

Because IOMMUs should never be added to address_space_memory.

TCG should only encounter an IOMMU during device emulation (DMA), not
because of reads/writes from the CPU.  So the IOTLBs should never point
to an IOMMU region.

Paolo

>>  Thus I removed the is_write argument from
>> address_space_translate_internal and moved the IOMMU handling to
>> address_space_translate.  I'll push to my iommu branch after some more
>> testing.  If you reorganize the old_portio handling along the lines I
>> suggested in my previous email you should have no conflicts when rebasing.
> 
> old_portio should rather be eliminated on the long run. But that's a
> future story.
> 
> Jan
> 

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-27  8:19                     ` Paolo Bonzini
@ 2013-05-27  8:37                       ` Jan Kiszka
  2013-05-27 10:33                       ` Peter Maydell
  1 sibling, 0 replies; 106+ messages in thread
From: Jan Kiszka @ 2013-05-27  8:37 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: peter.maydell, qemu-devel, David Gibson

On 2013-05-27 10:19, Paolo Bonzini wrote:
> Il 27/05/2013 09:23, Jan Kiszka ha scritto:
>> On 2013-05-27 09:20, Paolo Bonzini wrote:
>>> Il 26/05/2013 11:02, Jan Kiszka ha scritto:
>>>>>>
>>>>>> Nice patches.  Only one thing, how is .impl.unaligned different
>>>>>> from the existing .valid.unaligned?
>>>> See memory.h: valid controls is an unaligned access traps or gets
>>>> processed, impl manages if it is passed as-is to the device or
>>>> broken up and aligned first.
>>>
>>> I took the following patches:
>>>
>>>     exec: Allow unaligned address_space_rw
>>>     exec: Resolve subpages in one step except for IOTLB fills
>>>     exec: Implement subpage_read/write via address_space_rw
>>>
>>> to limit the conflicts and because I realized that TCG should never
>>> encounter an IOMMU.
>>
>> Err, why? Will we emulate IOMMUs for TCG differently?
> 
> Because IOMMUs should never be added to address_space_memory.
> 
> TCG should only encounter an IOMMU during device emulation (DMA), not
> because of reads/writes from the CPU.  So the IOTLBs should never point
> to an IOMMU region.

OK. That's true for the current QEMU architecture, but may no longer be
like this if we once emulate device controllers via TCG (in hybrid
system setups). Anyway, I guess it's fine to optimize this for now.

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-27  8:19                     ` Paolo Bonzini
  2013-05-27  8:37                       ` Jan Kiszka
@ 2013-05-27 10:33                       ` Peter Maydell
  2013-05-27 10:45                         ` Paolo Bonzini
  1 sibling, 1 reply; 106+ messages in thread
From: Peter Maydell @ 2013-05-27 10:33 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Jan Kiszka, qemu-devel, David Gibson

On 27 May 2013 09:19, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 27/05/2013 09:23, Jan Kiszka ha scritto:
>> Err, why? Will we emulate IOMMUs for TCG differently?
>
> Because IOMMUs should never be added to address_space_memory.
>
> TCG should only encounter an IOMMU during device emulation (DMA), not
> because of reads/writes from the CPU.  So the IOTLBs should never point
> to an IOMMU region.

This seems a slightly dubious assumption to me. For instance
here's a sample system diagram that puts a Cortex-M3 CPU
behind an IOMMU (the MMU-500 dotted line):
http://www.arm.com/images/CoreLink_MMU-500_in_System.jpg
Admittedly we're a long way from being able to model that
since we don't support multiple CPUs in one system yet.

Can we have an assertion if you try to add an IOMMU to
the CPU's view of memory, so it's obvious if we ever do
run into this case?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-27 10:33                       ` Peter Maydell
@ 2013-05-27 10:45                         ` Paolo Bonzini
  2013-05-27 11:33                           ` Peter Maydell
  0 siblings, 1 reply; 106+ messages in thread
From: Paolo Bonzini @ 2013-05-27 10:45 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Jan Kiszka, qemu-devel, David Gibson

Il 27/05/2013 12:33, Peter Maydell ha scritto:
> On 27 May 2013 09:19, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> Il 27/05/2013 09:23, Jan Kiszka ha scritto:
>>> Err, why? Will we emulate IOMMUs for TCG differently?
>>
>> Because IOMMUs should never be added to address_space_memory.
>>
>> TCG should only encounter an IOMMU during device emulation (DMA), not
>> because of reads/writes from the CPU.  So the IOTLBs should never point
>> to an IOMMU region.
> 
> This seems a slightly dubious assumption to me. For instance
> here's a sample system diagram that puts a Cortex-M3 CPU
> behind an IOMMU (the MMU-500 dotted line):
> http://www.arm.com/images/CoreLink_MMU-500_in_System.jpg
> Admittedly we're a long way from being able to model that
> since we don't support multiple CPUs in one system yet.

It is possible to do it.

One way is to add IOMMU handling to the memory dispatch routines.  This
was present in Avi's patches.  With the changes to propagate errors
through MMIO dispatch it raises some interesting points WRT
time-of-check-to-time-of-use (we need to ensure the translation is only
done once and reused), but it should be doable and anyway isn't the
biggest problem.  The biggest problem is that, I think, this wouldn't
work because all accesses including reading code would be treated as MMIO.

A second way is to use the IOMMU notifiers to flush the CPU TLB entry
whenever the corresponding IOMMU entry changes.  This is probably not
what hardware does, but it is faster and doesn't have the problem of
code accesses.  The previous versions I sent do this, except I didn't
have the IOMMU notifiers yet.

As in other cases, I prefer no code to untested code.  The design is
sane (it isn't mine, so I can say it :)) and we know it can be done.

> Can we have an assertion if you try to add an IOMMU to
> the CPU's view of memory, so it's obvious if we ever do
> run into this case?

Almost, I have an assertion that triggers if tlb_set_page would be
handed out an IOMMU region.

Paolo

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

* Re: [Qemu-devel] [PATCH 17/30] memory: add address_space_translate
  2013-05-27 10:45                         ` Paolo Bonzini
@ 2013-05-27 11:33                           ` Peter Maydell
  0 siblings, 0 replies; 106+ messages in thread
From: Peter Maydell @ 2013-05-27 11:33 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Jan Kiszka, qemu-devel, David Gibson

On 27 May 2013 11:45, Paolo Bonzini <pbonzini@redhat.com> wrote:
> It is possible to do it.

> As in other cases, I prefer no code to untested code.  The design is
> sane (it isn't mine, so I can say it :)) and we know it can be done.

Agreed; we're a long way from being able to make use of this.

> Almost, I have an assertion that triggers if tlb_set_page would be
> handed out an IOMMU region.

Sounds good.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 21/30] memory: Add iommu map/unmap notifiers
  2013-05-23 19:24     ` Paolo Bonzini
@ 2013-05-29  4:08       ` David Gibson
  0 siblings, 0 replies; 106+ messages in thread
From: David Gibson @ 2013-05-29  4:08 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Peter Maydell, qemu-devel, jan.kiszka

[-- Attachment #1: Type: text/plain, Size: 1543 bytes --]

On Thu, May 23, 2013 at 09:24:30PM +0200, Paolo Bonzini wrote:
> Il 23/05/2013 20:27, Peter Maydell ha scritto:
> > On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> >> From: David Gibson <david@gibson.dropbear.id.au>
> >>
> >> This patch adds a NotifierList to MemoryRegions which represent IOMMUs
> >> allowing other parts of the code to register interest in mappings or
> >> unmappings from the IOMMU.  All IOMMU implementations will need to call
> >> memory_region_notify_iommu() to inform those waiting on the notifier list,
> >> whenever an IOMMU mapping is made or removed.
> >>
> >> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> >> @@ -423,6 +425,11 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
> >>   */
> >>  bool memory_region_is_iommu(MemoryRegion *mr);
> >>
> >> +void memory_region_notify_iommu(MemoryRegion *mr,
> >> +                                IOMMUTLBEntry entry);
> >> +void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n);
> >> +void memory_region_unregister_iommu_notifier(Notifier *n);
> > 
> > These all need doc comments.
> 
> David, can you provide them?  (If not as a patch, just an inline reply
> to this email will do).

I'll see what I can do.  Working on this is no longer my day job, so
it may be a little while...

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

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

end of thread, other threads:[~2013-05-29  4:34 UTC | newest]

Thread overview: 106+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-21 10:57 [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Paolo Bonzini
2013-05-21 10:57 ` [Qemu-devel] [PATCH 01/30] exec: remove obsolete comment Paolo Bonzini
2013-05-21 11:36   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 02/30] exec: eliminate qemu_put_ram_ptr Paolo Bonzini
2013-05-21 11:38   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 03/30] exec: make qemu_get_ram_ptr private Paolo Bonzini
2013-05-21 11:38   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 04/30] exec: eliminate stq_phys_notdirty Paolo Bonzini
2013-05-23 17:32   ` Peter Maydell
2013-05-23 19:18     ` Anthony Liguori
2013-05-23 19:22     ` Paolo Bonzini
2013-05-23 23:14       ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 05/30] memory: assert that PhysPageEntry's ptr does not overflow Paolo Bonzini
2013-05-23 17:36   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 06/30] memory: allow memory_region_find() to run on non-root memory regions Paolo Bonzini
2013-05-23 17:52   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 07/30] memory: Replace open-coded memory_region_is_romd Paolo Bonzini
2013-05-21 11:54   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 08/30] memory: Rename readable flag to romd_mode Paolo Bonzini
2013-05-21 10:57 ` [Qemu-devel] [PATCH 09/30] memory: do not duplicate memory_region_destructor_none Paolo Bonzini
2013-05-21 11:55   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 10/30] memory: make memory_global_sync_dirty_bitmap take an AddressSpace Paolo Bonzini
2013-05-21 11:56   ` Peter Maydell
2013-05-23  1:05   ` David Gibson
2013-05-21 10:57 ` [Qemu-devel] [PATCH 11/30] memory: fix address space initialization/destruction Paolo Bonzini
2013-05-21 11:58   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 12/30] s390x: reduce TARGET_PHYS_ADDR_SPACE_BITS to 62 Paolo Bonzini
2013-05-21 10:57 ` [Qemu-devel] [PATCH 13/30] memory: limit sections in the radix tree to the actual address space size Paolo Bonzini
2013-05-21 12:02   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 14/30] memory: create FlatView for new address spaces Paolo Bonzini
2013-05-21 12:03   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 15/30] memory: add address_space_valid Paolo Bonzini
2013-05-23 12:05   ` David Gibson
2013-05-23 14:22     ` Jan Kiszka
2013-05-23 14:43       ` Paolo Bonzini
2013-05-23 18:04   ` Peter Maydell
2013-05-24  6:13     ` Jan Kiszka
2013-05-24 10:28       ` Jan Kiszka
2013-05-24 10:50       ` Peter Maydell
2013-05-24 11:02         ` Jan Kiszka
2013-05-24  8:02     ` Paolo Bonzini
2013-05-24 10:52       ` Peter Maydell
2013-05-24 12:58         ` Paolo Bonzini
2013-05-24 13:27           ` Peter Maydell
2013-05-24 13:33             ` Paolo Bonzini
2013-05-24 13:38               ` Peter Maydell
2013-05-25  3:44         ` David Gibson
2013-05-25  9:23           ` Peter Maydell
2013-05-26 13:02             ` David Gibson
2013-05-21 10:57 ` [Qemu-devel] [PATCH 16/30] memory: clean up phys_page_find Paolo Bonzini
2013-05-23 18:06   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 17/30] memory: add address_space_translate Paolo Bonzini
2013-05-23  7:09   ` liu ping fan
2013-05-23  9:59     ` Paolo Bonzini
2013-05-23 13:06       ` liu ping fan
2013-05-23 13:17         ` Paolo Bonzini
2013-05-23 18:15   ` Peter Maydell
2013-05-25  6:40   ` Jan Kiszka
2013-05-25  7:47     ` Paolo Bonzini
2013-05-25 10:19       ` Jan Kiszka
2013-05-25 11:20         ` Paolo Bonzini
2013-05-25 11:30           ` Jan Kiszka
2013-05-26  8:56             ` Paolo Bonzini
2013-05-26  9:02               ` Jan Kiszka
2013-05-27  7:20                 ` Paolo Bonzini
2013-05-27  7:23                   ` Jan Kiszka
2013-05-27  8:19                     ` Paolo Bonzini
2013-05-27  8:37                       ` Jan Kiszka
2013-05-27 10:33                       ` Peter Maydell
2013-05-27 10:45                         ` Paolo Bonzini
2013-05-27 11:33                           ` Peter Maydell
2013-05-26  9:01             ` Paolo Bonzini
2013-05-26  9:12               ` Jan Kiszka
2013-05-26 18:23                 ` Paolo Bonzini
2013-05-21 10:57 ` [Qemu-devel] [PATCH 18/30] memory: add return value to address_space_rw/read/write Paolo Bonzini
2013-05-23 18:18   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 19/30] memory: Introduce address_space_lookup_region Paolo Bonzini
2013-05-23 18:19   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 20/30] memory: iommu support Paolo Bonzini
2013-05-23 18:24   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 21/30] memory: Add iommu map/unmap notifiers Paolo Bonzini
2013-05-23 18:27   ` Peter Maydell
2013-05-23 19:24     ` Paolo Bonzini
2013-05-29  4:08       ` David Gibson
2013-05-21 10:57 ` [Qemu-devel] [PATCH 22/30] vfio: abort if an emulated iommu is used Paolo Bonzini
2013-05-21 10:57 ` [Qemu-devel] [PATCH 23/30] spapr: convert TCE API to use an opaque type Paolo Bonzini
2013-05-21 10:57 ` [Qemu-devel] [PATCH 24/30] spapr: make IOMMU translation go through IOMMUTLBEntry Paolo Bonzini
2013-05-21 10:57 ` [Qemu-devel] [PATCH 25/30] spapr: use memory core for iommu support Paolo Bonzini
2013-05-21 10:57 ` [Qemu-devel] [PATCH 26/30] dma: eliminate old-style IOMMU support Paolo Bonzini
2013-05-23 18:31   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 27/30] pci: use memory core for iommu support Paolo Bonzini
2013-05-23 18:36   ` Peter Maydell
2013-05-23 21:22   ` Michael S. Tsirkin
2013-05-21 10:57 ` [Qemu-devel] [PATCH 28/30] spapr_vio: take care of creating our own AddressSpace/DMAContext Paolo Bonzini
2013-05-21 10:57 ` [Qemu-devel] [PATCH 29/30] dma: eliminate DMAContext Paolo Bonzini
2013-05-23 18:40   ` Peter Maydell
2013-05-21 10:57 ` [Qemu-devel] [PATCH 30/30] memory: give name to every AddressSpace Paolo Bonzini
2013-05-23 18:46   ` Peter Maydell
2013-05-22  2:30 ` [Qemu-devel] [PATCH 00/30] Introduction of IOMMUs into the memory API Alexey Kardashevskiy
2013-05-22  9:24   ` Paolo Bonzini
2013-05-23 17:08     ` Paolo Bonzini
2013-05-23 17:25       ` Peter Maydell
2013-05-23 17:30         ` Paolo Bonzini
2013-05-23 18:47         ` Peter Maydell
2013-05-24 14:12       ` Alexey Kardashevskiy
2013-05-24 14:20         ` Paolo Bonzini

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.