render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
Blob Blame History Raw
From 050eb598af9291f385998cb1127d5bdf83305501 Mon Sep 17 00:00:00 2001
Message-Id: <050eb598af9291f385998cb1127d5bdf83305501@dist-git>
From: Yi Min Zhao <zyimin@linux.ibm.com>
Date: Mon, 8 Apr 2019 10:57:21 +0200
Subject: [PATCH] conf: Introduce extension flag and zPCI member for PCI
 address
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch introduces PCI address extension flag for virDomainDeviceInfo
and virPCIDeviceAddress. The extension flag in virDomainDeviceInfo is
used internally during calculating PCI extension flag. The one in
virPCIDeviceAddress is the duplicate to indicate extension address is
being used. Currently only zPCI extension address is introduced to deal
with 'uid' and 'fid' on the S390 platform.

Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Andrea Bolognani <abologna@redhat.com>

(cherry picked from commit 478e5f90fd4c0c0a8c1b3a8e19b9cae93ed78a4e)

https://bugzilla.redhat.com/show_bug.cgi?id=1508149

Conflicts:

  * src/qemu/qemu_domain_address.c
    + context
      - missing db98a426a640

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Message-Id: <20190408085732.28684-5-abologna@redhat.com>
Reviewed-by: Laine Stump <laine@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
---
 src/conf/device_conf.h         |   4 +
 src/conf/domain_addr.h         |   5 ++
 src/qemu/qemu_domain_address.c | 140 ++++++++++++++++++++++++++++++++-
 src/util/virpci.h              |   2 +
 4 files changed, 149 insertions(+), 2 deletions(-)

diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index a31ce9c376..c79066ec02 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -164,6 +164,10 @@ struct _virDomainDeviceInfo {
      * assignment, never saved and never reported.
      */
     int pciConnectFlags; /* enum virDomainPCIConnectFlags */
+    /* pciAddrExtFlags is only used internally to calculate PCI
+     * address extension flags during address assignment.
+     */
+    int pciAddrExtFlags; /* enum virDomainPCIAddressExtensionFlags */
     char *loadparm;
 
     /* PCI devices will only be automatically placed on a PCI bus
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index 3236b7d6de..fd06008e26 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -29,6 +29,11 @@
 # define VIR_PCI_ADDRESS_SLOT_LAST 31
 # define VIR_PCI_ADDRESS_FUNCTION_LAST 7
 
+typedef enum {
+    VIR_PCI_ADDRESS_EXTENSION_NONE = 0, /* no extension */
+    VIR_PCI_ADDRESS_EXTENSION_ZPCI = 1 << 0, /* zPCI support */
+} virPCIDeviceAddressExtensionFlags;
+
 typedef enum {
    VIR_PCI_CONNECT_HOTPLUGGABLE = 1 << 0, /* is hotplug needed/supported */
 
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 79d2b9f9c4..3d01d14b46 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -511,6 +511,64 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def,
 }
 
 
+static bool
+qemuDomainDeviceSupportZPCI(virDomainDeviceDefPtr device)
+{
+    switch ((virDomainDeviceType)device->type) {
+    case VIR_DOMAIN_DEVICE_CHR:
+        return false;
+
+    case VIR_DOMAIN_DEVICE_CONTROLLER:
+    case VIR_DOMAIN_DEVICE_DISK:
+    case VIR_DOMAIN_DEVICE_LEASE:
+    case VIR_DOMAIN_DEVICE_FS:
+    case VIR_DOMAIN_DEVICE_NET:
+    case VIR_DOMAIN_DEVICE_INPUT:
+    case VIR_DOMAIN_DEVICE_SOUND:
+    case VIR_DOMAIN_DEVICE_VIDEO:
+    case VIR_DOMAIN_DEVICE_HOSTDEV:
+    case VIR_DOMAIN_DEVICE_WATCHDOG:
+    case VIR_DOMAIN_DEVICE_GRAPHICS:
+    case VIR_DOMAIN_DEVICE_HUB:
+    case VIR_DOMAIN_DEVICE_REDIRDEV:
+    case VIR_DOMAIN_DEVICE_SMARTCARD:
+    case VIR_DOMAIN_DEVICE_MEMBALLOON:
+    case VIR_DOMAIN_DEVICE_NVRAM:
+    case VIR_DOMAIN_DEVICE_RNG:
+    case VIR_DOMAIN_DEVICE_SHMEM:
+    case VIR_DOMAIN_DEVICE_TPM:
+    case VIR_DOMAIN_DEVICE_PANIC:
+    case VIR_DOMAIN_DEVICE_MEMORY:
+    case VIR_DOMAIN_DEVICE_IOMMU:
+    case VIR_DOMAIN_DEVICE_VSOCK:
+        break;
+
+    case VIR_DOMAIN_DEVICE_NONE:
+    case VIR_DOMAIN_DEVICE_LAST:
+    default:
+        virReportEnumRangeError(virDomainDeviceType, device->type);
+        return false;
+    }
+
+    return true;
+}
+
+
+static virPCIDeviceAddressExtensionFlags
+qemuDomainDeviceCalculatePCIAddressExtensionFlags(virQEMUCapsPtr qemuCaps,
+                                                  virDomainDeviceDefPtr dev)
+{
+    virPCIDeviceAddressExtensionFlags extFlags = 0;
+
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ZPCI) &&
+        qemuDomainDeviceSupportZPCI(dev)) {
+        extFlags |= VIR_PCI_ADDRESS_EXTENSION_ZPCI;
+    }
+
+    return extFlags;
+}
+
+
 /**
  * qemuDomainDeviceCalculatePCIConnectFlags:
  *
@@ -993,6 +1051,56 @@ qemuDomainFillAllPCIConnectFlags(virDomainDefPtr def,
 }
 
 
+/**
+ * qemuDomainFillDevicePCIExtensionFlagsIter:
+ *
+ * @def: the entire DomainDef
+ * @dev: The device to be checked
+ * @info: virDomainDeviceInfo within the device
+ * @opaque: qemu capabilities
+ *
+ * Sets the pciAddressExtFlags for a single device's info. Has properly
+ * formatted arguments to be called by virDomainDeviceInfoIterate().
+ *
+ * Always returns 0 - there is no failure.
+ */
+static int
+qemuDomainFillDevicePCIExtensionFlagsIter(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                                          virDomainDeviceDefPtr dev,
+                                          virDomainDeviceInfoPtr info,
+                                          void *opaque)
+{
+    virQEMUCapsPtr qemuCaps = opaque;
+
+    info->pciAddrExtFlags =
+        qemuDomainDeviceCalculatePCIAddressExtensionFlags(qemuCaps, dev);
+
+    return 0;
+}
+
+
+/**
+ * qemuDomainFillAllPCIExtensionFlags:
+ *
+ * @def: the entire DomainDef
+ * @qemuCaps: as you'd expect
+ *
+ * Set the info->pciAddressExtFlags for all devices in the domain.
+ *
+ * Returns 0 on success or -1 on failure (the only possibility of
+ * failure would be some internal problem with
+ * virDomainDeviceInfoIterate())
+ */
+static int
+qemuDomainFillAllPCIExtensionFlags(virDomainDefPtr def,
+                                   virQEMUCapsPtr qemuCaps)
+{
+    return virDomainDeviceInfoIterate(def,
+                                      qemuDomainFillDevicePCIExtensionFlagsIter,
+                                      qemuCaps);
+}
+
+
 /**
  * qemuDomainFindUnusedIsolationGroupIter:
  * @def: domain definition
@@ -1267,6 +1375,27 @@ qemuDomainFillDevicePCIConnectFlags(virDomainDefPtr def,
 }
 
 
+/**
+ * qemuDomainFillDevicePCIExtensionFlags:
+ *
+ * @dev: The device to be checked
+ * @info: virDomainDeviceInfo within the device
+ * @qemuCaps: as you'd expect
+ *
+ * Set the info->pciAddressExtFlags for a single device.
+ *
+ * No return value.
+ */
+static void
+qemuDomainFillDevicePCIExtensionFlags(virDomainDeviceDefPtr dev,
+                                      virDomainDeviceInfoPtr info,
+                                      virQEMUCapsPtr qemuCaps)
+{
+    info->pciAddrExtFlags =
+        qemuDomainDeviceCalculatePCIAddressExtensionFlags(qemuCaps, dev);
+}
+
+
 static int
 qemuDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
                                     virDomainDeviceInfoPtr dev)
@@ -2400,6 +2529,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
     if (qemuDomainFillAllPCIConnectFlags(def, qemuCaps, driver) < 0)
         goto cleanup;
 
+    if (qemuDomainFillAllPCIExtensionFlags(def, qemuCaps) < 0)
+        goto cleanup;
+
     if (qemuDomainSetupIsolationGroups(def) < 0)
         goto cleanup;
 
@@ -2435,7 +2567,8 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
              */
             virDomainDeviceInfo info = {
                 .pciConnectFlags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
-                                    VIR_PCI_CONNECT_TYPE_PCI_DEVICE)
+                                    VIR_PCI_CONNECT_TYPE_PCI_DEVICE),
+                .pciAddrExtFlags = VIR_PCI_ADDRESS_EXTENSION_NONE
             };
             bool buses_reserved = true;
 
@@ -2472,7 +2605,8 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
             qemuDomainHasPCIeRoot(def)) {
             virDomainDeviceInfo info = {
                 .pciConnectFlags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
-                                    VIR_PCI_CONNECT_TYPE_PCIE_DEVICE)
+                                    VIR_PCI_CONNECT_TYPE_PCIE_DEVICE),
+                .pciAddrExtFlags = VIR_PCI_ADDRESS_EXTENSION_NONE
             };
 
             /* if there isn't an empty pcie-root-port, this will
@@ -2989,6 +3123,8 @@ qemuDomainEnsurePCIAddress(virDomainObjPtr obj,
 
     qemuDomainFillDevicePCIConnectFlags(obj->def, dev, priv->qemuCaps, driver);
 
+    qemuDomainFillDevicePCIExtensionFlags(dev, info, priv->qemuCaps);
+
     return virDomainPCIAddressEnsureAddr(priv->pciaddrs, info,
                                          info->pciConnectFlags);
 }
diff --git a/src/util/virpci.h b/src/util/virpci.h
index 01df652b86..b366d7d9c3 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -49,6 +49,8 @@ struct _virPCIDeviceAddress {
     unsigned int slot;
     unsigned int function;
     int multi; /* virTristateSwitch */
+    int extFlags; /* enum virPCIDeviceAddressExtensionFlags */
+    virZPCIDeviceAddress zpci;
 };
 
 typedef enum {
-- 
2.22.0