From e3ce39195c82c4e8f54ddad73e192d9317c9bb39 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Wed, 21 Jun 2023 15:31:24 +0200 Subject: [PATCH] qemu_domain: Properly validate count of memory slots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Memory slots are required only for DIMM-like devices, while other devices defined via such as virtio-mem may use the PCI bus and thus do not require/consume a memory slot. Fix the validation code to calculate the required count of memory devices only for DIMMs and NVDIMMs. Signed-off-by: Peter Krempa Reviewed-by: Ján Tomko --- src/qemu/qemu_domain.c | 31 ++++++++++++++----- ...mory-hotplug-virtio-mem.x86_64-latest.args | 2 +- .../memory-hotplug-virtio-mem.xml | 2 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 8f77e8fc58..c65c571398 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -9279,6 +9279,7 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, unsigned int nmems = def->nmems; unsigned long long hotplugSpace; unsigned long long hotplugMemory = 0; + size_t slotsNeeded = 0; size_t i; hotplugSpace = def->mem.max_memory - virDomainDefGetMemoryInitial(def); @@ -9289,6 +9290,20 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, if (qemuDomainDefValidateMemoryHotplugDevice(mem, def) < 0) return -1; + + switch (mem->model) { + case VIR_DOMAIN_MEMORY_MODEL_DIMM: + case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + slotsNeeded++; + break; + + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: + case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: + case VIR_DOMAIN_MEMORY_MODEL_SGX_EPC: + case VIR_DOMAIN_MEMORY_MODEL_LAST: + case VIR_DOMAIN_MEMORY_MODEL_NONE: + break; + } } if (!virDomainDefHasMemoryHotplug(def)) { @@ -9315,19 +9330,14 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, } } - if (nmems > def->mem.memory_slots) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("memory device count '%1$u' exceeds slots count '%2$u'"), - nmems, def->mem.memory_slots); - return -1; - } - for (i = 0; i < def->nmems; i++) { hotplugMemory += def->mems[i]->size; switch (def->mems[i]->model) { case VIR_DOMAIN_MEMORY_MODEL_DIMM: case VIR_DOMAIN_MEMORY_MODEL_NVDIMM: + slotsNeeded++; + G_GNUC_FALLTHROUGH; case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM: case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM: /* already existing devices don't need to be checked on hotplug */ @@ -9344,6 +9354,13 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, } } + if (slotsNeeded > def->mem.memory_slots) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("count of memory devices requiring memory slots '%1$zu' exceeds slots count '%2$u'"), + slotsNeeded, def->mem.memory_slots); + return -1; + } + if (hotplugMemory > hotplugSpace) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("memory device total size exceeds hotplug space")); diff --git a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.x86_64-latest.args b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.x86_64-latest.args index 592578fb59..7309fea2ff 100644 --- a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.x86_64-latest.args +++ b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.x86_64-latest.args @@ -13,7 +13,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -machine pc,usb=off,dump-guest-core=off,acpi=off \ -accel kvm \ -cpu qemu64 \ --m size=2095104k,slots=16,maxmem=1099511627776k \ +-m size=2095104k,slots=1,maxmem=1099511627776k \ -overcommit mem-lock=off \ -smp 2,sockets=2,dies=1,cores=1,threads=1 \ -object '{"qom-type":"memory-backend-ram","id":"ram-node0","size":2145386496}' \ diff --git a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml index f5cc4a35ed..6220ab4c82 100644 --- a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml +++ b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml @@ -1,7 +1,7 @@ QEMUGuest1 c7a5fdbd-edaf-9455-926a-d65c16db1809 - 1099511627776 + 1099511627776 8388608 8388608 2