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