|
|
c480ed |
From 051451a1b9cefa42ecfd6d27dcb6a12ef49de072 Mon Sep 17 00:00:00 2001
|
|
|
c480ed |
Message-Id: <051451a1b9cefa42ecfd6d27dcb6a12ef49de072@dist-git>
|
|
|
c480ed |
From: Daniel Henrique Barboza <danielhb413@gmail.com>
|
|
|
c480ed |
Date: Fri, 3 May 2019 13:54:51 +0200
|
|
|
c480ed |
Subject: [PATCH] qemu_domain: add a PPC64 memLockLimit helper
|
|
|
c480ed |
|
|
|
c480ed |
There is a lot of documentation in the comments about how PPC64 handles
|
|
|
c480ed |
passthrough VFIO devices to calculate the @memLockLimit. And more will
|
|
|
c480ed |
be added with the PPC64 NVLink2 support code.
|
|
|
c480ed |
|
|
|
c480ed |
Let's remove the PPC64 code from qemuDomainGetMemLockLimitBytes()
|
|
|
c480ed |
body and put it into a helper function. This will simplify the
|
|
|
c480ed |
flow of qemuDomainGetMemLockLimitBytes() that handles all the other
|
|
|
c480ed |
platforms and improves readability of the PPC64 specifics.
|
|
|
c480ed |
|
|
|
c480ed |
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
|
|
|
c480ed |
Reviewed-by: Erik Skultety <eskultet@redhat.com>
|
|
|
c480ed |
(cherry picked from commit 7a686fd2eae8d5674bb1213d8517dc5814fa6bf3)
|
|
|
c480ed |
|
|
|
c480ed |
https: //bugzilla.redhat.com/show_bug.cgi?id=1505998
|
|
|
c480ed |
Signed-off-by: Erik Skultety <eskultet@redhat.com>
|
|
|
c480ed |
Message-Id: <ccdf9fefeb624585559606d00b6ac19b574733b3.1556884443.git.eskultet@redhat.com>
|
|
|
c480ed |
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
|
|
|
c480ed |
---
|
|
|
c480ed |
src/qemu/qemu_domain.c | 171 ++++++++++++++++++++++-------------------
|
|
|
c480ed |
1 file changed, 93 insertions(+), 78 deletions(-)
|
|
|
c480ed |
|
|
|
c480ed |
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
|
|
c480ed |
index d936090d87..f91de0b743 100644
|
|
|
c480ed |
--- a/src/qemu/qemu_domain.c
|
|
|
c480ed |
+++ b/src/qemu/qemu_domain.c
|
|
|
c480ed |
@@ -9805,6 +9805,97 @@ qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver,
|
|
|
c480ed |
}
|
|
|
c480ed |
|
|
|
c480ed |
|
|
|
c480ed |
+/**
|
|
|
c480ed |
+ * getPPC64MemLockLimitBytes:
|
|
|
c480ed |
+ * @def: domain definition
|
|
|
c480ed |
+ *
|
|
|
c480ed |
+ * A PPC64 helper that calculates the memory locking limit in order for
|
|
|
c480ed |
+ * the guest to operate properly.
|
|
|
c480ed |
+ */
|
|
|
c480ed |
+static unsigned long long
|
|
|
c480ed |
+getPPC64MemLockLimitBytes(virDomainDefPtr def)
|
|
|
c480ed |
+{
|
|
|
c480ed |
+ unsigned long long memKB = 0;
|
|
|
c480ed |
+ unsigned long long baseLimit = 0;
|
|
|
c480ed |
+ unsigned long long memory = 0;
|
|
|
c480ed |
+ unsigned long long maxMemory = 0;
|
|
|
c480ed |
+ unsigned long long passthroughLimit = 0;
|
|
|
c480ed |
+ size_t i, nPCIHostBridges = 0;
|
|
|
c480ed |
+ bool usesVFIO = false;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ for (i = 0; i < def->ncontrollers; i++) {
|
|
|
c480ed |
+ virDomainControllerDefPtr cont = def->controllers[i];
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (!virDomainControllerIsPSeriesPHB(cont))
|
|
|
c480ed |
+ continue;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ nPCIHostBridges++;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+
|
|
|
c480ed |
+ for (i = 0; i < def->nhostdevs; i++) {
|
|
|
c480ed |
+ virDomainHostdevDefPtr dev = def->hostdevs[i];
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (dev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
|
|
c480ed |
+ dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
|
|
|
c480ed |
+ dev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
|
|
|
c480ed |
+ usesVFIO = true;
|
|
|
c480ed |
+ break;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+
|
|
|
c480ed |
+ memory = virDomainDefGetMemoryTotal(def);
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (def->mem.max_memory)
|
|
|
c480ed |
+ maxMemory = def->mem.max_memory;
|
|
|
c480ed |
+ else
|
|
|
c480ed |
+ maxMemory = memory;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ /* baseLimit := maxMemory / 128 (a)
|
|
|
c480ed |
+ * + 4 MiB * #PHBs + 8 MiB (b)
|
|
|
c480ed |
+ *
|
|
|
c480ed |
+ * (a) is the hash table
|
|
|
c480ed |
+ *
|
|
|
c480ed |
+ * (b) is accounting for the 32-bit DMA window - it could be either the
|
|
|
c480ed |
+ * KVM accelerated TCE tables for emulated devices, or the VFIO
|
|
|
c480ed |
+ * userspace view. The 4 MiB per-PHB (including the default one) covers
|
|
|
c480ed |
+ * a 2GiB DMA window: default is 1GiB, but it's possible it'll be
|
|
|
c480ed |
+ * increased to help performance. The 8 MiB extra should be plenty for
|
|
|
c480ed |
+ * the TCE table index for any reasonable number of PHBs and several
|
|
|
c480ed |
+ * spapr-vlan or spapr-vscsi devices (512kB + a tiny bit each) */
|
|
|
c480ed |
+ baseLimit = maxMemory / 128 +
|
|
|
c480ed |
+ 4096 * nPCIHostBridges +
|
|
|
c480ed |
+ 8192;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ /* passthroughLimit := max( 2 GiB * #PHBs, (c)
|
|
|
c480ed |
+ * memory (d)
|
|
|
c480ed |
+ * + memory * 1/512 * #PHBs + 8 MiB ) (e)
|
|
|
c480ed |
+ *
|
|
|
c480ed |
+ * (c) is the pre-DDW VFIO DMA window accounting. We're allowing 2 GiB
|
|
|
c480ed |
+ * rather than 1 GiB
|
|
|
c480ed |
+ *
|
|
|
c480ed |
+ * (d) is the with-DDW (and memory pre-registration and related
|
|
|
c480ed |
+ * features) DMA window accounting - assuming that we only account RAM
|
|
|
c480ed |
+ * once, even if mapped to multiple PHBs
|
|
|
c480ed |
+ *
|
|
|
c480ed |
+ * (e) is the with-DDW userspace view and overhead for the 64-bit DMA
|
|
|
c480ed |
+ * window. This is based a bit on expected guest behaviour, but there
|
|
|
c480ed |
+ * really isn't a way to completely avoid that. We assume the guest
|
|
|
c480ed |
+ * requests a 64-bit DMA window (per PHB) just big enough to map all
|
|
|
c480ed |
+ * its RAM. 4 kiB page size gives the 1/512; it will be less with 64
|
|
|
c480ed |
+ * kiB pages, less still if the guest is mapped with hugepages (unlike
|
|
|
c480ed |
+ * the default 32-bit DMA window, DDW windows can use large IOMMU
|
|
|
c480ed |
+ * pages). 8 MiB is for second and further level overheads, like (b) */
|
|
|
c480ed |
+ if (usesVFIO)
|
|
|
c480ed |
+ passthroughLimit = MAX(2 * 1024 * 1024 * nPCIHostBridges,
|
|
|
c480ed |
+ memory +
|
|
|
c480ed |
+ memory / 512 * nPCIHostBridges + 8192);
|
|
|
c480ed |
+
|
|
|
c480ed |
+ memKB = baseLimit + passthroughLimit;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ return memKB << 10;
|
|
|
c480ed |
+}
|
|
|
c480ed |
+
|
|
|
c480ed |
+
|
|
|
c480ed |
/**
|
|
|
c480ed |
* qemuDomainGetMemLockLimitBytes:
|
|
|
c480ed |
* @def: domain definition
|
|
|
c480ed |
@@ -9836,84 +9927,8 @@ qemuDomainGetMemLockLimitBytes(virDomainDefPtr def)
|
|
|
c480ed |
if (def->mem.locked)
|
|
|
c480ed |
return VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
|
|
|
c480ed |
|
|
|
c480ed |
- if (ARCH_IS_PPC64(def->os.arch) && def->virtType == VIR_DOMAIN_VIRT_KVM) {
|
|
|
c480ed |
- unsigned long long maxMemory;
|
|
|
c480ed |
- unsigned long long memory;
|
|
|
c480ed |
- unsigned long long baseLimit;
|
|
|
c480ed |
- unsigned long long passthroughLimit = 0;
|
|
|
c480ed |
- size_t nPCIHostBridges = 0;
|
|
|
c480ed |
- bool usesVFIO = false;
|
|
|
c480ed |
-
|
|
|
c480ed |
- for (i = 0; i < def->ncontrollers; i++) {
|
|
|
c480ed |
- virDomainControllerDefPtr cont = def->controllers[i];
|
|
|
c480ed |
-
|
|
|
c480ed |
- if (!virDomainControllerIsPSeriesPHB(cont))
|
|
|
c480ed |
- continue;
|
|
|
c480ed |
-
|
|
|
c480ed |
- nPCIHostBridges++;
|
|
|
c480ed |
- }
|
|
|
c480ed |
-
|
|
|
c480ed |
- for (i = 0; i < def->nhostdevs; i++) {
|
|
|
c480ed |
- virDomainHostdevDefPtr dev = def->hostdevs[i];
|
|
|
c480ed |
-
|
|
|
c480ed |
- if (dev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
|
|
c480ed |
- dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
|
|
|
c480ed |
- dev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
|
|
|
c480ed |
- usesVFIO = true;
|
|
|
c480ed |
- break;
|
|
|
c480ed |
- }
|
|
|
c480ed |
- }
|
|
|
c480ed |
-
|
|
|
c480ed |
- memory = virDomainDefGetMemoryTotal(def);
|
|
|
c480ed |
-
|
|
|
c480ed |
- if (def->mem.max_memory)
|
|
|
c480ed |
- maxMemory = def->mem.max_memory;
|
|
|
c480ed |
- else
|
|
|
c480ed |
- maxMemory = memory;
|
|
|
c480ed |
-
|
|
|
c480ed |
- /* baseLimit := maxMemory / 128 (a)
|
|
|
c480ed |
- * + 4 MiB * #PHBs + 8 MiB (b)
|
|
|
c480ed |
- *
|
|
|
c480ed |
- * (a) is the hash table
|
|
|
c480ed |
- *
|
|
|
c480ed |
- * (b) is accounting for the 32-bit DMA window - it could be either the
|
|
|
c480ed |
- * KVM accelerated TCE tables for emulated devices, or the VFIO
|
|
|
c480ed |
- * userspace view. The 4 MiB per-PHB (including the default one) covers
|
|
|
c480ed |
- * a 2GiB DMA window: default is 1GiB, but it's possible it'll be
|
|
|
c480ed |
- * increased to help performance. The 8 MiB extra should be plenty for
|
|
|
c480ed |
- * the TCE table index for any reasonable number of PHBs and several
|
|
|
c480ed |
- * spapr-vlan or spapr-vscsi devices (512kB + a tiny bit each) */
|
|
|
c480ed |
- baseLimit = maxMemory / 128 +
|
|
|
c480ed |
- 4096 * nPCIHostBridges +
|
|
|
c480ed |
- 8192;
|
|
|
c480ed |
-
|
|
|
c480ed |
- /* passthroughLimit := max( 2 GiB * #PHBs, (c)
|
|
|
c480ed |
- * memory (d)
|
|
|
c480ed |
- * + memory * 1/512 * #PHBs + 8 MiB ) (e)
|
|
|
c480ed |
- *
|
|
|
c480ed |
- * (c) is the pre-DDW VFIO DMA window accounting. We're allowing 2 GiB
|
|
|
c480ed |
- * rather than 1 GiB
|
|
|
c480ed |
- *
|
|
|
c480ed |
- * (d) is the with-DDW (and memory pre-registration and related
|
|
|
c480ed |
- * features) DMA window accounting - assuming that we only account RAM
|
|
|
c480ed |
- * once, even if mapped to multiple PHBs
|
|
|
c480ed |
- *
|
|
|
c480ed |
- * (e) is the with-DDW userspace view and overhead for the 64-bit DMA
|
|
|
c480ed |
- * window. This is based a bit on expected guest behaviour, but there
|
|
|
c480ed |
- * really isn't a way to completely avoid that. We assume the guest
|
|
|
c480ed |
- * requests a 64-bit DMA window (per PHB) just big enough to map all
|
|
|
c480ed |
- * its RAM. 4 kiB page size gives the 1/512; it will be less with 64
|
|
|
c480ed |
- * kiB pages, less still if the guest is mapped with hugepages (unlike
|
|
|
c480ed |
- * the default 32-bit DMA window, DDW windows can use large IOMMU
|
|
|
c480ed |
- * pages). 8 MiB is for second and further level overheads, like (b) */
|
|
|
c480ed |
- if (usesVFIO)
|
|
|
c480ed |
- passthroughLimit = MAX(2 * 1024 * 1024 * nPCIHostBridges,
|
|
|
c480ed |
- memory +
|
|
|
c480ed |
- memory / 512 * nPCIHostBridges + 8192);
|
|
|
c480ed |
-
|
|
|
c480ed |
- memKB = baseLimit + passthroughLimit;
|
|
|
c480ed |
- goto done;
|
|
|
c480ed |
- }
|
|
|
c480ed |
+ if (ARCH_IS_PPC64(def->os.arch) && def->virtType == VIR_DOMAIN_VIRT_KVM)
|
|
|
c480ed |
+ return getPPC64MemLockLimitBytes(def);
|
|
|
c480ed |
|
|
|
c480ed |
/* For device passthrough using VFIO the guest memory and MMIO memory
|
|
|
c480ed |
* regions need to be locked persistent in order to allow DMA.
|
|
|
c480ed |
--
|
|
|
c480ed |
2.21.0
|
|
|
c480ed |
|