Using the 'uuid' element for ppc64 NVDIMM memory added in the
previous patch, use it in qemuBuildMemoryDeviceStr() to pass
it over to QEMU.
Another ppc64 restriction is the necessity of a mem->labelsize,
given than ppc64 only support label-area backed NVDIMMs.
Finally, we don't want ppc64 NVDIMMs to align up due to the
high risk of going beyond the end of file with a 256MiB
increment that the user didn't predict. Align it down
instead.
Signed-off-by: Daniel Henrique Barboza <danielhb413(a)gmail.com>
---
src/conf/domain_conf.c | 7 +++
src/qemu/qemu_command.c | 7 +++
src/qemu/qemu_domain.c | 47 +++++++++++++++++--
.../memory-hotplug-nvdimm-ppc64.args | 32 +++++++++++++
.../memory-hotplug-nvdimm-ppc64.xml | 5 +-
tests/qemuxml2argvtest.c | 4 ++
.../memory-hotplug-nvdimm-ppc64.xml | 5 +-
7 files changed, 102 insertions(+), 5 deletions(-)
create mode 100644 tests/qemuxml2argvdata/memory-hotplug-nvdimm-ppc64.args
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3ae6c181c2..7f8018fed2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16582,6 +16582,13 @@ virDomainMemoryDefParseXML(virDomainXMLOptionPtr xmlopt,
if (virDomainMemoryTargetDefParseXML(node, ctxt, def) < 0)
goto error;
+ if (def->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM &&
+ ARCH_IS_PPC64(dom->os.arch) && def->labelsize == 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("label size is required for NVDIMM device"));
+ goto error;
+ }
+
if (virDomainDeviceInfoParseXML(xmlopt, memdevNode,
&def->info, flags) < 0)
goto error;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 9e0334a3e7..76f1247329 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3677,6 +3677,13 @@ qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem,
if (mem->labelsize)
virBufferAsprintf(&buf, "label-size=%llu,", mem->labelsize *
1024);
+ if (virUUIDIsValid(mem->uuid)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ virUUIDFormat(mem->uuid, uuidstr);
+ virBufferAsprintf(&buf, "uuid=%s,", uuidstr);
+ }
+
if (mem->readonly) {
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_NVDIMM_UNARMED)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 3d3f796d85..2f420a43cd 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -12418,6 +12418,35 @@ qemuDomainGetMemoryModuleSizeAlignment(const virDomainDef *def,
}
+static void
+qemuDomainNVDimmAlignSizePseries(virDomainDefPtr def,
+ virDomainMemoryDefPtr mem)
+{
+ /* For NVDIMMs in ppc64 in we want to align down the guest
+ * visible space, instead of align up, to avoid writing
+ * beyond the end of file by adding a potential 256MiB
+ * to the user specified size.
+ *
+ * The label-size is mandatory for ppc64 as well, meaning that
+ * the guest visible space will be target_size-label_size.
+ *
+ * Finally, target_size must include label_size.
+ *
+ * The above can be summed up as follows:
+ *
+ * target_size = AlignDown(target_size - label_size) + label_size
+ */
+ unsigned long long ppc64AlignSize = qemuDomainGetMemorySizeAlignment(def);
+ unsigned long long guestArea = mem->size - mem->labelsize;
+
+ /* Align down guest_area. 256MiB is the minimum size. */
+ guestArea = (guestArea/ppc64AlignSize) * ppc64AlignSize;
+ guestArea = MAX(guestArea, ppc64AlignSize);
+
+ mem->size = guestArea + mem->labelsize;
+}
+
+
int
qemuDomainAlignMemorySizes(virDomainDefPtr def)
{
@@ -12464,8 +12493,14 @@ qemuDomainAlignMemorySizes(virDomainDefPtr def)
/* Align memory module sizes */
for (i = 0; i < def->nmems; i++) {
- align = qemuDomainGetMemoryModuleSizeAlignment(def, def->mems[i]);
- def->mems[i]->size = VIR_ROUND_UP(def->mems[i]->size, align);
+ if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM &&
+ ARCH_IS_PPC64(def->os.arch)) {
+ qemuDomainNVDimmAlignSizePseries(def, def->mems[i]);
+ } else {
+ align = qemuDomainGetMemoryModuleSizeAlignment(def, def->mems[i]);
+ def->mems[i]->size = VIR_ROUND_UP(def->mems[i]->size, align);
+ }
+
hotplugmem += def->mems[i]->size;
if (def->mems[i]->size > maxmemkb) {
@@ -12494,7 +12529,13 @@ void
qemuDomainMemoryDeviceAlignSize(virDomainDefPtr def,
virDomainMemoryDefPtr mem)
{
- mem->size = VIR_ROUND_UP(mem->size, qemuDomainGetMemorySizeAlignment(def));
+ if (mem->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM &&
+ ARCH_IS_PPC64(def->os.arch)) {
+ qemuDomainNVDimmAlignSizePseries(def, mem);
+ } else {
+ mem->size = VIR_ROUND_UP(mem->size,
+ qemuDomainGetMemorySizeAlignment(def));
+ }
}
diff --git a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-ppc64.args
b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-ppc64.args
new file mode 100644
index 0000000000..92e6c538fb
--- /dev/null
+++ b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-ppc64.args
@@ -0,0 +1,32 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-ppc64 \
+-name QEMUGuest1 \
+-S \
+-machine pseries,accel=tcg,usb=off,dump-guest-core=off,nvdimm=on \
+-m size=1048576k,slots=16,maxmem=1099511627776k \
+-realtime mlock=off \
+-smp 2,sockets=2,cores=1,threads=1 \
+-numa node,nodeid=0,cpus=0-1,mem=1024 \
+-object memory-backend-file,id=memnvdimm0,prealloc=yes,mem-path=/tmp/nvdimm,\
+size=537001984 \
+-device nvdimm,node=0,label-size=131072,\
+uuid=49545eb3-75e1-2d0a-acdd-f0294406c99e,memdev=memnvdimm0,id=nvdimm0,slot=0 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-usb \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2
diff --git a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-ppc64.xml
b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-ppc64.xml
index 59352d3c52..ae5a17d3c8 100644
--- a/tests/qemuxml2argvdata/memory-hotplug-nvdimm-ppc64.xml
+++ b/tests/qemuxml2argvdata/memory-hotplug-nvdimm-ppc64.xml
@@ -38,8 +38,11 @@
<path>/tmp/nvdimm</path>
</source>
<target>
- <size unit='KiB'>523264</size>
+ <size unit='KiB'>550000</size>
<node>0</node>
+ <label>
+ <size unit='KiB'>128</size>
+ </label>
</target>
<address type='dimm' slot='0'/>
</memory>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 35d413d40b..077f7e7650 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2790,6 +2790,10 @@ mymain(void)
DO_TEST_CAPS_LATEST("memory-hotplug-nvdimm-align");
DO_TEST_CAPS_LATEST("memory-hotplug-nvdimm-pmem");
DO_TEST_CAPS_LATEST("memory-hotplug-nvdimm-readonly");
+ DO_TEST("memory-hotplug-nvdimm-ppc64", QEMU_CAPS_KVM,
QEMU_CAPS_DEVICE_NVDIMM,
+ QEMU_CAPS_NUMA, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE,
+ QEMU_CAPS_OBJECT_MEMORY_RAM,
+ QEMU_CAPS_OBJECT_MEMORY_FILE);
DO_TEST("machine-aeskeywrap-on-caps",
QEMU_CAPS_AES_KEY_WRAP,
diff --git a/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64.xml
b/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64.xml
index 59352d3c52..ae5a17d3c8 100644
--- a/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64.xml
+++ b/tests/qemuxml2xmloutdata/memory-hotplug-nvdimm-ppc64.xml
@@ -38,8 +38,11 @@
<path>/tmp/nvdimm</path>
</source>
<target>
- <size unit='KiB'>523264</size>
+ <size unit='KiB'>550000</size>
<node>0</node>
+ <label>
+ <size unit='KiB'>128</size>
+ </label>
</target>
<address type='dimm' slot='0'/>
</memory>
--
2.24.1