[PATCH v2 02/21] utils: PCI multifunction detection helpers

Daniel Henrique Barboza danielhb413 at gmail.com
Thu Jan 30 16:44:14 UTC 2020


This patch introduces two helpers that will be used in the next
patches. One is virpci.c:virPCIDeviceIsMultifunction(), and
the other is virhostdev.c:virHostdevIsPCIMultifunctionDevice().

Signed-off-by: Daniel Henrique Barboza <danielhb413 at gmail.com>
---
 src/libvirt_private.syms |  2 ++
 src/util/virhostdev.c    | 25 +++++++++++++++++++++++++
 src/util/virhostdev.h    |  3 +++
 src/util/virpci.c        | 17 +++++++++++++++++
 src/util/virpci.h        |  2 ++
 5 files changed, 49 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ebf830791e..962963a3ff 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2162,6 +2162,7 @@ virHostCPUStatsAssign;
 # util/virhostdev.h
 virHostdevFindUSBDevice;
 virHostdevIsMdevDevice;
+virHostdevIsPCIMultifunctionDevice;
 virHostdevIsSCSIDevice;
 virHostdevIsVFIODevice;
 virHostdevManagerGetDefault;
@@ -2768,6 +2769,7 @@ virPCIDeviceGetUnbindFromStub;
 virPCIDeviceGetUsedBy;
 virPCIDeviceHasPCIExpressLink;
 virPCIDeviceIsAssignable;
+virPCIDeviceIsMultifunction;
 virPCIDeviceIsPCIExpress;
 virPCIDeviceListAdd;
 virPCIDeviceListAddCopy;
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
index f8f7989206..f0526d97d0 100644
--- a/src/util/virhostdev.c
+++ b/src/util/virhostdev.c
@@ -2564,3 +2564,28 @@ virHostdevUpdateActiveNVMeDevices(virHostdevManagerPtr hostdev_mgr,
     }
     goto cleanup;
 }
+
+
+bool
+virHostdevIsPCIMultifunctionDevice(virDomainHostdevDefPtr hostdev)
+{
+    g_autoptr(virPCIDevice) pciDev = NULL;
+    virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
+
+    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
+        hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+        return false;
+
+    /* Libvirt should be able to perform all the operations in
+     * virPCIDeviceNew() even if it's running unprivileged, so if this
+     * fails, the device apparently doesn't currently exist on the host.
+     * Since we can't speculate, assume this device is not multifunction.
+     */
+    pciDev = virPCIDeviceNew(pcisrc->addr.domain, pcisrc->addr.bus,
+                             pcisrc->addr.slot, pcisrc->addr.function);
+
+    if (!pciDev)
+        return false;
+
+    return virPCIDeviceIsMultifunction(pciDev);
+}
diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h
index ae84ed3d20..80aea577ed 100644
--- a/src/util/virhostdev.h
+++ b/src/util/virhostdev.h
@@ -198,6 +198,9 @@ bool
 virHostdevIsMdevDevice(const virDomainHostdevDef *hostdev)
     ATTRIBUTE_NONNULL(1);
 bool
+virHostdevIsPCIMultifunctionDevice(virDomainHostdevDefPtr hostdev)
+    ATTRIBUTE_NONNULL(1);
+bool
 virHostdevIsVFIODevice(const virDomainHostdevDef *hostdev)
     ATTRIBUTE_NONNULL(1);
 
diff --git a/src/util/virpci.c b/src/util/virpci.c
index 0b1222373e..f564d7b9fd 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -2842,6 +2842,23 @@ int virPCIGetHeaderType(virPCIDevicePtr dev, int *hdrType)
 }
 
 
+bool
+virPCIDeviceIsMultifunction(virPCIDevicePtr dev)
+{
+   int fd;
+   uint8_t type;
+
+   if ((fd = virPCIDeviceConfigOpen(dev)) < 0)
+       return -1;
+
+   type = virPCIDeviceRead8(dev, fd, PCI_HEADER_TYPE);
+
+   virPCIDeviceConfigClose(dev, fd);
+
+   return type & PCI_HEADER_TYPE_MULTI;
+}
+
+
 void
 virPCIEDeviceInfoFree(virPCIEDeviceInfoPtr dev)
 {
diff --git a/src/util/virpci.h b/src/util/virpci.h
index f6796fc422..9d8dcfec05 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -271,6 +271,8 @@ int virPCIDeviceGetLinkCapSta(virPCIDevicePtr dev,
 
 int virPCIGetHeaderType(virPCIDevicePtr dev, int *hdrType);
 
+bool virPCIDeviceIsMultifunction(virPCIDevicePtr dev);
+
 void virPCIEDeviceInfoFree(virPCIEDeviceInfoPtr dev);
 
 ssize_t virPCIGetMdevTypes(const char *sysfspath,
-- 
2.24.1





More information about the libvir-list mailing list