[libvirt] [PATCH] qemu: New XML to disable memory merge at guest startup

Osier Yang jyang at redhat.com
Wed Apr 17 14:22:00 UTC 2013


QEMU introduced command line "-mem-merge=on|off" (defaults to on) to
enable/disable the memory merge (KSM) at guest startup. This exposes
it by new XML:
  <memoryBacking>
    <nosharepages/>
  </memoryBacking>

The XML tag is same with what we used internally for old RHEL.
---
 docs/formatdomain.html.in                          | 13 +++++++---
 docs/schemas/domaincommon.rng                      |  5 ++++
 src/conf/domain_conf.c                             | 20 ++++++++++-----
 src/conf/domain_conf.h                             |  1 +
 src/qemu/qemu_capabilities.c                       |  4 +++
 src/qemu/qemu_capabilities.h                       |  1 +
 src/qemu/qemu_command.c                            | 11 ++++++++
 .../qemuxml2argv-nosharepages.args                 |  4 +++
 .../qemuxml2argvdata/qemuxml2argv-nosharepages.xml | 29 ++++++++++++++++++++++
 tests/qemuxml2argvtest.c                           |  1 +
 tests/qemuxml2xmltest.c                            |  1 +
 11 files changed, 80 insertions(+), 10 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-nosharepages.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-nosharepages.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 0cc56d9..4350610 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -558,6 +558,7 @@
   ...
   <memoryBacking>
     <hugepages/>
+    <nosharepages/>
   </memoryBacking>
   ...
 </domain>
@@ -565,10 +566,14 @@
 
     <dl>
       <dt><code>memoryBacking</code></dt>
-      <dd>The optional <code>memoryBacking</code> element, may have an
-        <code>hugepages</code> element set within it. This tells the
-        hypervisor that the guest should have its memory allocated using
-        hugepages instead of the normal native page size.</dd>
+      <dd>The optional <code>memoryBacking</code> element has two
+        optional elements. The element <code>hugepages</code> tells
+        the hypervisor that the guest should have its memory allocated
+        using hugepages instead of the normal native page size. And the
+        optional element <code>nosharepages</code> tells the hypervisor
+        that share pages (memory merge, KSM) should be disabled on guest
+        startup.
+      </dd>
     </dl>
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 468c49c..a1e25ca 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -495,6 +495,11 @@
               <empty/>
             </element>
           </optional>
+          <optional>
+            <element name="nosharepages">
+              <empty/>
+            </element>
+          </optional>
         </element>
       </optional>
 
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 548368e..231cc41 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10018,6 +10018,9 @@ virDomainDefParseXML(xmlDocPtr xml,
     if ((node = virXPathNode("./memoryBacking/hugepages", ctxt)))
         def->mem.hugepage_backed = true;
 
+    if ((node = virXPathNode("./memoryBacking/nosharepages", ctxt)))
+        def->mem.nosharepages = true;
+
     /* Extract blkio cgroup tunables */
     if (virXPathUInt("string(./blkiotune/weight)", ctxt,
                      &def->blkio.weight) < 0)
@@ -15263,12 +15266,17 @@ virDomainDefFormatInternal(virDomainDefPtr def,
         def->mem.swap_hard_limit)
         virBufferAddLit(buf, "  </memtune>\n");
 
-    if (def->mem.hugepage_backed) {
-        virBufferStrcat(buf,
-                        "  <memoryBacking>\n",
-                        "    <hugepages/>\n",
-                        "  </memoryBacking>\n", NULL);
-    }
+    if (def->mem.hugepage_backed || def->mem.nosharepages)
+        virBufferAddLit(buf, "  <memoryBacking>\n");
+
+    if (def->mem.hugepage_backed)
+        virBufferAddLit(buf, "    <hugepages/>\n");
+
+    if (def->mem.nosharepages)
+        virBufferAddLit(buf, "    <nosharepages/>\n");
+
+    if (def->mem.hugepage_backed || def->mem.nosharepages)
+        virBufferAddLit(buf, "  </memoryBacking>\n");
 
     virBufferAddLit(buf, "  <vcpu");
     virBufferAsprintf(buf, " placement='%s'",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f1f01fa..0ba72d5 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1811,6 +1811,7 @@ struct _virDomainDef {
         unsigned long long max_balloon; /* in kibibytes */
         unsigned long long cur_balloon; /* in kibibytes */
         bool hugepage_backed;
+        bool nosharepages;
         int dump_core; /* enum virDomainMemDump */
         unsigned long long hard_limit; /* in kibibytes */
         unsigned long long soft_limit; /* in kibibytes */
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index d10c8aa..e5d89f9 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -220,6 +220,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
               "machine-usb-opt",
               "tpm-passthrough",
               "tpm-tis",
+              "mem-merge",
     );
 
 struct _virQEMUCaps {
@@ -1082,6 +1083,9 @@ virQEMUCapsComputeCmdFlags(const char *help,
     if (strstr(help, "-machine"))
         virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_OPT);
 
+    if (strstr(help, "-mem-merge"))
+        virQEMUCapsSet(qemuCaps, QEMU_CAPS_MEM_MERGE);
+
      /* USB option is supported v1.3.0 onwards */
     if (qemuCaps->version >= 1003000)
         virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_USB_OPT);
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 4e76799..55ffd35 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -178,6 +178,7 @@ enum virQEMUCapsFlags {
     QEMU_CAPS_MACHINE_USB_OPT    = 137, /* -machine xxx,usb=on/off */
     QEMU_CAPS_DEVICE_TPM_PASSTHROUGH = 138, /* -tpmdev passthrough */
     QEMU_CAPS_DEVICE_TPM_TIS     = 139, /* -device tpm_tis */
+    QEMU_CAPS_MEM_MERGE          = 140, /* Is -mem-merge available? */
 
     QEMU_CAPS_LAST,                   /* this must always be the last item */
 };
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 009d42d..bb0ccff 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5993,6 +5993,17 @@ qemuBuildCommandLine(virConnectPtr conn,
     virCommandAddArg(cmd, smp);
     VIR_FREE(smp);
 
+    if (def->mem.nosharepages) {
+        if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_MEM_MERGE)) {
+            virCommandAddArg(cmd, "-mem-merge=off");
+        } else {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("the QEMU binary %s does not support to "
+                             "disable shared memory"), emulator);
+            goto error;
+        }
+    }
+
     if (def->cpu && def->cpu->ncells)
         if (qemuBuildNumaArgStr(def, cmd) < 0)
             goto error;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.args b/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.args
new file mode 100644
index 0000000..f9ef1c1
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.args
@@ -0,0 +1,4 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
+-S -M pc -m 215 -smp 1 -mem-merge=off -nographic \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi \
+-boot c -usb -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.xml b/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.xml
new file mode 100644
index 0000000..57701a0
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-nosharepages.xml
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219200</memory>
+  <currentMemory unit='KiB'>219200</currentMemory>
+  <memoryBacking>
+    <nosharepages/>
+  </memoryBacking>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <controller type='usb' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 4bf13f0..48aa07e 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -433,6 +433,7 @@ mymain(void)
     DO_TEST("hyperv", NONE);
 
     DO_TEST("hugepages", QEMU_CAPS_MEM_PATH);
+    DO_TEST("nosharepages", QEMU_CAPS_MEM_MERGE);
     DO_TEST("disk-cdrom", NONE);
     DO_TEST("disk-cdrom-empty", QEMU_CAPS_DRIVE);
     DO_TEST("disk-cdrom-tray",
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 7434190..c16f866 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -157,6 +157,7 @@ mymain(void)
     DO_TEST("hyperv");
 
     DO_TEST("hugepages");
+    DO_TEST("nosharepages");
     DO_TEST("disk-aio");
     DO_TEST("disk-cdrom");
     DO_TEST("disk-floppy");
-- 
1.8.1.4




More information about the libvir-list mailing list