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

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

On 04/17/2013 08:22 AM, Osier Yang wrote:
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.
Good - that means that RHEL 6 (and any other downstream distro that was already borrowing the RHEL extension) will not break when rebasing to pick up this change from upstream in place of their downstream extension (RHEL will actually want to add a followup patch on top of this that _also_ tries the older -redhat-disable-KSM downstream spelling of the option, but that's a problem for RHEL and not this list).
--- 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
Couple of problems:
+ <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.
Please add a "since" tag, mentioning that nosharepages was added in 1.0.5.
+++ b/docs/schemas/domaincommon.rng @@ -495,6 +495,11 @@ <empty/> </element> </optional> + <optional> + <element name="nosharepages"> + <empty/> + </element> + </optional>
Please add an <interleave> around the two optional sub-elements, so that users can specify them in either order (as written, RNG would reject <memoryBacking><nosharepages/><hugepages/></memoryBacking>).
@@ -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);
This would only scrape the existence of -mem-merge in qemu 1.2 and earlier, since we don't read -help in 1.3 and later. But qemu 1.2 doesn't have -mem-merge, so this bit will never get set. You need to instead populate the new capability based on a QMP probe, not string scraping. But I don't know offhand what that probe would be; you may need to ask on the qemu list. Looking forward to v2. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 17/04/13 22:54, Eric Blake wrote:
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. Good - that means that RHEL 6 (and any other downstream distro that was already borrowing the RHEL extension) will not break when rebasing to
On 04/17/2013 08:22 AM, Osier Yang wrote: pick up this change from upstream in place of their downstream extension (RHEL will actually want to add a followup patch on top of this that _also_ tries the older -redhat-disable-KSM downstream spelling of the option, but that's a problem for RHEL and not this list).
--- 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 Couple of problems:
+ <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. Please add a "since" tag, mentioning that nosharepages was added in 1.0.5.
+++ b/docs/schemas/domaincommon.rng @@ -495,6 +495,11 @@ <empty/> </element> </optional> + <optional> + <element name="nosharepages"> + <empty/> + </element> + </optional> Please add an <interleave> around the two optional sub-elements, so that users can specify them in either order (as written, RNG would reject <memoryBacking><nosharepages/><hugepages/></memoryBacking>).
@@ -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); This would only scrape the existence of -mem-merge in qemu 1.2 and earlier, since we don't read -help in 1.3 and later. But qemu 1.2 doesn't have -mem-merge, so this bit will never get set. You need to instead populate the new capability based on a QMP probe, not string scraping. But I don't know offhand what that probe would be; you may need to ask on the qemu list. hum, there is no way to query the qemu config schema via qmp yet...
https://www.redhat.com/archives/libvir-list/2013-January/msg01656.html The patch from Amos looks fine to me except: 1) I think either libvirt or qemu won't want the hmp command anymore, as long as a new command is introduced. 2) the name should be query-config-schema, as query-config sounds like we are trying to get the current config of the guest 3) If no option name is specified, it's good to output all the config schema qemu supports. I asked Amos to repost the patch, let's see if we can get the support soon. Osier

On 04/17/2013 08:54 AM, Eric Blake wrote:
On 04/17/2013 08:22 AM, Osier Yang wrote:
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.
Good - that means that RHEL 6 (and any other downstream distro that was already borrowing the RHEL extension) will not break when rebasing to pick up this change from upstream in place of their downstream extension (RHEL will actually want to add a followup patch on top of this that _also_ tries the older -redhat-disable-KSM downstream spelling of the option, but that's a problem for RHEL and not this list).
+ if (strstr(help, "-mem-merge")) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_MEM_MERGE);
This would only scrape the existence of -mem-merge in qemu 1.2 and earlier, since we don't read -help in 1.3 and later. But qemu 1.2 doesn't have -mem-merge, so this bit will never get set. You need to instead populate the new capability based on a QMP probe, not string scraping. But I don't know offhand what that probe would be; you may need to ask on the qemu list.
And we have a winner. We are getting query-command-line-options for qemu 1.5, and it looks easy enough that distros may be able to backport it into earlier qemu (again, I'll leave it up to Red Hat internal lists on whether it will be backported to RHEL). https://lists.gnu.org/archive/html/qemu-devel/2013-04/msg05040.html
Looking forward to v2.
Do you need help writing the src/qemu/qemu_monitor_json.c changes needed to utilize the new query-command-line-options QMP command, since I kind of spearheaded the design review on the qemu list? -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 25/04/13 22:14, Eric Blake wrote:
On 04/17/2013 08:54 AM, Eric Blake wrote:
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. Good - that means that RHEL 6 (and any other downstream distro that was already borrowing the RHEL extension) will not break when rebasing to
On 04/17/2013 08:22 AM, Osier Yang wrote: pick up this change from upstream in place of their downstream extension (RHEL will actually want to add a followup patch on top of this that _also_ tries the older -redhat-disable-KSM downstream spelling of the option, but that's a problem for RHEL and not this list).
+ if (strstr(help, "-mem-merge")) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_MEM_MERGE);
This would only scrape the existence of -mem-merge in qemu 1.2 and earlier, since we don't read -help in 1.3 and later. But qemu 1.2 doesn't have -mem-merge, so this bit will never get set. You need to instead populate the new capability based on a QMP probe, not string scraping. But I don't know offhand what that probe would be; you may need to ask on the qemu list. And we have a winner. We are getting query-command-line-options for qemu 1.5, and it looks easy enough that distros may be able to backport it into earlier qemu (again, I'll leave it up to Red Hat internal lists on whether it will be backported to RHEL).
https://lists.gnu.org/archive/html/qemu-devel/2013-04/msg05040.html
Looking forward to v2. Do you need help writing the src/qemu/qemu_monitor_json.c changes needed to utilize the new query-command-line-options QMP command, since I kind of spearheaded the design review on the qemu list?
I don't have much time before the beginning of May. Appreciated if you can do it. Or I can take it if it's delayed. :-) Regards, Osier
participants (2)
-
Eric Blake
-
Osier Yang