render / rpms / libvirt

Forked from rpms/libvirt 11 months ago
Clone
Pablo Greco 40546a
From 87e3a5f2f797c79516a560ddc224074c834ef528 Mon Sep 17 00:00:00 2001
Pablo Greco 40546a
Message-Id: <87e3a5f2f797c79516a560ddc224074c834ef528@dist-git>
Pablo Greco 40546a
From: Yi Min Zhao <zyimin@linux.ibm.com>
Pablo Greco 40546a
Date: Mon, 8 Apr 2019 10:57:27 +0200
Pablo Greco 40546a
Subject: [PATCH] conf: Allocate/release 'uid' and 'fid' in PCI address
Pablo Greco 40546a
MIME-Version: 1.0
Pablo Greco 40546a
Content-Type: text/plain; charset=UTF-8
Pablo Greco 40546a
Content-Transfer-Encoding: 8bit
Pablo Greco 40546a
Pablo Greco 40546a
This patch adds new functions for reservation, assignment and release
Pablo Greco 40546a
to handle the uid/fid. If the uid/fid is defined in the domain XML,
Pablo Greco 40546a
they will be reserved directly in the collecting phase. If any of them
Pablo Greco 40546a
is not defined, we will find out an available value for them from the
Pablo Greco 40546a
zPCI address hashtable, and reserve them. For the hotplug case there
Pablo Greco 40546a
might not be a zPCI definition. So allocate and reserve uid/fid the
Pablo Greco 40546a
case. Assign if needed and reserve uid/fid for the defined case.
Pablo Greco 40546a
Pablo Greco 40546a
Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
Pablo Greco 40546a
Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
Pablo Greco 40546a
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Pablo Greco 40546a
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
Pablo Greco 40546a
Pablo Greco 40546a
(cherry picked from commit f183b87fc1dbcc6446ac3c1cef9cdd345b9725fb)
Pablo Greco 40546a
Pablo Greco 40546a
https://bugzilla.redhat.com/show_bug.cgi?id=1508149
Pablo Greco 40546a
Pablo Greco 40546a
Conflicts:
Pablo Greco 40546a
Pablo Greco 40546a
  * src/libvirt_private.syms
Pablo Greco 40546a
    + several symbols are not present in the list
Pablo Greco 40546a
      - missing 9ad119f4db5, ab3f781a10c, edeef779585, b899726faa5
Pablo Greco 40546a
Pablo Greco 40546a
  * src/qemu/qemu_domain_address.c
Pablo Greco 40546a
    + the old name for virDeviceInfoPCIAddressIsPresent() is used
Pablo Greco 40546a
      - missing 76151a53a100
Pablo Greco 40546a
Pablo Greco 40546a
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Pablo Greco 40546a
Message-Id: <20190408085732.28684-11-abologna@redhat.com>
Pablo Greco 40546a
Reviewed-by: Laine Stump <laine@redhat.com>
Pablo Greco 40546a
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Pablo Greco 40546a
---
Pablo Greco 40546a
 src/conf/device_conf.c         |  16 +++
Pablo Greco 40546a
 src/conf/device_conf.h         |   3 +
Pablo Greco 40546a
 src/conf/domain_addr.c         | 244 +++++++++++++++++++++++++++++++++
Pablo Greco 40546a
 src/conf/domain_addr.h         |  12 ++
Pablo Greco 40546a
 src/libvirt_private.syms       |   5 +
Pablo Greco 40546a
 src/qemu/qemu_domain_address.c |  59 +++++++-
Pablo Greco 40546a
 6 files changed, 338 insertions(+), 1 deletion(-)
Pablo Greco 40546a
Pablo Greco 40546a
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
Pablo Greco 40546a
index cadac32603..76370d30a2 100644
Pablo Greco 40546a
--- a/src/conf/device_conf.c
Pablo Greco 40546a
+++ b/src/conf/device_conf.c
Pablo Greco 40546a
@@ -28,6 +28,7 @@
Pablo Greco 40546a
 #include "viruuid.h"
Pablo Greco 40546a
 #include "virbuffer.h"
Pablo Greco 40546a
 #include "device_conf.h"
Pablo Greco 40546a
+#include "domain_addr.h"
Pablo Greco 40546a
 #include "virstring.h"
Pablo Greco 40546a
 
Pablo Greco 40546a
 #define VIR_FROM_THIS VIR_FROM_DEVICE
Pablo Greco 40546a
@@ -230,6 +231,21 @@ int virPCIDeviceAddressIsValid(virPCIDeviceAddressPtr addr,
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
+bool
Pablo Greco 40546a
+virDeviceInfoPCIAddressExtensionIsWanted(const virDomainDeviceInfo *info)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    return (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) &&
Pablo Greco 40546a
+           virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci);
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+bool
Pablo Greco 40546a
+virDeviceInfoPCIAddressExtensionIsPresent(const virDomainDeviceInfo *info)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    return (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) &&
Pablo Greco 40546a
+           !virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci);
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
 int
Pablo Greco 40546a
 virPCIDeviceAddressParseXML(xmlNodePtr node,
Pablo Greco 40546a
                             virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
Pablo Greco 40546a
index c79066ec02..6bef2f093a 100644
Pablo Greco 40546a
--- a/src/conf/device_conf.h
Pablo Greco 40546a
+++ b/src/conf/device_conf.h
Pablo Greco 40546a
@@ -214,6 +214,9 @@ virDeviceInfoPCIAddressPresent(const virDomainDeviceInfo *info)
Pablo Greco 40546a
        !virPCIDeviceAddressIsEmpty(&info->addr.pci);
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
+bool virDeviceInfoPCIAddressExtensionIsWanted(const virDomainDeviceInfo *info);
Pablo Greco 40546a
+bool virDeviceInfoPCIAddressExtensionIsPresent(const virDomainDeviceInfo *info);
Pablo Greco 40546a
+
Pablo Greco 40546a
 int virPCIDeviceAddressParseXML(xmlNodePtr node,
Pablo Greco 40546a
                                 virPCIDeviceAddressPtr addr);
Pablo Greco 40546a
 
Pablo Greco 40546a
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
Pablo Greco 40546a
index 9e0a0fdf95..a58910c394 100644
Pablo Greco 40546a
--- a/src/conf/domain_addr.c
Pablo Greco 40546a
+++ b/src/conf/domain_addr.c
Pablo Greco 40546a
@@ -33,6 +33,238 @@
Pablo Greco 40546a
 
Pablo Greco 40546a
 VIR_LOG_INIT("conf.domain_addr");
Pablo Greco 40546a
 
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainZPCIAddressReserveId(virHashTablePtr set,
Pablo Greco 40546a
+                              unsigned int id,
Pablo Greco 40546a
+                              const char *name)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (virHashLookup(set, &id)) {
Pablo Greco 40546a
+        virReportError(VIR_ERR_INTERNAL_ERROR,
Pablo Greco 40546a
+                       _("zPCI %s %o is already reserved"),
Pablo Greco 40546a
+                       name, id);
Pablo Greco 40546a
+        return -1;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (virHashAddEntry(set, &id, (void*)1) < 0) {
Pablo Greco 40546a
+        virReportError(VIR_ERR_INTERNAL_ERROR,
Pablo Greco 40546a
+                       _("Failed to reserve %s %o"),
Pablo Greco 40546a
+                       name, id);
Pablo Greco 40546a
+        return -1;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainZPCIAddressReserveUid(virHashTablePtr set,
Pablo Greco 40546a
+                               virZPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    return virDomainZPCIAddressReserveId(set, addr->uid, "uid");
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainZPCIAddressReserveFid(virHashTablePtr set,
Pablo Greco 40546a
+                               virZPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    return virDomainZPCIAddressReserveId(set, addr->fid, "fid");
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainZPCIAddressAssignId(virHashTablePtr set,
Pablo Greco 40546a
+                             unsigned int *id,
Pablo Greco 40546a
+                             unsigned int min,
Pablo Greco 40546a
+                             unsigned int max,
Pablo Greco 40546a
+                             const char *name)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    while (virHashLookup(set, &min)) {
Pablo Greco 40546a
+        if (min == max) {
Pablo Greco 40546a
+            virReportError(VIR_ERR_INTERNAL_ERROR,
Pablo Greco 40546a
+                           _("There is no more free %s."),
Pablo Greco 40546a
+                           name);
Pablo Greco 40546a
+            return -1;
Pablo Greco 40546a
+        }
Pablo Greco 40546a
+        ++min;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+    *id = min;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainZPCIAddressAssignUid(virHashTablePtr set,
Pablo Greco 40546a
+                              virZPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    return virDomainZPCIAddressAssignId(set, &addr->uid, 1,
Pablo Greco 40546a
+                                        VIR_DOMAIN_DEVICE_ZPCI_MAX_UID, "uid");
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainZPCIAddressAssignFid(virHashTablePtr set,
Pablo Greco 40546a
+                              virZPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    return virDomainZPCIAddressAssignId(set, &addr->fid, 0,
Pablo Greco 40546a
+                                        VIR_DOMAIN_DEVICE_ZPCI_MAX_FID, "fid");
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static void
Pablo Greco 40546a
+virDomainZPCIAddressReleaseId(virHashTablePtr set,
Pablo Greco 40546a
+                              unsigned int *id,
Pablo Greco 40546a
+                              const char *name)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (virHashRemoveEntry(set, id) < 0) {
Pablo Greco 40546a
+        virReportError(VIR_ERR_INTERNAL_ERROR,
Pablo Greco 40546a
+                       _("Release %s %o failed"),
Pablo Greco 40546a
+                       name, *id);
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
+    *id = 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static void
Pablo Greco 40546a
+virDomainZPCIAddressReleaseUid(virHashTablePtr set,
Pablo Greco 40546a
+                               virZPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    virDomainZPCIAddressReleaseId(set, &addr->uid, "uid");
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static void
Pablo Greco 40546a
+virDomainZPCIAddressReleaseFid(virHashTablePtr set,
Pablo Greco 40546a
+                               virZPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    virDomainZPCIAddressReleaseId(set, &addr->fid, "fid");
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static void
Pablo Greco 40546a
+virDomainZPCIAddressReleaseIds(virDomainZPCIAddressIdsPtr zpciIds,
Pablo Greco 40546a
+                               virZPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (!zpciIds || virZPCIDeviceAddressIsEmpty(addr))
Pablo Greco 40546a
+        return;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
Pablo Greco 40546a
+
Pablo Greco 40546a
+    virDomainZPCIAddressReleaseFid(zpciIds->fids, addr);
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainZPCIAddressReserveNextUid(virHashTablePtr uids,
Pablo Greco 40546a
+                                   virZPCIDeviceAddressPtr zpci)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (virDomainZPCIAddressAssignUid(uids, zpci) < 0)
Pablo Greco 40546a
+        return -1;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (virDomainZPCIAddressReserveUid(uids, zpci) < 0)
Pablo Greco 40546a
+        return -1;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainZPCIAddressReserveNextFid(virHashTablePtr fids,
Pablo Greco 40546a
+                                   virZPCIDeviceAddressPtr zpci)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (virDomainZPCIAddressAssignFid(fids, zpci) < 0)
Pablo Greco 40546a
+        return -1;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (virDomainZPCIAddressReserveFid(fids, zpci) < 0)
Pablo Greco 40546a
+        return -1;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainZPCIAddressReserveAddr(virDomainZPCIAddressIdsPtr zpciIds,
Pablo Greco 40546a
+                                virZPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (virDomainZPCIAddressReserveUid(zpciIds->uids, addr) < 0)
Pablo Greco 40546a
+        return -1;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (virDomainZPCIAddressReserveFid(zpciIds->fids, addr) < 0) {
Pablo Greco 40546a
+        virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
Pablo Greco 40546a
+        return -1;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainZPCIAddressReserveNextAddr(virDomainZPCIAddressIdsPtr zpciIds,
Pablo Greco 40546a
+                                    virZPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (virDomainZPCIAddressReserveNextUid(zpciIds->uids, addr) < 0)
Pablo Greco 40546a
+        return -1;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (virDomainZPCIAddressReserveNextFid(zpciIds->fids, addr) < 0) {
Pablo Greco 40546a
+        virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
Pablo Greco 40546a
+        return -1;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+int
Pablo Greco 40546a
+virDomainPCIAddressExtensionReserveAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
+                                        virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
Pablo Greco 40546a
+        /* Reserve uid/fid to ZPCI device which has defined uid/fid
Pablo Greco 40546a
+         * in the domain.
Pablo Greco 40546a
+         */
Pablo Greco 40546a
+        return virDomainZPCIAddressReserveAddr(addrs->zpciIds, &addr->zpci);
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+int
Pablo Greco 40546a
+virDomainPCIAddressExtensionReserveNextAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
+                                            virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
Pablo Greco 40546a
+        virZPCIDeviceAddress zpci = { 0 };
Pablo Greco 40546a
+
Pablo Greco 40546a
+        if (virDomainZPCIAddressReserveNextAddr(addrs->zpciIds, &zpci) < 0)
Pablo Greco 40546a
+            return -1;
Pablo Greco 40546a
+
Pablo Greco 40546a
+        if (!addrs->dryRun)
Pablo Greco 40546a
+            addr->zpci = zpci;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainPCIAddressExtensionEnsureAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
+                                       virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
Pablo Greco 40546a
+        virZPCIDeviceAddressPtr zpci = &addr->zpci;
Pablo Greco 40546a
+
Pablo Greco 40546a
+        if (virZPCIDeviceAddressIsEmpty(zpci))
Pablo Greco 40546a
+            return virDomainZPCIAddressReserveNextAddr(addrs->zpciIds, zpci);
Pablo Greco 40546a
+        else
Pablo Greco 40546a
+            return virDomainZPCIAddressReserveAddr(addrs->zpciIds, zpci);
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
 virDomainPCIConnectFlags
Pablo Greco 40546a
 virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model)
Pablo Greco 40546a
 {
Pablo Greco 40546a
@@ -729,12 +961,24 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
         ret = virDomainPCIAddressReserveNextAddr(addrs, dev, flags, -1);
Pablo Greco 40546a
     }
Pablo Greco 40546a
 
Pablo Greco 40546a
+    dev->addr.pci.extFlags = dev->pciAddrExtFlags;
Pablo Greco 40546a
+    ret = virDomainPCIAddressExtensionEnsureAddr(addrs, &dev->addr.pci);
Pablo Greco 40546a
+
Pablo Greco 40546a
  cleanup:
Pablo Greco 40546a
     VIR_FREE(addrStr);
Pablo Greco 40546a
     return ret;
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
+void
Pablo Greco 40546a
+virDomainPCIAddressExtensionReleaseAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
+                                        virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
Pablo Greco 40546a
+        virDomainZPCIAddressReleaseIds(addrs->zpciIds, &addr->zpci);
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
 void
Pablo Greco 40546a
 virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
                                virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
Pablo Greco 40546a
index b01e6b9d20..e5ce4868d5 100644
Pablo Greco 40546a
--- a/src/conf/domain_addr.h
Pablo Greco 40546a
+++ b/src/conf/domain_addr.h
Pablo Greco 40546a
@@ -166,6 +166,14 @@ bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
                                   virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
Pablo Greco 40546a
 
Pablo Greco 40546a
+int virDomainPCIAddressExtensionReserveAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
+                                            virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
Pablo Greco 40546a
+
Pablo Greco 40546a
+int virDomainPCIAddressExtensionReserveNextAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
+                                                virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
Pablo Greco 40546a
+
Pablo Greco 40546a
 int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
                                    virPCIDeviceAddressPtr addr,
Pablo Greco 40546a
                                    virDomainPCIConnectFlags flags,
Pablo Greco 40546a
@@ -187,6 +195,10 @@ void virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
                                     virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
Pablo Greco 40546a
 
Pablo Greco 40546a
+void virDomainPCIAddressExtensionReleaseAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
+                                             virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
Pablo Greco 40546a
+
Pablo Greco 40546a
 void virDomainPCIAddressSetAllMulti(virDomainDefPtr def)
Pablo Greco 40546a
     ATTRIBUTE_NONNULL(1);
Pablo Greco 40546a
 
Pablo Greco 40546a
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
Pablo Greco 40546a
index b2a2a1f265..ee7625b0f3 100644
Pablo Greco 40546a
--- a/src/libvirt_private.syms
Pablo Greco 40546a
+++ b/src/libvirt_private.syms
Pablo Greco 40546a
@@ -93,6 +93,8 @@ virCPUModeTypeToString;
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
 # conf/device_conf.h
Pablo Greco 40546a
+virDeviceInfoPCIAddressExtensionIsPresent;
Pablo Greco 40546a
+virDeviceInfoPCIAddressExtensionIsWanted;
Pablo Greco 40546a
 virDomainDeviceInfoAddressIsEqual;
Pablo Greco 40546a
 virDomainDeviceInfoCopy;
Pablo Greco 40546a
 virInterfaceLinkFormat;
Pablo Greco 40546a
@@ -114,6 +116,9 @@ virDomainPCIAddressAsString;
Pablo Greco 40546a
 virDomainPCIAddressBusIsFullyReserved;
Pablo Greco 40546a
 virDomainPCIAddressBusSetModel;
Pablo Greco 40546a
 virDomainPCIAddressEnsureAddr;
Pablo Greco 40546a
+virDomainPCIAddressExtensionReleaseAddr;
Pablo Greco 40546a
+virDomainPCIAddressExtensionReserveAddr;
Pablo Greco 40546a
+virDomainPCIAddressExtensionReserveNextAddr;
Pablo Greco 40546a
 virDomainPCIAddressReleaseAddr;
Pablo Greco 40546a
 virDomainPCIAddressReserveAddr;
Pablo Greco 40546a
 virDomainPCIAddressReserveNextAddr;
Pablo Greco 40546a
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
Pablo Greco 40546a
index ba870d56b1..8338241cba 100644
Pablo Greco 40546a
--- a/src/qemu/qemu_domain_address.c
Pablo Greco 40546a
+++ b/src/qemu/qemu_domain_address.c
Pablo Greco 40546a
@@ -1405,6 +1405,24 @@ qemuDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
 
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+qemuDomainAssignPCIAddressExtension(virDomainDefPtr def ATTRIBUTE_UNUSED,
Pablo Greco 40546a
+                                    virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
Pablo Greco 40546a
+                                    virDomainDeviceInfoPtr info,
Pablo Greco 40546a
+                                    void *opaque)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    virDomainPCIAddressSetPtr addrs = opaque;
Pablo Greco 40546a
+    virPCIDeviceAddressPtr addr = &info->addr.pci;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
Pablo Greco 40546a
+        addr->extFlags = info->pciAddrExtFlags;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (virDeviceInfoPCIAddressExtensionIsWanted(info))
Pablo Greco 40546a
+        return virDomainPCIAddressExtensionReserveNextAddr(addrs, addr);
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
 static int
Pablo Greco 40546a
 qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
Pablo Greco 40546a
                             virDomainDeviceDefPtr device,
Pablo Greco 40546a
@@ -1498,6 +1516,31 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
Pablo Greco 40546a
     return ret;
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+qemuDomainCollectPCIAddressExtension(virDomainDefPtr def ATTRIBUTE_UNUSED,
Pablo Greco 40546a
+                                     virDomainDeviceDefPtr device,
Pablo Greco 40546a
+                                     virDomainDeviceInfoPtr info,
Pablo Greco 40546a
+                                     void *opaque)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    virDomainPCIAddressSetPtr addrs = opaque;
Pablo Greco 40546a
+    virPCIDeviceAddressPtr addr = &info->addr.pci;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
Pablo Greco 40546a
+        addr->extFlags = info->pciAddrExtFlags;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (!virDeviceInfoPCIAddressExtensionIsPresent(info) ||
Pablo Greco 40546a
+        ((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) &&
Pablo Greco 40546a
+         (device->data.hostdev->parent.type != VIR_DOMAIN_DEVICE_NONE))) {
Pablo Greco 40546a
+        /* If a hostdev has a parent, its info will be a part of the
Pablo Greco 40546a
+         * parent, and will have its address collected during the scan
Pablo Greco 40546a
+         * of the parent's device type.
Pablo Greco 40546a
+        */
Pablo Greco 40546a
+        return 0;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return virDomainPCIAddressExtensionReserveAddr(addrs, addr);
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
 static virDomainPCIAddressSetPtr
Pablo Greco 40546a
 qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
Pablo Greco 40546a
                               virQEMUCapsPtr qemuCaps,
Pablo Greco 40546a
@@ -1589,6 +1632,12 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
Pablo Greco 40546a
     if (virDomainDeviceInfoIterate(def, qemuDomainCollectPCIAddress, addrs) < 0)
Pablo Greco 40546a
         goto error;
Pablo Greco 40546a
 
Pablo Greco 40546a
+    if (virDomainDeviceInfoIterate(def,
Pablo Greco 40546a
+                                   qemuDomainCollectPCIAddressExtension,
Pablo Greco 40546a
+                                   addrs) < 0) {
Pablo Greco 40546a
+        goto error;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
     return addrs;
Pablo Greco 40546a
 
Pablo Greco 40546a
  error:
Pablo Greco 40546a
@@ -2590,6 +2639,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
Pablo Greco 40546a
         if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
Pablo Greco 40546a
             goto cleanup;
Pablo Greco 40546a
 
Pablo Greco 40546a
+        if (virDomainDeviceInfoIterate(def, qemuDomainAssignPCIAddressExtension, addrs) < 0)
Pablo Greco 40546a
+            goto cleanup;
Pablo Greco 40546a
+
Pablo Greco 40546a
         /* Only for *new* domains with pcie-root (and no other
Pablo Greco 40546a
          * manually specified PCI controllers in the definition): If,
Pablo Greco 40546a
          * after assigning addresses/reserving slots for all devices,
Pablo Greco 40546a
@@ -2684,6 +2736,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
Pablo Greco 40546a
         if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
Pablo Greco 40546a
             goto cleanup;
Pablo Greco 40546a
 
Pablo Greco 40546a
+        if (virDomainDeviceInfoIterate(def, qemuDomainAssignPCIAddressExtension, addrs) < 0)
Pablo Greco 40546a
+            goto cleanup;
Pablo Greco 40546a
+
Pablo Greco 40546a
         /* set multi attribute for devices at function 0 of
Pablo Greco 40546a
          * any slot that has multiple functions in use
Pablo Greco 40546a
          */
Pablo Greco 40546a
@@ -3143,8 +3198,10 @@ qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
Pablo Greco 40546a
     if (!devstr)
Pablo Greco 40546a
         devstr = info->alias;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    if (virDeviceInfoPCIAddressPresent(info))
Pablo Greco 40546a
+    if (virDeviceInfoPCIAddressPresent(info)) {
Pablo Greco 40546a
         virDomainPCIAddressReleaseAddr(priv->pciaddrs, &info->addr.pci);
Pablo Greco 40546a
+        virDomainPCIAddressExtensionReleaseAddr(priv->pciaddrs, &info->addr.pci);
Pablo Greco 40546a
+    }
Pablo Greco 40546a
 
Pablo Greco 40546a
     if (virDomainUSBAddressRelease(priv->usbaddrs, info) < 0)
Pablo Greco 40546a
         VIR_WARN("Unable to release USB address on %s", NULLSTR(devstr));
Pablo Greco 40546a
-- 
Pablo Greco 40546a
2.22.0
Pablo Greco 40546a