On 03/04/17 22:53, Philippe Mathieu-Daudé wrote: > On 04/01/2017 09:37 AM, 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. >> >> This defines memory_region_init_iommu_type() to allow creating >> IOMMUMemoryRegion subclasses. In order to support custom QOM type, >> this splits memory_region_init() to object_initialize() + >> memory_region_do_init. >> >> Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru> > > Reviewed-by: Philippe Mathieu-Daudé <f4...@amsat.org>
This could go first as it is an independent thing and the rest of the series depends on kernel headers update or does not depends on this patch. Paolo? > >> --- >> Changes: >> v3: >> * added mr->is_iommu >> * updated i386/x86_64/s390/sun >> --- >> hw/s390x/s390-pci-bus.h | 2 +- >> include/exec/memory.h | 64 ++++++++++++++++++------ >> include/hw/i386/intel_iommu.h | 2 +- >> include/hw/ppc/spapr.h | 3 +- >> include/hw/vfio/vfio-common.h | 2 +- >> include/qemu/typedefs.h | 1 + >> exec.c | 16 +++--- >> hw/dma/sun4m_iommu.c | 2 +- >> hw/i386/amd_iommu.c | 11 ++-- >> hw/i386/intel_iommu.c | 14 +++--- >> hw/ppc/spapr_iommu.c | 20 +++++--- >> 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 | 114 >> +++++++++++++++++++++++++++++------------- >> 16 files changed, 188 insertions(+), 92 deletions(-) >> >> diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h >> index dcbf4820c9..441ddbedcb 100644 >> --- a/hw/s390x/s390-pci-bus.h >> +++ b/hw/s390x/s390-pci-bus.h >> @@ -267,7 +267,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 e39256ad03..29d59f4f7f 100644 >> --- a/include/exec/memory.h >> +++ b/include/exec/memory.h >> @@ -37,6 +37,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; >> >> @@ -167,11 +171,12 @@ typedef struct MemoryRegionIOMMUOps >> MemoryRegionIOMMUOps; >> >> struct MemoryRegionIOMMUOps { >> /* Return a TLB entry that contains a given address. */ >> - IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, bool >> is_write); >> + IOMMUTLBEntry (*translate)(IOMMUMemoryRegion *iommu, hwaddr addr, >> + bool is_write); >> /* 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); >> }; >> @@ -195,7 +200,6 @@ struct MemoryRegion { >> uint8_t dirty_log_mask; >> RAMBlock *ram_block; >> Object *owner; >> - const MemoryRegionIOMMUOps *iommu_ops; >> >> const MemoryRegionOps *ops; >> void *opaque; >> @@ -218,6 +222,13 @@ struct MemoryRegion { >> const char *name; >> unsigned ioeventfd_nb; >> MemoryRegionIoeventfd *ioeventfds; >> + bool is_iommu; >> +}; >> + >> +struct IOMMUMemoryRegion { >> + MemoryRegion parent_obj; >> + >> + const MemoryRegionIOMMUOps *iommu_ops; >> QLIST_HEAD(, IOMMUNotifier) iommu_notify; >> IOMMUNotifierFlag iommu_notify_flags; >> }; >> @@ -555,19 +566,39 @@ static inline void >> memory_region_init_reservation(MemoryRegion *mr, >> } >> >> /** >> + * memory_region_init_iommu_type: Initialize a memory region of a custom >> type >> + * that translates addresses >> + * >> + * An IOMMU region translates addresses and forwards accesses to a target >> + * memory region. >> + * >> + * @typename: QOM class name >> + * @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_type(const char *mrtypename, >> + IOMMUMemoryRegion *iommumr, >> + Object *owner, >> + const MemoryRegionIOMMUOps *ops, >> + const char *name, >> + uint64_t size); >> +/** >> * memory_region_init_iommu: Initialize a memory region that translates >> * addresses >> * >> * An IOMMU region translates addresses and forwards accesses to a target >> * memory region. >> * >> - * @mr: the #MemoryRegion to be initialized >> + * @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 *iommumr, >> struct Object *owner, >> const MemoryRegionIOMMUOps *ops, >> const char *name, >> @@ -622,20 +653,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 >> @@ -645,7 +681,7 @@ static inline bool >> memory_region_is_iommu(MemoryRegion *mr) >> * >> * @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 *mr); >> >> /** >> * memory_region_notify_iommu: notify a change in an IOMMU translation >> entry. >> @@ -664,7 +700,7 @@ uint64_t >> memory_region_iommu_get_min_page_size(MemoryRegion *mr); >> * 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 *mr, >> IOMMUTLBEntry entry); >> >> /** >> @@ -689,7 +725,7 @@ void >> memory_region_register_iommu_notifier(MemoryRegion *mr, >> * @is_write: Whether to treat the replay as a translate "write" >> * through the iommu >> */ >> -void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n, >> +void memory_region_iommu_replay(IOMMUMemoryRegion *mr, IOMMUNotifier *n, >> bool is_write); >> >> /** >> diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h >> index fe645aa93a..34f1b61957 100644 >> --- a/include/hw/i386/intel_iommu.h >> +++ b/include/hw/i386/intel_iommu.h >> @@ -82,7 +82,7 @@ struct VTDAddressSpace { >> PCIBus *bus; >> uint8_t devfn; >> AddressSpace as; >> - MemoryRegion iommu; >> + IOMMUMemoryRegion iommu; >> MemoryRegion iommu_ir; /* Interrupt region: 0xfeeXXXXX */ >> IntelIOMMUState *iommu_state; >> VTDContextCacheEntry context_cache_entry; >> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h >> index e27de64d31..6997ed7e98 100644 >> --- a/include/hw/ppc/spapr.h >> +++ b/include/hw/ppc/spapr.h >> @@ -590,7 +590,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 c582de18c9..7a4135ae6f 100644 >> --- a/include/hw/vfio/vfio-common.h >> +++ b/include/hw/vfio/vfio-common.h >> @@ -94,7 +94,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 e95f28cfec..b45f71ec11 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 e57a8a2178..bbd8df7a9d 100644 >> --- a/exec.c >> +++ b/exec.c >> @@ -462,20 +462,20 @@ IOMMUTLBEntry >> address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr, >> { >> IOMMUTLBEntry iotlb = {0}; >> MemoryRegionSection *section; >> - MemoryRegion *mr; >> + IOMMUMemoryRegion *iommumr; >> >> for (;;) { >> AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch); >> section = address_space_lookup_region(d, addr, false); >> addr = addr - section->offset_within_address_space >> + section->offset_within_region; >> - mr = section->mr; >> >> - if (!mr->iommu_ops) { >> + iommumr = memory_region_get_iommu(section->mr); >> + if (!iommumr) { >> break; >> } >> >> - iotlb = mr->iommu_ops->translate(mr, addr, is_write); >> + iotlb = iommumr->iommu_ops->translate(iommumr, addr, is_write); >> if (!(iotlb.perm & (1 << is_write))) { >> iotlb.target_as = NULL; >> break; >> @@ -497,17 +497,19 @@ MemoryRegion *address_space_translate(AddressSpace >> *as, hwaddr addr, >> IOMMUTLBEntry iotlb; >> MemoryRegionSection *section; >> MemoryRegion *mr; >> + IOMMUMemoryRegion *iommumr; >> >> for (;;) { >> AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch); >> section = address_space_translate_internal(d, addr, &addr, plen, >> true); >> mr = section->mr; >> >> - if (!mr->iommu_ops) { >> + iommumr = memory_region_get_iommu(mr); >> + if (!iommumr) { >> break; >> } >> >> - iotlb = mr->iommu_ops->translate(mr, addr, is_write); >> + iotlb = iommumr->iommu_ops->translate(iommumr, addr, is_write); >> addr = ((iotlb.translated_addr & ~iotlb.addr_mask) >> | (addr & iotlb.addr_mask)); >> *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); >> @@ -538,7 +540,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/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c >> index b3cbc54c23..539115b629 100644 >> --- a/hw/dma/sun4m_iommu.c >> +++ b/hw/dma/sun4m_iommu.c >> @@ -134,7 +134,7 @@ >> typedef struct IOMMUState { >> SysBusDevice parent_obj; >> >> - MemoryRegion iomem; >> + IOMMUMemoryRegion iomem; >> uint32_t regs[IOMMU_NREGS]; >> hwaddr iostart; >> qemu_irq irq; >> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c >> index f86a40aa30..e76c29aec6 100644 >> --- a/hw/i386/amd_iommu.c >> +++ b/hw/i386/amd_iommu.c >> @@ -51,7 +51,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 */ >> }; >> @@ -986,7 +986,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, >> bool is_write) >> { >> AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu); >> @@ -1045,8 +1045,9 @@ 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, >> - "amd-iommu"); >> + address_space_init(&iommu_as[devfn]->as, >> + MEMORY_REGION(&iommu_as[devfn]->iommu), >> + "amd-iommu"); >> } >> return &iommu_as[devfn]->as; >> } >> @@ -1066,7 +1067,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 22d8226e43..233fa75b64 100644 >> --- a/hw/i386/intel_iommu.c >> +++ b/hw/i386/intel_iommu.c >> @@ -1457,7 +1457,8 @@ static bool >> vtd_process_device_iotlb_desc(IntelIOMMUState *s, >> entry.iova = addr; >> entry.perm = IOMMU_NONE; >> entry.translated_addr = 0; >> - memory_region_notify_iommu(entry.target_as->root, entry); >> + >> memory_region_notify_iommu(memory_region_get_iommu(entry.target_as->root), >> + entry); >> >> done: >> return true; >> @@ -1968,7 +1969,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, >> bool is_write) >> { >> VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu); >> @@ -2000,7 +2001,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) >> { >> @@ -2394,10 +2395,11 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState >> *s, PCIBus *bus, int devfn) >> memory_region_init_io(&vtd_dev_as->iommu_ir, OBJECT(s), >> &vtd_mem_ir_ops, s, "intel_iommu_ir", >> VTD_INTERRUPT_ADDR_SIZE); >> - memory_region_add_subregion(&vtd_dev_as->iommu, >> VTD_INTERRUPT_ADDR_FIRST, >> - &vtd_dev_as->iommu_ir); >> + memory_region_add_subregion(MEMORY_REGION(&vtd_dev_as->iommu), >> + VTD_INTERRUPT_ADDR_FIRST, >> + &vtd_dev_as->iommu_ir); >> address_space_init(&vtd_dev_as->as, >> - &vtd_dev_as->iommu, name); >> + MEMORY_REGION(&vtd_dev_as->iommu), name); >> } >> return vtd_dev_as; >> } >> diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c >> index 9e30e148d6..5051110b9d 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, >> bool is_write) >> { >> 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) >> { >> @@ -265,7 +266,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_type(TYPE_IOMMU_MEMORY_REGION, >> + &tcet->iommu, tcetobj, &spapr_iommu_ops, >> + tmp, 0); >> >> QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list); >> >> @@ -341,9 +344,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) >> @@ -352,8 +356,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 69b0291e8a..27e7336a76 100644 >> --- a/hw/s390x/s390-pci-bus.c >> +++ b/hw/s390x/s390-pci-bus.c >> @@ -354,7 +354,7 @@ out: >> return pte; >> } >> >> -static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *mr, hwaddr addr, >> +static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr >> addr, >> bool is_write) >> { >> uint64_t pte; >> @@ -523,14 +523,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 d2a8c0a083..b4fe4da798 100644 >> --- a/hw/s390x/s390-pci-inst.c >> +++ b/hw/s390x/s390-pci-inst.c >> @@ -561,7 +561,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, >> uint8_t r2) >> S390PCIIOMMU *iommu; >> hwaddr start, end; >> IOMMUTLBEntry entry; >> - MemoryRegion *mr; >> + IOMMUMemoryRegion *iommumr; >> >> cpu_synchronize_state(CPU(cpu)); >> >> @@ -620,9 +620,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, >> uint8_t r2) >> goto out; >> } >> >> - mr = &iommu->iommu_mr; >> + iommumr = &iommu->iommu_mr; >> while (start < end) { >> - entry = mr->iommu_ops->translate(mr, start, 0); >> + entry = iommumr->iommu_ops->translate(iommumr, start, 0); >> >> if (!entry.translated_addr) { >> pbdev->state = ZPCI_FS_ERROR; >> @@ -633,7 +633,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(iommumr, entry); >> start += entry.addr_mask + 1; >> } >> >> diff --git a/hw/vfio/common.c b/hw/vfio/common.c >> index f3ba9b9007..ab95db689c 100644 >> --- a/hw/vfio/common.c >> +++ b/hw/vfio/common.c >> @@ -465,6 +465,7 @@ static void vfio_listener_region_add(MemoryListener >> *listener, >> >> if (memory_region_is_iommu(section->mr)) { >> VFIOGuestIOMMU *giommu; >> + IOMMUMemoryRegion *iommumr = IOMMU_MEMORY_REGION(section->mr); >> >> trace_vfio_listener_region_add_iommu(iova, end); >> /* >> @@ -474,7 +475,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 = iommumr; >> giommu->iommu_offset = section->offset_within_address_space - >> section->offset_within_region; >> giommu->container = container; >> @@ -482,7 +483,7 @@ static void vfio_listener_region_add(MemoryListener >> *listener, >> giommu->n.notifier_flags = IOMMU_NOTIFIER_ALL; >> 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, false); >> >> return; >> @@ -550,8 +551,8 @@ static void vfio_listener_region_del(MemoryListener >> *listener, >> VFIOGuestIOMMU *giommu; >> >> QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) { >> - if (giommu->iommu == section->mr) { >> - memory_region_unregister_iommu_notifier(giommu->iommu, >> + if (MEMORY_REGION(giommu->iommu) == section->mr) { >> + memory_region_unregister_iommu_notifier(section->mr, >> &giommu->n); >> QLIST_REMOVE(giommu, giommu_next); >> g_free(giommu); >> @@ -1141,7 +1142,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..551870d46b 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 *iommumr = IOMMU_MEMORY_REGION(section->mr); >> + unsigned pagesize = memory_region_iommu_get_min_page_size(iommumr); >> unsigned entries, pages; >> struct vfio_iommu_spapr_tce_create create = { .argsz = >> sizeof(create) }; >> >> diff --git a/memory.c b/memory.c >> index 4c95aaf39c..62796536dc 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,33 @@ void memory_region_init_rom_device(MemoryRegion *mr, >> mr->ram_block = qemu_ram_alloc(size, mr, errp); >> } >> >> -void memory_region_init_iommu(MemoryRegion *mr, >> - Object *owner, >> - const MemoryRegionIOMMUOps *ops, >> - const char *name, >> - uint64_t size) >> +void memory_region_init_iommu_type(const char *mrtypename, >> + IOMMUMemoryRegion *iommumr, >> + 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; >> + size_t instance_size = object_type_get_instance_size(mrtypename); >> + >> + object_initialize(iommumr, instance_size, mrtypename); >> + mr = MEMORY_REGION(iommumr); >> + memory_region_do_init(mr, owner, name, size); >> + iommumr->iommu_ops = ops, >> mr->terminates = true; /* then re-forwards */ >> - QLIST_INIT(&mr->iommu_notify); >> - mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE; >> + QLIST_INIT(&iommumr->iommu_notify); >> + iommumr->iommu_notify_flags = IOMMU_NOTIFIER_NONE; >> +} >> + >> +void memory_region_init_iommu(IOMMUMemoryRegion *iommumr, >> + Object *owner, >> + const MemoryRegionIOMMUOps *ops, >> + const char *name, >> + uint64_t size) >> +{ >> + memory_region_init_iommu_type(TYPE_IOMMU_MEMORY_REGION, iommumr, >> + owner, ops, name, size); >> } >> >> static void memory_region_finalize(Object *obj) >> @@ -1578,57 +1609,61 @@ 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 >> *iommumr) >> { >> IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE; >> IOMMUNotifier *iommu_notifier; >> >> - QLIST_FOREACH(iommu_notifier, &mr->iommu_notify, node) { >> + QLIST_FOREACH(iommu_notifier, &iommumr->iommu_notify, node) { >> 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 != iommumr->iommu_notify_flags && >> + iommumr->iommu_ops->notify_flag_changed) { >> + iommumr->iommu_ops->notify_flag_changed(iommumr, >> + >> iommumr->iommu_notify_flags, >> + flags); >> } >> >> - mr->iommu_notify_flags = flags; >> + iommumr->iommu_notify_flags = flags; >> } >> >> void memory_region_register_iommu_notifier(MemoryRegion *mr, >> IOMMUNotifier *n) >> { >> + IOMMUMemoryRegion *iommumr; >> + >> if (mr->alias) { >> memory_region_register_iommu_notifier(mr->alias, n); >> return; >> } >> >> /* We need to register for at least one bitfield */ >> + iommumr = IOMMU_MEMORY_REGION(mr); >> assert(n->notifier_flags != IOMMU_NOTIFIER_NONE); >> - QLIST_INSERT_HEAD(&mr->iommu_notify, n, node); >> - memory_region_update_iommu_notify_flags(mr); >> + QLIST_INSERT_HEAD(&iommumr->iommu_notify, n, node); >> + memory_region_update_iommu_notify_flags(iommumr); >> } >> >> -uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr) >> +uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommumr) >> { >> - 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 (iommumr->iommu_ops && iommumr->iommu_ops->get_min_page_size) { >> + return iommumr->iommu_ops->get_min_page_size(iommumr); >> } >> return TARGET_PAGE_SIZE; >> } >> >> -void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n, >> +void memory_region_iommu_replay(IOMMUMemoryRegion *iommumr, >> IOMMUNotifier *n, >> bool is_write) >> { >> + MemoryRegion *mr = MEMORY_REGION(iommumr); >> hwaddr addr, granularity; >> IOMMUTLBEntry iotlb; >> >> - granularity = memory_region_iommu_get_min_page_size(mr); >> + granularity = memory_region_iommu_get_min_page_size(iommumr); >> >> for (addr = 0; addr < memory_region_size(mr); addr += granularity) { >> - iotlb = mr->iommu_ops->translate(mr, addr, is_write); >> + iotlb = iommumr->iommu_ops->translate(iommumr, addr, is_write); >> if (iotlb.perm != IOMMU_NONE) { >> n->notify(n, &iotlb); >> } >> @@ -1644,21 +1679,24 @@ void memory_region_iommu_replay(MemoryRegion *mr, >> IOMMUNotifier *n, >> void memory_region_unregister_iommu_notifier(MemoryRegion *mr, >> IOMMUNotifier *n) >> { >> + IOMMUMemoryRegion *iommumr; >> + >> if (mr->alias) { >> memory_region_unregister_iommu_notifier(mr->alias, n); >> return; >> } >> QLIST_REMOVE(n, node); >> - memory_region_update_iommu_notify_flags(mr); >> + iommumr = IOMMU_MEMORY_REGION(mr); >> + memory_region_update_iommu_notify_flags(iommumr); >> } >> >> -void memory_region_notify_iommu(MemoryRegion *mr, >> +void memory_region_notify_iommu(IOMMUMemoryRegion *iommumr, >> IOMMUTLBEntry entry) >> { >> IOMMUNotifier *iommu_notifier; >> IOMMUNotifierFlag request_flags; >> >> - assert(memory_region_is_iommu(mr)); >> + assert(memory_region_is_iommu(MEMORY_REGION(iommumr))); >> >> if (entry.perm & IOMMU_RW) { >> request_flags = IOMMU_NOTIFIER_MAP; >> @@ -1666,7 +1704,7 @@ void memory_region_notify_iommu(MemoryRegion *mr, >> request_flags = IOMMU_NOTIFIER_UNMAP; >> } >> >> - QLIST_FOREACH(iommu_notifier, &mr->iommu_notify, node) { >> + QLIST_FOREACH(iommu_notifier, &iommumr->iommu_notify, node) { >> if (iommu_notifier->notifier_flags & request_flags) { >> iommu_notifier->notify(iommu_notifier, &entry); >> } >> @@ -2660,9 +2698,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) >> -- Alexey