render / rpms / libvirt

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