render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
c480ed
From 050eb598af9291f385998cb1127d5bdf83305501 Mon Sep 17 00:00:00 2001
c480ed
Message-Id: <050eb598af9291f385998cb1127d5bdf83305501@dist-git>
c480ed
From: Yi Min Zhao <zyimin@linux.ibm.com>
c480ed
Date: Mon, 8 Apr 2019 10:57:21 +0200
c480ed
Subject: [PATCH] conf: Introduce extension flag and zPCI member for PCI
c480ed
 address
c480ed
MIME-Version: 1.0
c480ed
Content-Type: text/plain; charset=UTF-8
c480ed
Content-Transfer-Encoding: 8bit
c480ed
c480ed
This patch introduces PCI address extension flag for virDomainDeviceInfo
c480ed
and virPCIDeviceAddress. The extension flag in virDomainDeviceInfo is
c480ed
used internally during calculating PCI extension flag. The one in
c480ed
virPCIDeviceAddress is the duplicate to indicate extension address is
c480ed
being used. Currently only zPCI extension address is introduced to deal
c480ed
with 'uid' and 'fid' on the S390 platform.
c480ed
c480ed
Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
c480ed
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
c480ed
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c480ed
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
c480ed
c480ed
(cherry picked from commit 478e5f90fd4c0c0a8c1b3a8e19b9cae93ed78a4e)
c480ed
c480ed
https://bugzilla.redhat.com/show_bug.cgi?id=1508149
c480ed
c480ed
Conflicts:
c480ed
c480ed
  * src/qemu/qemu_domain_address.c
c480ed
    + context
c480ed
      - missing db98a426a640
c480ed
c480ed
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
c480ed
Message-Id: <20190408085732.28684-5-abologna@redhat.com>
c480ed
Reviewed-by: Laine Stump <laine@redhat.com>
c480ed
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c480ed
---
c480ed
 src/conf/device_conf.h         |   4 +
c480ed
 src/conf/domain_addr.h         |   5 ++
c480ed
 src/qemu/qemu_domain_address.c | 140 ++++++++++++++++++++++++++++++++-
c480ed
 src/util/virpci.h              |   2 +
c480ed
 4 files changed, 149 insertions(+), 2 deletions(-)
c480ed
c480ed
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
c480ed
index a31ce9c376..c79066ec02 100644
c480ed
--- a/src/conf/device_conf.h
c480ed
+++ b/src/conf/device_conf.h
c480ed
@@ -164,6 +164,10 @@ struct _virDomainDeviceInfo {
c480ed
      * assignment, never saved and never reported.
c480ed
      */
c480ed
     int pciConnectFlags; /* enum virDomainPCIConnectFlags */
c480ed
+    /* pciAddrExtFlags is only used internally to calculate PCI
c480ed
+     * address extension flags during address assignment.
c480ed
+     */
c480ed
+    int pciAddrExtFlags; /* enum virDomainPCIAddressExtensionFlags */
c480ed
     char *loadparm;
c480ed
 
c480ed
     /* PCI devices will only be automatically placed on a PCI bus
c480ed
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
c480ed
index 3236b7d6de..fd06008e26 100644
c480ed
--- a/src/conf/domain_addr.h
c480ed
+++ b/src/conf/domain_addr.h
c480ed
@@ -29,6 +29,11 @@
c480ed
 # define VIR_PCI_ADDRESS_SLOT_LAST 31
c480ed
 # define VIR_PCI_ADDRESS_FUNCTION_LAST 7
c480ed
 
c480ed
+typedef enum {
c480ed
+    VIR_PCI_ADDRESS_EXTENSION_NONE = 0, /* no extension */
c480ed
+    VIR_PCI_ADDRESS_EXTENSION_ZPCI = 1 << 0, /* zPCI support */
c480ed
+} virPCIDeviceAddressExtensionFlags;
c480ed
+
c480ed
 typedef enum {
c480ed
    VIR_PCI_CONNECT_HOTPLUGGABLE = 1 << 0, /* is hotplug needed/supported */
c480ed
 
c480ed
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
c480ed
index 79d2b9f9c4..3d01d14b46 100644
c480ed
--- a/src/qemu/qemu_domain_address.c
c480ed
+++ b/src/qemu/qemu_domain_address.c
c480ed
@@ -511,6 +511,64 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def,
c480ed
 }
c480ed
 
c480ed
 
c480ed
+static bool
c480ed
+qemuDomainDeviceSupportZPCI(virDomainDeviceDefPtr device)
c480ed
+{
c480ed
+    switch ((virDomainDeviceType)device->type) {
c480ed
+    case VIR_DOMAIN_DEVICE_CHR:
c480ed
+        return false;
c480ed
+
c480ed
+    case VIR_DOMAIN_DEVICE_CONTROLLER:
c480ed
+    case VIR_DOMAIN_DEVICE_DISK:
c480ed
+    case VIR_DOMAIN_DEVICE_LEASE:
c480ed
+    case VIR_DOMAIN_DEVICE_FS:
c480ed
+    case VIR_DOMAIN_DEVICE_NET:
c480ed
+    case VIR_DOMAIN_DEVICE_INPUT:
c480ed
+    case VIR_DOMAIN_DEVICE_SOUND:
c480ed
+    case VIR_DOMAIN_DEVICE_VIDEO:
c480ed
+    case VIR_DOMAIN_DEVICE_HOSTDEV:
c480ed
+    case VIR_DOMAIN_DEVICE_WATCHDOG:
c480ed
+    case VIR_DOMAIN_DEVICE_GRAPHICS:
c480ed
+    case VIR_DOMAIN_DEVICE_HUB:
c480ed
+    case VIR_DOMAIN_DEVICE_REDIRDEV:
c480ed
+    case VIR_DOMAIN_DEVICE_SMARTCARD:
c480ed
+    case VIR_DOMAIN_DEVICE_MEMBALLOON:
c480ed
+    case VIR_DOMAIN_DEVICE_NVRAM:
c480ed
+    case VIR_DOMAIN_DEVICE_RNG:
c480ed
+    case VIR_DOMAIN_DEVICE_SHMEM:
c480ed
+    case VIR_DOMAIN_DEVICE_TPM:
c480ed
+    case VIR_DOMAIN_DEVICE_PANIC:
c480ed
+    case VIR_DOMAIN_DEVICE_MEMORY:
c480ed
+    case VIR_DOMAIN_DEVICE_IOMMU:
c480ed
+    case VIR_DOMAIN_DEVICE_VSOCK:
c480ed
+        break;
c480ed
+
c480ed
+    case VIR_DOMAIN_DEVICE_NONE:
c480ed
+    case VIR_DOMAIN_DEVICE_LAST:
c480ed
+    default:
c480ed
+        virReportEnumRangeError(virDomainDeviceType, device->type);
c480ed
+        return false;
c480ed
+    }
c480ed
+
c480ed
+    return true;
c480ed
+}
c480ed
+
c480ed
+
c480ed
+static virPCIDeviceAddressExtensionFlags
c480ed
+qemuDomainDeviceCalculatePCIAddressExtensionFlags(virQEMUCapsPtr qemuCaps,
c480ed
+                                                  virDomainDeviceDefPtr dev)
c480ed
+{
c480ed
+    virPCIDeviceAddressExtensionFlags extFlags = 0;
c480ed
+
c480ed
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ZPCI) &&
c480ed
+        qemuDomainDeviceSupportZPCI(dev)) {
c480ed
+        extFlags |= VIR_PCI_ADDRESS_EXTENSION_ZPCI;
c480ed
+    }
c480ed
+
c480ed
+    return extFlags;
c480ed
+}
c480ed
+
c480ed
+
c480ed
 /**
c480ed
  * qemuDomainDeviceCalculatePCIConnectFlags:
c480ed
  *
c480ed
@@ -993,6 +1051,56 @@ qemuDomainFillAllPCIConnectFlags(virDomainDefPtr def,
c480ed
 }
c480ed
 
c480ed
 
c480ed
+/**
c480ed
+ * qemuDomainFillDevicePCIExtensionFlagsIter:
c480ed
+ *
c480ed
+ * @def: the entire DomainDef
c480ed
+ * @dev: The device to be checked
c480ed
+ * @info: virDomainDeviceInfo within the device
c480ed
+ * @opaque: qemu capabilities
c480ed
+ *
c480ed
+ * Sets the pciAddressExtFlags for a single device's info. Has properly
c480ed
+ * formatted arguments to be called by virDomainDeviceInfoIterate().
c480ed
+ *
c480ed
+ * Always returns 0 - there is no failure.
c480ed
+ */
c480ed
+static int
c480ed
+qemuDomainFillDevicePCIExtensionFlagsIter(virDomainDefPtr def ATTRIBUTE_UNUSED,
c480ed
+                                          virDomainDeviceDefPtr dev,
c480ed
+                                          virDomainDeviceInfoPtr info,
c480ed
+                                          void *opaque)
c480ed
+{
c480ed
+    virQEMUCapsPtr qemuCaps = opaque;
c480ed
+
c480ed
+    info->pciAddrExtFlags =
c480ed
+        qemuDomainDeviceCalculatePCIAddressExtensionFlags(qemuCaps, dev);
c480ed
+
c480ed
+    return 0;
c480ed
+}
c480ed
+
c480ed
+
c480ed
+/**
c480ed
+ * qemuDomainFillAllPCIExtensionFlags:
c480ed
+ *
c480ed
+ * @def: the entire DomainDef
c480ed
+ * @qemuCaps: as you'd expect
c480ed
+ *
c480ed
+ * Set the info->pciAddressExtFlags for all devices in the domain.
c480ed
+ *
c480ed
+ * Returns 0 on success or -1 on failure (the only possibility of
c480ed
+ * failure would be some internal problem with
c480ed
+ * virDomainDeviceInfoIterate())
c480ed
+ */
c480ed
+static int
c480ed
+qemuDomainFillAllPCIExtensionFlags(virDomainDefPtr def,
c480ed
+                                   virQEMUCapsPtr qemuCaps)
c480ed
+{
c480ed
+    return virDomainDeviceInfoIterate(def,
c480ed
+                                      qemuDomainFillDevicePCIExtensionFlagsIter,
c480ed
+                                      qemuCaps);
c480ed
+}
c480ed
+
c480ed
+
c480ed
 /**
c480ed
  * qemuDomainFindUnusedIsolationGroupIter:
c480ed
  * @def: domain definition
c480ed
@@ -1267,6 +1375,27 @@ qemuDomainFillDevicePCIConnectFlags(virDomainDefPtr def,
c480ed
 }
c480ed
 
c480ed
 
c480ed
+/**
c480ed
+ * qemuDomainFillDevicePCIExtensionFlags:
c480ed
+ *
c480ed
+ * @dev: The device to be checked
c480ed
+ * @info: virDomainDeviceInfo within the device
c480ed
+ * @qemuCaps: as you'd expect
c480ed
+ *
c480ed
+ * Set the info->pciAddressExtFlags for a single device.
c480ed
+ *
c480ed
+ * No return value.
c480ed
+ */
c480ed
+static void
c480ed
+qemuDomainFillDevicePCIExtensionFlags(virDomainDeviceDefPtr dev,
c480ed
+                                      virDomainDeviceInfoPtr info,
c480ed
+                                      virQEMUCapsPtr qemuCaps)
c480ed
+{
c480ed
+    info->pciAddrExtFlags =
c480ed
+        qemuDomainDeviceCalculatePCIAddressExtensionFlags(qemuCaps, dev);
c480ed
+}
c480ed
+
c480ed
+
c480ed
 static int
c480ed
 qemuDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
c480ed
                                     virDomainDeviceInfoPtr dev)
c480ed
@@ -2400,6 +2529,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
c480ed
     if (qemuDomainFillAllPCIConnectFlags(def, qemuCaps, driver) < 0)
c480ed
         goto cleanup;
c480ed
 
c480ed
+    if (qemuDomainFillAllPCIExtensionFlags(def, qemuCaps) < 0)
c480ed
+        goto cleanup;
c480ed
+
c480ed
     if (qemuDomainSetupIsolationGroups(def) < 0)
c480ed
         goto cleanup;
c480ed
 
c480ed
@@ -2435,7 +2567,8 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
c480ed
              */
c480ed
             virDomainDeviceInfo info = {
c480ed
                 .pciConnectFlags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
c480ed
-                                    VIR_PCI_CONNECT_TYPE_PCI_DEVICE)
c480ed
+                                    VIR_PCI_CONNECT_TYPE_PCI_DEVICE),
c480ed
+                .pciAddrExtFlags = VIR_PCI_ADDRESS_EXTENSION_NONE
c480ed
             };
c480ed
             bool buses_reserved = true;
c480ed
 
c480ed
@@ -2472,7 +2605,8 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
c480ed
             qemuDomainHasPCIeRoot(def)) {
c480ed
             virDomainDeviceInfo info = {
c480ed
                 .pciConnectFlags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
c480ed
-                                    VIR_PCI_CONNECT_TYPE_PCIE_DEVICE)
c480ed
+                                    VIR_PCI_CONNECT_TYPE_PCIE_DEVICE),
c480ed
+                .pciAddrExtFlags = VIR_PCI_ADDRESS_EXTENSION_NONE
c480ed
             };
c480ed
 
c480ed
             /* if there isn't an empty pcie-root-port, this will
c480ed
@@ -2989,6 +3123,8 @@ qemuDomainEnsurePCIAddress(virDomainObjPtr obj,
c480ed
 
c480ed
     qemuDomainFillDevicePCIConnectFlags(obj->def, dev, priv->qemuCaps, driver);
c480ed
 
c480ed
+    qemuDomainFillDevicePCIExtensionFlags(dev, info, priv->qemuCaps);
c480ed
+
c480ed
     return virDomainPCIAddressEnsureAddr(priv->pciaddrs, info,
c480ed
                                          info->pciConnectFlags);
c480ed
 }
c480ed
diff --git a/src/util/virpci.h b/src/util/virpci.h
c480ed
index 01df652b86..b366d7d9c3 100644
c480ed
--- a/src/util/virpci.h
c480ed
+++ b/src/util/virpci.h
c480ed
@@ -49,6 +49,8 @@ struct _virPCIDeviceAddress {
c480ed
     unsigned int slot;
c480ed
     unsigned int function;
c480ed
     int multi; /* virTristateSwitch */
c480ed
+    int extFlags; /* enum virPCIDeviceAddressExtensionFlags */
c480ed
+    virZPCIDeviceAddress zpci;
c480ed
 };
c480ed
 
c480ed
 typedef enum {
c480ed
-- 
c480ed
2.22.0
c480ed