From c3e0320ddff500c851b8297fd37f8bfa660167bb Mon Sep 17 00:00:00 2001
From: Jaroslav Safka <jaroslavx.safka@intel.com>
Date: Tue, 21 Jun 2016 12:11:07 +0200
Subject: [PATCH] Add xml to argv for memorybacking access,source,..

Add conversion from xml to argv for subelements
source,access and allocation of <memoryBacking>

This change introduces support for preallocated
shared file descriptor based memory backing.
It allows vhost-user to be used without hugepages.

Configured by these elements:
<memoryBacking>
      <source type="file|anonymous"/>
      <access Mode="shared|private"/>
      <allocation mode="immediate|ondemand"/>
</memoryBacking>
---
 src/qemu/qemu_command.c                            | 56 ++++++++++++++++++++++
 src/qemu/qemu_command.h                            |  4 ++
 .../qemuxml2argv-memorybacking-set.args            |  6 ++-
 tests/qemuxml2argvtest.c                           |  3 ++
 4 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 4a8def1..11c270d 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -9327,6 +9327,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
     if (qemuBuildNVRAMCommandLine(cmd, def, qemuCaps) < 0)
         goto error;
 
+    if (qemuBuildMemoryBackendCommandLine(cmd, def, qemuCaps) < 0)
+        goto error;
+
     if (snapshot)
         virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
@@ -9591,3 +9594,56 @@ qemuBuildChrDeviceStr(char **deviceStr,
 
     return ret;
 }
+
+static char *
+qemuBuildMemoryBackendFileStr(const virDomainDef *def)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    const char template[] = "memory-backend-file,id=mem,size=1024M,mem-path=/var/lib/libvirt/qemu";
+
+    if (VIR_DOMAIN_MEMORY_ACCESS_SHARED == def->mem.access) {
+        // add ",share=on" to -object memory-backend-file
+        virBufferAsprintf(&buf, "%s,share=on", template);
+    } else {
+        virBufferAsprintf(&buf, "%s", template);
+    }
+
+
+    if (virBufferCheckError(&buf) < 0)
+        goto error;
+
+    return virBufferContentAndReset(&buf);
+
+ error:
+    virBufferFreeAndReset(&buf);
+    return NULL;
+}
+
+
+int
+qemuBuildMemoryBackendCommandLine(virCommandPtr cmd,
+                          const virDomainDef *def,
+                          virQEMUCapsPtr qemuCaps __attribute__((unused)))
+{
+    char *optstr = NULL;
+
+    if (VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE == def->mem.allocation) {
+        // add '-mem-prealloc'
+        virCommandAddArg(cmd, "-mem-prealloc");
+    }
+
+    if (VIR_DOMAIN_MEMORY_SOURCE_FILE == def->mem.source) {
+        optstr = qemuBuildMemoryBackendFileStr(def);
+        if (optstr) {
+            virCommandAddArg(cmd, "-object");
+            virCommandAddArg(cmd, optstr);
+            VIR_FREE(optstr);
+        }
+
+        // add '-object memory-backend-file,id=mem,size=1024M,mem-path=/var/lib/libvirt/qemu'
+        // add '-numa node,memdev=mem'
+        virCommandAddArgList(cmd, "-numa", "node,memdev=mem", NULL);
+    }
+
+    return 0;
+}
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 9ff4edb..f95d0ea 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -175,5 +175,9 @@ bool qemuCheckCCWS390AddressSupport(const virDomainDef *def,
                                     virDomainDeviceInfo info,
                                     virQEMUCapsPtr qemuCaps,
                                     const char *devicename);
+int
+qemuBuildMemoryBackendCommandLine(virCommandPtr cmd,
+                          const virDomainDef *def,
+                          virQEMUCapsPtr qemuCaps);
 
 #endif /* __QEMU_COMMAND_H__*/
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.args b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.args
index bb702dc..626fb21 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-memorybacking-set.args
@@ -19,4 +19,8 @@ QEMU_AUDIO_DRV=none \
 -usb \
 -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
 -device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
--device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 \
+-mem-prealloc \
+-object memory-backend-file,id=mem,size=1024M,mem-path=/var/lib/libvirt/qemu,\
+share=on \
+-numa node,memdev=mem
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index c406b64..d381f2d 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2016,6 +2016,9 @@ mymain(void)
 
     DO_TEST("acpi-table", NONE);
 
+    DO_TEST("memorybacking-unset", NONE);
+    DO_TEST("memorybacking-set", NONE);
+
     qemuTestDriverFree(&driver);
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-- 
2.9.0

