aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2015-09-30 12:13:56 +1000
committerAlex Williamson <alex.williamson@redhat.com>2015-10-05 12:39:47 -0600
commit508ce5eb00070809f0d19917a1b2960dfcf5a64b (patch)
tree828d231a49a1e45c8e3f46599b326aa3037dbed0 /hw
parenta788f227ef7bd2912fcaacdfe13d13ece2998149 (diff)
vfio: Allow hotplug of containers onto existing guest IOMMU mappings
At present the memory listener used by vfio to keep host IOMMU mappings in sync with the guest memory image assumes that if a guest IOMMU appears, then it has no existing mappings. This may not be true if a VFIO device is hotplugged onto a guest bus which didn't previously include a VFIO device, and which has existing guest IOMMU mappings. Therefore, use the memory_region_register_iommu_notifier_replay() function in order to fix this case, replaying existing guest IOMMU mappings, bringing the host IOMMU into sync with the guest IOMMU. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/vfio/common.c23
1 files changed, 9 insertions, 14 deletions
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index f666de2c96..6797208cc1 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -312,6 +312,11 @@ out:
rcu_read_unlock();
}
+static hwaddr vfio_container_granularity(VFIOContainer *container)
+{
+ return (hwaddr)1 << ctz64(container->iova_pgsizes);
+}
+
static void vfio_listener_region_add(MemoryListener *listener,
MemoryRegionSection *section)
{
@@ -369,26 +374,16 @@ static void vfio_listener_region_add(MemoryListener *listener,
* would be the right place to wire that up (tell the KVM
* device emulation the VFIO iommu handles to use).
*/
- /*
- * This assumes that the guest IOMMU is empty of
- * mappings at this point.
- *
- * One way of doing this is:
- * 1. Avoid sharing IOMMUs between emulated devices or different
- * IOMMU groups.
- * 2. Implement VFIO_IOMMU_ENABLE in the host kernel to fail if
- * there are some mappings in IOMMU.
- *
- * VFIO on SPAPR does that. Other IOMMU models may do that different,
- * they must make sure there are no existing mappings or
- * loop through existing mappings to map them into VFIO.
- */
giommu = g_malloc0(sizeof(*giommu));
giommu->iommu = section->mr;
giommu->container = container;
giommu->n.notify = vfio_iommu_map_notify;
QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
+
memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);
+ memory_region_iommu_replay(giommu->iommu, &giommu->n,
+ vfio_container_granularity(container),
+ false);
return;
}