[PATCH qemu v8 0/2] memory/iommu: QOM'fy IOMMU MemoryRegion

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH qemu v8 0/2] memory/iommu: QOM'fy IOMMU MemoryRegion

Alexey Kardashevskiy

Here is a couple of patches to QOM'fy IOMMU memory regions.

I have made them in order to proceed with in-kernel TCE stuff acceleration
enablement which sort of depends on sPAPR IOMMU MR being QOM'ed.


This is based on sha1
3f0602927b Peter Maydell "Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20170613' into staging".

Please comment. Thanks.


Changes:
v8:
* now 2 patches



Alexey Kardashevskiy (2):
  memory/iommu: QOM'fy IOMMU MemoryRegion
  memory/iommu: introduce IOMMUMemoryRegionClass

 hw/i386/amd_iommu.h           |   3 --
 hw/s390x/s390-pci-bus.h       |   2 +-
 include/exec/memory.h         |  94 +++++++++++++++++++++++++----------
 include/hw/i386/intel_iommu.h |   3 +-
 include/hw/mips/mips.h        |   2 +-
 include/hw/ppc/spapr.h        |   7 ++-
 include/hw/vfio/vfio-common.h |   2 +-
 include/qemu/typedefs.h       |   1 +
 exec.c                        |  14 +++---
 hw/alpha/typhoon.c            |  31 +++++++++---
 hw/dma/rc4030.c               |  34 +++++++++----
 hw/i386/amd_iommu.c           |  35 ++++++++++---
 hw/i386/intel_iommu.c         |  44 +++++++++++-----
 hw/mips/mips_jazz.c           |   2 +-
 hw/pci-host/apb.c             |  29 ++++++++---
 hw/ppc/spapr_iommu.c          |  42 ++++++++++------
 hw/s390x/s390-pci-bus.c       |  31 ++++++++----
 hw/s390x/s390-pci-inst.c      |  11 ++--
 hw/vfio/common.c              |  12 +++--
 hw/vfio/spapr.c               |   3 +-
 memory.c                      | 113 ++++++++++++++++++++++++++++--------------
 21 files changed, 356 insertions(+), 159 deletions(-)

--
2.11.0


Reply | Threaded
Open this post in threaded view
|

[PATCH qemu v8 1/2] memory/iommu: QOM'fy IOMMU MemoryRegion

Alexey Kardashevskiy
This defines new QOM object - IOMMUMemoryRegion - with MemoryRegion
as a parent.

This moves IOMMU-related fields from MR to IOMMU MR. However to avoid
dymanic QOM casting in fast path (address_space_translate, etc),
this adds an @is_iommu boolean flag to MR and provides new helper to
do simple cast to IOMMU MR - memory_region_get_iommu. The flag
is set in the instance init callback. This defines
memory_region_is_iommu as memory_region_get_iommu()!=NULL.

This switches MemoryRegion to IOMMUMemoryRegion in most places except
the ones where MemoryRegion may be an alias.

Signed-off-by: Alexey Kardashevskiy <[hidden email]>
---
Changes:
v8:
* moved is_iommu flag closer to the beginning of the MemoryRegion struct
* removed memory_region_init_iommu_type()

v7:
* rebased on top of the current upstream

v6:
* s/\<iommumr\>/iommu_mr/g

v5:
* fixed sparc64, first time in many years did run "./configure" without
--target-list :-D Sorry for the noise though :(

v4:
* fixed alpha, mips64el and sparc

v3:
* rebased on sha1 81b2d5ceb0

v2:
* added mr->is_iommu
* updated i386/x86_64/s390/sun
---
 hw/s390x/s390-pci-bus.h       |   2 +-
 include/exec/memory.h         |  55 ++++++++++++++--------
 include/hw/i386/intel_iommu.h |   2 +-
 include/hw/mips/mips.h        |   2 +-
 include/hw/ppc/spapr.h        |   3 +-
 include/hw/vfio/vfio-common.h |   2 +-
 include/qemu/typedefs.h       |   1 +
 exec.c                        |  12 ++---
 hw/alpha/typhoon.c            |   8 ++--
 hw/dma/rc4030.c               |   8 ++--
 hw/i386/amd_iommu.c           |   9 ++--
 hw/i386/intel_iommu.c         |  17 +++----
 hw/mips/mips_jazz.c           |   2 +-
 hw/pci-host/apb.c             |   6 +--
 hw/ppc/spapr_iommu.c          |  16 ++++---
 hw/s390x/s390-pci-bus.c       |   6 +--
 hw/s390x/s390-pci-inst.c      |   8 ++--
 hw/vfio/common.c              |  12 +++--
 hw/vfio/spapr.c               |   3 +-
 memory.c                      | 105 ++++++++++++++++++++++++++++--------------
 20 files changed, 170 insertions(+), 109 deletions(-)

diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index cf142a3e68..6a599ed353 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -266,7 +266,7 @@ typedef struct S390PCIIOMMU {
     S390PCIBusDevice *pbdev;
     AddressSpace as;
     MemoryRegion mr;
-    MemoryRegion iommu_mr;
+    IOMMUMemoryRegion iommu_mr;
     bool enabled;
     uint64_t g_iota;
     uint64_t pba;
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 80e605a96a..8aefea3abc 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -35,6 +35,10 @@
 #define MEMORY_REGION(obj) \
         OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION)
 
+#define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region"
+#define IOMMU_MEMORY_REGION(obj) \
+        OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION)
+
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegionMmio MemoryRegionMmio;
 
@@ -189,16 +193,16 @@ struct MemoryRegionIOMMUOps {
      * set flag to IOMMU_NONE to mean that we don't need any
      * read/write permission checks, like, when for region replay.
      */
-    IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr,
+    IOMMUTLBEntry (*translate)(IOMMUMemoryRegion *iommu, hwaddr addr,
                                IOMMUAccessFlags flag);
     /* Returns minimum supported page size */
-    uint64_t (*get_min_page_size)(MemoryRegion *iommu);
+    uint64_t (*get_min_page_size)(IOMMUMemoryRegion *iommu);
     /* Called when IOMMU Notifier flag changed */
-    void (*notify_flag_changed)(MemoryRegion *iommu,
+    void (*notify_flag_changed)(IOMMUMemoryRegion *iommu,
                                 IOMMUNotifierFlag old_flags,
                                 IOMMUNotifierFlag new_flags);
     /* Set this up to provide customized IOMMU replay function */
-    void (*replay)(MemoryRegion *iommu, IOMMUNotifier *notifier);
+    void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier);
 };
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
@@ -218,9 +222,9 @@ struct MemoryRegion {
     bool flush_coalesced_mmio;
     bool global_locking;
     uint8_t dirty_log_mask;
+    bool is_iommu;
     RAMBlock *ram_block;
     Object *owner;
-    const MemoryRegionIOMMUOps *iommu_ops;
 
     const MemoryRegionOps *ops;
     void *opaque;
@@ -243,6 +247,12 @@ struct MemoryRegion {
     const char *name;
     unsigned ioeventfd_nb;
     MemoryRegionIoeventfd *ioeventfds;
+};
+
+struct IOMMUMemoryRegion {
+    MemoryRegion parent_obj;
+
+    const MemoryRegionIOMMUOps *iommu_ops;
     QLIST_HEAD(, IOMMUNotifier) iommu_notify;
     IOMMUNotifierFlag iommu_notify_flags;
 };
@@ -589,13 +599,13 @@ static inline void memory_region_init_reservation(MemoryRegion *mr,
  * An IOMMU region translates addresses and forwards accesses to a target
  * memory region.
  *
- * @mr: the #MemoryRegion to be initialized
+ * @iommu_mr: the #IOMMUMemoryRegion to be initialized
  * @owner: the object that tracks the region's reference count
  * @ops: a function that translates addresses into the @target region
  * @name: used for debugging; not visible to the user or ABI
  * @size: size of the region.
  */
-void memory_region_init_iommu(MemoryRegion *mr,
+void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
                               struct Object *owner,
                               const MemoryRegionIOMMUOps *ops,
                               const char *name,
@@ -650,20 +660,25 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
 }
 
 /**
- * memory_region_is_iommu: check whether a memory region is an iommu
+ * memory_region_get_iommu: check whether a memory region is an iommu
  *
- * Returns %true is a memory region is an iommu.
+ * Returns pointer to IOMMUMemoryRegion if a memory region is an iommu,
+ * otherwise NULL.
  *
  * @mr: the memory region being queried
  */
-static inline bool memory_region_is_iommu(MemoryRegion *mr)
+static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr)
 {
     if (mr->alias) {
-        return memory_region_is_iommu(mr->alias);
+        return memory_region_get_iommu(mr->alias);
     }
-    return mr->iommu_ops;
+    if (mr->is_iommu) {
+        return (IOMMUMemoryRegion *) mr;
+    }
+    return NULL;
 }
 
+#define memory_region_is_iommu(mr) (memory_region_get_iommu(mr) != NULL)
 
 /**
  * memory_region_iommu_get_min_page_size: get minimum supported page size
@@ -671,9 +686,9 @@ static inline bool memory_region_is_iommu(MemoryRegion *mr)
  *
  * Returns minimum supported page size for an iommu.
  *
- * @mr: the memory region being queried
+ * @iommu_mr: the memory region being queried
  */
-uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
+uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr);
 
 /**
  * memory_region_notify_iommu: notify a change in an IOMMU translation entry.
@@ -687,12 +702,12 @@ uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
  * Note: for any IOMMU implementation, an in-place mapping change
  * should be notified with an UNMAP followed by a MAP.
  *
- * @mr: the memory region that was changed
+ * @iommu_mr: the memory region that was changed
  * @entry: the new entry in the IOMMU translation table.  The entry
  *         replaces all old entries for the same virtual I/O address range.
  *         Deleted entries have .@perm == 0.
  */
-void memory_region_notify_iommu(MemoryRegion *mr,
+void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
                                 IOMMUTLBEntry entry);
 
 /**
@@ -727,18 +742,18 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr,
  * a notifier with the minimum page granularity returned by
  * mr->iommu_ops->get_page_size().
  *
- * @mr: the memory region to observe
+ * @iommu_mr: the memory region to observe
  * @n: the notifier to which to replay iommu mappings
  */
-void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n);
+void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n);
 
 /**
  * memory_region_iommu_replay_all: replay existing IOMMU translations
  * to all the notifiers registered.
  *
- * @mr: the memory region to observe
+ * @iommu_mr: the memory region to observe
  */
-void memory_region_iommu_replay_all(MemoryRegion *mr);
+void memory_region_iommu_replay_all(IOMMUMemoryRegion *iommu_mr);
 
 /**
  * memory_region_unregister_iommu_notifier: unregister a notifier for
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 3e51876b75..45fba4ff97 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -83,7 +83,7 @@ struct VTDAddressSpace {
     PCIBus *bus;
     uint8_t devfn;
     AddressSpace as;
-    MemoryRegion iommu;
+    IOMMUMemoryRegion iommu;
     MemoryRegion root;
     MemoryRegion sys_alias;
     MemoryRegion iommu_ir;      /* Interrupt region: 0xfeeXXXXX */
diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h
index 16412dc150..2f6774d540 100644
--- a/include/hw/mips/mips.h
+++ b/include/hw/mips/mips.h
@@ -19,6 +19,6 @@ typedef struct rc4030DMAState *rc4030_dma;
 void rc4030_dma_read(void *dma, uint8_t *buf, int len);
 void rc4030_dma_write(void *dma, uint8_t *buf, int len);
 
-DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr);
+DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr);
 
 #endif
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index f973b02845..6bd338156b 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -591,7 +591,8 @@ struct sPAPRTCETable {
     bool bypass;
     bool need_vfio;
     int fd;
-    MemoryRegion root, iommu;
+    MemoryRegion root;
+    IOMMUMemoryRegion iommu;
     struct VIOsPAPRDevice *vdev; /* for @bypass migration compatibility only */
     QLIST_ENTRY(sPAPRTCETable) list;
 };
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 9521013d52..d67779729c 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -95,7 +95,7 @@ typedef struct VFIOContainer {
 
 typedef struct VFIOGuestIOMMU {
     VFIOContainer *container;
-    MemoryRegion *iommu;
+    IOMMUMemoryRegion *iommu;
     hwaddr iommu_offset;
     IOMMUNotifier n;
     QLIST_ENTRY(VFIOGuestIOMMU) giommu_next;
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 51958bf7d3..f517c3d88c 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -45,6 +45,7 @@ typedef struct MachineState MachineState;
 typedef struct MemoryListener MemoryListener;
 typedef struct MemoryMappingList MemoryMappingList;
 typedef struct MemoryRegion MemoryRegion;
+typedef struct IOMMUMemoryRegion IOMMUMemoryRegion;
 typedef struct MemoryRegionCache MemoryRegionCache;
 typedef struct MemoryRegionSection MemoryRegionSection;
 typedef struct MigrationIncomingState MigrationIncomingState;
diff --git a/exec.c b/exec.c
index a93e209625..182cc9b9b9 100644
--- a/exec.c
+++ b/exec.c
@@ -475,19 +475,19 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
 {
     IOMMUTLBEntry iotlb;
     MemoryRegionSection *section;
-    MemoryRegion *mr;
+    IOMMUMemoryRegion *iommu_mr;
 
     for (;;) {
         AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
         section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);
-        mr = section->mr;
 
-        if (!mr->iommu_ops) {
+        iommu_mr = memory_region_get_iommu(section->mr);
+        if (!iommu_mr) {
             break;
         }
 
-        iotlb = mr->iommu_ops->translate(mr, addr, is_write ?
-                                         IOMMU_WO : IOMMU_RO);
+        iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, is_write ?
+                                               IOMMU_WO : IOMMU_RO);
         addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
                 | (addr & iotlb.addr_mask));
         *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
@@ -583,7 +583,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr,
 
     section = address_space_translate_internal(d, addr, xlat, plen, false);
 
-    assert(!section->mr->iommu_ops);
+    assert(!memory_region_is_iommu(section->mr));
     return section;
 }
 #endif
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index c1cf7802a4..dd47b4569f 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -41,7 +41,7 @@ typedef struct TyphoonPchip {
     MemoryRegion reg_conf;
 
     AddressSpace iommu_as;
-    MemoryRegion iommu;
+    IOMMUMemoryRegion iommu;
 
     uint64_t ctl;
     TyphoonWindow win[4];
@@ -663,7 +663,8 @@ static bool window_translate(TyphoonWindow *win, hwaddr addr,
 /* Handle PCI-to-system address translation.  */
 /* TODO: A translation failure here ought to set PCI error codes on the
    Pchip and generate a machine check interrupt.  */
-static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
+                                             hwaddr addr,
                                              IOMMUAccessFlags flag)
 {
     TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
@@ -893,7 +894,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
     /* Host memory as seen from the PCI side, via the IOMMU.  */
     memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
                              "iommu-typhoon", UINT64_MAX);
-    address_space_init(&s->pchip.iommu_as, &s->pchip.iommu, "pchip0-pci");
+    address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu),
+                       "pchip0-pci");
     pci_setup_iommu(b, typhoon_pci_dma_iommu, s);
 
     /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index edf9432051..32c06760ef 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -90,7 +90,7 @@ typedef struct rc4030State
     qemu_irq jazz_bus_irq;
 
     /* whole DMA memory region, root of DMA address space */
-    MemoryRegion dma_mr;
+    IOMMUMemoryRegion dma_mr;
     AddressSpace dma_as;
 
     MemoryRegion iomem_chipset;
@@ -488,7 +488,7 @@ static const MemoryRegionOps jazzio_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
                                           IOMMUAccessFlags flag)
 {
     rc4030State *s = container_of(iommu, rc4030State, dma_mr);
@@ -679,7 +679,7 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
 
     memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
                              "rc4030.dma", UINT32_MAX);
-    address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
+    address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma");
 }
 
 static void rc4030_unrealize(DeviceState *dev, Error **errp)
@@ -717,7 +717,7 @@ static void rc4030_register_types(void)
 
 type_init(rc4030_register_types)
 
-DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr)
+DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr)
 {
     DeviceState *dev;
 
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 7b6d4ea3f3..69e68a3e1b 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -52,7 +52,7 @@ struct AMDVIAddressSpace {
     uint8_t bus_num;            /* bus number                           */
     uint8_t devfn;              /* device function                      */
     AMDVIState *iommu_state;    /* AMDVI - one per machine              */
-    MemoryRegion iommu;         /* Device's address translation region  */
+    IOMMUMemoryRegion iommu;    /* Device's address translation region  */
     MemoryRegion iommu_ir;      /* Device's interrupt remapping region  */
     AddressSpace as;            /* device's corresponding address space */
 };
@@ -987,7 +987,7 @@ static inline bool amdvi_is_interrupt_addr(hwaddr addr)
     return addr >= AMDVI_INT_ADDR_FIRST && addr <= AMDVI_INT_ADDR_LAST;
 }
 
-static IOMMUTLBEntry amdvi_translate(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry amdvi_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
                                      IOMMUAccessFlags flag)
 {
     AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
@@ -1046,7 +1046,8 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
 
         memory_region_init_iommu(&iommu_as[devfn]->iommu, OBJECT(s),
                                  &s->iommu_ops, "amd-iommu", UINT64_MAX);
-        address_space_init(&iommu_as[devfn]->as, &iommu_as[devfn]->iommu,
+        address_space_init(&iommu_as[devfn]->as,
+                           MEMORY_REGION(&iommu_as[devfn]->iommu),
                            "amd-iommu");
     }
     return &iommu_as[devfn]->as;
@@ -1067,7 +1068,7 @@ static const MemoryRegionOps mmio_mem_ops = {
     }
 };
 
-static void amdvi_iommu_notify_flag_changed(MemoryRegion *iommu,
+static void amdvi_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
                                             IOMMUNotifierFlag old,
                                             IOMMUNotifierFlag new)
 {
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 15610b9de8..b38d701b32 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -993,9 +993,9 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)
     /* Turn off first then on the other */
     if (use_iommu) {
         memory_region_set_enabled(&as->sys_alias, false);
-        memory_region_set_enabled(&as->iommu, true);
+        memory_region_set_enabled(MEMORY_REGION(&as->iommu), true);
     } else {
-        memory_region_set_enabled(&as->iommu, false);
+        memory_region_set_enabled(MEMORY_REGION(&as->iommu), false);
         memory_region_set_enabled(&as->sys_alias, true);
     }
 
@@ -1378,7 +1378,7 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)
 static int vtd_page_invalidate_notify_hook(IOMMUTLBEntry *entry,
                                            void *private)
 {
-    memory_region_notify_iommu((MemoryRegion *)private, *entry);
+    memory_region_notify_iommu((IOMMUMemoryRegion *)private, *entry);
     return 0;
 }
 
@@ -2357,7 +2357,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
     }
 }
 
-static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
                                          IOMMUAccessFlags flag)
 {
     VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
@@ -2389,7 +2389,7 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
     return ret;
 }
 
-static void vtd_iommu_notify_flag_changed(MemoryRegion *iommu,
+static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
                                           IOMMUNotifierFlag old,
                                           IOMMUNotifierFlag new)
 {
@@ -2832,7 +2832,8 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
         memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
                                             &vtd_dev_as->sys_alias, 1);
         memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
-                                            &vtd_dev_as->iommu, 1);
+                                            MEMORY_REGION(&vtd_dev_as->iommu),
+                                            1);
         vtd_switch_address_space(vtd_dev_as);
     }
     return vtd_dev_as;
@@ -2912,9 +2913,9 @@ static int vtd_replay_hook(IOMMUTLBEntry *entry, void *private)
     return 0;
 }
 
-static void vtd_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
+static void vtd_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
 {
-    VTDAddressSpace *vtd_as = container_of(mr, VTDAddressSpace, iommu);
+    VTDAddressSpace *vtd_as = container_of(iommu_mr, VTDAddressSpace, iommu);
     IntelIOMMUState *s = vtd_as->iommu_state;
     uint8_t bus_n = pci_bus_num(vtd_as->bus);
     VTDContextEntry ce;
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 1cef581878..1f69322c15 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -130,7 +130,7 @@ static void mips_jazz_init(MachineState *machine,
     CPUMIPSState *env;
     qemu_irq *i8259;
     rc4030_dma *dmas;
-    MemoryRegion *rc4030_dma_mr;
+    IOMMUMemoryRegion *rc4030_dma_mr;
     MemoryRegion *isa_mem = g_new(MemoryRegion, 1);
     MemoryRegion *isa_io = g_new(MemoryRegion, 1);
     MemoryRegion *rtc = g_new(MemoryRegion, 1);
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 326f5ef024..76a56ae29b 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -123,7 +123,7 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
 
 typedef struct IOMMUState {
     AddressSpace iommu_as;
-    MemoryRegion iommu;
+    IOMMUMemoryRegion iommu;
 
     uint64_t regs[IOMMU_NREGS];
 } IOMMUState;
@@ -208,7 +208,7 @@ static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
 }
 
 /* Called from RCU critical section */
-static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
                                          IOMMUAccessFlags flag)
 {
     IOMMUState *is = container_of(iommu, IOMMUState, iommu);
@@ -699,7 +699,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
 
     memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
                              "iommu-apb", UINT64_MAX);
-    address_space_init(&is->iommu_as, &is->iommu, "pbm-as");
+    address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as");
     pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
 
     /* APB secondary busses */
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 0341bc069d..05910a608b 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -110,7 +110,8 @@ static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table)
 }
 
 /* Called from RCU critical section */
-static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
+static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMemoryRegion *iommu,
+                                               hwaddr addr,
                                                IOMMUAccessFlags flag)
 {
     sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
@@ -150,14 +151,14 @@ static void spapr_tce_table_pre_save(void *opaque)
                                tcet->bus_offset, tcet->page_shift);
 }
 
-static uint64_t spapr_tce_get_min_page_size(MemoryRegion *iommu)
+static uint64_t spapr_tce_get_min_page_size(IOMMUMemoryRegion *iommu)
 {
     sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
 
     return 1ULL << tcet->page_shift;
 }
 
-static void spapr_tce_notify_flag_changed(MemoryRegion *iommu,
+static void spapr_tce_notify_flag_changed(IOMMUMemoryRegion *iommu,
                                           IOMMUNotifierFlag old,
                                           IOMMUNotifierFlag new)
 {
@@ -348,9 +349,10 @@ void spapr_tce_table_enable(sPAPRTCETable *tcet,
                                         &tcet->fd,
                                         tcet->need_vfio);
 
-    memory_region_set_size(&tcet->iommu,
+    memory_region_set_size(MEMORY_REGION(&tcet->iommu),
                            (uint64_t)tcet->nb_table << tcet->page_shift);
-    memory_region_add_subregion(&tcet->root, tcet->bus_offset, &tcet->iommu);
+    memory_region_add_subregion(&tcet->root, tcet->bus_offset,
+                                MEMORY_REGION(&tcet->iommu));
 }
 
 void spapr_tce_table_disable(sPAPRTCETable *tcet)
@@ -359,8 +361,8 @@ void spapr_tce_table_disable(sPAPRTCETable *tcet)
         return;
     }
 
-    memory_region_del_subregion(&tcet->root, &tcet->iommu);
-    memory_region_set_size(&tcet->iommu, 0);
+    memory_region_del_subregion(&tcet->root, MEMORY_REGION(&tcet->iommu));
+    memory_region_set_size(MEMORY_REGION(&tcet->iommu), 0);
 
     spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
     tcet->fd = -1;
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 5651483781..e4fc82cbe1 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -356,7 +356,7 @@ out:
     return pte;
 }
 
-static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *mr, hwaddr addr,
+static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
                                           IOMMUAccessFlags flag)
 {
     uint64_t pte;
@@ -525,14 +525,14 @@ void s390_pci_iommu_enable(S390PCIIOMMU *iommu)
     memory_region_init_iommu(&iommu->iommu_mr, OBJECT(&iommu->mr),
                              &s390_iommu_ops, name, iommu->pal + 1);
     iommu->enabled = true;
-    memory_region_add_subregion(&iommu->mr, 0, &iommu->iommu_mr);
+    memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu_mr));
     g_free(name);
 }
 
 void s390_pci_iommu_disable(S390PCIIOMMU *iommu)
 {
     iommu->enabled = false;
-    memory_region_del_subregion(&iommu->mr, &iommu->iommu_mr);
+    memory_region_del_subregion(&iommu->mr, MEMORY_REGION(&iommu->iommu_mr));
     object_unparent(OBJECT(&iommu->iommu_mr));
 }
 
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 8bc7c98682..a53c29c487 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -563,7 +563,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
     S390PCIIOMMU *iommu;
     hwaddr start, end;
     IOMMUTLBEntry entry;
-    MemoryRegion *mr;
+    IOMMUMemoryRegion *iommu_mr;
 
     cpu_synchronize_state(CPU(cpu));
 
@@ -622,9 +622,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
         goto out;
     }
 
-    mr = &iommu->iommu_mr;
+    iommu_mr = &iommu->iommu_mr;
     while (start < end) {
-        entry = mr->iommu_ops->translate(mr, start, IOMMU_NONE);
+        entry = iommu_mr->iommu_ops->translate(iommu_mr, start, IOMMU_NONE);
 
         if (!entry.translated_addr) {
             pbdev->state = ZPCI_FS_ERROR;
@@ -635,7 +635,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
             goto out;
         }
 
-        memory_region_notify_iommu(mr, entry);
+        memory_region_notify_iommu(iommu_mr, entry);
         start += entry.addr_mask + 1;
     }
 
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b9abe77f5a..2965b68e5d 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -479,6 +479,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
 
     if (memory_region_is_iommu(section->mr)) {
         VFIOGuestIOMMU *giommu;
+        IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
 
         trace_vfio_listener_region_add_iommu(iova, end);
         /*
@@ -488,7 +489,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
          * device emulation the VFIO iommu handles to use).
          */
         giommu = g_malloc0(sizeof(*giommu));
-        giommu->iommu = section->mr;
+        giommu->iommu = iommu_mr;
         giommu->iommu_offset = section->offset_within_address_space -
                                section->offset_within_region;
         giommu->container = container;
@@ -501,7 +502,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
                             int128_get64(llend));
         QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
 
-        memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);
+        memory_region_register_iommu_notifier(section->mr, &giommu->n);
         memory_region_iommu_replay(giommu->iommu, &giommu->n);
 
         return;
@@ -569,9 +570,9 @@ static void vfio_listener_region_del(MemoryListener *listener,
         VFIOGuestIOMMU *giommu;
 
         QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
-            if (giommu->iommu == section->mr &&
+            if (MEMORY_REGION(giommu->iommu) == section->mr &&
                 giommu->n.start == section->offset_within_region) {
-                memory_region_unregister_iommu_notifier(giommu->iommu,
+                memory_region_unregister_iommu_notifier(section->mr,
                                                         &giommu->n);
                 QLIST_REMOVE(giommu, giommu_next);
                 g_free(giommu);
@@ -1161,7 +1162,8 @@ static void vfio_disconnect_container(VFIOGroup *group)
         QLIST_REMOVE(container, next);
 
         QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
-            memory_region_unregister_iommu_notifier(giommu->iommu, &giommu->n);
+            memory_region_unregister_iommu_notifier(
+                    MEMORY_REGION(giommu->iommu), &giommu->n);
             QLIST_REMOVE(giommu, giommu_next);
             g_free(giommu);
         }
diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
index 4409bcc0d7..32fd6a9b54 100644
--- a/hw/vfio/spapr.c
+++ b/hw/vfio/spapr.c
@@ -143,7 +143,8 @@ int vfio_spapr_create_window(VFIOContainer *container,
                              hwaddr *pgsize)
 {
     int ret;
-    unsigned pagesize = memory_region_iommu_get_min_page_size(section->mr);
+    IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
+    unsigned pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
     unsigned entries, pages;
     struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
 
diff --git a/memory.c b/memory.c
index 0ddc4cc28d..f55b420d88 100644
--- a/memory.c
+++ b/memory.c
@@ -975,12 +975,11 @@ static char *memory_region_escape_name(const char *name)
     return escaped;
 }
 
-void memory_region_init(MemoryRegion *mr,
-                        Object *owner,
-                        const char *name,
-                        uint64_t size)
+static void memory_region_do_init(MemoryRegion *mr,
+                                  Object *owner,
+                                  const char *name,
+                                  uint64_t size)
 {
-    object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
     mr->size = int128_make64(size);
     if (size == UINT64_MAX) {
         mr->size = int128_2_64();
@@ -1004,6 +1003,15 @@ void memory_region_init(MemoryRegion *mr,
     }
 }
 
+void memory_region_init(MemoryRegion *mr,
+                        Object *owner,
+                        const char *name,
+                        uint64_t size)
+{
+    object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
+    memory_region_do_init(mr, owner, name, size);
+}
+
 static void memory_region_get_addr(Object *obj, Visitor *v, const char *name,
                                    void *opaque, Error **errp)
 {
@@ -1090,6 +1098,13 @@ static void memory_region_initfn(Object *obj)
                         NULL, NULL, &error_abort);
 }
 
+static void iommu_memory_region_initfn(Object *obj)
+{
+    MemoryRegion *mr = MEMORY_REGION(obj);
+
+    mr->is_iommu = true;
+}
+
 static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
                                     unsigned size)
 {
@@ -1473,17 +1488,22 @@ void memory_region_init_rom_device(MemoryRegion *mr,
     mr->ram_block = qemu_ram_alloc(size, mr, errp);
 }
 
-void memory_region_init_iommu(MemoryRegion *mr,
+void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
                               Object *owner,
                               const MemoryRegionIOMMUOps *ops,
                               const char *name,
                               uint64_t size)
 {
-    memory_region_init(mr, owner, name, size);
-    mr->iommu_ops = ops,
+    struct MemoryRegion *mr;
+
+    object_initialize(iommu_mr, sizeof(*iommu_mr), TYPE_IOMMU_MEMORY_REGION);
+    mr = MEMORY_REGION(iommu_mr);
+    memory_region_do_init(mr, owner, name, size);
+    iommu_mr = IOMMU_MEMORY_REGION(mr);
+    iommu_mr->iommu_ops = ops,
     mr->terminates = true;  /* then re-forwards */
-    QLIST_INIT(&mr->iommu_notify);
-    mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
+    QLIST_INIT(&iommu_mr->iommu_notify);
+    iommu_mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
 }
 
 static void memory_region_finalize(Object *obj)
@@ -1578,63 +1598,67 @@ bool memory_region_is_logging(MemoryRegion *mr, uint8_t client)
     return memory_region_get_dirty_log_mask(mr) & (1 << client);
 }
 
-static void memory_region_update_iommu_notify_flags(MemoryRegion *mr)
+static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr)
 {
     IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE;
     IOMMUNotifier *iommu_notifier;
 
-    IOMMU_NOTIFIER_FOREACH(iommu_notifier, mr) {
+    IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
         flags |= iommu_notifier->notifier_flags;
     }
 
-    if (flags != mr->iommu_notify_flags &&
-        mr->iommu_ops->notify_flag_changed) {
-        mr->iommu_ops->notify_flag_changed(mr, mr->iommu_notify_flags,
-                                           flags);
+    if (flags != iommu_mr->iommu_notify_flags &&
+        iommu_mr->iommu_ops->notify_flag_changed) {
+        iommu_mr->iommu_ops->notify_flag_changed(iommu_mr,
+                                                iommu_mr->iommu_notify_flags,
+                                                flags);
     }
 
-    mr->iommu_notify_flags = flags;
+    iommu_mr->iommu_notify_flags = flags;
 }
 
 void memory_region_register_iommu_notifier(MemoryRegion *mr,
                                            IOMMUNotifier *n)
 {
+    IOMMUMemoryRegion *iommu_mr;
+
     if (mr->alias) {
         memory_region_register_iommu_notifier(mr->alias, n);
         return;
     }
 
     /* We need to register for at least one bitfield */
+    iommu_mr = IOMMU_MEMORY_REGION(mr);
     assert(n->notifier_flags != IOMMU_NOTIFIER_NONE);
     assert(n->start <= n->end);
-    QLIST_INSERT_HEAD(&mr->iommu_notify, n, node);
-    memory_region_update_iommu_notify_flags(mr);
+    QLIST_INSERT_HEAD(&iommu_mr->iommu_notify, n, node);
+    memory_region_update_iommu_notify_flags(iommu_mr);
 }
 
-uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr)
+uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
 {
-    assert(memory_region_is_iommu(mr));
-    if (mr->iommu_ops && mr->iommu_ops->get_min_page_size) {
-        return mr->iommu_ops->get_min_page_size(mr);
+    if (iommu_mr->iommu_ops && iommu_mr->iommu_ops->get_min_page_size) {
+        return iommu_mr->iommu_ops->get_min_page_size(iommu_mr);
     }
     return TARGET_PAGE_SIZE;
 }
 
-void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
+void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
 {
+    MemoryRegion *mr = MEMORY_REGION(iommu_mr);
     hwaddr addr, granularity;
     IOMMUTLBEntry iotlb;
 
     /* If the IOMMU has its own replay callback, override */
-    if (mr->iommu_ops->replay) {
-        mr->iommu_ops->replay(mr, n);
+    if (iommu_mr->iommu_ops->replay) {
+        iommu_mr->iommu_ops->replay(iommu_mr, n);
         return;
     }
 
-    granularity = memory_region_iommu_get_min_page_size(mr);
+    granularity = memory_region_iommu_get_min_page_size(iommu_mr);
 
     for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
-        iotlb = mr->iommu_ops->translate(mr, addr, IOMMU_NONE);
+        iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, IOMMU_NONE);
         if (iotlb.perm != IOMMU_NONE) {
             n->notify(n, &iotlb);
         }
@@ -1647,24 +1671,27 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
     }
 }
 
-void memory_region_iommu_replay_all(MemoryRegion *mr)
+void memory_region_iommu_replay_all(IOMMUMemoryRegion *iommu_mr)
 {
     IOMMUNotifier *notifier;
 
-    IOMMU_NOTIFIER_FOREACH(notifier, mr) {
-        memory_region_iommu_replay(mr, notifier);
+    IOMMU_NOTIFIER_FOREACH(notifier, iommu_mr) {
+        memory_region_iommu_replay(iommu_mr, notifier);
     }
 }
 
 void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
                                              IOMMUNotifier *n)
 {
+    IOMMUMemoryRegion *iommu_mr;
+
     if (mr->alias) {
         memory_region_unregister_iommu_notifier(mr->alias, n);
         return;
     }
     QLIST_REMOVE(n, node);
-    memory_region_update_iommu_notify_flags(mr);
+    iommu_mr = IOMMU_MEMORY_REGION(mr);
+    memory_region_update_iommu_notify_flags(iommu_mr);
 }
 
 void memory_region_notify_one(IOMMUNotifier *notifier,
@@ -1692,14 +1719,14 @@ void memory_region_notify_one(IOMMUNotifier *notifier,
     }
 }
 
-void memory_region_notify_iommu(MemoryRegion *mr,
+void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
                                 IOMMUTLBEntry entry)
 {
     IOMMUNotifier *iommu_notifier;
 
-    assert(memory_region_is_iommu(mr));
+    assert(memory_region_is_iommu(MEMORY_REGION(iommu_mr)));
 
-    IOMMU_NOTIFIER_FOREACH(iommu_notifier, mr) {
+    IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
         memory_region_notify_one(iommu_notifier, &entry);
     }
 }
@@ -2708,9 +2735,17 @@ static const TypeInfo memory_region_info = {
     .instance_finalize  = memory_region_finalize,
 };
 
+static const TypeInfo iommu_memory_region_info = {
+    .parent             = TYPE_MEMORY_REGION,
+    .name               = TYPE_IOMMU_MEMORY_REGION,
+    .instance_size      = sizeof(IOMMUMemoryRegion),
+    .instance_init      = iommu_memory_region_initfn,
+};
+
 static void memory_register_types(void)
 {
     type_register_static(&memory_region_info);
+    type_register_static(&iommu_memory_region_info);
 }
 
 type_init(memory_register_types)
--
2.11.0


Reply | Threaded
Open this post in threaded view
|

[PATCH qemu v8 2/2] memory/iommu: introduce IOMMUMemoryRegionClass

Alexey Kardashevskiy
In reply to this post by Alexey Kardashevskiy
This finishes QOM'fication of IOMMUMemoryRegion by introducing
a IOMMUMemoryRegionClass. This also provides a fastpath analog for
IOMMU_MEMORY_REGION_GET_CLASS().

Signed-off-by: Alexey Kardashevskiy <[hidden email]>
---
 hw/i386/amd_iommu.h           |  3 ---
 include/exec/memory.h         | 45 +++++++++++++++++++++++++++++++++----------
 include/hw/i386/intel_iommu.h |  1 -
 include/hw/ppc/spapr.h        |  4 ++++
 exec.c                        |  6 ++++--
 hw/alpha/typhoon.c            | 23 +++++++++++++++++-----
 hw/dma/rc4030.c               | 26 +++++++++++++++++++------
 hw/i386/amd_iommu.c           | 26 +++++++++++++++++++++----
 hw/i386/intel_iommu.c         | 27 +++++++++++++++++++++-----
 hw/pci-host/apb.c             | 23 +++++++++++++++++-----
 hw/ppc/spapr_iommu.c          | 26 ++++++++++++++++++-------
 hw/s390x/s390-pci-bus.c       | 25 ++++++++++++++++++------
 hw/s390x/s390-pci-inst.c      |  5 ++++-
 memory.c                      | 36 +++++++++++++++++++---------------
 14 files changed, 206 insertions(+), 70 deletions(-)

diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
index 0d3dc6a9f2..a5a1c32c8b 100644
--- a/hw/i386/amd_iommu.h
+++ b/hw/i386/amd_iommu.h
@@ -276,9 +276,6 @@ typedef struct AMDVIState {
     uint8_t romask[AMDVI_MMIO_SIZE];   /* MMIO read/only mask          */
     bool mmio_enabled;
 
-    /* IOMMU function */
-    MemoryRegionIOMMUOps iommu_ops;
-
     /* for each served device */
     AMDVIAddressSpace **address_spaces[PCI_BUS_MAX];
 
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 8aefea3abc..64f6735aaa 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -25,6 +25,7 @@
 #include "qemu/notify.h"
 #include "qom/object.h"
 #include "qemu/rcu.h"
+#include "hw/qdev-core.h"
 
 #define RAM_ADDR_INVALID (~(ram_addr_t)0)
 
@@ -38,6 +39,12 @@
 #define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region"
 #define IOMMU_MEMORY_REGION(obj) \
         OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION)
+#define IOMMU_MEMORY_REGION_CLASS(klass) \
+        OBJECT_CLASS_CHECK(IOMMUMemoryRegionClass, (klass), \
+                         TYPE_IOMMU_MEMORY_REGION)
+#define IOMMU_MEMORY_REGION_GET_CLASS(obj) \
+        OBJECT_GET_CLASS(IOMMUMemoryRegionClass, (obj), \
+                         TYPE_IOMMU_MEMORY_REGION)
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegionMmio MemoryRegionMmio;
@@ -184,9 +191,10 @@ struct MemoryRegionOps {
     const MemoryRegionMmio old_mmio;
 };
 
-typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;
+typedef struct IOMMUMemoryRegionClass {
+    /* private */
+    struct DeviceClass parent_class;
 
-struct MemoryRegionIOMMUOps {
     /*
      * Return a TLB entry that contains a given address. Flag should
      * be the access permission of this translation operation. We can
@@ -203,7 +211,7 @@ struct MemoryRegionIOMMUOps {
                                 IOMMUNotifierFlag new_flags);
     /* Set this up to provide customized IOMMU replay function */
     void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier);
-};
+} IOMMUMemoryRegionClass;
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
 typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
@@ -252,7 +260,6 @@ struct MemoryRegion {
 struct IOMMUMemoryRegion {
     MemoryRegion parent_obj;
 
-    const MemoryRegionIOMMUOps *iommu_ops;
     QLIST_HEAD(, IOMMUNotifier) iommu_notify;
     IOMMUNotifierFlag iommu_notify_flags;
 };
@@ -593,21 +600,24 @@ static inline void memory_region_init_reservation(MemoryRegion *mr,
 }
 
 /**
- * memory_region_init_iommu: Initialize a memory region that translates
- * addresses
+ * memory_region_init_iommu: Initialize a memory region of a custom type
+ * that translates addresses
  *
  * An IOMMU region translates addresses and forwards accesses to a target
  * memory region.
  *
- * @iommu_mr: the #IOMMUMemoryRegion to be initialized
+ * @typename: QOM class name
+ * @_iommu_mr: the #IOMMUMemoryRegion to be initialized
+ * @instance_size: the IOMMUMemoryRegion subclass instance size
  * @owner: the object that tracks the region's reference count
  * @ops: a function that translates addresses into the @target region
  * @name: used for debugging; not visible to the user or ABI
  * @size: size of the region.
  */
-void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
-                              struct Object *owner,
-                              const MemoryRegionIOMMUOps *ops,
+void memory_region_init_iommu(void *_iommu_mr,
+                              size_t instance_size,
+                              const char *mrtypename,
+                              Object *owner,
                               const char *name,
                               uint64_t size);
 
@@ -678,6 +688,21 @@ static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr)
     return NULL;
 }
 
+/**
+ * memory_region_get_iommu_class_nocheck: returns iommu memory region class
+ *   if an iommu or NULL if not
+ *
+ * Returns pointer to IOMMUMemoryRegioniClass if a memory region is an iommu,
+ * otherwise NULL. This is fast path avoinding QOM checking, use with caution.
+ *
+ * @mr: the memory region being queried
+ */
+static inline IOMMUMemoryRegionClass *memory_region_get_iommu_class_nocheck(
+        IOMMUMemoryRegion *iommu_mr)
+{
+    return (IOMMUMemoryRegionClass *) (((Object *)iommu_mr)->class);
+}
+
 #define memory_region_is_iommu(mr) (memory_region_get_iommu(mr) != NULL)
 
 /**
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 45fba4ff97..e5b5a8ff27 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -289,7 +289,6 @@ struct IntelIOMMUState {
     uint32_t context_cache_gen;     /* Should be in [1,MAX] */
     GHashTable *iotlb;              /* IOTLB */
 
-    MemoryRegionIOMMUOps iommu_ops;
     GHashTable *vtd_as_by_busptr;   /* VTDBus objects indexed by PCIBus* reference */
     VTDBus *vtd_as_by_bus_num[VTD_PCI_BUS_MAX]; /* VTDBus objects indexed by bus number */
     /* list of registered notifiers */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 6bd338156b..13b2d88330 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -579,6 +579,10 @@ typedef struct sPAPRTCETable sPAPRTCETable;
 #define SPAPR_TCE_TABLE(obj) \
     OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE)
 
+#define TYPE_SPAPR_IOMMU_MEMORY_REGION "qemu:spapr-iommu-memory-region"
+#define SPAPR_IOMMU_MEMORY_REGION(obj) \
+        OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_SPAPR_IOMMU_MEMORY_REGION)
+
 struct sPAPRTCETable {
     DeviceState parent;
     uint32_t liobn;
diff --git a/exec.c b/exec.c
index 182cc9b9b9..acba7fc303 100644
--- a/exec.c
+++ b/exec.c
@@ -476,6 +476,7 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
     IOMMUTLBEntry iotlb;
     MemoryRegionSection *section;
     IOMMUMemoryRegion *iommu_mr;
+    IOMMUMemoryRegionClass *imrc;
 
     for (;;) {
         AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
@@ -485,9 +486,10 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
         if (!iommu_mr) {
             break;
         }
+        imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
 
-        iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, is_write ?
-                                               IOMMU_WO : IOMMU_RO);
+        iotlb = imrc->translate(iommu_mr, addr, is_write ?
+                                IOMMU_WO : IOMMU_RO);
         addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
                 | (addr & iotlb.addr_mask));
         *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index dd47b4569f..491433e12f 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -17,6 +17,7 @@
 
 
 #define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
+#define TYPE_TYPHOON_IOMMU_MEMORY_REGION "typhoon:iommu_memory_region"
 
 typedef struct TyphoonCchip {
     MemoryRegion region;
@@ -725,10 +726,6 @@ static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
     return ret;
 }
 
-static const MemoryRegionIOMMUOps typhoon_iommu_ops = {
-    .translate = typhoon_translate_iommu,
-};
-
 static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
 {
     TyphoonState *s = opaque;
@@ -892,7 +889,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
     qdev_init_nofail(dev);
 
     /* Host memory as seen from the PCI side, via the IOMMU.  */
-    memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
+    memory_region_init_iommu(&s->pchip.iommu, sizeof(s->pchip.iommu),
+                             TYPE_TYPHOON_IOMMU_MEMORY_REGION, OBJECT(s),
                              "iommu-typhoon", UINT64_MAX);
     address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu),
                        "pchip0-pci");
@@ -953,9 +951,24 @@ static const TypeInfo typhoon_pcihost_info = {
     .class_init    = typhoon_pcihost_class_init,
 };
 
+static void typhoon_iommu_memory_region_class_init(ObjectClass *klass,
+                                                   void *data)
+{
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+    imrc->translate = typhoon_translate_iommu;
+}
+
+static const TypeInfo typhoon_iommu_memory_region_info = {
+    .parent = TYPE_IOMMU_MEMORY_REGION,
+    .name = TYPE_TYPHOON_IOMMU_MEMORY_REGION,
+    .class_init = typhoon_iommu_memory_region_class_init,
+};
+
 static void typhoon_register_types(void)
 {
     type_register_static(&typhoon_pcihost_info);
+    type_register_static(&typhoon_iommu_memory_region_info);
 }
 
 type_init(typhoon_register_types)
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index 32c06760ef..6a49e4ef4a 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -54,6 +54,8 @@ typedef struct dma_pagetable_entry {
 #define RC4030(obj) \
     OBJECT_CHECK(rc4030State, (obj), TYPE_RC4030)
 
+#define TYPE_RC4030_IOMMU_MEMORY_REGION "rc4030:iommu_memory_region"
+
 typedef struct rc4030State
 {
     SysBusDevice parent;
@@ -516,10 +518,6 @@ static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
     return ret;
 }
 
-static const MemoryRegionIOMMUOps rc4030_dma_ops = {
-    .translate = rc4030_dma_translate,
-};
-
 static void rc4030_reset(DeviceState *dev)
 {
     rc4030State *s = RC4030(dev);
@@ -677,8 +675,9 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
     memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
                           "rc4030.jazzio", 0x00001000);
 
-    memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
-                             "rc4030.dma", UINT32_MAX);
+    memory_region_init_iommu(&s->dma_mr, sizeof(s->dma_mr),
+                             TYPE_RC4030_IOMMU_MEMORY_REGION,
+                             o, "rc4030.dma", UINT32_MAX);
     address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma");
 }
 
@@ -710,9 +709,24 @@ static const TypeInfo rc4030_info = {
     .class_init = rc4030_class_init,
 };
 
+static void rc4030_iommu_memory_region_class_init(ObjectClass *klass,
+                                                  void *data)
+{
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+    imrc->translate = rc4030_dma_translate;
+}
+
+static const TypeInfo rc4030_iommu_memory_region_info = {
+    .parent = TYPE_IOMMU_MEMORY_REGION,
+    .name = TYPE_RC4030_IOMMU_MEMORY_REGION,
+    .class_init = rc4030_iommu_memory_region_class_init,
+};
+
 static void rc4030_register_types(void)
 {
     type_register_static(&rc4030_info);
+    type_register_static(&rc4030_iommu_memory_region_info);
 }
 
 type_init(rc4030_register_types)
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 69e68a3e1b..af19e8ea41 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -25,6 +25,8 @@
 #include "qemu/error-report.h"
 #include "trace.h"
 
+#define TYPE_AMD_VI_IOMMU_MEMORY_REGION "amd_vi:iommu_memory_region"
+
 /* used AMD-Vi MMIO registers */
 const char *amdvi_mmio_low[] = {
     "AMDVI_MMIO_DEVTAB_BASE",
@@ -1044,8 +1046,11 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
         iommu_as[devfn]->devfn = (uint8_t)devfn;
         iommu_as[devfn]->iommu_state = s;
 
-        memory_region_init_iommu(&iommu_as[devfn]->iommu, OBJECT(s),
-                                 &s->iommu_ops, "amd-iommu", UINT64_MAX);
+        memory_region_init_iommu(&iommu_as[devfn]->iommu,
+                                 sizeof(iommu_as[devfn]->iommu),
+                                 TYPE_AMD_VI_IOMMU_MEMORY_REGION,
+                                 OBJECT(s),
+                                 "amd-iommu", UINT64_MAX);
         address_space_init(&iommu_as[devfn]->as,
                            MEMORY_REGION(&iommu_as[devfn]->iommu),
                            "amd-iommu");
@@ -1086,8 +1091,6 @@ static void amdvi_init(AMDVIState *s)
 {
     amdvi_iotlb_reset(s);
 
-    s->iommu_ops.translate = amdvi_translate;
-    s->iommu_ops.notify_flag_changed = amdvi_iommu_notify_flag_changed;
     s->devtab_len = 0;
     s->cmdbuf_len = 0;
     s->cmdbuf_head = 0;
@@ -1218,10 +1221,25 @@ static const TypeInfo amdviPCI = {
     .instance_size = sizeof(AMDVIPCIState),
 };
 
+static void amdvi_iommu_memory_region_class_init(ObjectClass *klass, void *data)
+{
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+    imrc->translate = amdvi_translate;
+    imrc->notify_flag_changed = amdvi_iommu_notify_flag_changed;
+}
+
+static const TypeInfo amdvi_iommu_memory_region_info = {
+    .parent = TYPE_IOMMU_MEMORY_REGION,
+    .name = TYPE_AMD_VI_IOMMU_MEMORY_REGION,
+    .class_init = amdvi_iommu_memory_region_class_init,
+};
+
 static void amdviPCI_register_types(void)
 {
     type_register_static(&amdviPCI);
     type_register_static(&amdvi);
+    type_register_static(&amdvi_iommu_memory_region_info);
 }
 
 type_init(amdviPCI_register_types);
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index b38d701b32..8aafd6ba5b 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -37,6 +37,8 @@
 #include "kvm_i386.h"
 #include "trace.h"
 
+#define TYPE_INTEL_VTD_IOMMU_MEMORY_REGION "intel_vtd:iommu_memory_region"
+
 /*#define DEBUG_INTEL_IOMMU*/
 #ifdef DEBUG_INTEL_IOMMU
 enum {
@@ -2814,8 +2816,9 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
          * vtd_sys_alias and intel_iommu regions. IR region is always
          * enabled.
          */
-        memory_region_init_iommu(&vtd_dev_as->iommu, OBJECT(s),
-                                 &s->iommu_ops, "intel_iommu_dmar",
+        memory_region_init_iommu(&vtd_dev_as->iommu, sizeof(vtd_dev_as->iommu),
+                                 TYPE_INTEL_VTD_IOMMU_MEMORY_REGION, OBJECT(s),
+                                 "intel_iommu_dmar",
                                  UINT64_MAX);
         memory_region_init_alias(&vtd_dev_as->sys_alias, OBJECT(s),
                                  "vtd_sys_alias", get_system_memory(),
@@ -2953,9 +2956,6 @@ static void vtd_init(IntelIOMMUState *s)
     memset(s->w1cmask, 0, DMAR_REG_SIZE);
     memset(s->womask, 0, DMAR_REG_SIZE);
 
-    s->iommu_ops.translate = vtd_iommu_translate;
-    s->iommu_ops.notify_flag_changed = vtd_iommu_notify_flag_changed;
-    s->iommu_ops.replay = vtd_iommu_replay;
     s->root = 0;
     s->root_extended = false;
     s->dmar_enabled = false;
@@ -3172,10 +3172,27 @@ static const TypeInfo vtd_info = {
     .class_init    = vtd_class_init,
 };
 
+static void intel_vtd_iommu_memory_region_class_init(ObjectClass *klass,
+                                                     void *data)
+{
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+    imrc->translate = vtd_iommu_translate;
+    imrc->notify_flag_changed = vtd_iommu_notify_flag_changed;
+    imrc->replay = vtd_iommu_replay;
+}
+
+static const TypeInfo intel_vtd_iommu_memory_region_info = {
+    .parent = TYPE_IOMMU_MEMORY_REGION,
+    .name = TYPE_INTEL_VTD_IOMMU_MEMORY_REGION,
+    .class_init = intel_vtd_iommu_memory_region_class_init,
+};
+
 static void vtd_register_types(void)
 {
     VTD_DPRINTF(GENERAL, "");
     type_register_static(&vtd_info);
+    type_register_static(&intel_vtd_iommu_memory_region_info);
 }
 
 type_init(vtd_register_types)
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 76a56ae29b..f1a854159a 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -133,6 +133,8 @@ typedef struct IOMMUState {
 #define APB_DEVICE(obj) \
     OBJECT_CHECK(APBState, (obj), TYPE_APB)
 
+#define TYPE_PBM_IOMMU_MEMORY_REGION "pbm:iommu_memory_region"
+
 typedef struct APBState {
     PCIHostState parent_obj;
 
@@ -322,10 +324,6 @@ static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
     return ret;
 }
 
-static MemoryRegionIOMMUOps pbm_iommu_ops = {
-    .translate = pbm_translate_iommu,
-};
-
 static void iommu_config_write(void *opaque, hwaddr addr,
                                uint64_t val, unsigned size)
 {
@@ -697,7 +695,8 @@ PCIBus *pci_apb_init(hwaddr special_base,
     is = &d->iommu;
     memset(is, 0, sizeof(IOMMUState));
 
-    memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
+    memory_region_init_iommu(&is->iommu, sizeof(is->iommu),
+                             TYPE_PBM_IOMMU_MEMORY_REGION, OBJECT(dev),
                              "iommu-apb", UINT64_MAX);
     address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as");
     pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
@@ -860,11 +859,25 @@ static const TypeInfo pbm_pci_bridge_info = {
     .class_init    = pbm_pci_bridge_class_init,
 };
 
+static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data)
+{
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+    imrc->translate = pbm_translate_iommu;
+}
+
+static const TypeInfo pbm_iommu_memory_region_info = {
+    .parent = TYPE_IOMMU_MEMORY_REGION,
+    .name = TYPE_PBM_IOMMU_MEMORY_REGION,
+    .class_init = pbm_iommu_memory_region_class_init,
+};
+
 static void pbm_register_types(void)
 {
     type_register_static(&pbm_host_info);
     type_register_static(&pbm_pci_host_info);
     type_register_static(&pbm_pci_bridge_info);
+    type_register_static(&pbm_iommu_memory_region_info);
 }
 
 type_init(pbm_register_types)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 05910a608b..c1cb14b84a 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -248,12 +248,6 @@ static const VMStateDescription vmstate_spapr_tce_table = {
     }
 };
 
-static MemoryRegionIOMMUOps spapr_iommu_ops = {
-    .translate = spapr_tce_translate_iommu,
-    .get_min_page_size = spapr_tce_get_min_page_size,
-    .notify_flag_changed = spapr_tce_notify_flag_changed,
-};
-
 static int spapr_tce_table_realize(DeviceState *dev)
 {
     sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
@@ -266,7 +260,9 @@ static int spapr_tce_table_realize(DeviceState *dev)
     memory_region_init(&tcet->root, tcetobj, tmp, UINT64_MAX);
 
     snprintf(tmp, sizeof(tmp), "tce-iommu-%x", tcet->liobn);
-    memory_region_init_iommu(&tcet->iommu, tcetobj, &spapr_iommu_ops, tmp, 0);
+    memory_region_init_iommu(&tcet->iommu, sizeof(tcet->iommu),
+                             TYPE_SPAPR_IOMMU_MEMORY_REGION,
+                             tcetobj, tmp, 0);
 
     QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
 
@@ -639,9 +635,25 @@ static TypeInfo spapr_tce_table_info = {
     .class_init = spapr_tce_table_class_init,
 };
 
+static void spapr_iommu_memory_region_class_init(ObjectClass *klass, void *data)
+{
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+    imrc->translate = spapr_tce_translate_iommu;
+    imrc->get_min_page_size = spapr_tce_get_min_page_size;
+    imrc->notify_flag_changed = spapr_tce_notify_flag_changed;
+}
+
+static const TypeInfo spapr_iommu_memory_region_info = {
+    .parent = TYPE_IOMMU_MEMORY_REGION,
+    .name = TYPE_SPAPR_IOMMU_MEMORY_REGION,
+    .class_init = spapr_iommu_memory_region_class_init,
+};
+
 static void register_types(void)
 {
     type_register_static(&spapr_tce_table_info);
+    type_register_static(&spapr_iommu_memory_region_info);
 }
 
 type_init(register_types);
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index e4fc82cbe1..6720492d63 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -27,6 +27,8 @@
 #define DEBUG_S390PCI_BUS  0
 #endif
 
+#define TYPE_S390_IOMMU_MEMORY_REGION "s390:iommu_memory_region"
+
 #define DPRINTF(fmt, ...)                                         \
     do {                                                          \
         if (DEBUG_S390PCI_BUS) {                                  \
@@ -407,10 +409,6 @@ static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
     return ret;
 }
 
-static const MemoryRegionIOMMUOps s390_iommu_ops = {
-    .translate = s390_translate_iommu,
-};
-
 static S390PCIIOMMU *s390_pci_get_iommu(S390pciState *s, PCIBus *bus,
                                         int devfn)
 {
@@ -522,8 +520,9 @@ static const MemoryRegionOps s390_msi_ctrl_ops = {
 void s390_pci_iommu_enable(S390PCIIOMMU *iommu)
 {
     char *name = g_strdup_printf("iommu-s390-%04x", iommu->pbdev->uid);
-    memory_region_init_iommu(&iommu->iommu_mr, OBJECT(&iommu->mr),
-                             &s390_iommu_ops, name, iommu->pal + 1);
+    memory_region_init_iommu(&iommu->iommu_mr, sizeof(iommu->iommu_mr),
+                             TYPE_S390_IOMMU_MEMORY_REGION, OBJECT(&iommu->mr),
+                             name, iommu->pal + 1);
     iommu->enabled = true;
     memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu_mr));
     g_free(name);
@@ -1058,12 +1057,26 @@ static TypeInfo s390_pci_iommu_info = {
     .instance_size = sizeof(S390PCIIOMMU),
 };
 
+static void s390_iommu_memory_region_class_init(ObjectClass *klass, void *data)
+{
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+    imrc->translate = s390_translate_iommu;
+}
+
+static const TypeInfo s390_iommu_memory_region_info = {
+    .parent = TYPE_IOMMU_MEMORY_REGION,
+    .name = TYPE_S390_IOMMU_MEMORY_REGION,
+    .class_init = s390_iommu_memory_region_class_init,
+};
+
 static void s390_pci_register_types(void)
 {
     type_register_static(&s390_pcihost_info);
     type_register_static(&s390_pcibus_info);
     type_register_static(&s390_pci_device_info);
     type_register_static(&s390_pci_iommu_info);
+    type_register_static(&s390_iommu_memory_region_info);
 }
 
 type_init(s390_pci_register_types)
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index a53c29c487..b7beb8c36a 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -564,6 +564,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
     hwaddr start, end;
     IOMMUTLBEntry entry;
     IOMMUMemoryRegion *iommu_mr;
+    IOMMUMemoryRegionClass *imrc;
 
     cpu_synchronize_state(CPU(cpu));
 
@@ -623,8 +624,10 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
     }
 
     iommu_mr = &iommu->iommu_mr;
+    imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
+
     while (start < end) {
-        entry = iommu_mr->iommu_ops->translate(iommu_mr, start, IOMMU_NONE);
+        entry = imrc->translate(iommu_mr, start, IOMMU_NONE);
 
         if (!entry.translated_addr) {
             pbdev->state = ZPCI_FS_ERROR;
diff --git a/memory.c b/memory.c
index f55b420d88..20472ca19a 100644
--- a/memory.c
+++ b/memory.c
@@ -1488,19 +1488,20 @@ void memory_region_init_rom_device(MemoryRegion *mr,
     mr->ram_block = qemu_ram_alloc(size, mr, errp);
 }
 
-void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
+void memory_region_init_iommu(void *_iommu_mr,
+                              size_t instance_size,
+                              const char *mrtypename,
                               Object *owner,
-                              const MemoryRegionIOMMUOps *ops,
                               const char *name,
                               uint64_t size)
 {
+    struct IOMMUMemoryRegion *iommu_mr;
     struct MemoryRegion *mr;
 
-    object_initialize(iommu_mr, sizeof(*iommu_mr), TYPE_IOMMU_MEMORY_REGION);
-    mr = MEMORY_REGION(iommu_mr);
+    object_initialize(_iommu_mr, instance_size, mrtypename);
+    mr = MEMORY_REGION(_iommu_mr);
     memory_region_do_init(mr, owner, name, size);
     iommu_mr = IOMMU_MEMORY_REGION(mr);
-    iommu_mr->iommu_ops = ops,
     mr->terminates = true;  /* then re-forwards */
     QLIST_INIT(&iommu_mr->iommu_notify);
     iommu_mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
@@ -1602,16 +1603,16 @@ static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr)
 {
     IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE;
     IOMMUNotifier *iommu_notifier;
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
 
     IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
         flags |= iommu_notifier->notifier_flags;
     }
 
-    if (flags != iommu_mr->iommu_notify_flags &&
-        iommu_mr->iommu_ops->notify_flag_changed) {
-        iommu_mr->iommu_ops->notify_flag_changed(iommu_mr,
-                                                iommu_mr->iommu_notify_flags,
-                                                flags);
+    if (flags != iommu_mr->iommu_notify_flags && imrc->notify_flag_changed) {
+        imrc->notify_flag_changed(iommu_mr,
+                                  iommu_mr->iommu_notify_flags,
+                                  flags);
     }
 
     iommu_mr->iommu_notify_flags = flags;
@@ -1637,8 +1638,10 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr,
 
 uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
 {
-    if (iommu_mr->iommu_ops && iommu_mr->iommu_ops->get_min_page_size) {
-        return iommu_mr->iommu_ops->get_min_page_size(iommu_mr);
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
+
+    if (imrc->get_min_page_size) {
+        return imrc->get_min_page_size(iommu_mr);
     }
     return TARGET_PAGE_SIZE;
 }
@@ -1646,19 +1649,20 @@ uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
 void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
 {
     MemoryRegion *mr = MEMORY_REGION(iommu_mr);
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
     hwaddr addr, granularity;
     IOMMUTLBEntry iotlb;
 
     /* If the IOMMU has its own replay callback, override */
-    if (iommu_mr->iommu_ops->replay) {
-        iommu_mr->iommu_ops->replay(iommu_mr, n);
+    if (imrc->replay) {
+        imrc->replay(iommu_mr, n);
         return;
     }
 
     granularity = memory_region_iommu_get_min_page_size(iommu_mr);
 
     for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
-        iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, IOMMU_NONE);
+        iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE);
         if (iotlb.perm != IOMMU_NONE) {
             n->notify(n, &iotlb);
         }
@@ -2738,8 +2742,10 @@ static const TypeInfo memory_region_info = {
 static const TypeInfo iommu_memory_region_info = {
     .parent             = TYPE_MEMORY_REGION,
     .name               = TYPE_IOMMU_MEMORY_REGION,
+    .class_size         = sizeof(IOMMUMemoryRegionClass),
     .instance_size      = sizeof(IOMMUMemoryRegion),
     .instance_init      = iommu_memory_region_initfn,
+    .abstract           = true,
 };
 
 static void memory_register_types(void)
--
2.11.0


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH qemu v8 0/2] memory/iommu: QOM'fy IOMMU MemoryRegion

no-reply
In reply to this post by Alexey Kardashevskiy
Hi,

This series failed automatic build test. Please find the testing commands and
their output below. If you have docker installed, you can probably reproduce it
locally.

Subject: [Qemu-devel] [PATCH qemu v8 0/2] memory/iommu: QOM'fy IOMMU MemoryRegion
Message-id: [hidden email]
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
export J=8
time make docker-test-quick@centos6
time make docker-test-mingw@fedora
time make docker-test-build@min-glib
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/[hidden email] -> patchew/[hidden email]
Switched to a new branch 'test'
3d08aca memory/iommu: introduce IOMMUMemoryRegionClass
d1443b0 memory/iommu: QOM'fy IOMMU MemoryRegion

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-v86bvvd0/src/dtc'...
Submodule path 'dtc': checked out '558cd81bdd432769b59bff01240c44f82cfb1a9d'
  BUILD   centos6
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-v86bvvd0/src'
  ARCHIVE qemu.tgz
  ARCHIVE dtc.tgz
  COPY    RUNNER
    RUN test-quick in qemu:centos6
Packages installed:
SDL-devel-1.2.14-7.el6_7.1.x86_64
ccache-3.1.6-2.el6.x86_64
epel-release-6-8.noarch
gcc-4.4.7-17.el6.x86_64
git-1.7.1-4.el6_7.1.x86_64
glib2-devel-2.28.8-5.el6.x86_64
libfdt-devel-1.4.0-1.el6.x86_64
make-3.81-23.el6.x86_64
package g++ is not installed
pixman-devel-0.32.8-1.el6.x86_64
tar-1.23-15.el6_8.x86_64
zlib-devel-1.2.3-29.el6.x86_64

Environment variables:
PACKAGES=libfdt-devel ccache     tar git make gcc g++     zlib-devel glib2-devel SDL-devel pixman-devel     epel-release
HOSTNAME=9ac9c982a75b
TERM=xterm
MAKEFLAGS= -j8
HISTSIZE=1000
J=8
USER=root
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
LANG=en_US.UTF-8
TARGET_LIST=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES= dtc
DEBUG=
G_BROKEN_FILENAMES=1
CCACHE_HASHDIR=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/var/tmp/qemu-build/install
/tmp/qemu-test/src/configure: line 4683: c++: command not found
No C++ compiler available; disabling C++ specific optional code
Install prefix    /var/tmp/qemu-build/install
BIOS directory    /var/tmp/qemu-build/install/share/qemu
binary directory  /var/tmp/qemu-build/install/bin
library directory /var/tmp/qemu-build/install/lib
module directory  /var/tmp/qemu-build/install/lib/qemu
libexec directory /var/tmp/qemu-build/install/libexec
include directory /var/tmp/qemu-build/install/include
config directory  /var/tmp/qemu-build/install/etc
local state directory   /var/tmp/qemu-build/install/var
Manual directory  /var/tmp/qemu-build/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path       /tmp/qemu-test/src
C compiler        cc
Host C compiler   cc
C++ compiler      
Objective-C compiler cc
ARFLAGS           rv
CFLAGS            -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g
QEMU_CFLAGS       -I/usr/include/pixman-1   -I$(SRC_PATH)/dtc/libfdt -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include   -fPIE -DPIE -m64 -mcx16 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wendif-labels -Wno-missing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-all
LDFLAGS           -Wl,--warn-common -Wl,-z,relro -Wl,-z,now -pie -m64 -g
make              make
install           install
python            python -B
smbd              /usr/sbin/smbd
module support    no
host CPU          x86_64
host big endian   no
target list       x86_64-softmmu aarch64-softmmu
tcg debug enabled no
gprof enabled     no
sparse enabled    no
strip binaries    yes
profiler          no
static build      no
pixman            system
SDL support       yes (1.2.14)
GTK support       no
GTK GL support    no
VTE support       no
TLS priority      NORMAL
GNUTLS support    no
GNUTLS rnd        no
libgcrypt         no
libgcrypt kdf     no
nettle            no
nettle kdf        no
libtasn1          no
curses support    no
virgl support     no
curl support      no
mingw32 support   no
Audio drivers     oss
Block whitelist (rw)
Block whitelist (ro)
VirtFS support    no
VNC support       yes
VNC SASL support  no
VNC JPEG support  no
VNC PNG support   no
xen support       no
brlapi support    no
bluez  support    no
Documentation     no
PIE               yes
vde support       no
netmap support    no
Linux AIO support no
ATTR/XATTR support yes
Install blobs     yes
KVM support       yes
HAX support       no
RDMA support      no
TCG interpreter   no
fdt support       yes
preadv support    yes
fdatasync         yes
madvise           yes
posix_madvise     yes
libcap-ng support no
vhost-net support yes
vhost-scsi support yes
vhost-vsock support yes
Trace backends    log
spice support     no
rbd support       no
xfsctl support    no
smartcard support no
libusb            no
usb net redir     no
OpenGL support    no
OpenGL dmabufs    no
libiscsi support  no
libnfs support    no
build guest agent yes
QGA VSS support   no
QGA w32 disk info no
QGA MSI support   no
seccomp support   no
coroutine backend ucontext
coroutine pool    yes
debug stack usage no
GlusterFS support no
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   no
TPM passthrough   yes
QOM debugging     yes
Live block migration yes
lzo support       no
snappy support    no
bzip2 support     no
NUMA host support no
tcmalloc support  no
jemalloc support  no
avx2 optimization no
replication support yes
VxHS block device no
  GEN     x86_64-softmmu/config-devices.mak.tmp
mkdir -p dtc/libfdt
  GEN     aarch64-softmmu/config-devices.mak.tmp
mkdir -p dtc/tests
  GEN     qemu-options.def
  GEN     qmp-commands.h
  GEN     config-host.h
  GEN     qapi-visit.h
  GEN     qapi-types.h
  GEN     qapi-event.h
  GEN     x86_64-softmmu/config-devices.mak
  GEN     qmp-marshal.c
  GEN     aarch64-softmmu/config-devices.mak
  GEN     qapi-types.c
  GEN     qapi-visit.c
  GEN     qapi-event.c
  GEN     qmp-introspect.h
  GEN     qmp-introspect.c
  GEN     trace/generated-tcg-tracers.h
  GEN     trace/generated-helpers-wrappers.h
  GEN     trace/generated-helpers.h
  GEN     trace/generated-helpers.c
  GEN     module_block.h
  GEN     tests/test-qapi-types.h
  GEN     tests/test-qapi-visit.h
  GEN     tests/test-qmp-commands.h
  GEN     tests/test-qapi-event.h
  GEN     tests/test-qmp-introspect.h
  GEN     trace-root.h
  GEN     util/trace.h
  GEN     crypto/trace.h
  GEN     io/trace.h
  GEN     migration/trace.h
  GEN     block/trace.h
  GEN     backends/trace.h
  GEN     chardev/trace.h
  GEN     hw/block/trace.h
  GEN     hw/block/dataplane/trace.h
  GEN     hw/char/trace.h
  GEN     hw/intc/trace.h
  GEN     hw/net/trace.h
  GEN     hw/virtio/trace.h
  GEN     hw/audio/trace.h
  GEN     hw/misc/trace.h
  GEN     hw/usb/trace.h
  GEN     hw/scsi/trace.h
  GEN     hw/nvram/trace.h
  GEN     hw/display/trace.h
  GEN     hw/input/trace.h
  GEN     hw/timer/trace.h
  GEN     hw/dma/trace.h
  GEN     hw/sparc/trace.h
  GEN     hw/sd/trace.h
  GEN     hw/isa/trace.h
  GEN     hw/mem/trace.h
  GEN     hw/i386/trace.h
  GEN     hw/i386/xen/trace.h
  GEN     hw/9pfs/trace.h
  GEN     hw/ppc/trace.h
  GEN     hw/pci/trace.h
  GEN     hw/s390x/trace.h
  GEN     hw/vfio/trace.h
  GEN     hw/acpi/trace.h
  GEN     hw/arm/trace.h
  GEN     hw/alpha/trace.h
  GEN     hw/xen/trace.h
  GEN     ui/trace.h
  GEN     audio/trace.h
  GEN     net/trace.h
  GEN     target/arm/trace.h
  GEN     target/i386/trace.h
  GEN     target/mips/trace.h
  GEN     target/sparc/trace.h
  GEN     target/s390x/trace.h
  GEN     target/ppc/trace.h
  GEN     qom/trace.h
  GEN     linux-user/trace.h
  GEN     qapi/trace.h
  GEN     trace-root.c
  GEN     util/trace.c
  GEN     crypto/trace.c
  GEN     io/trace.c
  GEN     migration/trace.c
  GEN     block/trace.c
  GEN     backends/trace.c
  GEN     chardev/trace.c
  GEN     hw/block/trace.c
  GEN     hw/block/dataplane/trace.c
  GEN     hw/char/trace.c
  GEN     hw/intc/trace.c
  GEN     hw/net/trace.c
  GEN     hw/virtio/trace.c
  GEN     hw/audio/trace.c
  GEN     hw/misc/trace.c
  GEN     hw/usb/trace.c
  GEN     hw/scsi/trace.c
  GEN     hw/nvram/trace.c
  GEN     hw/display/trace.c
  GEN     hw/input/trace.c
  GEN     hw/timer/trace.c
  GEN     hw/dma/trace.c
  GEN     hw/sparc/trace.c
  GEN     hw/sd/trace.c
  GEN     hw/isa/trace.c
  GEN     hw/mem/trace.c
  GEN     hw/i386/trace.c
  GEN     hw/i386/xen/trace.c
  GEN     hw/9pfs/trace.c
  GEN     hw/ppc/trace.c
  GEN     hw/pci/trace.c
  GEN     hw/s390x/trace.c
  GEN     hw/vfio/trace.c
  GEN     hw/acpi/trace.c
  GEN     hw/arm/trace.c
  GEN     hw/alpha/trace.c
  GEN     hw/xen/trace.c
  GEN     ui/trace.c
  GEN     audio/trace.c
  GEN     net/trace.c
  GEN     target/arm/trace.c
  GEN     target/i386/trace.c
  GEN     target/mips/trace.c
  GEN     target/sparc/trace.c
  GEN     target/s390x/trace.c
  GEN     target/ppc/trace.c
  GEN     qom/trace.c
  GEN     linux-user/trace.c
  GEN     qapi/trace.c
  GEN     config-all-devices.mak
         DEP /tmp/qemu-test/src/dtc/tests/testutils.c
         DEP /tmp/qemu-test/src/dtc/tests/value-labels.c
         DEP /tmp/qemu-test/src/dtc/tests/trees.S
         DEP /tmp/qemu-test/src/dtc/tests/dumptrees.c
         DEP /tmp/qemu-test/src/dtc/tests/asm_tree_dump.c
         DEP /tmp/qemu-test/src/dtc/tests/truncated_property.c
         DEP /tmp/qemu-test/src/dtc/tests/check_path.c
         DEP /tmp/qemu-test/src/dtc/tests/overlay_bad_fixup.c
         DEP /tmp/qemu-test/src/dtc/tests/overlay.c
         DEP /tmp/qemu-test/src/dtc/tests/subnode_iterate.c
         DEP /tmp/qemu-test/src/dtc/tests/integer-expressions.c
         DEP /tmp/qemu-test/src/dtc/tests/property_iterate.c
         DEP /tmp/qemu-test/src/dtc/tests/utilfdt_test.c
         DEP /tmp/qemu-test/src/dtc/tests/path_offset_aliases.c
         DEP /tmp/qemu-test/src/dtc/tests/add_subnode_with_nops.c
         DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_unordered.c
         DEP /tmp/qemu-test/src/dtc/tests/dtb_reverse.c
         DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_ordered.c
         DEP /tmp/qemu-test/src/dtc/tests/extra-terminating-null.c
         DEP /tmp/qemu-test/src/dtc/tests/incbin.c
         DEP /tmp/qemu-test/src/dtc/tests/boot-cpuid.c
         DEP /tmp/qemu-test/src/dtc/tests/phandle_format.c
         DEP /tmp/qemu-test/src/dtc/tests/path-references.c
         DEP /tmp/qemu-test/src/dtc/tests/references.c
         DEP /tmp/qemu-test/src/dtc/tests/string_escapes.c
         DEP /tmp/qemu-test/src/dtc/tests/appendprop2.c
         DEP /tmp/qemu-test/src/dtc/tests/propname_escapes.c
         DEP /tmp/qemu-test/src/dtc/tests/appendprop1.c
         DEP /tmp/qemu-test/src/dtc/tests/del_node.c
         DEP /tmp/qemu-test/src/dtc/tests/del_property.c
         DEP /tmp/qemu-test/src/dtc/tests/setprop.c
         DEP /tmp/qemu-test/src/dtc/tests/set_name.c
         DEP /tmp/qemu-test/src/dtc/tests/rw_tree1.c
         DEP /tmp/qemu-test/src/dtc/tests/open_pack.c
         DEP /tmp/qemu-test/src/dtc/tests/nopulate.c
         DEP /tmp/qemu-test/src/dtc/tests/mangle-layout.c
         DEP /tmp/qemu-test/src/dtc/tests/move_and_save.c
         DEP /tmp/qemu-test/src/dtc/tests/sw_tree1.c
         DEP /tmp/qemu-test/src/dtc/tests/nop_property.c
         DEP /tmp/qemu-test/src/dtc/tests/setprop_inplace.c
         DEP /tmp/qemu-test/src/dtc/tests/nop_node.c
         DEP /tmp/qemu-test/src/dtc/tests/stringlist.c
         DEP /tmp/qemu-test/src/dtc/tests/addr_size_cells.c
         DEP /tmp/qemu-test/src/dtc/tests/notfound.c
         DEP /tmp/qemu-test/src/dtc/tests/sized_cells.c
         DEP /tmp/qemu-test/src/dtc/tests/char_literal.c
         DEP /tmp/qemu-test/src/dtc/tests/get_alias.c
         DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_compatible.c
         DEP /tmp/qemu-test/src/dtc/tests/node_check_compatible.c
         DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_phandle.c
         DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_prop_value.c
         DEP /tmp/qemu-test/src/dtc/tests/parent_offset.c
         DEP /tmp/qemu-test/src/dtc/tests/supernode_atdepth_offset.c
         DEP /tmp/qemu-test/src/dtc/tests/get_path.c
         DEP /tmp/qemu-test/src/dtc/tests/get_phandle.c
         DEP /tmp/qemu-test/src/dtc/tests/getprop.c
         DEP /tmp/qemu-test/src/dtc/tests/get_name.c
         DEP /tmp/qemu-test/src/dtc/tests/path_offset.c
         DEP /tmp/qemu-test/src/dtc/tests/subnode_offset.c
         DEP /tmp/qemu-test/src/dtc/tests/find_property.c
         DEP /tmp/qemu-test/src/dtc/tests/root_node.c
         DEP /tmp/qemu-test/src/dtc/tests/get_mem_rsv.c
         DEP /tmp/qemu-test/src/dtc/libfdt/fdt_overlay.c
         DEP /tmp/qemu-test/src/dtc/libfdt/fdt_addresses.c
         DEP /tmp/qemu-test/src/dtc/libfdt/fdt_empty_tree.c
         DEP /tmp/qemu-test/src/dtc/libfdt/fdt_strerror.c
         DEP /tmp/qemu-test/src/dtc/libfdt/fdt_rw.c
         DEP /tmp/qemu-test/src/dtc/libfdt/fdt_sw.c
         DEP /tmp/qemu-test/src/dtc/libfdt/fdt_ro.c
         DEP /tmp/qemu-test/src/dtc/libfdt/fdt_wip.c
         DEP /tmp/qemu-test/src/dtc/util.c
         DEP /tmp/qemu-test/src/dtc/fdtput.c
         DEP /tmp/qemu-test/src/dtc/libfdt/fdt.c
         DEP /tmp/qemu-test/src/dtc/fdtget.c
         DEP /tmp/qemu-test/src/dtc/fdtdump.c
         LEX convert-dtsv0-lexer.lex.c
make[1]: flex: Command not found
         BISON dtc-parser.tab.c
         DEP /tmp/qemu-test/src/dtc/srcpos.c
make[1]: bison: Command not found
         LEX dtc-lexer.lex.c
make[1]: flex: Command not found
         DEP /tmp/qemu-test/src/dtc/treesource.c
         DEP /tmp/qemu-test/src/dtc/livetree.c
         DEP /tmp/qemu-test/src/dtc/fstree.c
         DEP /tmp/qemu-test/src/dtc/flattree.c
         DEP /tmp/qemu-test/src/dtc/dtc.c
         DEP /tmp/qemu-test/src/dtc/data.c
         DEP /tmp/qemu-test/src/dtc/checks.c
         LEX convert-dtsv0-lexer.lex.c
make[1]: flex: Command not found
         LEX dtc-lexer.lex.c
        CHK version_gen.h
make[1]: flex: Command not found
         BISON dtc-parser.tab.c
make[1]: bison: Command not found
        UPD version_gen.h
         DEP /tmp/qemu-test/src/dtc/util.c
         LEX convert-dtsv0-lexer.lex.c
make[1]: flex: Command not found
         LEX dtc-lexer.lex.c
make[1]: flex: Command not found
         BISON dtc-parser.tab.c
make[1]: bison: Command not found
         CC libfdt/fdt.o
         CC libfdt/fdt_ro.o
         CC libfdt/fdt_wip.o
         CC libfdt/fdt_rw.o
         CC libfdt/fdt_sw.o
         CC libfdt/fdt_strerror.o
         CC libfdt/fdt_empty_tree.o
         CC libfdt/fdt_addresses.o
         CC libfdt/fdt_overlay.o
         AR libfdt/libfdt.a
ar: creating libfdt/libfdt.a
a - libfdt/fdt.o
a - libfdt/fdt_ro.o
a - libfdt/fdt_wip.o
a - libfdt/fdt_sw.o
a - libfdt/fdt_rw.o
a - libfdt/fdt_strerror.o
a - libfdt/fdt_empty_tree.o
a - libfdt/fdt_addresses.o
a - libfdt/fdt_overlay.o
         BISON dtc-parser.tab.c
         LEX convert-dtsv0-lexer.lex.c
make[1]: bison: Command not found
make[1]: flex: Command not found
         LEX dtc-lexer.lex.c
make[1]: flex: Command not found
  CC      tests/qemu-iotests/socket_scm_helper.o
  GEN     qga/qapi-generated/qga-qapi-types.h
  GEN     qga/qapi-generated/qga-qapi-types.c
  GEN     qga/qapi-generated/qga-qmp-commands.h
  GEN     qga/qapi-generated/qga-qapi-visit.c
  GEN     qga/qapi-generated/qga-qapi-visit.h
  GEN     qga/qapi-generated/qga-qmp-marshal.c
  CC      qmp-introspect.o
  CC      qapi-types.o
  CC      qapi-visit.o
  CC      qapi-event.o
  CC      qapi/qapi-visit-core.o
  CC      qapi/qapi-dealloc-visitor.o
  CC      qapi/qobject-input-visitor.o
  CC      qapi/qobject-output-visitor.o
  CC      qapi/qmp-registry.o
  CC      qapi/qmp-dispatch.o
  CC      qapi/string-input-visitor.o
  CC      qapi/string-output-visitor.o
  CC      qapi/opts-visitor.o
  CC      qapi/qapi-clone-visitor.o
  CC      qapi/qmp-event.o
  CC      qapi/qapi-util.o
  CC      qobject/qnull.o
  CC      qobject/qint.o
  CC      qobject/qstring.o
  CC      qobject/qdict.o
  CC      qobject/qlist.o
  CC      qobject/qfloat.o
  CC      qobject/qbool.o
  CC      qobject/qjson.o
  CC      qobject/qobject.o
  CC      qobject/json-lexer.o
  CC      qobject/json-streamer.o
  CC      qobject/json-parser.o
  CC      trace/control.o
  CC      trace/qmp.o
  CC      util/osdep.o
  CC      util/cutils.o
  CC      util/unicode.o
  CC      util/qemu-timer-common.o
  CC      util/bufferiszero.o
  CC      util/lockcnt.o
  CC      util/aiocb.o
  CC      util/async.o
  CC      util/thread-pool.o
  CC      util/qemu-timer.o
  CC      util/main-loop.o
  CC      util/iohandler.o
  CC      util/aio-posix.o
  CC      util/compatfd.o
  CC      util/event_notifier-posix.o
  CC      util/mmap-alloc.o
  CC      util/oslib-posix.o
  CC      util/qemu-openpty.o
  CC      util/qemu-thread-posix.o
  CC      util/memfd.o
  CC      util/envlist.o
  CC      util/path.o
  CC      util/module.o
  CC      util/host-utils.o
  CC      util/bitmap.o
  CC      util/bitops.o
  CC      util/hbitmap.o
  CC      util/fifo8.o
  CC      util/acl.o
  CC      util/error.o
  CC      util/qemu-error.o
  CC      util/id.o
  CC      util/iov.o
  CC      util/qemu-config.o
  CC      util/qemu-sockets.o
  CC      util/uri.o
  CC      util/notify.o
  CC      util/qemu-option.o
  CC      util/qemu-progress.o
  CC      util/keyval.o
  CC      util/hexdump.o
  CC      util/crc32c.o
  CC      util/uuid.o
  CC      util/throttle.o
  CC      util/getauxval.o
  CC      util/readline.o
  CC      util/rcu.o
  CC      util/qemu-coroutine.o
  CC      util/qemu-coroutine-lock.o
  CC      util/qemu-coroutine-io.o
  CC      util/qemu-coroutine-sleep.o
  CC      util/coroutine-ucontext.o
  CC      util/buffer.o
  CC      util/timed-average.o
  CC      util/base64.o
  CC      util/log.o
  CC      util/qdist.o
  CC      util/qht.o
  CC      util/range.o
  CC      util/systemd.o
  CC      trace-root.o
  CC      util/trace.o
  CC      crypto/trace.o
  CC      io/trace.o
  CC      migration/trace.o
  CC      block/trace.o
  CC      backends/trace.o
  CC      chardev/trace.o
  CC      hw/block/trace.o
  CC      hw/block/dataplane/trace.o
  CC      hw/char/trace.o
  CC      hw/intc/trace.o
  CC      hw/net/trace.o
  CC      hw/virtio/trace.o
  CC      hw/audio/trace.o
  CC      hw/misc/trace.o
  CC      hw/usb/trace.o
  CC      hw/scsi/trace.o
  CC      hw/nvram/trace.o
  CC      hw/display/trace.o
  CC      hw/input/trace.o
  CC      hw/timer/trace.o
  CC      hw/dma/trace.o
  CC      hw/sparc/trace.o
  CC      hw/sd/trace.o
  CC      hw/isa/trace.o
  CC      hw/mem/trace.o
  CC      hw/i386/trace.o
  CC      hw/i386/xen/trace.o
  CC      hw/9pfs/trace.o
  CC      hw/ppc/trace.o
  CC      hw/pci/trace.o
  CC      hw/s390x/trace.o
  CC      hw/vfio/trace.o
  CC      hw/acpi/trace.o
  CC      hw/arm/trace.o
  CC      hw/alpha/trace.o
  CC      hw/xen/trace.o
  CC      ui/trace.o
  CC      audio/trace.o
  CC      net/trace.o
  CC      target/arm/trace.o
  CC      target/i386/trace.o
  CC      target/mips/trace.o
  CC      target/sparc/trace.o
  CC      target/s390x/trace.o
  CC      target/ppc/trace.o
  CC      qom/trace.o
  CC      linux-user/trace.o
  CC      qapi/trace.o
  CC      crypto/pbkdf-stub.o
  CC      stubs/arch-query-cpu-def.o
  CC      stubs/arch-query-cpu-model-expansion.o
  CC      stubs/arch-query-cpu-model-comparison.o
  CC      stubs/arch-query-cpu-model-baseline.o
  CC      stubs/bdrv-next-monitor-owned.o
  CC      stubs/blk-commit-all.o
  CC      stubs/blockdev-close-all-bdrv-states.o
  CC      stubs/clock-warp.o
  CC      stubs/cpu-get-clock.o
  CC      stubs/cpu-get-icount.o
  CC      stubs/dump.o
  CC      stubs/error-printf.o
  CC      stubs/fdset.o
  CC      stubs/gdbstub.o
  CC      stubs/get-vm-name.o
  CC      stubs/iothread.o
  CC      stubs/iothread-lock.o
  CC      stubs/machine-init-done.o
  CC      stubs/is-daemonized.o
  CC      stubs/migr-blocker.o
  CC      stubs/monitor.o
  CC      stubs/notify-event.o
  CC      stubs/qtest.o
  CC      stubs/replay.o
  CC      stubs/runstate-check.o
  CC      stubs/set-fd-handler.o
  CC      stubs/slirp.o
  CC      stubs/sysbus.o
  CC      stubs/trace-control.o
  CC      stubs/uuid.o
  CC      stubs/vm-stop.o
  CC      stubs/vmstate.o
  CC      stubs/qmp_pc_dimm_device_list.o
  CC      stubs/target-monitor-defs.o
  CC      stubs/target-get-monitor-def.o
  CC      stubs/pc_madt_cpu_entry.o
  CC      stubs/vmgenid.o
  CC      stubs/xen-common.o
  CC      stubs/xen-hvm.o
  CC      contrib/ivshmem-client/ivshmem-client.o
  CC      contrib/ivshmem-client/main.o
  CC      contrib/ivshmem-server/ivshmem-server.o
  CC      contrib/ivshmem-server/main.o
  CC      qemu-nbd.o
  CC      block.o
  CC      blockjob.o
  CC      qemu-io-cmds.o
  CC      replication.o
  CC      block/raw-format.o
  CC      block/qcow.o
  CC      block/vdi.o
  CC      block/vmdk.o
  CC      block/cloop.o
  CC      block/bochs.o
  CC      block/vpc.o
  CC      block/vvfat.o
  CC      block/dmg.o
  CC      block/qcow2.o
  CC      block/qcow2-refcount.o
  CC      block/qcow2-cluster.o
  CC      block/qcow2-snapshot.o
  CC      block/qcow2-cache.o
  CC      block/qed.o
  CC      block/qed-gencb.o
  CC      block/qed-l2-cache.o
  CC      block/qed-table.o
  CC      block/qed-cluster.o
  CC      block/qed-check.o
  CC      block/vhdx.o
  CC      block/vhdx-endian.o
  CC      block/vhdx-log.o
  CC      block/quorum.o
  CC      block/parallels.o
  CC      block/blkdebug.o
  CC      block/blkverify.o
  CC      block/blkreplay.o
  CC      block/block-backend.o
  CC      block/snapshot.o
  CC      block/qapi.o
  CC      block/file-posix.o
  CC      block/null.o
  CC      block/mirror.o
  CC      block/commit.o
  CC      block/io.o
  CC      block/throttle-groups.o
  CC      block/nbd.o
  CC      block/nbd-client.o
  CC      block/sheepdog.o
  CC      block/accounting.o
  CC      block/dirty-bitmap.o
  CC      block/write-threshold.o
  CC      block/backup.o
  CC      block/replication.o
  CC      block/crypto.o
  CC      nbd/server.o
  CC      nbd/client.o
  CC      nbd/common.o
  CC      crypto/init.o
  CC      crypto/hash.o
  CC      crypto/hash-glib.o
  CC      crypto/hmac.o
  CC      crypto/hmac-glib.o
  CC      crypto/aes.o
  CC      crypto/desrfb.o
  CC      crypto/cipher.o
  CC      crypto/tlscreds.o
  CC      crypto/tlscredsanon.o
  CC      crypto/tlscredsx509.o
  CC      crypto/tlssession.o
  CC      crypto/secret.o
  CC      crypto/random-platform.o
  CC      crypto/pbkdf.o
  CC      crypto/ivgen.o
  CC      crypto/ivgen-essiv.o
  CC      crypto/ivgen-plain.o
  CC      crypto/ivgen-plain64.o
  CC      crypto/afsplit.o
  CC      crypto/xts.o
  CC      crypto/block.o
  CC      crypto/block-qcow.o
  CC      crypto/block-luks.o
  CC      io/channel.o
  CC      io/channel-buffer.o
  CC      io/channel-command.o
  CC      io/channel-file.o
  CC      io/channel-socket.o
  CC      io/channel-tls.o
  CC      io/channel-watch.o
  CC      io/channel-websock.o
  CC      io/channel-util.o
  CC      io/dns-resolver.o
  CC      io/task.o
  CC      qom/object.o
  CC      qom/container.o
  CC      qom/qom-qobject.o
  CC      qom/object_interfaces.o
  GEN     qemu-img-cmds.h
  CC      qemu-io.o
  CC      qemu-bridge-helper.o
  CC      blockdev-nbd.o
  CC      blockdev.o
  CC      iothread.o
  CC      qdev-monitor.o
  CC      device-hotplug.o
  CC      os-posix.o
  CC      accel.o
  CC      bt-host.o
  CC      bt-vhci.o
  CC      dma-helpers.o
  CC      vl.o
  CC      tpm.o
  CC      device_tree.o
  CC      qmp-marshal.o
  CC      qmp.o
  CC      hmp.o
  CC      cpus-common.o
  CC      audio/audio.o
  CC      audio/noaudio.o
  CC      audio/wavaudio.o
  CC      audio/mixeng.o
  CC      audio/sdlaudio.o
  CC      audio/ossaudio.o
  CC      audio/wavcapture.o
  CC      backends/rng.o
  CC      backends/rng-egd.o
  CC      backends/rng-random.o
  CC      backends/tpm.o
  CC      backends/hostmem.o
  CC      backends/hostmem-ram.o
  CC      backends/hostmem-file.o
  CC      backends/cryptodev.o
  CC      backends/cryptodev-builtin.o
  CC      block/stream.o
  CC      chardev/msmouse.o
  CC      chardev/wctablet.o
  CC      chardev/testdev.o
  CC      disas/arm.o
  CC      disas/i386.o
  CC      fsdev/qemu-fsdev-dummy.o
  CC      fsdev/qemu-fsdev-opts.o
  CC      fsdev/qemu-fsdev-throttle.o
  CC      hw/acpi/core.o
  CC      hw/acpi/piix4.o
  CC      hw/acpi/pcihp.o
  CC      hw/acpi/ich9.o
  CC      hw/acpi/tco.o
  CC      hw/acpi/cpu_hotplug.o
  CC      hw/acpi/memory_hotplug.o
  CC      hw/acpi/cpu.o
  CC      hw/acpi/nvdimm.o
  CC      hw/acpi/vmgenid.o
  CC      hw/acpi/acpi_interface.o
  CC      hw/acpi/bios-linker-loader.o
  CC      hw/acpi/aml-build.o
  CC      hw/acpi/ipmi.o
  CC      hw/acpi/acpi-stub.o
  CC      hw/acpi/ipmi-stub.o
  CC      hw/audio/sb16.o
  CC      hw/audio/es1370.o
  CC      hw/audio/ac97.o
  CC      hw/audio/fmopl.o
  CC      hw/audio/adlib.o
  CC      hw/audio/gus.o
  CC      hw/audio/gusemu_hal.o
  CC      hw/audio/gusemu_mixer.o
  CC      hw/audio/cs4231a.o
  CC      hw/audio/intel-hda.o
  CC      hw/audio/hda-codec.o
  CC      hw/audio/pcspk.o
  CC      hw/audio/wm8750.o
  CC      hw/audio/pl041.o
  CC      hw/audio/lm4549.o
  CC      hw/audio/marvell_88w8618.o
  CC      hw/audio/soundhw.o
  CC      hw/block/block.o
  CC      hw/block/cdrom.o
  CC      hw/block/hd-geometry.o
  CC      hw/block/fdc.o
  CC      hw/block/m25p80.o
  CC      hw/block/nand.o
  CC      hw/block/pflash_cfi01.o
  CC      hw/block/pflash_cfi02.o
  CC      hw/block/ecc.o
  CC      hw/block/onenand.o
  CC      hw/bt/core.o
  CC      hw/block/nvme.o
  CC      hw/bt/l2cap.o
  CC      hw/bt/sdp.o
  CC      hw/bt/hci.o
  CC      hw/bt/hid.o
  CC      hw/bt/hci-csr.o
  CC      hw/char/ipoctal232.o
  CC      hw/char/parallel.o
  CC      hw/char/pl011.o
  CC      hw/char/serial.o
  CC      hw/char/serial-isa.o
  CC      hw/char/serial-pci.o
  CC      hw/char/virtio-console.o
  CC      hw/char/cadence_uart.o
  CC      hw/char/debugcon.o
  CC      hw/char/imx_serial.o
  CC      hw/core/qdev.o
  CC      hw/core/qdev-properties.o
  CC      hw/core/bus.o
  CC      hw/core/reset.o
  CC      hw/core/fw-path-provider.o
  CC      hw/core/irq.o
  CC      hw/core/hotplug.o
  CC      hw/core/nmi.o
  CC      hw/core/ptimer.o
  CC      hw/core/sysbus.o
  CC      hw/core/machine.o
  CC      hw/core/loader.o
  CC      hw/core/qdev-properties-system.o
  CC      hw/core/register.o
  CC      hw/core/or-irq.o
  CC      hw/core/platform-bus.o
  CC      hw/cpu/core.o
  CC      hw/display/ads7846.o
  CC      hw/display/cirrus_vga.o
  CC      hw/display/pl110.o
  CC      hw/display/ssd0303.o
  CC      hw/display/ssd0323.o
  CC      hw/display/vga-pci.o
  CC      hw/display/vga-isa.o
  CC      hw/display/vmware_vga.o
  CC      hw/display/blizzard.o
  CC      hw/display/exynos4210_fimd.o
  CC      hw/display/framebuffer.o
  CC      hw/display/tc6393xb.o
  CC      hw/dma/pl080.o
  CC      hw/dma/pl330.o
  CC      hw/dma/i8257.o
  CC      hw/dma/xlnx-zynq-devcfg.o
  CC      hw/gpio/zaurus.o
  CC      hw/gpio/gpio_key.o
  CC      hw/gpio/max7310.o
  CC      hw/gpio/pl061.o
  CC      hw/i2c/smbus_eeprom.o
  CC      hw/i2c/smbus.o
  CC      hw/i2c/core.o
  CC      hw/i2c/smbus_ich9.o
  CC      hw/i2c/i2c-ddc.o
  CC      hw/i2c/aspeed_i2c.o
  CC      hw/i2c/pm_smbus.o
  CC      hw/i2c/versatile_i2c.o
  CC      hw/i2c/bitbang_i2c.o
  CC      hw/i2c/exynos4210_i2c.o
  CC      hw/i2c/imx_i2c.o
  CC      hw/ide/core.o
  CC      hw/ide/qdev.o
  CC      hw/ide/atapi.o
  CC      hw/ide/pci.o
  CC      hw/ide/isa.o
  CC      hw/ide/piix.o
  CC      hw/ide/microdrive.o
  CC      hw/ide/ahci.o
  CC      hw/ide/ich.o
  CC      hw/input/hid.o
  CC      hw/input/pckbd.o
  CC      hw/input/lm832x.o
  CC      hw/input/pl050.o
  CC      hw/input/ps2.o
  CC      hw/input/stellaris_input.o
  CC      hw/input/tsc2005.o
  CC      hw/input/vmmouse.o
  CC      hw/input/virtio-input.o
  CC      hw/input/virtio-input-hid.o
  CC      hw/input/virtio-input-host.o
  CC      hw/intc/i8259_common.o
  CC      hw/intc/i8259.o
  CC      hw/intc/pl190.o
  CC      hw/intc/imx_avic.o
  CC      hw/intc/realview_gic.o
  CC      hw/intc/ioapic_common.o
  CC      hw/intc/arm_gic_common.o
  CC      hw/intc/arm_gic.o
  CC      hw/intc/arm_gicv2m.o
  CC      hw/intc/arm_gicv3_common.o
  CC      hw/intc/arm_gicv3.o
  CC      hw/intc/arm_gicv3_dist.o
  CC      hw/intc/arm_gicv3_redist.o
  CC      hw/intc/arm_gicv3_its_common.o
  CC      hw/intc/intc.o
  CC      hw/ipack/ipack.o
  CC      hw/ipack/tpci200.o
  CC      hw/ipmi/ipmi.o
  CC      hw/ipmi/ipmi_bmc_sim.o
  CC      hw/ipmi/ipmi_bmc_extern.o
  CC      hw/ipmi/isa_ipmi_kcs.o
  CC      hw/ipmi/isa_ipmi_bt.o
  CC      hw/isa/isa-bus.o
  CC      hw/isa/apm.o
  CC      hw/mem/pc-dimm.o
  CC      hw/mem/nvdimm.o
  CC      hw/misc/applesmc.o
  CC      hw/misc/max111x.o
  CC      hw/misc/tmp105.o
  CC      hw/misc/tmp421.o
  CC      hw/misc/debugexit.o
  CC      hw/misc/sga.o
  CC      hw/misc/pc-testdev.o
  CC      hw/misc/pci-testdev.o
  CC      hw/misc/unimp.o
  CC      hw/misc/arm_l2x0.o
  CC      hw/misc/arm_integrator_debug.o
  CC      hw/misc/a9scu.o
  CC      hw/misc/arm11scu.o
  CC      hw/net/ne2000.o
  CC      hw/net/eepro100.o
  CC      hw/net/pcnet-pci.o
  CC      hw/net/pcnet.o
  CC      hw/net/e1000.o
  CC      hw/net/e1000x_common.o
  CC      hw/net/net_tx_pkt.o
  CC      hw/net/net_rx_pkt.o
  CC      hw/net/e1000e.o
  CC      hw/net/e1000e_core.o
  CC      hw/net/rtl8139.o
  CC      hw/net/vmxnet3.o
  CC      hw/net/smc91c111.o
  CC      hw/net/lan9118.o
In file included from /tmp/qemu-test/src/hw/net/vmxnet3.c:30:
/tmp/qemu-test/src/include/migration/register.h:18: error: redefinition of typedef ‘LoadStateHandler’
/tmp/qemu-test/src/include/migration/vmstate.h:32: note: previous declaration of ‘LoadStateHandler’ was here
make: *** [hw/net/vmxnet3.o] Error 1
make: *** Waiting for unfinished jobs....
  CC      hw/net/ne2000-isa.o
tests/docker/Makefile.include:118: recipe for target 'docker-run' failed
make[1]: *** [docker-run] Error 2
make[1]: Leaving directory '/var/tmp/patchew-tester-tmp-v86bvvd0/src'
tests/docker/Makefile.include:149: recipe for target 'docker-run-test-quick@centos6' failed
make: *** [docker-run-test-quick@centos6] Error 2
=== OUTPUT END ===

Test command exited with code: 2


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH qemu v8 0/2] memory/iommu: QOM'fy IOMMU MemoryRegion

no-reply
In reply to this post by Alexey Kardashevskiy
Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [Qemu-devel] [PATCH qemu v8 0/2] memory/iommu: QOM'fy IOMMU MemoryRegion
Message-id: [hidden email]
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]      patchew/[hidden email] -> patchew/[hidden email]
 * [new tag]         patchew/[hidden email] -> patchew/[hidden email]
Switched to a new branch 'test'
3d08aca memory/iommu: introduce IOMMUMemoryRegionClass
d1443b0 memory/iommu: QOM'fy IOMMU MemoryRegion

=== OUTPUT BEGIN ===
Checking PATCH 1/2: memory/iommu: QOM'fy IOMMU MemoryRegion...
ERROR: spaces required around that '*' (ctx:WxO)
#129: FILE: hw/dma/rc4030.c:720:
+DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr)
                                     ^

total: 1 errors, 0 warnings, 772 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 2/2: memory/iommu: introduce IOMMUMemoryRegionClass...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH qemu v8 0/2] memory/iommu: QOM'fy IOMMU MemoryRegion

Fam Zheng-2
In reply to this post by no-reply
On Tue, 06/13 23:51, [hidden email] wrote:

> In file included from /tmp/qemu-test/src/hw/net/vmxnet3.c:30:
> /tmp/qemu-test/src/include/migration/register.h:18: error: redefinition of typedef ‘LoadStateHandler’
> /tmp/qemu-test/src/include/migration/vmstate.h:32: note: previous declaration of ‘LoadStateHandler’ was here
> make: *** [hw/net/vmxnet3.o] Error 1
> make: *** Waiting for unfinished jobs....
>   CC      hw/net/ne2000-isa.o
> tests/docker/Makefile.include:118: recipe for target 'docker-run' failed
> make[1]: *** [docker-run] Error 2
> make[1]: Leaving directory '/var/tmp/patchew-tester-tmp-v86bvvd0/src'
> tests/docker/Makefile.include:149: recipe for target 'docker-run-test-quick@centos6' failed
> make: *** [docker-run-test-quick@centos6] Error 2

Not related to this patch, the bug is on master.

Fam

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH qemu v8 0/2] memory/iommu: QOM'fy IOMMU MemoryRegion

David Gibson
In reply to this post by no-reply
On Tue, Jun 13, 2017 at 11:52:41PM -0700, [hidden email] wrote:

> Hi,
>
> This series seems to have some coding style problems. See output below for
> more information:
>
> Subject: [Qemu-devel] [PATCH qemu v8 0/2] memory/iommu: QOM'fy IOMMU MemoryRegion
> Message-id: [hidden email]
> Type: series
>
> === TEST SCRIPT BEGIN ===
> #!/bin/bash
>
> BASE=base
> n=1
> total=$(git log --oneline $BASE.. | wc -l)
> failed=0
>
> git config --local diff.renamelimit 0
> git config --local diff.renames True
>
> commits="$(git log --format=%H --reverse $BASE..)"
> for c in $commits; do
>     echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
>     if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
>         failed=1
>         echo
>     fi
>     n=$((n+1))
> done
>
> exit $failed
> === TEST SCRIPT END ===
>
> Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
> From https://github.com/patchew-project/qemu
>  - [tag update]      patchew/[hidden email] -> patchew/[hidden email]
>  * [new tag]         patchew/[hidden email] -> patchew/[hidden email]
> Switched to a new branch 'test'
> 3d08aca memory/iommu: introduce IOMMUMemoryRegionClass
> d1443b0 memory/iommu: QOM'fy IOMMU MemoryRegion
>
> === OUTPUT BEGIN ===
> Checking PATCH 1/2: memory/iommu: QOM'fy IOMMU MemoryRegion...
> ERROR: spaces required around that '*' (ctx:WxO)
> #129: FILE: hw/dma/rc4030.c:720:
> +DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr)
>                                      ^
False positive.  checkpatch thinks this is a multiplicatin rather
thana pointer designation.

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

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH qemu v8 1/2] memory/iommu: QOM'fy IOMMU MemoryRegion

David Gibson
In reply to this post by Alexey Kardashevskiy
On Wed, Jun 14, 2017 at 04:36:06PM +1000, Alexey Kardashevskiy wrote:

> This defines new QOM object - IOMMUMemoryRegion - with MemoryRegion
> as a parent.
>
> This moves IOMMU-related fields from MR to IOMMU MR. However to avoid
> dymanic QOM casting in fast path (address_space_translate, etc),
> this adds an @is_iommu boolean flag to MR and provides new helper to
> do simple cast to IOMMU MR - memory_region_get_iommu. The flag
> is set in the instance init callback. This defines
> memory_region_is_iommu as memory_region_get_iommu()!=NULL.
>
> This switches MemoryRegion to IOMMUMemoryRegion in most places except
> the ones where MemoryRegion may be an alias.
>
> Signed-off-by: Alexey Kardashevskiy <[hidden email]>
Reviewed-by: David Gibson <[hidden email]>

> ---
> Changes:
> v8:
> * moved is_iommu flag closer to the beginning of the MemoryRegion struct
> * removed memory_region_init_iommu_type()
>
> v7:
> * rebased on top of the current upstream
>
> v6:
> * s/\<iommumr\>/iommu_mr/g
>
> v5:
> * fixed sparc64, first time in many years did run "./configure" without
> --target-list :-D Sorry for the noise though :(
>
> v4:
> * fixed alpha, mips64el and sparc
>
> v3:
> * rebased on sha1 81b2d5ceb0
>
> v2:
> * added mr->is_iommu
> * updated i386/x86_64/s390/sun
> ---
>  hw/s390x/s390-pci-bus.h       |   2 +-
>  include/exec/memory.h         |  55 ++++++++++++++--------
>  include/hw/i386/intel_iommu.h |   2 +-
>  include/hw/mips/mips.h        |   2 +-
>  include/hw/ppc/spapr.h        |   3 +-
>  include/hw/vfio/vfio-common.h |   2 +-
>  include/qemu/typedefs.h       |   1 +
>  exec.c                        |  12 ++---
>  hw/alpha/typhoon.c            |   8 ++--
>  hw/dma/rc4030.c               |   8 ++--
>  hw/i386/amd_iommu.c           |   9 ++--
>  hw/i386/intel_iommu.c         |  17 +++----
>  hw/mips/mips_jazz.c           |   2 +-
>  hw/pci-host/apb.c             |   6 +--
>  hw/ppc/spapr_iommu.c          |  16 ++++---
>  hw/s390x/s390-pci-bus.c       |   6 +--
>  hw/s390x/s390-pci-inst.c      |   8 ++--
>  hw/vfio/common.c              |  12 +++--
>  hw/vfio/spapr.c               |   3 +-
>  memory.c                      | 105 ++++++++++++++++++++++++++++--------------
>  20 files changed, 170 insertions(+), 109 deletions(-)
>
> diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
> index cf142a3e68..6a599ed353 100644
> --- a/hw/s390x/s390-pci-bus.h
> +++ b/hw/s390x/s390-pci-bus.h
> @@ -266,7 +266,7 @@ typedef struct S390PCIIOMMU {
>      S390PCIBusDevice *pbdev;
>      AddressSpace as;
>      MemoryRegion mr;
> -    MemoryRegion iommu_mr;
> +    IOMMUMemoryRegion iommu_mr;
>      bool enabled;
>      uint64_t g_iota;
>      uint64_t pba;
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 80e605a96a..8aefea3abc 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -35,6 +35,10 @@
>  #define MEMORY_REGION(obj) \
>          OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION)
>  
> +#define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region"
> +#define IOMMU_MEMORY_REGION(obj) \
> +        OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION)
> +
>  typedef struct MemoryRegionOps MemoryRegionOps;
>  typedef struct MemoryRegionMmio MemoryRegionMmio;
>  
> @@ -189,16 +193,16 @@ struct MemoryRegionIOMMUOps {
>       * set flag to IOMMU_NONE to mean that we don't need any
>       * read/write permission checks, like, when for region replay.
>       */
> -    IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr,
> +    IOMMUTLBEntry (*translate)(IOMMUMemoryRegion *iommu, hwaddr addr,
>                                 IOMMUAccessFlags flag);
>      /* Returns minimum supported page size */
> -    uint64_t (*get_min_page_size)(MemoryRegion *iommu);
> +    uint64_t (*get_min_page_size)(IOMMUMemoryRegion *iommu);
>      /* Called when IOMMU Notifier flag changed */
> -    void (*notify_flag_changed)(MemoryRegion *iommu,
> +    void (*notify_flag_changed)(IOMMUMemoryRegion *iommu,
>                                  IOMMUNotifierFlag old_flags,
>                                  IOMMUNotifierFlag new_flags);
>      /* Set this up to provide customized IOMMU replay function */
> -    void (*replay)(MemoryRegion *iommu, IOMMUNotifier *notifier);
> +    void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier);
>  };
>  
>  typedef struct CoalescedMemoryRange CoalescedMemoryRange;
> @@ -218,9 +222,9 @@ struct MemoryRegion {
>      bool flush_coalesced_mmio;
>      bool global_locking;
>      uint8_t dirty_log_mask;
> +    bool is_iommu;
>      RAMBlock *ram_block;
>      Object *owner;
> -    const MemoryRegionIOMMUOps *iommu_ops;
>  
>      const MemoryRegionOps *ops;
>      void *opaque;
> @@ -243,6 +247,12 @@ struct MemoryRegion {
>      const char *name;
>      unsigned ioeventfd_nb;
>      MemoryRegionIoeventfd *ioeventfds;
> +};
> +
> +struct IOMMUMemoryRegion {
> +    MemoryRegion parent_obj;
> +
> +    const MemoryRegionIOMMUOps *iommu_ops;
>      QLIST_HEAD(, IOMMUNotifier) iommu_notify;
>      IOMMUNotifierFlag iommu_notify_flags;
>  };
> @@ -589,13 +599,13 @@ static inline void memory_region_init_reservation(MemoryRegion *mr,
>   * An IOMMU region translates addresses and forwards accesses to a target
>   * memory region.
>   *
> - * @mr: the #MemoryRegion to be initialized
> + * @iommu_mr: the #IOMMUMemoryRegion to be initialized
>   * @owner: the object that tracks the region's reference count
>   * @ops: a function that translates addresses into the @target region
>   * @name: used for debugging; not visible to the user or ABI
>   * @size: size of the region.
>   */
> -void memory_region_init_iommu(MemoryRegion *mr,
> +void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
>                                struct Object *owner,
>                                const MemoryRegionIOMMUOps *ops,
>                                const char *name,
> @@ -650,20 +660,25 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
>  }
>  
>  /**
> - * memory_region_is_iommu: check whether a memory region is an iommu
> + * memory_region_get_iommu: check whether a memory region is an iommu
>   *
> - * Returns %true is a memory region is an iommu.
> + * Returns pointer to IOMMUMemoryRegion if a memory region is an iommu,
> + * otherwise NULL.
>   *
>   * @mr: the memory region being queried
>   */
> -static inline bool memory_region_is_iommu(MemoryRegion *mr)
> +static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr)
>  {
>      if (mr->alias) {
> -        return memory_region_is_iommu(mr->alias);
> +        return memory_region_get_iommu(mr->alias);
>      }
> -    return mr->iommu_ops;
> +    if (mr->is_iommu) {
> +        return (IOMMUMemoryRegion *) mr;
> +    }
> +    return NULL;
>  }
>  
> +#define memory_region_is_iommu(mr) (memory_region_get_iommu(mr) != NULL)
>  
>  /**
>   * memory_region_iommu_get_min_page_size: get minimum supported page size
> @@ -671,9 +686,9 @@ static inline bool memory_region_is_iommu(MemoryRegion *mr)
>   *
>   * Returns minimum supported page size for an iommu.
>   *
> - * @mr: the memory region being queried
> + * @iommu_mr: the memory region being queried
>   */
> -uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
> +uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr);
>  
>  /**
>   * memory_region_notify_iommu: notify a change in an IOMMU translation entry.
> @@ -687,12 +702,12 @@ uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
>   * Note: for any IOMMU implementation, an in-place mapping change
>   * should be notified with an UNMAP followed by a MAP.
>   *
> - * @mr: the memory region that was changed
> + * @iommu_mr: the memory region that was changed
>   * @entry: the new entry in the IOMMU translation table.  The entry
>   *         replaces all old entries for the same virtual I/O address range.
>   *         Deleted entries have .@perm == 0.
>   */
> -void memory_region_notify_iommu(MemoryRegion *mr,
> +void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
>                                  IOMMUTLBEntry entry);
>  
>  /**
> @@ -727,18 +742,18 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr,
>   * a notifier with the minimum page granularity returned by
>   * mr->iommu_ops->get_page_size().
>   *
> - * @mr: the memory region to observe
> + * @iommu_mr: the memory region to observe
>   * @n: the notifier to which to replay iommu mappings
>   */
> -void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n);
> +void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n);
>  
>  /**
>   * memory_region_iommu_replay_all: replay existing IOMMU translations
>   * to all the notifiers registered.
>   *
> - * @mr: the memory region to observe
> + * @iommu_mr: the memory region to observe
>   */
> -void memory_region_iommu_replay_all(MemoryRegion *mr);
> +void memory_region_iommu_replay_all(IOMMUMemoryRegion *iommu_mr);
>  
>  /**
>   * memory_region_unregister_iommu_notifier: unregister a notifier for
> diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
> index 3e51876b75..45fba4ff97 100644
> --- a/include/hw/i386/intel_iommu.h
> +++ b/include/hw/i386/intel_iommu.h
> @@ -83,7 +83,7 @@ struct VTDAddressSpace {
>      PCIBus *bus;
>      uint8_t devfn;
>      AddressSpace as;
> -    MemoryRegion iommu;
> +    IOMMUMemoryRegion iommu;
>      MemoryRegion root;
>      MemoryRegion sys_alias;
>      MemoryRegion iommu_ir;      /* Interrupt region: 0xfeeXXXXX */
> diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h
> index 16412dc150..2f6774d540 100644
> --- a/include/hw/mips/mips.h
> +++ b/include/hw/mips/mips.h
> @@ -19,6 +19,6 @@ typedef struct rc4030DMAState *rc4030_dma;
>  void rc4030_dma_read(void *dma, uint8_t *buf, int len);
>  void rc4030_dma_write(void *dma, uint8_t *buf, int len);
>  
> -DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr);
> +DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr);
>  
>  #endif
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index f973b02845..6bd338156b 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -591,7 +591,8 @@ struct sPAPRTCETable {
>      bool bypass;
>      bool need_vfio;
>      int fd;
> -    MemoryRegion root, iommu;
> +    MemoryRegion root;
> +    IOMMUMemoryRegion iommu;
>      struct VIOsPAPRDevice *vdev; /* for @bypass migration compatibility only */
>      QLIST_ENTRY(sPAPRTCETable) list;
>  };
> diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
> index 9521013d52..d67779729c 100644
> --- a/include/hw/vfio/vfio-common.h
> +++ b/include/hw/vfio/vfio-common.h
> @@ -95,7 +95,7 @@ typedef struct VFIOContainer {
>  
>  typedef struct VFIOGuestIOMMU {
>      VFIOContainer *container;
> -    MemoryRegion *iommu;
> +    IOMMUMemoryRegion *iommu;
>      hwaddr iommu_offset;
>      IOMMUNotifier n;
>      QLIST_ENTRY(VFIOGuestIOMMU) giommu_next;
> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
> index 51958bf7d3..f517c3d88c 100644
> --- a/include/qemu/typedefs.h
> +++ b/include/qemu/typedefs.h
> @@ -45,6 +45,7 @@ typedef struct MachineState MachineState;
>  typedef struct MemoryListener MemoryListener;
>  typedef struct MemoryMappingList MemoryMappingList;
>  typedef struct MemoryRegion MemoryRegion;
> +typedef struct IOMMUMemoryRegion IOMMUMemoryRegion;
>  typedef struct MemoryRegionCache MemoryRegionCache;
>  typedef struct MemoryRegionSection MemoryRegionSection;
>  typedef struct MigrationIncomingState MigrationIncomingState;
> diff --git a/exec.c b/exec.c
> index a93e209625..182cc9b9b9 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -475,19 +475,19 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
>  {
>      IOMMUTLBEntry iotlb;
>      MemoryRegionSection *section;
> -    MemoryRegion *mr;
> +    IOMMUMemoryRegion *iommu_mr;
>  
>      for (;;) {
>          AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
>          section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);
> -        mr = section->mr;
>  
> -        if (!mr->iommu_ops) {
> +        iommu_mr = memory_region_get_iommu(section->mr);
> +        if (!iommu_mr) {
>              break;
>          }
>  
> -        iotlb = mr->iommu_ops->translate(mr, addr, is_write ?
> -                                         IOMMU_WO : IOMMU_RO);
> +        iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, is_write ?
> +                                               IOMMU_WO : IOMMU_RO);
>          addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
>                  | (addr & iotlb.addr_mask));
>          *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
> @@ -583,7 +583,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr,
>  
>      section = address_space_translate_internal(d, addr, xlat, plen, false);
>  
> -    assert(!section->mr->iommu_ops);
> +    assert(!memory_region_is_iommu(section->mr));
>      return section;
>  }
>  #endif
> diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
> index c1cf7802a4..dd47b4569f 100644
> --- a/hw/alpha/typhoon.c
> +++ b/hw/alpha/typhoon.c
> @@ -41,7 +41,7 @@ typedef struct TyphoonPchip {
>      MemoryRegion reg_conf;
>  
>      AddressSpace iommu_as;
> -    MemoryRegion iommu;
> +    IOMMUMemoryRegion iommu;
>  
>      uint64_t ctl;
>      TyphoonWindow win[4];
> @@ -663,7 +663,8 @@ static bool window_translate(TyphoonWindow *win, hwaddr addr,
>  /* Handle PCI-to-system address translation.  */
>  /* TODO: A translation failure here ought to set PCI error codes on the
>     Pchip and generate a machine check interrupt.  */
> -static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr,
> +static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
> +                                             hwaddr addr,
>                                               IOMMUAccessFlags flag)
>  {
>      TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
> @@ -893,7 +894,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
>      /* Host memory as seen from the PCI side, via the IOMMU.  */
>      memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
>                               "iommu-typhoon", UINT64_MAX);
> -    address_space_init(&s->pchip.iommu_as, &s->pchip.iommu, "pchip0-pci");
> +    address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu),
> +                       "pchip0-pci");
>      pci_setup_iommu(b, typhoon_pci_dma_iommu, s);
>  
>      /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
> diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
> index edf9432051..32c06760ef 100644
> --- a/hw/dma/rc4030.c
> +++ b/hw/dma/rc4030.c
> @@ -90,7 +90,7 @@ typedef struct rc4030State
>      qemu_irq jazz_bus_irq;
>  
>      /* whole DMA memory region, root of DMA address space */
> -    MemoryRegion dma_mr;
> +    IOMMUMemoryRegion dma_mr;
>      AddressSpace dma_as;
>  
>      MemoryRegion iomem_chipset;
> @@ -488,7 +488,7 @@ static const MemoryRegionOps jazzio_ops = {
>      .endianness = DEVICE_NATIVE_ENDIAN,
>  };
>  
> -static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
> +static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
>                                            IOMMUAccessFlags flag)
>  {
>      rc4030State *s = container_of(iommu, rc4030State, dma_mr);
> @@ -679,7 +679,7 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
>  
>      memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
>                               "rc4030.dma", UINT32_MAX);
> -    address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
> +    address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma");
>  }
>  
>  static void rc4030_unrealize(DeviceState *dev, Error **errp)
> @@ -717,7 +717,7 @@ static void rc4030_register_types(void)
>  
>  type_init(rc4030_register_types)
>  
> -DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr)
> +DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr)
>  {
>      DeviceState *dev;
>  
> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
> index 7b6d4ea3f3..69e68a3e1b 100644
> --- a/hw/i386/amd_iommu.c
> +++ b/hw/i386/amd_iommu.c
> @@ -52,7 +52,7 @@ struct AMDVIAddressSpace {
>      uint8_t bus_num;            /* bus number                           */
>      uint8_t devfn;              /* device function                      */
>      AMDVIState *iommu_state;    /* AMDVI - one per machine              */
> -    MemoryRegion iommu;         /* Device's address translation region  */
> +    IOMMUMemoryRegion iommu;    /* Device's address translation region  */
>      MemoryRegion iommu_ir;      /* Device's interrupt remapping region  */
>      AddressSpace as;            /* device's corresponding address space */
>  };
> @@ -987,7 +987,7 @@ static inline bool amdvi_is_interrupt_addr(hwaddr addr)
>      return addr >= AMDVI_INT_ADDR_FIRST && addr <= AMDVI_INT_ADDR_LAST;
>  }
>  
> -static IOMMUTLBEntry amdvi_translate(MemoryRegion *iommu, hwaddr addr,
> +static IOMMUTLBEntry amdvi_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
>                                       IOMMUAccessFlags flag)
>  {
>      AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
> @@ -1046,7 +1046,8 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>  
>          memory_region_init_iommu(&iommu_as[devfn]->iommu, OBJECT(s),
>                                   &s->iommu_ops, "amd-iommu", UINT64_MAX);
> -        address_space_init(&iommu_as[devfn]->as, &iommu_as[devfn]->iommu,
> +        address_space_init(&iommu_as[devfn]->as,
> +                           MEMORY_REGION(&iommu_as[devfn]->iommu),
>                             "amd-iommu");
>      }
>      return &iommu_as[devfn]->as;
> @@ -1067,7 +1068,7 @@ static const MemoryRegionOps mmio_mem_ops = {
>      }
>  };
>  
> -static void amdvi_iommu_notify_flag_changed(MemoryRegion *iommu,
> +static void amdvi_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
>                                              IOMMUNotifierFlag old,
>                                              IOMMUNotifierFlag new)
>  {
> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> index 15610b9de8..b38d701b32 100644
> --- a/hw/i386/intel_iommu.c
> +++ b/hw/i386/intel_iommu.c
> @@ -993,9 +993,9 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)
>      /* Turn off first then on the other */
>      if (use_iommu) {
>          memory_region_set_enabled(&as->sys_alias, false);
> -        memory_region_set_enabled(&as->iommu, true);
> +        memory_region_set_enabled(MEMORY_REGION(&as->iommu), true);
>      } else {
> -        memory_region_set_enabled(&as->iommu, false);
> +        memory_region_set_enabled(MEMORY_REGION(&as->iommu), false);
>          memory_region_set_enabled(&as->sys_alias, true);
>      }
>  
> @@ -1378,7 +1378,7 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)
>  static int vtd_page_invalidate_notify_hook(IOMMUTLBEntry *entry,
>                                             void *private)
>  {
> -    memory_region_notify_iommu((MemoryRegion *)private, *entry);
> +    memory_region_notify_iommu((IOMMUMemoryRegion *)private, *entry);
>      return 0;
>  }
>  
> @@ -2357,7 +2357,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
>      }
>  }
>  
> -static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
> +static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
>                                           IOMMUAccessFlags flag)
>  {
>      VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
> @@ -2389,7 +2389,7 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
>      return ret;
>  }
>  
> -static void vtd_iommu_notify_flag_changed(MemoryRegion *iommu,
> +static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
>                                            IOMMUNotifierFlag old,
>                                            IOMMUNotifierFlag new)
>  {
> @@ -2832,7 +2832,8 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
>          memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
>                                              &vtd_dev_as->sys_alias, 1);
>          memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
> -                                            &vtd_dev_as->iommu, 1);
> +                                            MEMORY_REGION(&vtd_dev_as->iommu),
> +                                            1);
>          vtd_switch_address_space(vtd_dev_as);
>      }
>      return vtd_dev_as;
> @@ -2912,9 +2913,9 @@ static int vtd_replay_hook(IOMMUTLBEntry *entry, void *private)
>      return 0;
>  }
>  
> -static void vtd_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
> +static void vtd_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
>  {
> -    VTDAddressSpace *vtd_as = container_of(mr, VTDAddressSpace, iommu);
> +    VTDAddressSpace *vtd_as = container_of(iommu_mr, VTDAddressSpace, iommu);
>      IntelIOMMUState *s = vtd_as->iommu_state;
>      uint8_t bus_n = pci_bus_num(vtd_as->bus);
>      VTDContextEntry ce;
> diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
> index 1cef581878..1f69322c15 100644
> --- a/hw/mips/mips_jazz.c
> +++ b/hw/mips/mips_jazz.c
> @@ -130,7 +130,7 @@ static void mips_jazz_init(MachineState *machine,
>      CPUMIPSState *env;
>      qemu_irq *i8259;
>      rc4030_dma *dmas;
> -    MemoryRegion *rc4030_dma_mr;
> +    IOMMUMemoryRegion *rc4030_dma_mr;
>      MemoryRegion *isa_mem = g_new(MemoryRegion, 1);
>      MemoryRegion *isa_io = g_new(MemoryRegion, 1);
>      MemoryRegion *rtc = g_new(MemoryRegion, 1);
> diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
> index 326f5ef024..76a56ae29b 100644
> --- a/hw/pci-host/apb.c
> +++ b/hw/pci-host/apb.c
> @@ -123,7 +123,7 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
>  
>  typedef struct IOMMUState {
>      AddressSpace iommu_as;
> -    MemoryRegion iommu;
> +    IOMMUMemoryRegion iommu;
>  
>      uint64_t regs[IOMMU_NREGS];
>  } IOMMUState;
> @@ -208,7 +208,7 @@ static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>  }
>  
>  /* Called from RCU critical section */
> -static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
> +static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
>                                           IOMMUAccessFlags flag)
>  {
>      IOMMUState *is = container_of(iommu, IOMMUState, iommu);
> @@ -699,7 +699,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
>  
>      memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
>                               "iommu-apb", UINT64_MAX);
> -    address_space_init(&is->iommu_as, &is->iommu, "pbm-as");
> +    address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as");
>      pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
>  
>      /* APB secondary busses */
> diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
> index 0341bc069d..05910a608b 100644
> --- a/hw/ppc/spapr_iommu.c
> +++ b/hw/ppc/spapr_iommu.c
> @@ -110,7 +110,8 @@ static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table)
>  }
>  
>  /* Called from RCU critical section */
> -static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
> +static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMemoryRegion *iommu,
> +                                               hwaddr addr,
>                                                 IOMMUAccessFlags flag)
>  {
>      sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
> @@ -150,14 +151,14 @@ static void spapr_tce_table_pre_save(void *opaque)
>                                 tcet->bus_offset, tcet->page_shift);
>  }
>  
> -static uint64_t spapr_tce_get_min_page_size(MemoryRegion *iommu)
> +static uint64_t spapr_tce_get_min_page_size(IOMMUMemoryRegion *iommu)
>  {
>      sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
>  
>      return 1ULL << tcet->page_shift;
>  }
>  
> -static void spapr_tce_notify_flag_changed(MemoryRegion *iommu,
> +static void spapr_tce_notify_flag_changed(IOMMUMemoryRegion *iommu,
>                                            IOMMUNotifierFlag old,
>                                            IOMMUNotifierFlag new)
>  {
> @@ -348,9 +349,10 @@ void spapr_tce_table_enable(sPAPRTCETable *tcet,
>                                          &tcet->fd,
>                                          tcet->need_vfio);
>  
> -    memory_region_set_size(&tcet->iommu,
> +    memory_region_set_size(MEMORY_REGION(&tcet->iommu),
>                             (uint64_t)tcet->nb_table << tcet->page_shift);
> -    memory_region_add_subregion(&tcet->root, tcet->bus_offset, &tcet->iommu);
> +    memory_region_add_subregion(&tcet->root, tcet->bus_offset,
> +                                MEMORY_REGION(&tcet->iommu));
>  }
>  
>  void spapr_tce_table_disable(sPAPRTCETable *tcet)
> @@ -359,8 +361,8 @@ void spapr_tce_table_disable(sPAPRTCETable *tcet)
>          return;
>      }
>  
> -    memory_region_del_subregion(&tcet->root, &tcet->iommu);
> -    memory_region_set_size(&tcet->iommu, 0);
> +    memory_region_del_subregion(&tcet->root, MEMORY_REGION(&tcet->iommu));
> +    memory_region_set_size(MEMORY_REGION(&tcet->iommu), 0);
>  
>      spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
>      tcet->fd = -1;
> diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
> index 5651483781..e4fc82cbe1 100644
> --- a/hw/s390x/s390-pci-bus.c
> +++ b/hw/s390x/s390-pci-bus.c
> @@ -356,7 +356,7 @@ out:
>      return pte;
>  }
>  
> -static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *mr, hwaddr addr,
> +static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
>                                            IOMMUAccessFlags flag)
>  {
>      uint64_t pte;
> @@ -525,14 +525,14 @@ void s390_pci_iommu_enable(S390PCIIOMMU *iommu)
>      memory_region_init_iommu(&iommu->iommu_mr, OBJECT(&iommu->mr),
>                               &s390_iommu_ops, name, iommu->pal + 1);
>      iommu->enabled = true;
> -    memory_region_add_subregion(&iommu->mr, 0, &iommu->iommu_mr);
> +    memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu_mr));
>      g_free(name);
>  }
>  
>  void s390_pci_iommu_disable(S390PCIIOMMU *iommu)
>  {
>      iommu->enabled = false;
> -    memory_region_del_subregion(&iommu->mr, &iommu->iommu_mr);
> +    memory_region_del_subregion(&iommu->mr, MEMORY_REGION(&iommu->iommu_mr));
>      object_unparent(OBJECT(&iommu->iommu_mr));
>  }
>  
> diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
> index 8bc7c98682..a53c29c487 100644
> --- a/hw/s390x/s390-pci-inst.c
> +++ b/hw/s390x/s390-pci-inst.c
> @@ -563,7 +563,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
>      S390PCIIOMMU *iommu;
>      hwaddr start, end;
>      IOMMUTLBEntry entry;
> -    MemoryRegion *mr;
> +    IOMMUMemoryRegion *iommu_mr;
>  
>      cpu_synchronize_state(CPU(cpu));
>  
> @@ -622,9 +622,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
>          goto out;
>      }
>  
> -    mr = &iommu->iommu_mr;
> +    iommu_mr = &iommu->iommu_mr;
>      while (start < end) {
> -        entry = mr->iommu_ops->translate(mr, start, IOMMU_NONE);
> +        entry = iommu_mr->iommu_ops->translate(iommu_mr, start, IOMMU_NONE);
>  
>          if (!entry.translated_addr) {
>              pbdev->state = ZPCI_FS_ERROR;
> @@ -635,7 +635,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
>              goto out;
>          }
>  
> -        memory_region_notify_iommu(mr, entry);
> +        memory_region_notify_iommu(iommu_mr, entry);
>          start += entry.addr_mask + 1;
>      }
>  
> diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> index b9abe77f5a..2965b68e5d 100644
> --- a/hw/vfio/common.c
> +++ b/hw/vfio/common.c
> @@ -479,6 +479,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
>  
>      if (memory_region_is_iommu(section->mr)) {
>          VFIOGuestIOMMU *giommu;
> +        IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
>  
>          trace_vfio_listener_region_add_iommu(iova, end);
>          /*
> @@ -488,7 +489,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
>           * device emulation the VFIO iommu handles to use).
>           */
>          giommu = g_malloc0(sizeof(*giommu));
> -        giommu->iommu = section->mr;
> +        giommu->iommu = iommu_mr;
>          giommu->iommu_offset = section->offset_within_address_space -
>                                 section->offset_within_region;
>          giommu->container = container;
> @@ -501,7 +502,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
>                              int128_get64(llend));
>          QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
>  
> -        memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);
> +        memory_region_register_iommu_notifier(section->mr, &giommu->n);
>          memory_region_iommu_replay(giommu->iommu, &giommu->n);
>  
>          return;
> @@ -569,9 +570,9 @@ static void vfio_listener_region_del(MemoryListener *listener,
>          VFIOGuestIOMMU *giommu;
>  
>          QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
> -            if (giommu->iommu == section->mr &&
> +            if (MEMORY_REGION(giommu->iommu) == section->mr &&
>                  giommu->n.start == section->offset_within_region) {
> -                memory_region_unregister_iommu_notifier(giommu->iommu,
> +                memory_region_unregister_iommu_notifier(section->mr,
>                                                          &giommu->n);
>                  QLIST_REMOVE(giommu, giommu_next);
>                  g_free(giommu);
> @@ -1161,7 +1162,8 @@ static void vfio_disconnect_container(VFIOGroup *group)
>          QLIST_REMOVE(container, next);
>  
>          QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
> -            memory_region_unregister_iommu_notifier(giommu->iommu, &giommu->n);
> +            memory_region_unregister_iommu_notifier(
> +                    MEMORY_REGION(giommu->iommu), &giommu->n);
>              QLIST_REMOVE(giommu, giommu_next);
>              g_free(giommu);
>          }
> diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
> index 4409bcc0d7..32fd6a9b54 100644
> --- a/hw/vfio/spapr.c
> +++ b/hw/vfio/spapr.c
> @@ -143,7 +143,8 @@ int vfio_spapr_create_window(VFIOContainer *container,
>                               hwaddr *pgsize)
>  {
>      int ret;
> -    unsigned pagesize = memory_region_iommu_get_min_page_size(section->mr);
> +    IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
> +    unsigned pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
>      unsigned entries, pages;
>      struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
>  
> diff --git a/memory.c b/memory.c
> index 0ddc4cc28d..f55b420d88 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -975,12 +975,11 @@ static char *memory_region_escape_name(const char *name)
>      return escaped;
>  }
>  
> -void memory_region_init(MemoryRegion *mr,
> -                        Object *owner,
> -                        const char *name,
> -                        uint64_t size)
> +static void memory_region_do_init(MemoryRegion *mr,
> +                                  Object *owner,
> +                                  const char *name,
> +                                  uint64_t size)
>  {
> -    object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
>      mr->size = int128_make64(size);
>      if (size == UINT64_MAX) {
>          mr->size = int128_2_64();
> @@ -1004,6 +1003,15 @@ void memory_region_init(MemoryRegion *mr,
>      }
>  }
>  
> +void memory_region_init(MemoryRegion *mr,
> +                        Object *owner,
> +                        const char *name,
> +                        uint64_t size)
> +{
> +    object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
> +    memory_region_do_init(mr, owner, name, size);
> +}
> +
>  static void memory_region_get_addr(Object *obj, Visitor *v, const char *name,
>                                     void *opaque, Error **errp)
>  {
> @@ -1090,6 +1098,13 @@ static void memory_region_initfn(Object *obj)
>                          NULL, NULL, &error_abort);
>  }
>  
> +static void iommu_memory_region_initfn(Object *obj)
> +{
> +    MemoryRegion *mr = MEMORY_REGION(obj);
> +
> +    mr->is_iommu = true;
> +}
> +
>  static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
>                                      unsigned size)
>  {
> @@ -1473,17 +1488,22 @@ void memory_region_init_rom_device(MemoryRegion *mr,
>      mr->ram_block = qemu_ram_alloc(size, mr, errp);
>  }
>  
> -void memory_region_init_iommu(MemoryRegion *mr,
> +void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
>                                Object *owner,
>                                const MemoryRegionIOMMUOps *ops,
>                                const char *name,
>                                uint64_t size)
>  {
> -    memory_region_init(mr, owner, name, size);
> -    mr->iommu_ops = ops,
> +    struct MemoryRegion *mr;
> +
> +    object_initialize(iommu_mr, sizeof(*iommu_mr), TYPE_IOMMU_MEMORY_REGION);
> +    mr = MEMORY_REGION(iommu_mr);
> +    memory_region_do_init(mr, owner, name, size);
> +    iommu_mr = IOMMU_MEMORY_REGION(mr);
> +    iommu_mr->iommu_ops = ops,
>      mr->terminates = true;  /* then re-forwards */
> -    QLIST_INIT(&mr->iommu_notify);
> -    mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
> +    QLIST_INIT(&iommu_mr->iommu_notify);
> +    iommu_mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
>  }
>  
>  static void memory_region_finalize(Object *obj)
> @@ -1578,63 +1598,67 @@ bool memory_region_is_logging(MemoryRegion *mr, uint8_t client)
>      return memory_region_get_dirty_log_mask(mr) & (1 << client);
>  }
>  
> -static void memory_region_update_iommu_notify_flags(MemoryRegion *mr)
> +static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr)
>  {
>      IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE;
>      IOMMUNotifier *iommu_notifier;
>  
> -    IOMMU_NOTIFIER_FOREACH(iommu_notifier, mr) {
> +    IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
>          flags |= iommu_notifier->notifier_flags;
>      }
>  
> -    if (flags != mr->iommu_notify_flags &&
> -        mr->iommu_ops->notify_flag_changed) {
> -        mr->iommu_ops->notify_flag_changed(mr, mr->iommu_notify_flags,
> -                                           flags);
> +    if (flags != iommu_mr->iommu_notify_flags &&
> +        iommu_mr->iommu_ops->notify_flag_changed) {
> +        iommu_mr->iommu_ops->notify_flag_changed(iommu_mr,
> +                                                iommu_mr->iommu_notify_flags,
> +                                                flags);
>      }
>  
> -    mr->iommu_notify_flags = flags;
> +    iommu_mr->iommu_notify_flags = flags;
>  }
>  
>  void memory_region_register_iommu_notifier(MemoryRegion *mr,
>                                             IOMMUNotifier *n)
>  {
> +    IOMMUMemoryRegion *iommu_mr;
> +
>      if (mr->alias) {
>          memory_region_register_iommu_notifier(mr->alias, n);
>          return;
>      }
>  
>      /* We need to register for at least one bitfield */
> +    iommu_mr = IOMMU_MEMORY_REGION(mr);
>      assert(n->notifier_flags != IOMMU_NOTIFIER_NONE);
>      assert(n->start <= n->end);
> -    QLIST_INSERT_HEAD(&mr->iommu_notify, n, node);
> -    memory_region_update_iommu_notify_flags(mr);
> +    QLIST_INSERT_HEAD(&iommu_mr->iommu_notify, n, node);
> +    memory_region_update_iommu_notify_flags(iommu_mr);
>  }
>  
> -uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr)
> +uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
>  {
> -    assert(memory_region_is_iommu(mr));
> -    if (mr->iommu_ops && mr->iommu_ops->get_min_page_size) {
> -        return mr->iommu_ops->get_min_page_size(mr);
> +    if (iommu_mr->iommu_ops && iommu_mr->iommu_ops->get_min_page_size) {
> +        return iommu_mr->iommu_ops->get_min_page_size(iommu_mr);
>      }
>      return TARGET_PAGE_SIZE;
>  }
>  
> -void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
> +void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
>  {
> +    MemoryRegion *mr = MEMORY_REGION(iommu_mr);
>      hwaddr addr, granularity;
>      IOMMUTLBEntry iotlb;
>  
>      /* If the IOMMU has its own replay callback, override */
> -    if (mr->iommu_ops->replay) {
> -        mr->iommu_ops->replay(mr, n);
> +    if (iommu_mr->iommu_ops->replay) {
> +        iommu_mr->iommu_ops->replay(iommu_mr, n);
>          return;
>      }
>  
> -    granularity = memory_region_iommu_get_min_page_size(mr);
> +    granularity = memory_region_iommu_get_min_page_size(iommu_mr);
>  
>      for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
> -        iotlb = mr->iommu_ops->translate(mr, addr, IOMMU_NONE);
> +        iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, IOMMU_NONE);
>          if (iotlb.perm != IOMMU_NONE) {
>              n->notify(n, &iotlb);
>          }
> @@ -1647,24 +1671,27 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
>      }
>  }
>  
> -void memory_region_iommu_replay_all(MemoryRegion *mr)
> +void memory_region_iommu_replay_all(IOMMUMemoryRegion *iommu_mr)
>  {
>      IOMMUNotifier *notifier;
>  
> -    IOMMU_NOTIFIER_FOREACH(notifier, mr) {
> -        memory_region_iommu_replay(mr, notifier);
> +    IOMMU_NOTIFIER_FOREACH(notifier, iommu_mr) {
> +        memory_region_iommu_replay(iommu_mr, notifier);
>      }
>  }
>  
>  void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
>                                               IOMMUNotifier *n)
>  {
> +    IOMMUMemoryRegion *iommu_mr;
> +
>      if (mr->alias) {
>          memory_region_unregister_iommu_notifier(mr->alias, n);
>          return;
>      }
>      QLIST_REMOVE(n, node);
> -    memory_region_update_iommu_notify_flags(mr);
> +    iommu_mr = IOMMU_MEMORY_REGION(mr);
> +    memory_region_update_iommu_notify_flags(iommu_mr);
>  }
>  
>  void memory_region_notify_one(IOMMUNotifier *notifier,
> @@ -1692,14 +1719,14 @@ void memory_region_notify_one(IOMMUNotifier *notifier,
>      }
>  }
>  
> -void memory_region_notify_iommu(MemoryRegion *mr,
> +void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
>                                  IOMMUTLBEntry entry)
>  {
>      IOMMUNotifier *iommu_notifier;
>  
> -    assert(memory_region_is_iommu(mr));
> +    assert(memory_region_is_iommu(MEMORY_REGION(iommu_mr)));
>  
> -    IOMMU_NOTIFIER_FOREACH(iommu_notifier, mr) {
> +    IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
>          memory_region_notify_one(iommu_notifier, &entry);
>      }
>  }
> @@ -2708,9 +2735,17 @@ static const TypeInfo memory_region_info = {
>      .instance_finalize  = memory_region_finalize,
>  };
>  
> +static const TypeInfo iommu_memory_region_info = {
> +    .parent             = TYPE_MEMORY_REGION,
> +    .name               = TYPE_IOMMU_MEMORY_REGION,
> +    .instance_size      = sizeof(IOMMUMemoryRegion),
> +    .instance_init      = iommu_memory_region_initfn,
> +};
> +
>  static void memory_register_types(void)
>  {
>      type_register_static(&memory_region_info);
> +    type_register_static(&iommu_memory_region_info);
>  }
>  
>  type_init(memory_register_types)
--
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

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH qemu v8 2/2] memory/iommu: introduce IOMMUMemoryRegionClass

Alexey Kardashevskiy
In reply to this post by Alexey Kardashevskiy
On 14/06/17 16:36, Alexey Kardashevskiy wrote:
> This finishes QOM'fication of IOMMUMemoryRegion by introducing
> a IOMMUMemoryRegionClass. This also provides a fastpath analog for
> IOMMU_MEMORY_REGION_GET_CLASS().


Ping?


>
> Signed-off-by: Alexey Kardashevskiy <[hidden email]>
> ---
>  hw/i386/amd_iommu.h           |  3 ---
>  include/exec/memory.h         | 45 +++++++++++++++++++++++++++++++++----------
>  include/hw/i386/intel_iommu.h |  1 -
>  include/hw/ppc/spapr.h        |  4 ++++
>  exec.c                        |  6 ++++--
>  hw/alpha/typhoon.c            | 23 +++++++++++++++++-----
>  hw/dma/rc4030.c               | 26 +++++++++++++++++++------
>  hw/i386/amd_iommu.c           | 26 +++++++++++++++++++++----
>  hw/i386/intel_iommu.c         | 27 +++++++++++++++++++++-----
>  hw/pci-host/apb.c             | 23 +++++++++++++++++-----
>  hw/ppc/spapr_iommu.c          | 26 ++++++++++++++++++-------
>  hw/s390x/s390-pci-bus.c       | 25 ++++++++++++++++++------
>  hw/s390x/s390-pci-inst.c      |  5 ++++-
>  memory.c                      | 36 +++++++++++++++++++---------------
>  14 files changed, 206 insertions(+), 70 deletions(-)
>
> diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h
> index 0d3dc6a9f2..a5a1c32c8b 100644
> --- a/hw/i386/amd_iommu.h
> +++ b/hw/i386/amd_iommu.h
> @@ -276,9 +276,6 @@ typedef struct AMDVIState {
>      uint8_t romask[AMDVI_MMIO_SIZE];   /* MMIO read/only mask          */
>      bool mmio_enabled;
>  
> -    /* IOMMU function */
> -    MemoryRegionIOMMUOps iommu_ops;
> -
>      /* for each served device */
>      AMDVIAddressSpace **address_spaces[PCI_BUS_MAX];
>  
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 8aefea3abc..64f6735aaa 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -25,6 +25,7 @@
>  #include "qemu/notify.h"
>  #include "qom/object.h"
>  #include "qemu/rcu.h"
> +#include "hw/qdev-core.h"
>  
>  #define RAM_ADDR_INVALID (~(ram_addr_t)0)
>  
> @@ -38,6 +39,12 @@
>  #define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region"
>  #define IOMMU_MEMORY_REGION(obj) \
>          OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION)
> +#define IOMMU_MEMORY_REGION_CLASS(klass) \
> +        OBJECT_CLASS_CHECK(IOMMUMemoryRegionClass, (klass), \
> +                         TYPE_IOMMU_MEMORY_REGION)
> +#define IOMMU_MEMORY_REGION_GET_CLASS(obj) \
> +        OBJECT_GET_CLASS(IOMMUMemoryRegionClass, (obj), \
> +                         TYPE_IOMMU_MEMORY_REGION)
>  
>  typedef struct MemoryRegionOps MemoryRegionOps;
>  typedef struct MemoryRegionMmio MemoryRegionMmio;
> @@ -184,9 +191,10 @@ struct MemoryRegionOps {
>      const MemoryRegionMmio old_mmio;
>  };
>  
> -typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;
> +typedef struct IOMMUMemoryRegionClass {
> +    /* private */
> +    struct DeviceClass parent_class;
>  
> -struct MemoryRegionIOMMUOps {
>      /*
>       * Return a TLB entry that contains a given address. Flag should
>       * be the access permission of this translation operation. We can
> @@ -203,7 +211,7 @@ struct MemoryRegionIOMMUOps {
>                                  IOMMUNotifierFlag new_flags);
>      /* Set this up to provide customized IOMMU replay function */
>      void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier);
> -};
> +} IOMMUMemoryRegionClass;
>  
>  typedef struct CoalescedMemoryRange CoalescedMemoryRange;
>  typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
> @@ -252,7 +260,6 @@ struct MemoryRegion {
>  struct IOMMUMemoryRegion {
>      MemoryRegion parent_obj;
>  
> -    const MemoryRegionIOMMUOps *iommu_ops;
>      QLIST_HEAD(, IOMMUNotifier) iommu_notify;
>      IOMMUNotifierFlag iommu_notify_flags;
>  };
> @@ -593,21 +600,24 @@ static inline void memory_region_init_reservation(MemoryRegion *mr,
>  }
>  
>  /**
> - * memory_region_init_iommu: Initialize a memory region that translates
> - * addresses
> + * memory_region_init_iommu: Initialize a memory region of a custom type
> + * that translates addresses
>   *
>   * An IOMMU region translates addresses and forwards accesses to a target
>   * memory region.
>   *
> - * @iommu_mr: the #IOMMUMemoryRegion to be initialized
> + * @typename: QOM class name
> + * @_iommu_mr: the #IOMMUMemoryRegion to be initialized
> + * @instance_size: the IOMMUMemoryRegion subclass instance size
>   * @owner: the object that tracks the region's reference count
>   * @ops: a function that translates addresses into the @target region
>   * @name: used for debugging; not visible to the user or ABI
>   * @size: size of the region.
>   */
> -void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
> -                              struct Object *owner,
> -                              const MemoryRegionIOMMUOps *ops,
> +void memory_region_init_iommu(void *_iommu_mr,
> +                              size_t instance_size,
> +                              const char *mrtypename,
> +                              Object *owner,
>                                const char *name,
>                                uint64_t size);
>  
> @@ -678,6 +688,21 @@ static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr)
>      return NULL;
>  }
>  
> +/**
> + * memory_region_get_iommu_class_nocheck: returns iommu memory region class
> + *   if an iommu or NULL if not
> + *
> + * Returns pointer to IOMMUMemoryRegioniClass if a memory region is an iommu,
> + * otherwise NULL. This is fast path avoinding QOM checking, use with caution.
> + *
> + * @mr: the memory region being queried
> + */
> +static inline IOMMUMemoryRegionClass *memory_region_get_iommu_class_nocheck(
> +        IOMMUMemoryRegion *iommu_mr)
> +{
> +    return (IOMMUMemoryRegionClass *) (((Object *)iommu_mr)->class);
> +}
> +
>  #define memory_region_is_iommu(mr) (memory_region_get_iommu(mr) != NULL)
>  
>  /**
> diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
> index 45fba4ff97..e5b5a8ff27 100644
> --- a/include/hw/i386/intel_iommu.h
> +++ b/include/hw/i386/intel_iommu.h
> @@ -289,7 +289,6 @@ struct IntelIOMMUState {
>      uint32_t context_cache_gen;     /* Should be in [1,MAX] */
>      GHashTable *iotlb;              /* IOTLB */
>  
> -    MemoryRegionIOMMUOps iommu_ops;
>      GHashTable *vtd_as_by_busptr;   /* VTDBus objects indexed by PCIBus* reference */
>      VTDBus *vtd_as_by_bus_num[VTD_PCI_BUS_MAX]; /* VTDBus objects indexed by bus number */
>      /* list of registered notifiers */
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 6bd338156b..13b2d88330 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -579,6 +579,10 @@ typedef struct sPAPRTCETable sPAPRTCETable;
>  #define SPAPR_TCE_TABLE(obj) \
>      OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE)
>  
> +#define TYPE_SPAPR_IOMMU_MEMORY_REGION "qemu:spapr-iommu-memory-region"
> +#define SPAPR_IOMMU_MEMORY_REGION(obj) \
> +        OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_SPAPR_IOMMU_MEMORY_REGION)
> +
>  struct sPAPRTCETable {
>      DeviceState parent;
>      uint32_t liobn;
> diff --git a/exec.c b/exec.c
> index 182cc9b9b9..acba7fc303 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -476,6 +476,7 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
>      IOMMUTLBEntry iotlb;
>      MemoryRegionSection *section;
>      IOMMUMemoryRegion *iommu_mr;
> +    IOMMUMemoryRegionClass *imrc;
>  
>      for (;;) {
>          AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
> @@ -485,9 +486,10 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
>          if (!iommu_mr) {
>              break;
>          }
> +        imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
>  
> -        iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, is_write ?
> -                                               IOMMU_WO : IOMMU_RO);
> +        iotlb = imrc->translate(iommu_mr, addr, is_write ?
> +                                IOMMU_WO : IOMMU_RO);
>          addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
>                  | (addr & iotlb.addr_mask));
>          *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
> diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
> index dd47b4569f..491433e12f 100644
> --- a/hw/alpha/typhoon.c
> +++ b/hw/alpha/typhoon.c
> @@ -17,6 +17,7 @@
>  
>  
>  #define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
> +#define TYPE_TYPHOON_IOMMU_MEMORY_REGION "typhoon:iommu_memory_region"
>  
>  typedef struct TyphoonCchip {
>      MemoryRegion region;
> @@ -725,10 +726,6 @@ static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
>      return ret;
>  }
>  
> -static const MemoryRegionIOMMUOps typhoon_iommu_ops = {
> -    .translate = typhoon_translate_iommu,
> -};
> -
>  static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>  {
>      TyphoonState *s = opaque;
> @@ -892,7 +889,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
>      qdev_init_nofail(dev);
>  
>      /* Host memory as seen from the PCI side, via the IOMMU.  */
> -    memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
> +    memory_region_init_iommu(&s->pchip.iommu, sizeof(s->pchip.iommu),
> +                             TYPE_TYPHOON_IOMMU_MEMORY_REGION, OBJECT(s),
>                               "iommu-typhoon", UINT64_MAX);
>      address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu),
>                         "pchip0-pci");
> @@ -953,9 +951,24 @@ static const TypeInfo typhoon_pcihost_info = {
>      .class_init    = typhoon_pcihost_class_init,
>  };
>  
> +static void typhoon_iommu_memory_region_class_init(ObjectClass *klass,
> +                                                   void *data)
> +{
> +    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
> +
> +    imrc->translate = typhoon_translate_iommu;
> +}
> +
> +static const TypeInfo typhoon_iommu_memory_region_info = {
> +    .parent = TYPE_IOMMU_MEMORY_REGION,
> +    .name = TYPE_TYPHOON_IOMMU_MEMORY_REGION,
> +    .class_init = typhoon_iommu_memory_region_class_init,
> +};
> +
>  static void typhoon_register_types(void)
>  {
>      type_register_static(&typhoon_pcihost_info);
> +    type_register_static(&typhoon_iommu_memory_region_info);
>  }
>  
>  type_init(typhoon_register_types)
> diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
> index 32c06760ef..6a49e4ef4a 100644
> --- a/hw/dma/rc4030.c
> +++ b/hw/dma/rc4030.c
> @@ -54,6 +54,8 @@ typedef struct dma_pagetable_entry {
>  #define RC4030(obj) \
>      OBJECT_CHECK(rc4030State, (obj), TYPE_RC4030)
>  
> +#define TYPE_RC4030_IOMMU_MEMORY_REGION "rc4030:iommu_memory_region"
> +
>  typedef struct rc4030State
>  {
>      SysBusDevice parent;
> @@ -516,10 +518,6 @@ static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
>      return ret;
>  }
>  
> -static const MemoryRegionIOMMUOps rc4030_dma_ops = {
> -    .translate = rc4030_dma_translate,
> -};
> -
>  static void rc4030_reset(DeviceState *dev)
>  {
>      rc4030State *s = RC4030(dev);
> @@ -677,8 +675,9 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
>      memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
>                            "rc4030.jazzio", 0x00001000);
>  
> -    memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
> -                             "rc4030.dma", UINT32_MAX);
> +    memory_region_init_iommu(&s->dma_mr, sizeof(s->dma_mr),
> +                             TYPE_RC4030_IOMMU_MEMORY_REGION,
> +                             o, "rc4030.dma", UINT32_MAX);
>      address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma");
>  }
>  
> @@ -710,9 +709,24 @@ static const TypeInfo rc4030_info = {
>      .class_init = rc4030_class_init,
>  };
>  
> +static void rc4030_iommu_memory_region_class_init(ObjectClass *klass,
> +                                                  void *data)
> +{
> +    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
> +
> +    imrc->translate = rc4030_dma_translate;
> +}
> +
> +static const TypeInfo rc4030_iommu_memory_region_info = {
> +    .parent = TYPE_IOMMU_MEMORY_REGION,
> +    .name = TYPE_RC4030_IOMMU_MEMORY_REGION,
> +    .class_init = rc4030_iommu_memory_region_class_init,
> +};
> +
>  static void rc4030_register_types(void)
>  {
>      type_register_static(&rc4030_info);
> +    type_register_static(&rc4030_iommu_memory_region_info);
>  }
>  
>  type_init(rc4030_register_types)
> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
> index 69e68a3e1b..af19e8ea41 100644
> --- a/hw/i386/amd_iommu.c
> +++ b/hw/i386/amd_iommu.c
> @@ -25,6 +25,8 @@
>  #include "qemu/error-report.h"
>  #include "trace.h"
>  
> +#define TYPE_AMD_VI_IOMMU_MEMORY_REGION "amd_vi:iommu_memory_region"
> +
>  /* used AMD-Vi MMIO registers */
>  const char *amdvi_mmio_low[] = {
>      "AMDVI_MMIO_DEVTAB_BASE",
> @@ -1044,8 +1046,11 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
>          iommu_as[devfn]->devfn = (uint8_t)devfn;
>          iommu_as[devfn]->iommu_state = s;
>  
> -        memory_region_init_iommu(&iommu_as[devfn]->iommu, OBJECT(s),
> -                                 &s->iommu_ops, "amd-iommu", UINT64_MAX);
> +        memory_region_init_iommu(&iommu_as[devfn]->iommu,
> +                                 sizeof(iommu_as[devfn]->iommu),
> +                                 TYPE_AMD_VI_IOMMU_MEMORY_REGION,
> +                                 OBJECT(s),
> +                                 "amd-iommu", UINT64_MAX);
>          address_space_init(&iommu_as[devfn]->as,
>                             MEMORY_REGION(&iommu_as[devfn]->iommu),
>                             "amd-iommu");
> @@ -1086,8 +1091,6 @@ static void amdvi_init(AMDVIState *s)
>  {
>      amdvi_iotlb_reset(s);
>  
> -    s->iommu_ops.translate = amdvi_translate;
> -    s->iommu_ops.notify_flag_changed = amdvi_iommu_notify_flag_changed;
>      s->devtab_len = 0;
>      s->cmdbuf_len = 0;
>      s->cmdbuf_head = 0;
> @@ -1218,10 +1221,25 @@ static const TypeInfo amdviPCI = {
>      .instance_size = sizeof(AMDVIPCIState),
>  };
>  
> +static void amdvi_iommu_memory_region_class_init(ObjectClass *klass, void *data)
> +{
> +    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
> +
> +    imrc->translate = amdvi_translate;
> +    imrc->notify_flag_changed = amdvi_iommu_notify_flag_changed;
> +}
> +
> +static const TypeInfo amdvi_iommu_memory_region_info = {
> +    .parent = TYPE_IOMMU_MEMORY_REGION,
> +    .name = TYPE_AMD_VI_IOMMU_MEMORY_REGION,
> +    .class_init = amdvi_iommu_memory_region_class_init,
> +};
> +
>  static void amdviPCI_register_types(void)
>  {
>      type_register_static(&amdviPCI);
>      type_register_static(&amdvi);
> +    type_register_static(&amdvi_iommu_memory_region_info);
>  }
>  
>  type_init(amdviPCI_register_types);
> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> index b38d701b32..8aafd6ba5b 100644
> --- a/hw/i386/intel_iommu.c
> +++ b/hw/i386/intel_iommu.c
> @@ -37,6 +37,8 @@
>  #include "kvm_i386.h"
>  #include "trace.h"
>  
> +#define TYPE_INTEL_VTD_IOMMU_MEMORY_REGION "intel_vtd:iommu_memory_region"
> +
>  /*#define DEBUG_INTEL_IOMMU*/
>  #ifdef DEBUG_INTEL_IOMMU
>  enum {
> @@ -2814,8 +2816,9 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
>           * vtd_sys_alias and intel_iommu regions. IR region is always
>           * enabled.
>           */
> -        memory_region_init_iommu(&vtd_dev_as->iommu, OBJECT(s),
> -                                 &s->iommu_ops, "intel_iommu_dmar",
> +        memory_region_init_iommu(&vtd_dev_as->iommu, sizeof(vtd_dev_as->iommu),
> +                                 TYPE_INTEL_VTD_IOMMU_MEMORY_REGION, OBJECT(s),
> +                                 "intel_iommu_dmar",
>                                   UINT64_MAX);
>          memory_region_init_alias(&vtd_dev_as->sys_alias, OBJECT(s),
>                                   "vtd_sys_alias", get_system_memory(),
> @@ -2953,9 +2956,6 @@ static void vtd_init(IntelIOMMUState *s)
>      memset(s->w1cmask, 0, DMAR_REG_SIZE);
>      memset(s->womask, 0, DMAR_REG_SIZE);
>  
> -    s->iommu_ops.translate = vtd_iommu_translate;
> -    s->iommu_ops.notify_flag_changed = vtd_iommu_notify_flag_changed;
> -    s->iommu_ops.replay = vtd_iommu_replay;
>      s->root = 0;
>      s->root_extended = false;
>      s->dmar_enabled = false;
> @@ -3172,10 +3172,27 @@ static const TypeInfo vtd_info = {
>      .class_init    = vtd_class_init,
>  };
>  
> +static void intel_vtd_iommu_memory_region_class_init(ObjectClass *klass,
> +                                                     void *data)
> +{
> +    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
> +
> +    imrc->translate = vtd_iommu_translate;
> +    imrc->notify_flag_changed = vtd_iommu_notify_flag_changed;
> +    imrc->replay = vtd_iommu_replay;
> +}
> +
> +static const TypeInfo intel_vtd_iommu_memory_region_info = {
> +    .parent = TYPE_IOMMU_MEMORY_REGION,
> +    .name = TYPE_INTEL_VTD_IOMMU_MEMORY_REGION,
> +    .class_init = intel_vtd_iommu_memory_region_class_init,
> +};
> +
>  static void vtd_register_types(void)
>  {
>      VTD_DPRINTF(GENERAL, "");
>      type_register_static(&vtd_info);
> +    type_register_static(&intel_vtd_iommu_memory_region_info);
>  }
>  
>  type_init(vtd_register_types)
> diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
> index 76a56ae29b..f1a854159a 100644
> --- a/hw/pci-host/apb.c
> +++ b/hw/pci-host/apb.c
> @@ -133,6 +133,8 @@ typedef struct IOMMUState {
>  #define APB_DEVICE(obj) \
>      OBJECT_CHECK(APBState, (obj), TYPE_APB)
>  
> +#define TYPE_PBM_IOMMU_MEMORY_REGION "pbm:iommu_memory_region"
> +
>  typedef struct APBState {
>      PCIHostState parent_obj;
>  
> @@ -322,10 +324,6 @@ static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
>      return ret;
>  }
>  
> -static MemoryRegionIOMMUOps pbm_iommu_ops = {
> -    .translate = pbm_translate_iommu,
> -};
> -
>  static void iommu_config_write(void *opaque, hwaddr addr,
>                                 uint64_t val, unsigned size)
>  {
> @@ -697,7 +695,8 @@ PCIBus *pci_apb_init(hwaddr special_base,
>      is = &d->iommu;
>      memset(is, 0, sizeof(IOMMUState));
>  
> -    memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
> +    memory_region_init_iommu(&is->iommu, sizeof(is->iommu),
> +                             TYPE_PBM_IOMMU_MEMORY_REGION, OBJECT(dev),
>                               "iommu-apb", UINT64_MAX);
>      address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as");
>      pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
> @@ -860,11 +859,25 @@ static const TypeInfo pbm_pci_bridge_info = {
>      .class_init    = pbm_pci_bridge_class_init,
>  };
>  
> +static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data)
> +{
> +    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
> +
> +    imrc->translate = pbm_translate_iommu;
> +}
> +
> +static const TypeInfo pbm_iommu_memory_region_info = {
> +    .parent = TYPE_IOMMU_MEMORY_REGION,
> +    .name = TYPE_PBM_IOMMU_MEMORY_REGION,
> +    .class_init = pbm_iommu_memory_region_class_init,
> +};
> +
>  static void pbm_register_types(void)
>  {
>      type_register_static(&pbm_host_info);
>      type_register_static(&pbm_pci_host_info);
>      type_register_static(&pbm_pci_bridge_info);
> +    type_register_static(&pbm_iommu_memory_region_info);
>  }
>  
>  type_init(pbm_register_types)
> diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
> index 05910a608b..c1cb14b84a 100644
> --- a/hw/ppc/spapr_iommu.c
> +++ b/hw/ppc/spapr_iommu.c
> @@ -248,12 +248,6 @@ static const VMStateDescription vmstate_spapr_tce_table = {
>      }
>  };
>  
> -static MemoryRegionIOMMUOps spapr_iommu_ops = {
> -    .translate = spapr_tce_translate_iommu,
> -    .get_min_page_size = spapr_tce_get_min_page_size,
> -    .notify_flag_changed = spapr_tce_notify_flag_changed,
> -};
> -
>  static int spapr_tce_table_realize(DeviceState *dev)
>  {
>      sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
> @@ -266,7 +260,9 @@ static int spapr_tce_table_realize(DeviceState *dev)
>      memory_region_init(&tcet->root, tcetobj, tmp, UINT64_MAX);
>  
>      snprintf(tmp, sizeof(tmp), "tce-iommu-%x", tcet->liobn);
> -    memory_region_init_iommu(&tcet->iommu, tcetobj, &spapr_iommu_ops, tmp, 0);
> +    memory_region_init_iommu(&tcet->iommu, sizeof(tcet->iommu),
> +                             TYPE_SPAPR_IOMMU_MEMORY_REGION,
> +                             tcetobj, tmp, 0);
>  
>      QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
>  
> @@ -639,9 +635,25 @@ static TypeInfo spapr_tce_table_info = {
>      .class_init = spapr_tce_table_class_init,
>  };
>  
> +static void spapr_iommu_memory_region_class_init(ObjectClass *klass, void *data)
> +{
> +    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
> +
> +    imrc->translate = spapr_tce_translate_iommu;
> +    imrc->get_min_page_size = spapr_tce_get_min_page_size;
> +    imrc->notify_flag_changed = spapr_tce_notify_flag_changed;
> +}
> +
> +static const TypeInfo spapr_iommu_memory_region_info = {
> +    .parent = TYPE_IOMMU_MEMORY_REGION,
> +    .name = TYPE_SPAPR_IOMMU_MEMORY_REGION,
> +    .class_init = spapr_iommu_memory_region_class_init,
> +};
> +
>  static void register_types(void)
>  {
>      type_register_static(&spapr_tce_table_info);
> +    type_register_static(&spapr_iommu_memory_region_info);
>  }
>  
>  type_init(register_types);
> diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
> index e4fc82cbe1..6720492d63 100644
> --- a/hw/s390x/s390-pci-bus.c
> +++ b/hw/s390x/s390-pci-bus.c
> @@ -27,6 +27,8 @@
>  #define DEBUG_S390PCI_BUS  0
>  #endif
>  
> +#define TYPE_S390_IOMMU_MEMORY_REGION "s390:iommu_memory_region"
> +
>  #define DPRINTF(fmt, ...)                                         \
>      do {                                                          \
>          if (DEBUG_S390PCI_BUS) {                                  \
> @@ -407,10 +409,6 @@ static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
>      return ret;
>  }
>  
> -static const MemoryRegionIOMMUOps s390_iommu_ops = {
> -    .translate = s390_translate_iommu,
> -};
> -
>  static S390PCIIOMMU *s390_pci_get_iommu(S390pciState *s, PCIBus *bus,
>                                          int devfn)
>  {
> @@ -522,8 +520,9 @@ static const MemoryRegionOps s390_msi_ctrl_ops = {
>  void s390_pci_iommu_enable(S390PCIIOMMU *iommu)
>  {
>      char *name = g_strdup_printf("iommu-s390-%04x", iommu->pbdev->uid);
> -    memory_region_init_iommu(&iommu->iommu_mr, OBJECT(&iommu->mr),
> -                             &s390_iommu_ops, name, iommu->pal + 1);
> +    memory_region_init_iommu(&iommu->iommu_mr, sizeof(iommu->iommu_mr),
> +                             TYPE_S390_IOMMU_MEMORY_REGION, OBJECT(&iommu->mr),
> +                             name, iommu->pal + 1);
>      iommu->enabled = true;
>      memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu_mr));
>      g_free(name);
> @@ -1058,12 +1057,26 @@ static TypeInfo s390_pci_iommu_info = {
>      .instance_size = sizeof(S390PCIIOMMU),
>  };
>  
> +static void s390_iommu_memory_region_class_init(ObjectClass *klass, void *data)
> +{
> +    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
> +
> +    imrc->translate = s390_translate_iommu;
> +}
> +
> +static const TypeInfo s390_iommu_memory_region_info = {
> +    .parent = TYPE_IOMMU_MEMORY_REGION,
> +    .name = TYPE_S390_IOMMU_MEMORY_REGION,
> +    .class_init = s390_iommu_memory_region_class_init,
> +};
> +
>  static void s390_pci_register_types(void)
>  {
>      type_register_static(&s390_pcihost_info);
>      type_register_static(&s390_pcibus_info);
>      type_register_static(&s390_pci_device_info);
>      type_register_static(&s390_pci_iommu_info);
> +    type_register_static(&s390_iommu_memory_region_info);
>  }
>  
>  type_init(s390_pci_register_types)
> diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
> index a53c29c487..b7beb8c36a 100644
> --- a/hw/s390x/s390-pci-inst.c
> +++ b/hw/s390x/s390-pci-inst.c
> @@ -564,6 +564,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
>      hwaddr start, end;
>      IOMMUTLBEntry entry;
>      IOMMUMemoryRegion *iommu_mr;
> +    IOMMUMemoryRegionClass *imrc;
>  
>      cpu_synchronize_state(CPU(cpu));
>  
> @@ -623,8 +624,10 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
>      }
>  
>      iommu_mr = &iommu->iommu_mr;
> +    imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
> +
>      while (start < end) {
> -        entry = iommu_mr->iommu_ops->translate(iommu_mr, start, IOMMU_NONE);
> +        entry = imrc->translate(iommu_mr, start, IOMMU_NONE);
>  
>          if (!entry.translated_addr) {
>              pbdev->state = ZPCI_FS_ERROR;
> diff --git a/memory.c b/memory.c
> index f55b420d88..20472ca19a 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -1488,19 +1488,20 @@ void memory_region_init_rom_device(MemoryRegion *mr,
>      mr->ram_block = qemu_ram_alloc(size, mr, errp);
>  }
>  
> -void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr,
> +void memory_region_init_iommu(void *_iommu_mr,
> +                              size_t instance_size,
> +                              const char *mrtypename,
>                                Object *owner,
> -                              const MemoryRegionIOMMUOps *ops,
>                                const char *name,
>                                uint64_t size)
>  {
> +    struct IOMMUMemoryRegion *iommu_mr;
>      struct MemoryRegion *mr;
>  
> -    object_initialize(iommu_mr, sizeof(*iommu_mr), TYPE_IOMMU_MEMORY_REGION);
> -    mr = MEMORY_REGION(iommu_mr);
> +    object_initialize(_iommu_mr, instance_size, mrtypename);
> +    mr = MEMORY_REGION(_iommu_mr);
>      memory_region_do_init(mr, owner, name, size);
>      iommu_mr = IOMMU_MEMORY_REGION(mr);
> -    iommu_mr->iommu_ops = ops,
>      mr->terminates = true;  /* then re-forwards */
>      QLIST_INIT(&iommu_mr->iommu_notify);
>      iommu_mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
> @@ -1602,16 +1603,16 @@ static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr)
>  {
>      IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE;
>      IOMMUNotifier *iommu_notifier;
> +    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
>  
>      IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
>          flags |= iommu_notifier->notifier_flags;
>      }
>  
> -    if (flags != iommu_mr->iommu_notify_flags &&
> -        iommu_mr->iommu_ops->notify_flag_changed) {
> -        iommu_mr->iommu_ops->notify_flag_changed(iommu_mr,
> -                                                iommu_mr->iommu_notify_flags,
> -                                                flags);
> +    if (flags != iommu_mr->iommu_notify_flags && imrc->notify_flag_changed) {
> +        imrc->notify_flag_changed(iommu_mr,
> +                                  iommu_mr->iommu_notify_flags,
> +                                  flags);
>      }
>  
>      iommu_mr->iommu_notify_flags = flags;
> @@ -1637,8 +1638,10 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr,
>  
>  uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
>  {
> -    if (iommu_mr->iommu_ops && iommu_mr->iommu_ops->get_min_page_size) {
> -        return iommu_mr->iommu_ops->get_min_page_size(iommu_mr);
> +    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
> +
> +    if (imrc->get_min_page_size) {
> +        return imrc->get_min_page_size(iommu_mr);
>      }
>      return TARGET_PAGE_SIZE;
>  }
> @@ -1646,19 +1649,20 @@ uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
>  void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
>  {
>      MemoryRegion *mr = MEMORY_REGION(iommu_mr);
> +    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
>      hwaddr addr, granularity;
>      IOMMUTLBEntry iotlb;
>  
>      /* If the IOMMU has its own replay callback, override */
> -    if (iommu_mr->iommu_ops->replay) {
> -        iommu_mr->iommu_ops->replay(iommu_mr, n);
> +    if (imrc->replay) {
> +        imrc->replay(iommu_mr, n);
>          return;
>      }
>  
>      granularity = memory_region_iommu_get_min_page_size(iommu_mr);
>  
>      for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
> -        iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, IOMMU_NONE);
> +        iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE);
>          if (iotlb.perm != IOMMU_NONE) {
>              n->notify(n, &iotlb);
>          }
> @@ -2738,8 +2742,10 @@ static const TypeInfo memory_region_info = {
>  static const TypeInfo iommu_memory_region_info = {
>      .parent             = TYPE_MEMORY_REGION,
>      .name               = TYPE_IOMMU_MEMORY_REGION,
> +    .class_size         = sizeof(IOMMUMemoryRegionClass),
>      .instance_size      = sizeof(IOMMUMemoryRegion),
>      .instance_init      = iommu_memory_region_initfn,
> +    .abstract           = true,
>  };
>  
>  static void memory_register_types(void)
>


--
Alexey

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH qemu v8 2/2] memory/iommu: introduce IOMMUMemoryRegionClass

David Gibson
On Wed, Jun 21, 2017 at 12:05:08PM +1000, Alexey Kardashevskiy wrote:
> On 14/06/17 16:36, Alexey Kardashevskiy wrote:
> > This finishes QOM'fication of IOMMUMemoryRegion by introducing
> > a IOMMUMemoryRegionClass. This also provides a fastpath analog for
> > IOMMU_MEMORY_REGION_GET_CLASS().
>
>
> Ping?

Busy.. sick.. busy & sick..

I'll get to it eventually.

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

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH qemu v8 2/2] memory/iommu: introduce IOMMUMemoryRegionClass

Alexey Kardashevskiy
On 21/06/17 17:26, David Gibson wrote:

> On Wed, Jun 21, 2017 at 12:05:08PM +1000, Alexey Kardashevskiy wrote:
>> On 14/06/17 16:36, Alexey Kardashevskiy wrote:
>>> This finishes QOM'fication of IOMMUMemoryRegion by introducing
>>> a IOMMUMemoryRegionClass. This also provides a fastpath analog for
>>> IOMMU_MEMORY_REGION_GET_CLASS().
>>
>>
>> Ping?
>
> Busy.. sick.. busy & sick..
>
> I'll get to it eventually.
>
Well, if would be nice to hear from anyone...


--
Alexey


signature.asc (856 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH qemu v8 2/2] memory/iommu: introduce IOMMUMemoryRegionClass

David Gibson
On Wed, Jun 28, 2017 at 02:19:57PM +1000, Alexey Kardashevskiy wrote:

> On 21/06/17 17:26, David Gibson wrote:
> > On Wed, Jun 21, 2017 at 12:05:08PM +1000, Alexey Kardashevskiy wrote:
> >> On 14/06/17 16:36, Alexey Kardashevskiy wrote:
> >>> This finishes QOM'fication of IOMMUMemoryRegion by introducing
> >>> a IOMMUMemoryRegionClass. This also provides a fastpath analog for
> >>> IOMMU_MEMORY_REGION_GET_CLASS().
> >>
> >>
> >> Ping?
> >
> > Busy.. sick.. busy & sick..
> >
> > I'll get to it eventually.
>
> Well, if would be nice to hear from anyone...
Well, sure.

It would've been nice not to get an ear infection and stay stuck in a
hotel room in Beijing for a week, too.

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

signature.asc (836 bytes) Download Attachment