Blame SOURCES/libvirt-Allow-vfio-hotplug-of-a-device-to-the-domain-which-owns-the-iommu.patch

7a3408
From ceeaf62ea52df6cfacac8c1653ff9f7585ef0392 Mon Sep 17 00:00:00 2001
7a3408
Message-Id: <ceeaf62ea52df6cfacac8c1653ff9f7585ef0392@dist-git>
7a3408
From: Shivaprasad G Bhat <shivaprasadbhat@gmail.com>
7a3408
Date: Wed, 2 Sep 2015 15:55:23 -0400
7a3408
Subject: [PATCH] Allow vfio hotplug of a device to the domain which owns the
7a3408
 iommu
7a3408
7a3408
The commit 7e72de4 didn't consider the hotplug scenarios. The patch addresses
7a3408
the hotplug case whereby if atleast one of the pci function is owned by a
7a3408
guest, the hotplug of other functions/devices in the same iommu group to the
7a3408
same guest goes through successfully.
7a3408
7a3408
Prerequisite for the fix for:
7a3408
7a3408
  https://bugzilla.redhat.com/show_bug.cgi?id=1256486
7a3408
7a3408
Signed-off-by: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>
7a3408
(cherry picked from commit e3810db34f1acb74dfcfd69219930e23a30284f6)
7a3408
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
7a3408
---
7a3408
 src/util/virhostdev.c | 34 +++++++++++++++++++++++++++-------
7a3408
 1 file changed, 27 insertions(+), 7 deletions(-)
7a3408
7a3408
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
7a3408
index 809caed..529753c 100644
7a3408
--- a/src/util/virhostdev.c
7a3408
+++ b/src/util/virhostdev.c
7a3408
@@ -54,23 +54,35 @@ static virClassPtr virHostdevManagerClass;
7a3408
 static void virHostdevManagerDispose(void *obj);
7a3408
 static virHostdevManagerPtr virHostdevManagerNew(void);
7a3408
 
7a3408
+struct virHostdevIsPCINodeDeviceUsedData {
7a3408
+    virHostdevManagerPtr hostdev_mgr;
7a3408
+    const char *domainName;
7a3408
+    const bool usesVfio;
7a3408
+};
7a3408
+
7a3408
 static int virHostdevIsPCINodeDeviceUsed(virPCIDeviceAddressPtr devAddr, void *opaque)
7a3408
 {
7a3408
     virPCIDevicePtr other;
7a3408
     int ret = -1;
7a3408
     virPCIDevicePtr pci = NULL;
7a3408
-    virHostdevManagerPtr hostdev_mgr = opaque;
7a3408
+    struct virHostdevIsPCINodeDeviceUsedData *helperData = opaque;
7a3408
 
7a3408
     if (!(pci = virPCIDeviceNew(devAddr->domain, devAddr->bus,
7a3408
                                 devAddr->slot, devAddr->function)))
7a3408
         goto cleanup;
7a3408
 
7a3408
-    other = virPCIDeviceListFind(hostdev_mgr->activePCIHostdevs, pci);
7a3408
+    other = virPCIDeviceListFind(helperData->hostdev_mgr->activePCIHostdevs,
7a3408
+                                 pci);
7a3408
     if (other) {
7a3408
         const char *other_drvname = NULL;
7a3408
         const char *other_domname = NULL;
7a3408
         virPCIDeviceGetUsedBy(other, &other_drvname, &other_domname);
7a3408
 
7a3408
+        if (helperData->usesVfio &&
7a3408
+            (other_domname && helperData->domainName) &&
7a3408
+            (STREQ(other_domname, helperData->domainName)))
7a3408
+            goto iommu_owner;
7a3408
+
7a3408
         if (other_drvname && other_domname)
7a3408
             virReportError(VIR_ERR_OPERATION_INVALID,
7a3408
                            _("PCI device %s is in use by "
7a3408
@@ -83,6 +95,7 @@ static int virHostdevIsPCINodeDeviceUsed(virPCIDeviceAddressPtr devAddr, void *o
7a3408
                            virPCIDeviceGetName(pci));
7a3408
         goto cleanup;
7a3408
     }
7a3408
+ iommu_owner:
7a3408
     ret = 0;
7a3408
  cleanup:
7a3408
     virPCIDeviceFree(pci);
7a3408
@@ -562,6 +575,9 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr,
7a3408
     for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
7a3408
         virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
7a3408
         bool strict_acs_check = !!(flags & VIR_HOSTDEV_STRICT_ACS_CHECK);
7a3408
+        bool usesVfio = STREQ(virPCIDeviceGetStubDriver(dev), "vfio-pci");
7a3408
+        struct virHostdevIsPCINodeDeviceUsedData data = {hostdev_mgr, dom_name,
7a3408
+                                                         usesVfio};
7a3408
 
7a3408
         if (!virPCIDeviceIsAssignable(dev, strict_acs_check)) {
7a3408
             virReportError(VIR_ERR_OPERATION_INVALID,
7a3408
@@ -579,12 +595,12 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr,
7a3408
          * belonging to same iommu group can't be shared
7a3408
          * across guests.
7a3408
          */
7a3408
-        if (STREQ(virPCIDeviceGetStubDriver(dev), "vfio-pci")) {
7a3408
+        if (usesVfio) {
7a3408
             if (virPCIDeviceAddressIOMMUGroupIterate(devAddr,
7a3408
                                                      virHostdevIsPCINodeDeviceUsed,
7a3408
-                                                     hostdev_mgr) < 0)
7a3408
+                                                     &data) < 0)
7a3408
                 goto cleanup;
7a3408
-        } else if (virHostdevIsPCINodeDeviceUsed(devAddr, hostdev_mgr)) {
7a3408
+        } else if (virHostdevIsPCINodeDeviceUsed(devAddr, &data)) {
7a3408
             goto cleanup;
7a3408
         }
7a3408
     }
7a3408
@@ -1544,6 +1560,8 @@ virHostdevPCINodeDeviceDetach(virHostdevManagerPtr hostdev_mgr,
7a3408
                               virPCIDevicePtr pci)
7a3408
 {
7a3408
     virPCIDeviceAddressPtr devAddr = NULL;
7a3408
+    struct virHostdevIsPCINodeDeviceUsedData data = { hostdev_mgr, NULL,
7a3408
+                                                     false };
7a3408
     int ret = -1;
7a3408
 
7a3408
     virObjectLock(hostdev_mgr->activePCIHostdevs);
7a3408
@@ -1552,7 +1570,7 @@ virHostdevPCINodeDeviceDetach(virHostdevManagerPtr hostdev_mgr,
7a3408
     if (!(devAddr = virPCIDeviceGetAddress(pci)))
7a3408
         goto out;
7a3408
 
7a3408
-    if (virHostdevIsPCINodeDeviceUsed(devAddr, hostdev_mgr))
7a3408
+    if (virHostdevIsPCINodeDeviceUsed(devAddr, &data))
7a3408
         goto out;
7a3408
 
7a3408
     if (virPCIDeviceDetach(pci, hostdev_mgr->activePCIHostdevs,
7a3408
@@ -1573,6 +1591,8 @@ virHostdevPCINodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr,
7a3408
                                 virPCIDevicePtr pci)
7a3408
 {
7a3408
     virPCIDeviceAddressPtr devAddr = NULL;
7a3408
+    struct virHostdevIsPCINodeDeviceUsedData data = {hostdev_mgr, NULL,
7a3408
+                                                     false};
7a3408
     int ret = -1;
7a3408
 
7a3408
     virObjectLock(hostdev_mgr->activePCIHostdevs);
7a3408
@@ -1581,7 +1601,7 @@ virHostdevPCINodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr,
7a3408
     if (!(devAddr = virPCIDeviceGetAddress(pci)))
7a3408
         goto out;
7a3408
 
7a3408
-    if (virHostdevIsPCINodeDeviceUsed(devAddr, hostdev_mgr))
7a3408
+    if (virHostdevIsPCINodeDeviceUsed(devAddr, &data))
7a3408
         goto out;
7a3408
 
7a3408
     virPCIDeviceReattachInit(pci);
7a3408
-- 
7a3408
2.5.1
7a3408