diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 0f5d833521..06d16b2c23 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -7792,6 +7792,18 @@ Example: usage of the memory devices
524288
+
+
+ 1-3
+ 2048
+
+
+ 2097152
+ 0
+ 2048
+ 1048576
+
+
...
@@ -7799,7 +7811,8 @@ Example: usage of the memory devices
Provide ``dimm`` to add a virtual DIMM module to the guest. :since:`Since
1.2.14` Provide ``nvdimm`` model that adds a Non-Volatile DIMM module.
:since:`Since 3.2.0` Provide ``virtio-pmem`` model to add a paravirtualized
- persistent memory device. :since:`Since 7.1.0`
+ persistent memory device. :since:`Since 7.1.0` Provide ``virtio-mem`` model
+ to add paravirtualized memory device. :since:`Since 7.9.0`
``access``
An optional attribute ``access`` ( :since:`since 3.2.0` ) that provides
@@ -7822,10 +7835,11 @@ Example: usage of the memory devices
allowed only for ``model='nvdimm'`` for pSeries guests. :since:`Since 6.2.0`
``source``
- For model ``dimm`` this element is optional and allows to fine tune the
- source of the memory used for the given memory device. If the element is not
- provided defaults configured via ``numatune`` are used. If ``dimm`` is
- provided, then the following optional elements can be provided as well:
+ For model ``dimm`` and model ``virtio-mem`` this element is optional and
+ allows to fine tune the source of the memory used for the given memory
+ device. If the element is not provided defaults configured via ``numatune``
+ are used. If the element is provided, then the following optional elements
+ can be provided:
``pagesize``
This element can be used to override the default host page size used for
@@ -7864,7 +7878,8 @@ Example: usage of the memory devices
added memory from the perspective of the guest.
The mandatory ``size`` subelement configures the size of the added memory as
- a scaled integer.
+ a scaled integer. For ``virtio-mem`` this represents the maximum possible
+ size exposed to the guest.
The ``node`` subelement configures the guest NUMA node to attach the memory
to. The element shall be used only if the guest has NUMA nodes configured.
@@ -7891,6 +7906,17 @@ Example: usage of the memory devices
so other backend types should use the ``readonly`` element. :since:`Since
5.0.0`
+ ``block``
+ For ``virtio-mem`` only.
+ The size of an individual block, granularity of division of memory block.
+ Must be power of two and at least equal to size of a transparent hugepage
+ (2MiB on x84_64). The default is hypervisor dependent.
+
+ ``requested``
+ For ``virtio-mem`` only.
+ The total size exposed to the guest. Must respect ``block`` granularity
+ and be smaller than or equal to ``size``.
+
:anchor:``
IOMMU devices
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index fdc04f90aa..9e7d74d43e 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -6600,6 +6600,7 @@
dimmnvdimmvirtio-pmem
+ virtio-mem
@@ -6687,6 +6688,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f7025bffe4..4cbcf69bf0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1392,6 +1392,7 @@ VIR_ENUM_IMPL(virDomainMemoryModel,
"dimm",
"nvdimm",
"virtio-pmem",
+ "virtio-mem",
);
VIR_ENUM_IMPL(virDomainShmemModel,
@@ -5494,6 +5495,7 @@ virDomainMemoryDefPostParse(virDomainMemoryDef *mem,
}
break;
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
@@ -14653,6 +14655,7 @@ virDomainMemorySourceDefParseXML(xmlNodePtr node,
switch (def->model) {
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
if (virDomainParseMemory("./pagesize", "./pagesize/@unit", ctxt,
&def->pagesize, false, false) < 0)
return -1;
@@ -14719,7 +14722,8 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node,
&def->size, true, false) < 0)
return -1;
- if (def->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM) {
+ switch (def->model) {
+ case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
if (virDomainParseMemory("./label/size", "./label/size/@unit", ctxt,
&def->labelsize, false, false) < 0)
return -1;
@@ -14738,6 +14742,23 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node,
if (virXPathBoolean("boolean(./readonly)", ctxt))
def->readonly = true;
+ break;
+
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
+ if (virDomainParseMemory("./block", "./block/@unit", ctxt,
+ &def->blocksize, false, false) < 0)
+ return -1;
+
+ if (virDomainParseMemory("./requested", "./requested/@unit", ctxt,
+ &def->requestedsize, false, false) < 0)
+ return -1;
+ break;
+
+ case VIR_DOMAIN_MEMORY_MODEL_NONE:
+ case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
+ case VIR_DOMAIN_MEMORY_MODEL_LAST:
+ break;
}
return 0;
@@ -16494,11 +16515,14 @@ virDomainMemoryFindByDefInternal(virDomainDef *def,
/* target info -> always present */
if (tmp->model != mem->model ||
tmp->targetNode != mem->targetNode ||
- tmp->size != mem->size)
+ tmp->size != mem->size ||
+ tmp->blocksize != mem->blocksize ||
+ tmp->requestedsize != mem->requestedsize)
continue;
switch (mem->model) {
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
/* source stuff -> match with device */
if (tmp->pagesize != mem->pagesize)
continue;
@@ -21888,6 +21912,22 @@ virDomainMemoryDefCheckABIStability(virDomainMemoryDef *src,
return false;
}
+ if (src->blocksize != dst->blocksize) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target memory device block size '%llu' doesn't match "
+ "source memory device block size '%llu'"),
+ dst->blocksize, src->blocksize);
+ return false;
+ }
+
+ if (src->requestedsize != dst->requestedsize) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target memory device requested size '%llu' doesn't match "
+ "source memory device requested size '%llu'"),
+ dst->requestedsize, src->requestedsize);
+ return false;
+ }
+
if (src->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM) {
if (src->labelsize != dst->labelsize) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -25796,6 +25836,7 @@ virDomainMemorySourceDefFormat(virBuffer *buf,
switch (def->model) {
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
if (def->sourceNodes) {
if (!(bitmap = virBitmapFormat(def->sourceNodes)))
return -1;
@@ -25852,6 +25893,14 @@ virDomainMemoryTargetDefFormat(virBuffer *buf,
if (def->readonly)
virBufferAddLit(&childBuf, "\n");
+ if (def->blocksize) {
+ virBufferAsprintf(&childBuf, "%llu\n",
+ def->blocksize);
+
+ virBufferAsprintf(&childBuf, "%llu\n",
+ def->requestedsize);
+ }
+
virXMLFormatElement(buf, "target", NULL, &childBuf);
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 688a842660..8356d38dcb 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2473,6 +2473,7 @@ typedef enum {
VIR_DOMAIN_MEMORY_MODEL_DIMM, /* dimm hotpluggable memory device */
VIR_DOMAIN_MEMORY_MODEL_NVDIMM, /* nvdimm memory device */
VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM, /* virtio-pmem memory device */
+ VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM, /* virtio-mem memory device */
VIR_DOMAIN_MEMORY_MODEL_LAST
} virDomainMemoryModel;
@@ -2493,6 +2494,8 @@ struct _virDomainMemoryDef {
int targetNode;
unsigned long long size; /* kibibytes */
unsigned long long labelsize; /* kibibytes; valid only for NVDIMM */
+ unsigned long long blocksize; /* kibibytes; valid only for VIRTIO_MEM */
+ unsigned long long requestedsize; /* kibibytes; valid only for VIRTIO_MEM */
bool readonly; /* valid only for NVDIMM */
/* required for QEMU NVDIMM ppc64 support */
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 1bc62c364d..f023d22f23 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -28,6 +28,7 @@
#include "virlog.h"
#include "virutil.h"
#include "virstring.h"
+#include "virhostmem.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN
@@ -1966,6 +1967,8 @@ static int
virDomainMemoryDefValidate(const virDomainMemoryDef *mem,
const virDomainDef *def)
{
+ unsigned long long thpSize;
+
switch (mem->model) {
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
if (!mem->nvdimmPath) {
@@ -2019,6 +2022,42 @@ virDomainMemoryDefValidate(const virDomainMemoryDef *mem,
_("virtio-pmem does not support NUMA nodes"));
return -1;
}
+ break;
+
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
+ if (mem->requestedsize > mem->size) {
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
+ _("requested size must be smaller than or equal to @size"));
+ return -1;
+ }
+
+ if (!VIR_IS_POW2(mem->blocksize)) {
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
+ _("block size must be a power of two"));
+ return -1;
+ }
+
+ if (virHostMemGetTHPSize(&thpSize) < 0) {
+ /* We failed to get THP size, fall back to a sane default. On
+ * almost every architecture the size will be 2MiB, except for some
+ * funky arches like sparc and m68k. Use 2MiB and refine later if
+ * somebody complains. */
+ thpSize = 2048;
+ }
+
+ if (mem->blocksize < thpSize) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("block size too small, must be at least %lluKiB"),
+ thpSize);
+ return -1;
+ }
+
+ if (mem->requestedsize % mem->blocksize != 0) {
+ virReportError(VIR_ERR_XML_DETAIL, "%s",
+ _("requested size must be an integer multiple of block size"));
+ return -1;
+ }
+ break;
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
break;
diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c
index ed47fa335a..79e8953b2f 100644
--- a/src/qemu/qemu_alias.c
+++ b/src/qemu/qemu_alias.c
@@ -522,6 +522,7 @@ qemuAssignDeviceMemoryAlias(virDomainDef *def,
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
prefix = "virtiopmem";
break;
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
default:
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 402ff44213..0814e713f7 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3209,6 +3209,7 @@ qemuBuildMemoryDeviceStr(const virDomainDef *def,
device = "virtio-pmem-pci";
break;
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
default:
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 584bf5003f..9197090639 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -8875,6 +8875,16 @@ qemuDomainDefValidateMemoryHotplugDevice(const virDomainMemoryDef *mem,
needsNuma = false;
break;
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
+ if (mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
+ mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("only 'pci' addresses are supported for the %s device"),
+ virDomainMemoryModelTypeToString(mem->model));
+ return -1;
+ }
+ break;
+
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
return -1;
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 392368bd38..c43ad23cf5 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -380,9 +380,18 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDef *def,
}
for (i = 0; i < def->nmems; i++) {
- if (def->mems[i]->model == VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM &&
- def->mems[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
- def->mems[i]->info.type = type;
+ switch (def->mems[i]->model) {
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
+ if (def->mems[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ def->mems[i]->info.type = type;
+ break;
+ case VIR_DOMAIN_MEMORY_MODEL_NONE:
+ case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_LAST:
+ break;
+ }
}
if (type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
@@ -1010,6 +1019,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev,
case VIR_DOMAIN_DEVICE_MEMORY:
switch (dev->data.memory->model) {
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
return virtioFlags;
case VIR_DOMAIN_MEMORY_MODEL_NONE:
@@ -2370,12 +2380,19 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def,
for (i = 0; i < def->nmems; i++) {
virDomainMemoryDef *mem = def->mems[i];
- if (mem->model != VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM ||
- !virDeviceInfoPCIAddressIsWanted(&mem->info))
- continue;
-
- if (qemuDomainPCIAddressReserveNextAddr(addrs, &mem->info) < 0)
- return -1;
+ switch (mem->model) {
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
+ if (virDeviceInfoPCIAddressIsWanted(&mem->info) &&
+ qemuDomainPCIAddressReserveNextAddr(addrs, &mem->info) < 0)
+ return -1;
+ break;
+ case VIR_DOMAIN_MEMORY_MODEL_NONE:
+ case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_LAST:
+ break;
+ }
}
return 0;
@@ -3034,6 +3051,7 @@ qemuDomainAssignMemoryDeviceSlot(virQEMUDriver *driver,
break;
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
return qemuDomainEnsurePCIAddress(vm, &dev, driver);
break;
@@ -3059,6 +3077,7 @@ qemuDomainReleaseMemoryDeviceSlot(virDomainObj *vm,
break;
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
qemuDomainReleaseDeviceAddress(vm, &mem->info);
break;
@@ -3093,6 +3112,7 @@ qemuDomainAssignMemorySlots(virDomainDef *def)
break;
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
/* handled in qemuDomainAssignPCIAddresses() */
break;
case VIR_DOMAIN_MEMORY_MODEL_NONE:
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index fcdda4ffe1..ca53335d5d 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3791,6 +3791,7 @@ qemuProcessDomainMemoryDefNeedHugepagesPath(const virDomainMemoryDef *mem,
{
switch (mem->model) {
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
return mem->pagesize && mem->pagesize != system_pagesize;
case VIR_DOMAIN_MEMORY_MODEL_NONE:
@@ -3859,6 +3860,7 @@ qemuProcessNeedMemoryBackingPath(virDomainDef *def,
if (mem) {
switch (mem->model) {
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
if (mem->access != VIR_DOMAIN_MEMORY_ACCESS_DEFAULT) {
/* No need to check for access mode on the target node,
* it was checked for in the previous loop. */
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 294cc24b36..001f68b083 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -4932,6 +4932,14 @@ qemuValidateDomainDeviceDefMemory(virDomainMemoryDef *mem,
}
break;
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("virtio-mem isn't supported by this QEMU binary"));
+ return -1;
+ }
+ break;
+
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
break;
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index d942ea5005..2cc15ba6af 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -693,6 +693,7 @@ AppArmorSetMemoryLabel(virSecurityManager *mgr,
return reload_profile(mgr, def, mem->nvdimmPath, true);
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
break;
}
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 04b9ecf028..1733d63410 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1849,6 +1849,7 @@ virSecurityDACRestoreMemoryLabel(virSecurityManager *mgr,
break;
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
case VIR_DOMAIN_MEMORY_MODEL_NONE:
ret = 0;
@@ -2033,6 +2034,7 @@ virSecurityDACSetMemoryLabel(virSecurityManager *mgr,
break;
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
case VIR_DOMAIN_MEMORY_MODEL_NONE:
ret = 0;
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 0e5ea0366d..cc72453329 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -1582,6 +1582,7 @@ virSecuritySELinuxSetMemoryLabel(virSecurityManager *mgr,
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
break;
}
@@ -1609,6 +1610,7 @@ virSecuritySELinuxRestoreMemoryLabel(virSecurityManager *mgr,
break;
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
case VIR_DOMAIN_MEMORY_MODEL_NONE:
case VIR_DOMAIN_MEMORY_MODEL_LAST:
ret = 0;
diff --git a/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml
new file mode 100644
index 0000000000..c10528aad8
--- /dev/null
+++ b/tests/qemuxml2argvdata/memory-hotplug-virtio-mem.xml
@@ -0,0 +1,67 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 1099511627776
+ 8388608
+ 8388608
+ 2
+
+ hvm
+
+
+
+ qemu64
+
+
+
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-i386
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1048576
+ 0
+ 2048
+ 524288
+
+
+
+
+
+ 1-3
+ 2048
+
+
+ 2097152
+ 0
+ 2048
+ 1048576
+
+
+
+
+
diff --git a/tests/qemuxml2xmloutdata/memory-hotplug-virtio-mem.x86_64-latest.xml b/tests/qemuxml2xmloutdata/memory-hotplug-virtio-mem.x86_64-latest.xml
new file mode 120000
index 0000000000..a9d298129c
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/memory-hotplug-virtio-mem.x86_64-latest.xml
@@ -0,0 +1 @@
+../qemuxml2argvdata/memory-hotplug-virtio-mem.xml
\ No newline at end of file
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 49b291fadb..84d6bed6b1 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1213,6 +1213,7 @@ mymain(void)
QEMU_CAPS_DEVICE_NVDIMM,
QEMU_CAPS_LAST, ARG_END);
DO_TEST_CAPS_LATEST("memory-hotplug-virtio-pmem");
+ DO_TEST_CAPS_LATEST("memory-hotplug-virtio-mem");
DO_TEST_NOCAPS("net-udp");