From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33202) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZH5nH-0006g5-F5 for qemu-devel@nongnu.org; Mon, 20 Jul 2015 03:47:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZH5nC-0007l4-DU for qemu-devel@nongnu.org; Mon, 20 Jul 2015 03:47:23 -0400 Received: from e23smtp04.au.ibm.com ([202.81.31.146]:50007) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZH5nB-0007kS-ID for qemu-devel@nongnu.org; Mon, 20 Jul 2015 03:47:18 -0400 Received: from /spool/local by e23smtp04.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 20 Jul 2015 17:47:15 +1000 From: Alexey Kardashevskiy Date: Mon, 20 Jul 2015 17:46:08 +1000 Message-Id: <1437378370-6128-3-git-send-email-aik@ozlabs.ru> In-Reply-To: <1437378370-6128-1-git-send-email-aik@ozlabs.ru> References: <1437378370-6128-1-git-send-email-aik@ozlabs.ru> Subject: [Qemu-devel] [RFC PATCH qemu 2/4] vfio: Generalize IOMMU memory listener List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Peter Crosthwaite , Alexey Kardashevskiy , Michael Roth , Alex Williamson , qemu-ppc@nongnu.org, David Gibson At the moment VFIOContainer has an union for per IOMMU type data which is now an IOMMU memory listener and setup flags. The listener listens on PCI address space for both Type1 and sPAPR IOMMUs. The setup flags (@initialized and @error) are only used by Type1 now but the next patch will use it on sPAPR too. This introduces VFIOMemoryListener which is wrapper for MemoryListener and stores a pointer to the container. This allows having multiple memory listeners for the same container. This replaces Type1 listener with @iommu_listener. This moves @initialized and @error out of @iommu_data as these will be used soon for memory pre-registration. As there is only release() left in @iommu_data, this moves it to VFIOContainer and removes @iommu_data and VFIOType1. This stores @iommu_type in VFIOContainer. The prereg patch will use it to know whether or not to do proper cleanup. This should cause no change in behavior. Signed-off-by: Alexey Kardashevskiy --- Changes: v4: * used to be "vfio: Store IOMMU type in container" * moved VFIOType1 content to container as it is not IOMMU type specific --- hw/vfio/common.c | 74 +++++++++++++++++++++++++++---------------- include/hw/vfio/vfio-common.h | 25 +++++++-------- 2 files changed, 59 insertions(+), 40 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 85ee9b0..6eb85c7 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -312,11 +312,10 @@ out: rcu_read_unlock(); } -static void vfio_listener_region_add(MemoryListener *listener, +static void vfio_listener_region_add(VFIOMemoryListener *vlistener, MemoryRegionSection *section) { - VFIOContainer *container = container_of(listener, VFIOContainer, - iommu_data.type1.listener); + VFIOContainer *container = vlistener->container; hwaddr iova, end; Int128 llend; void *vaddr; @@ -406,9 +405,9 @@ static void vfio_listener_region_add(MemoryListener *listener, * can gracefully fail. Runtime, there's not much we can do other * than throw a hardware error. */ - if (!container->iommu_data.type1.initialized) { - if (!container->iommu_data.type1.error) { - container->iommu_data.type1.error = ret; + if (!container->initialized) { + if (!container->error) { + container->error = ret; } } else { hw_error("vfio: DMA mapping failed, unable to continue"); @@ -416,11 +415,10 @@ static void vfio_listener_region_add(MemoryListener *listener, } } -static void vfio_listener_region_del(MemoryListener *listener, +static void vfio_listener_region_del(VFIOMemoryListener *vlistener, MemoryRegionSection *section) { - VFIOContainer *container = container_of(listener, VFIOContainer, - iommu_data.type1.listener); + VFIOContainer *container = vlistener->container; hwaddr iova, end; int ret; @@ -478,14 +476,33 @@ static void vfio_listener_region_del(MemoryListener *listener, } } -static const MemoryListener vfio_memory_listener = { - .region_add = vfio_listener_region_add, - .region_del = vfio_listener_region_del, +static void vfio_iommu_listener_region_add(MemoryListener *listener, + MemoryRegionSection *section) +{ + VFIOMemoryListener *vlistener = container_of(listener, VFIOMemoryListener, + listener); + + vfio_listener_region_add(vlistener, section); +} + + +static void vfio_iommu_listener_region_del(MemoryListener *listener, + MemoryRegionSection *section) +{ + VFIOMemoryListener *vlistener = container_of(listener, VFIOMemoryListener, + listener); + + vfio_listener_region_del(vlistener, section); +} + +static const MemoryListener vfio_iommu_listener = { + .region_add = vfio_iommu_listener_region_add, + .region_del = vfio_iommu_listener_region_del, }; static void vfio_listener_release(VFIOContainer *container) { - memory_listener_unregister(&container->iommu_data.type1.listener); + memory_listener_unregister(&container->iommu_listener.listener); } int vfio_mmap_region(Object *obj, VFIORegion *region, @@ -676,27 +693,28 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) goto free_container_exit; } - ret = ioctl(fd, VFIO_SET_IOMMU, - v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU); + container->iommu_type = v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU; + ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type); if (ret) { error_report("vfio: failed to set iommu for container: %m"); ret = -errno; goto free_container_exit; } - container->iommu_data.type1.listener = vfio_memory_listener; - container->iommu_data.release = vfio_listener_release; + container->iommu_listener.container = container; + container->iommu_listener.listener = vfio_iommu_listener; + container->release = vfio_listener_release; - memory_listener_register(&container->iommu_data.type1.listener, + memory_listener_register(&container->iommu_listener.listener, container->space->as); - if (container->iommu_data.type1.error) { - ret = container->iommu_data.type1.error; + if (container->error) { + ret = container->error; error_report("vfio: memory listener initialization failed for container"); goto listener_release_exit; } - container->iommu_data.type1.initialized = true; + container->initialized = true; } else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_IOMMU)) { ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd); @@ -705,7 +723,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) ret = -errno; goto free_container_exit; } - ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_SPAPR_TCE_IOMMU); + container->iommu_type = VFIO_SPAPR_TCE_IOMMU; + ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type); if (ret) { error_report("vfio: failed to set iommu for container: %m"); ret = -errno; @@ -724,10 +743,11 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) goto free_container_exit; } - container->iommu_data.type1.listener = vfio_memory_listener; - container->iommu_data.release = vfio_listener_release; + container->iommu_listener.container = container; + container->iommu_listener.listener = vfio_iommu_listener; + container->release = vfio_listener_release; - memory_listener_register(&container->iommu_data.type1.listener, + memory_listener_register(&container->iommu_listener.listener, container->space->as); } else { @@ -774,8 +794,8 @@ static void vfio_disconnect_container(VFIOGroup *group) VFIOAddressSpace *space = container->space; VFIOGuestIOMMU *giommu, *tmp; - if (container->iommu_data.release) { - container->iommu_data.release(container); + if (container->release) { + container->release(container); } QLIST_REMOVE(container, next); diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 59a321d..a0f9d36 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -62,24 +62,23 @@ typedef struct VFIOAddressSpace { QLIST_ENTRY(VFIOAddressSpace) list; } VFIOAddressSpace; +typedef struct VFIOContainer VFIOContainer; + +typedef struct VFIOMemoryListener { + struct MemoryListener listener; + VFIOContainer *container; +} VFIOMemoryListener; + struct VFIOGroup; -typedef struct VFIOType1 { - MemoryListener listener; - int error; - bool initialized; -} VFIOType1; - typedef struct VFIOContainer { VFIOAddressSpace *space; int fd; /* /dev/vfio/vfio, empowered by the attached groups */ - struct { - /* enable abstraction to support various iommu backends */ - union { - VFIOType1 type1; - }; - void (*release)(struct VFIOContainer *); - } iommu_data; + unsigned iommu_type; + int error; + bool initialized; + VFIOMemoryListener iommu_listener; + void (*release)(struct VFIOContainer *); QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; QLIST_HEAD(, VFIOGroup) group_list; QLIST_ENTRY(VFIOContainer) next; -- 2.4.0.rc3.8.gfb3e7d5