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

Daniel Henrique Barboza danielhb413 at gmail.com
Wed May 20 21:11:24 UTC 2020


This patch introduces two helpers that will be used in the
next patches, virPCIDeviceIsMultifunction() and
virHostdevIsPCIMultifunctionDevice().

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

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c201fc901d..0d289fbab5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -32659,3 +32659,34 @@ virHostdevIsVFIODevice(const virDomainHostdevDef *hostdev)
         hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
         hostdev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
 }
+
+
+/**
+ * virHostdevIsPCIMultifunctionDevice
+ * @hostdev: host device to check
+ *
+ * Returns true if @hostdev is a PCI Multifunction device, false otherwise.
+ */
+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/conf/domain_conf.h b/src/conf/domain_conf.h
index ddc75d8de2..e6d3e04109 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3840,3 +3840,6 @@ virHostdevIsMdevDevice(const virDomainHostdevDef *hostdev)
 bool
 virHostdevIsVFIODevice(const virDomainHostdevDef *hostdev)
     ATTRIBUTE_NONNULL(1);
+bool
+virHostdevIsPCIMultifunctionDevice(virDomainHostdevDefPtr hostdev)
+    ATTRIBUTE_NONNULL(1);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fd04fcece3..c143264382 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -723,6 +723,7 @@ virDomainEventWatchdogNewFromObj;
 virDomainQemuMonitorEventNew;
 virDomainQemuMonitorEventStateRegisterID;
 virHostdevIsMdevDevice;
+virHostdevIsPCIMultifunctionDevice;
 virHostdevIsSCSIDevice;
 virHostdevIsVFIODevice;
 
@@ -2794,6 +2795,7 @@ virPCIDeviceGetUnbindFromStub;
 virPCIDeviceGetUsedBy;
 virPCIDeviceHasPCIExpressLink;
 virPCIDeviceIsAssignable;
+virPCIDeviceIsMultifunction;
 virPCIDeviceIsPCIExpress;
 virPCIDeviceListAdd;
 virPCIDeviceListAddCopy;
diff --git a/src/util/virpci.c b/src/util/virpci.c
index 6c7e6bbcab..82e86456c4 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -2837,6 +2837,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 f16d23614a..64a9109d9b 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -270,6 +270,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.26.2




More information about the libvir-list mailing list