qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH qemu v8 2/2] memory/iommu: introduce IOMMUMemory


From: Alexey Kardashevskiy
Subject: Re: [Qemu-devel] [PATCH qemu v8 2/2] memory/iommu: introduce IOMMUMemoryRegionClass
Date: Wed, 21 Jun 2017 12:05:08 +1000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.1.0

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 <address@hidden>
> ---
>  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 via email to

[Prev in Thread] Current Thread [Next in Thread]