Pablo Greco 40546a
From 7888472ef1d57d992995a16dc7c9ba0fe18562a8 Mon Sep 17 00:00:00 2001
Pablo Greco 40546a
Message-Id: <7888472ef1d57d992995a16dc7c9ba0fe18562a8@dist-git>
Pablo Greco 40546a
From: Yi Min Zhao <zyimin@linux.ibm.com>
Pablo Greco 40546a
Date: Mon, 8 Apr 2019 10:57:22 +0200
Pablo Greco 40546a
Subject: [PATCH] conf: Introduce address caching for PCI extensions
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 provides a caching mechanism for the device address
Pablo Greco 40546a
extensions uid and fid on S390. For efficient sparse address allocation,
Pablo Greco 40546a
we introduce two hash tables for uid/fid which hold the address set
Pablo Greco 40546a
information per domain. Also in order to improve performance of
Pablo Greco 40546a
searching available value, we introduce our own callbacks for the two
Pablo Greco 40546a
hashtables. In this way, uid/fid is saved in hash key and hash value
Pablo Greco 40546a
could be any non-NULL pointer due to no operation on hash value. That is
Pablo Greco 40546a
also the reason why we don't introduce hash value free callback.
Pablo Greco 40546a
Pablo Greco 40546a
Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
Pablo Greco 40546a
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Pablo Greco 40546a
Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
Pablo Greco 40546a
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Pablo Greco 40546a
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
Pablo Greco 40546a
Pablo Greco 40546a
(cherry picked from commit 28831e1f1ec001882e907f03f7618f7c00ebc98d)
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/conf/domain_addr.h
Pablo Greco 40546a
    + context
Pablo Greco 40546a
      - missing b72183223f3b
Pablo Greco 40546a
Pablo Greco 40546a
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Pablo Greco 40546a
Message-Id: <20190408085732.28684-6-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/bhyve/bhyve_device.c       |  3 +-
Pablo Greco 40546a
 src/conf/domain_addr.c         | 93 +++++++++++++++++++++++++++++++++-
Pablo Greco 40546a
 src/conf/domain_addr.h         | 10 +++-
Pablo Greco 40546a
 src/qemu/qemu_domain_address.c |  6 ++-
Pablo Greco 40546a
 4 files changed, 108 insertions(+), 4 deletions(-)
Pablo Greco 40546a
Pablo Greco 40546a
diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c
Pablo Greco 40546a
index 03aa6c93bd..8f0862b0b6 100644
Pablo Greco 40546a
--- a/src/bhyve/bhyve_device.c
Pablo Greco 40546a
+++ b/src/bhyve/bhyve_device.c
Pablo Greco 40546a
@@ -71,7 +71,8 @@ bhyveDomainPCIAddressSetCreate(virDomainDefPtr def, unsigned int nbuses)
Pablo Greco 40546a
 {
Pablo Greco 40546a
     virDomainPCIAddressSetPtr addrs;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
Pablo Greco 40546a
+    if ((addrs = virDomainPCIAddressSetAlloc(nbuses,
Pablo Greco 40546a
+                                             VIR_PCI_ADDRESS_EXTENSION_NONE)) == NULL)
Pablo Greco 40546a
         return NULL;
Pablo Greco 40546a
 
Pablo Greco 40546a
     if (virDomainPCIAddressBusSetModel(&addrs->buses[0],
Pablo Greco 40546a
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
Pablo Greco 40546a
index 39f22b82eb..3e33549c3d 100644
Pablo Greco 40546a
--- a/src/conf/domain_addr.c
Pablo Greco 40546a
+++ b/src/conf/domain_addr.c
Pablo Greco 40546a
@@ -27,6 +27,7 @@
Pablo Greco 40546a
 #include "virlog.h"
Pablo Greco 40546a
 #include "virstring.h"
Pablo Greco 40546a
 #include "domain_addr.h"
Pablo Greco 40546a
+#include "virhashcode.h"
Pablo Greco 40546a
 
Pablo Greco 40546a
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
Pablo Greco 40546a
 
Pablo Greco 40546a
@@ -741,8 +742,93 @@ virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
     addrs->buses[addr->bus].slot[addr->slot].functions &= ~(1 << addr->function);
Pablo Greco 40546a
 }
Pablo Greco 40546a
 
Pablo Greco 40546a
+
Pablo Greco 40546a
+static uint32_t
Pablo Greco 40546a
+virZPCIAddrKeyCode(const void *name,
Pablo Greco 40546a
+                   uint32_t seed)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    unsigned int value = *((unsigned int *)name);
Pablo Greco 40546a
+    return virHashCodeGen(&value, sizeof(value), seed);
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static bool
Pablo Greco 40546a
+virZPCIAddrKeyEqual(const void *namea,
Pablo Greco 40546a
+                    const void *nameb)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    return *((unsigned int *)namea) == *((unsigned int *)nameb);
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static void *
Pablo Greco 40546a
+virZPCIAddrKeyCopy(const void *name)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    unsigned int *copy;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (VIR_ALLOC(copy) < 0)
Pablo Greco 40546a
+        return NULL;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    *copy = *((unsigned int *)name);
Pablo Greco 40546a
+    return (void *)copy;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static void
Pablo Greco 40546a
+virZPCIAddrKeyFree(void *name)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    VIR_FREE(name);
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static void
Pablo Greco 40546a
+virDomainPCIAddressSetExtensionFree(virDomainPCIAddressSetPtr addrs)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (!addrs || !addrs->zpciIds)
Pablo Greco 40546a
+        return;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    virHashFree(addrs->zpciIds->uids);
Pablo Greco 40546a
+    virHashFree(addrs->zpciIds->fids);
Pablo Greco 40546a
+    VIR_FREE(addrs->zpciIds);
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
+static int
Pablo Greco 40546a
+virDomainPCIAddressSetExtensionAlloc(virDomainPCIAddressSetPtr addrs,
Pablo Greco 40546a
+                                     virPCIDeviceAddressExtensionFlags extFlags)
Pablo Greco 40546a
+{
Pablo Greco 40546a
+    if (extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
Pablo Greco 40546a
+        if (addrs->zpciIds)
Pablo Greco 40546a
+            return 0;
Pablo Greco 40546a
+
Pablo Greco 40546a
+        if (VIR_ALLOC(addrs->zpciIds) < 0)
Pablo Greco 40546a
+            return -1;
Pablo Greco 40546a
+
Pablo Greco 40546a
+        if (!(addrs->zpciIds->uids = virHashCreateFull(10, NULL,
Pablo Greco 40546a
+                                                       virZPCIAddrKeyCode,
Pablo Greco 40546a
+                                                       virZPCIAddrKeyEqual,
Pablo Greco 40546a
+                                                       virZPCIAddrKeyCopy,
Pablo Greco 40546a
+                                                       virZPCIAddrKeyFree)))
Pablo Greco 40546a
+            goto error;
Pablo Greco 40546a
+
Pablo Greco 40546a
+        if (!(addrs->zpciIds->fids = virHashCreateFull(10, NULL,
Pablo Greco 40546a
+                                                       virZPCIAddrKeyCode,
Pablo Greco 40546a
+                                                       virZPCIAddrKeyEqual,
Pablo Greco 40546a
+                                                       virZPCIAddrKeyCopy,
Pablo Greco 40546a
+                                                       virZPCIAddrKeyFree)))
Pablo Greco 40546a
+            goto error;
Pablo Greco 40546a
+    }
Pablo Greco 40546a
+
Pablo Greco 40546a
+    return 0;
Pablo Greco 40546a
+
Pablo Greco 40546a
+ error:
Pablo Greco 40546a
+    virDomainPCIAddressSetExtensionFree(addrs);
Pablo Greco 40546a
+    return -1;
Pablo Greco 40546a
+}
Pablo Greco 40546a
+
Pablo Greco 40546a
+
Pablo Greco 40546a
 virDomainPCIAddressSetPtr
Pablo Greco 40546a
-virDomainPCIAddressSetAlloc(unsigned int nbuses)
Pablo Greco 40546a
+virDomainPCIAddressSetAlloc(unsigned int nbuses,
Pablo Greco 40546a
+                            virPCIDeviceAddressExtensionFlags extFlags)
Pablo Greco 40546a
 {
Pablo Greco 40546a
     virDomainPCIAddressSetPtr addrs;
Pablo Greco 40546a
 
Pablo Greco 40546a
@@ -753,6 +839,10 @@ virDomainPCIAddressSetAlloc(unsigned int nbuses)
Pablo Greco 40546a
         goto error;
Pablo Greco 40546a
 
Pablo Greco 40546a
     addrs->nbuses = nbuses;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if (virDomainPCIAddressSetExtensionAlloc(addrs, extFlags) < 0)
Pablo Greco 40546a
+        goto error;
Pablo Greco 40546a
+
Pablo Greco 40546a
     return addrs;
Pablo Greco 40546a
 
Pablo Greco 40546a
  error:
Pablo Greco 40546a
@@ -767,6 +857,7 @@ virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs)
Pablo Greco 40546a
     if (!addrs)
Pablo Greco 40546a
         return;
Pablo Greco 40546a
 
Pablo Greco 40546a
+    virDomainPCIAddressSetExtensionFree(addrs);
Pablo Greco 40546a
     VIR_FREE(addrs->buses);
Pablo Greco 40546a
     VIR_FREE(addrs);
Pablo Greco 40546a
 }
Pablo Greco 40546a
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
Pablo Greco 40546a
index fd06008e26..b01e6b9d20 100644
Pablo Greco 40546a
--- a/src/conf/domain_addr.h
Pablo Greco 40546a
+++ b/src/conf/domain_addr.h
Pablo Greco 40546a
@@ -116,6 +116,12 @@ typedef struct {
Pablo Greco 40546a
 } virDomainPCIAddressBus;
Pablo Greco 40546a
 typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr;
Pablo Greco 40546a
 
Pablo Greco 40546a
+typedef struct {
Pablo Greco 40546a
+    virHashTablePtr uids;
Pablo Greco 40546a
+    virHashTablePtr fids;
Pablo Greco 40546a
+} virDomainZPCIAddressIds;
Pablo Greco 40546a
+typedef virDomainZPCIAddressIds *virDomainZPCIAddressIdsPtr;
Pablo Greco 40546a
+
Pablo Greco 40546a
 struct _virDomainPCIAddressSet {
Pablo Greco 40546a
     virDomainPCIAddressBus *buses;
Pablo Greco 40546a
     size_t nbuses;
Pablo Greco 40546a
@@ -125,6 +131,7 @@ struct _virDomainPCIAddressSet {
Pablo Greco 40546a
     bool areMultipleRootsSupported;
Pablo Greco 40546a
     /* If true, the guest can use the pcie-to-pci-bridge controller */
Pablo Greco 40546a
     bool isPCIeToPCIBridgeSupported;
Pablo Greco 40546a
+    virDomainZPCIAddressIdsPtr zpciIds;
Pablo Greco 40546a
 };
Pablo Greco 40546a
 typedef struct _virDomainPCIAddressSet virDomainPCIAddressSet;
Pablo Greco 40546a
 typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr;
Pablo Greco 40546a
@@ -132,7 +139,8 @@ typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr;
Pablo Greco 40546a
 char *virDomainPCIAddressAsString(virPCIDeviceAddressPtr addr)
Pablo Greco 40546a
       ATTRIBUTE_NONNULL(1);
Pablo Greco 40546a
 
Pablo Greco 40546a
-virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses);
Pablo Greco 40546a
+virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses,
Pablo Greco 40546a
+                                                      virPCIDeviceAddressExtensionFlags extFlags);
Pablo Greco 40546a
 
Pablo Greco 40546a
 void virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs);
Pablo Greco 40546a
 
Pablo Greco 40546a
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
Pablo Greco 40546a
index 3d01d14b46..ba870d56b1 100644
Pablo Greco 40546a
--- a/src/qemu/qemu_domain_address.c
Pablo Greco 40546a
+++ b/src/qemu/qemu_domain_address.c
Pablo Greco 40546a
@@ -1508,8 +1508,12 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
Pablo Greco 40546a
     size_t i;
Pablo Greco 40546a
     bool hasPCIeRoot = false;
Pablo Greco 40546a
     virDomainControllerModelPCI defaultModel;
Pablo Greco 40546a
+    virPCIDeviceAddressExtensionFlags extFlags = VIR_PCI_ADDRESS_EXTENSION_NONE;
Pablo Greco 40546a
 
Pablo Greco 40546a
-    if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
Pablo Greco 40546a
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ZPCI))
Pablo Greco 40546a
+        extFlags |= VIR_PCI_ADDRESS_EXTENSION_ZPCI;
Pablo Greco 40546a
+
Pablo Greco 40546a
+    if ((addrs = virDomainPCIAddressSetAlloc(nbuses, extFlags)) == NULL)
Pablo Greco 40546a
         return NULL;
Pablo Greco 40546a
 
Pablo Greco 40546a
     addrs->dryRun = dryRun;
Pablo Greco 40546a
-- 
Pablo Greco 40546a
2.22.0
Pablo Greco 40546a