kvm/vfio: Support for DMA coherent IOMMUs
authorAlex Williamson <alex.williamson@redhat.com>
Wed, 26 Feb 2014 18:38:40 +0000 (11:38 -0700)
committerAlex Williamson <alex.williamson@redhat.com>
Wed, 26 Feb 2014 18:38:40 +0000 (11:38 -0700)
VFIO now has support for using the IOMMU_CACHE flag and a mechanism
for an external user to test the current operating mode of the IOMMU.
Add support for this to the kvm-vfio pseudo device so that we only
register noncoherent DMA when necessary.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Cc: Gleb Natapov <gleb@kernel.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
virt/kvm/vfio.c

index b4f9507ae6503841e5506c947f39942b5b8bdbae..ba1a93f935c76ed9ea9047982ae8d68dc46fac99 100644 (file)
@@ -59,6 +59,22 @@ static void kvm_vfio_group_put_external_user(struct vfio_group *vfio_group)
        symbol_put(vfio_group_put_external_user);
 }
 
+static bool kvm_vfio_group_is_coherent(struct vfio_group *vfio_group)
+{
+       long (*fn)(struct vfio_group *, unsigned long);
+       long ret;
+
+       fn = symbol_get(vfio_external_check_extension);
+       if (!fn)
+               return false;
+
+       ret = fn(vfio_group, VFIO_DMA_CC_IOMMU);
+
+       symbol_put(vfio_external_check_extension);
+
+       return ret > 0;
+}
+
 /*
  * Groups can use the same or different IOMMU domains.  If the same then
  * adding a new group may change the coherency of groups we've previously
@@ -75,13 +91,10 @@ static void kvm_vfio_update_coherency(struct kvm_device *dev)
        mutex_lock(&kv->lock);
 
        list_for_each_entry(kvg, &kv->group_list, node) {
-               /*
-                * TODO: We need an interface to check the coherency of
-                * the IOMMU domain this group is using.  For now, assume
-                * it's always noncoherent.
-                */
-               noncoherent = true;
-               break;
+               if (!kvm_vfio_group_is_coherent(kvg->vfio_group)) {
+                       noncoherent = true;
+                       break;
+               }
        }
 
        if (noncoherent != kv->noncoherent) {