[PATCH v10 4/8] vfio/type1: handle unmap/unpin and replay for VFIO_IOVA_RESERVED slots

Eric Auger eric.auger at redhat.com
Tue Jun 7 09:03:49 PDT 2016

Before allowing the end-user to create VFIO_IOVA_RESERVED dma slots,
let's implement the expected behavior for removal and replay.

As opposed to user dma slots, reserved IOVAs are not systematically bound
to PAs and PAs are not pinned. VFIO just initializes the IOVA "aperture".
IOVAs are allocated outside of the VFIO framework, by the MSI layer which
is responsible to free and unmap them. The MSI mapping resources are freeed
by the IOMMU driver on domain destruction.

On the creation of a new domain, the "replay" of a reserved slot simply
needs to set the MSI aperture on the new domain.

Signed-off-by: Eric Auger <eric.auger at redhat.com>


v9 -> v10:
- replay of a reserved slot sets the MSI aperture on the new domain

v7 -> v8:
- do no destroy anything anymore, just bypass unmap/unpin and iommu_map
  on replay
 drivers/vfio/vfio_iommu_type1.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 65a4038..69c775e 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -36,6 +36,7 @@
 #include <linux/uaccess.h>
 #include <linux/vfio.h>
 #include <linux/workqueue.h>
+#include <linux/msi-iommu.h>
 #define DRIVER_VERSION  "0.2"
 #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
@@ -387,7 +388,7 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
 	struct vfio_domain *domain, *d;
 	long unlocked = 0;
-	if (!dma->size)
+	if (!dma->size || dma->type != VFIO_IOVA_USER)
 	 * We use the IOMMU to track the physical addresses, otherwise we'd
@@ -724,6 +725,14 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
 		dma = rb_entry(n, struct vfio_dma, node);
 		iova = dma->iova;
+		if (dma->type == VFIO_IOVA_RESERVED_MSI) {
+			ret = iommu_msi_set_aperture(domain->domain,
+						     dma->iova,
+						     iova + dma->size - 1);
+			WARN_ON(ret);
+			continue;
+		}
 		while (iova < dma->iova + dma->size) {
 			phys_addr_t phys = iommu_iova_to_phys(d->domain, iova);
 			size_t size;

More information about the linux-arm-kernel mailing list