[libvirt] [PATCH 2/4] conf, schema, docs: Add support for TSEG size setting
Laszlo Ersek
lersek at redhat.com
Thu Jun 7 18:40:37 UTC 2018
On 06/07/18 10:37, Martin Kletzander wrote:
> TSEG (Top of Memory Segment) is one of many regions that SMM (System Management
> Mode) can occupy. This one, however is special, because a) most of the SMM code
> lives in TSEG nowadays and b) QEMU just (well, some time ago) added support for
> so called 'extended' TSEG. The difference to the TSEG implemented in real q35's
> MCH (Memory Controller Hub) is that it can offer one extra size to the guest OS
> apart from the standard TSEG's 1, 2, and 8 MiB and that size can be selected in
> 1 MiB increments. Maximum may vary based on QEMU and is way too big, so we
> don't need to check for the maximum here. Similarly to the memory size we'll
> leave it to the hypervisor to try satisfying that and giving us an error message
> in case it is not possible.
>
> Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
> ---
> docs/formatdomain.html.in | 48 +++++++++++++++++++++-
> docs/schemas/domaincommon.rng | 5 +++
> src/conf/domain_conf.c | 64 ++++++++++++++++++++++++++++-
> src/conf/domain_conf.h | 3 ++
> tests/genericxml2xmlindata/tseg.xml | 23 +++++++++++
> tests/genericxml2xmltest.c | 2 +
> 6 files changed, 143 insertions(+), 2 deletions(-)
> create mode 100644 tests/genericxml2xmlindata/tseg.xml
>
> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index ba5bd1e5027e..2d1e1a7051d9 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -1924,6 +1924,9 @@
> <ioapic driver='qemu'/>
> <hpt resizing='required'/>
> <vmcoreinfo state='on'/>
> + <smm state='on'>
> + <tseg unit='MiB'>48</tseg>
> + </smm>
> </features>
> ...</pre>
>
> @@ -2079,10 +2082,53 @@
> <span class="since">Since 1.2.16</span>
> </dd>
> <dt><code>smm</code></dt>
> - <dd>Depending on the <code>state</code> attribute (values <code>on</code>,
> + <dd>
> + <p>
> + Depending on the <code>state</code> attribute (values <code>on</code>,
> <code>off</code>, default <code>on</code>) enable or disable
> System Management Mode.
> <span class="since">Since 2.1.0</span>
> + </p><p> Optional sub-element <code>tseg</code> can be used to specify
> + the amount of memory dedicated to SMM's extended TSEG. That offers a
> + fourth option size apart from the existing ones (1 MiB, 2 MiB and 8
> + MiB) that the guest OS (or rather loader) can choose from. The size
> + can be specified as a value of that element, optional attribute
> + <code>unit</code> can be used to specify the unit of the
> + aforementioned value (defaults to 'MiB').
> + </p><p>
> + <b>If the VM is booting you should leave this option alone, unless you
> + are very certain you know what you are doing.</b>
> + </p><p>
> + This value is configurable due to the fact that the calculation cannot
> + be done right with the guarantee that it will work correctly. In
> + QEMU, the user-configurable extended TSEG feature was unavailable up
> + to and including <code>pc-q35-2.9</code>. Starting with
> + <code>pc-q35-2.10</code> the feature is available, with default size
> + 16 MiB. That should suffice for up to roughly 272 VCPUs, 5 GiB guest
> + RAM in total, no hotplug memory range, and 32 GiB of 64-bit PCI MMIO
> + aperture. Or for 48 VCPUs, with 1TB of guest RAM, no hotplug DIMM
> + range, and 32GB of 64-bit PCI MMIO aperture. The values may also vary
> + based on the loader the VM is using.
> + </p><p>
> + Additional size might be needed for significantly higher VCPU counts
> + or increased address space (that can be memory, maxMemory, 64-bit PCI
> + MMIO aperture size; roughly 8 MiB of TSEG per 1 TiB of address space)
> + which can also be rounded up.
> + </p><p>
> + Due to the nature of this setting being similar to "how much RAM
> + should the guest have" users are advised to either consult the
> + documentation of the guest OS or loader (if there is any), or test
> + this by trial-and-error changing the value until the VM boots
> + successfully. Yet another guiding value for users might be the fact
> + that 48 MiB should be enough for pretty large guests (240 VCPUs and
> + 4TB guest RAM), but it is on purpose not set as default as 48 MiB of
> + unavailable RAM might be too much for small guests (e.g. with 512 MiB
> + of RAM).
> + </p><p>
> + See <a href="#elementsMemoryAllocation">Memory Allocation</a>
> + for more details about the <code>unit</code> attribute.
> + <span class="since">Since 4.5.0</span> (QEMU only)
> + </p>
> </dd>
> <dt><code>ioapic</code></dt>
> <dd>Tune the I/O APIC. Possible values for the
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index c5c8c575b8cd..550fb10159e5 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -4846,6 +4846,11 @@
> <attribute name="state">
> <ref name="virOnOff"/>
> </attribute>
> + <optional>
> + <element name="tseg">
> + <ref name="scaledInteger"/>
> + </element>
> + </optional>
> </optional>
> </element>
> </optional>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 5be773cda48a..62bf6bb803bb 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -19898,6 +19898,19 @@ virDomainDefParseXML(xmlDocPtr xml,
> VIR_FREE(nodes);
> }
>
> + if (def->features[VIR_DOMAIN_FEATURE_SMM] == VIR_TRISTATE_SWITCH_ON) {
> + int rv = virDomainParseScaledValue("string(./features/smm/tseg)",
> + "string(./features/smm/tseg/@unit)",
> + ctxt,
> + &def->tseg_size,
> + 1024 * 1024, /* Defaults to mebibytes */
> + ULLONG_MAX,
> + false);
> + if (rv < 0)
> + goto error;
> + def->tseg_specified = rv;
> + }
> +
> if ((n = virXPathNodeSet("./features/capabilities/*", ctxt, &nodes)) < 0)
> goto error;
>
> @@ -22020,6 +22033,32 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src,
> }
> }
>
> + /* smm */
> + if (src->features[VIR_DOMAIN_FEATURE_SMM] == VIR_TRISTATE_SWITCH_ON) {
> + if (src->tseg_specified != dst->tseg_specified) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> + _("SMM TSEG differs: source: %s, destination: '%s'"),
> + src->tseg_specified ? _("specified") : _("not specified"),
> + dst->tseg_specified ? _("specified") : _("not specified"));
> + return false;
> + }
> +
> + if (src->tseg_size != dst->tseg_size) {
> + const char *unit_src, *unit_dst;
> + unsigned long long short_size_src = virFormatIntPretty(src->tseg_size,
> + &unit_src);
> + unsigned long long short_size_dst = virFormatIntPretty(dst->tseg_size,
> + &unit_dst);
> +
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> + _("Size of SMM TSEG size differs: "
> + "source: '%llu %s', destination: '%llu %s'"),
> + short_size_src, unit_src,
> + short_size_dst, unit_dst);
> + return false;
> + }
> + }
> +
> return true;
> }
>
> @@ -27446,7 +27485,6 @@ virDomainDefFormatInternal(virDomainDefPtr def,
> case VIR_DOMAIN_FEATURE_PMU:
> case VIR_DOMAIN_FEATURE_PVSPINLOCK:
> case VIR_DOMAIN_FEATURE_VMPORT:
> - case VIR_DOMAIN_FEATURE_SMM:
> switch ((virTristateSwitch) def->features[i]) {
> case VIR_TRISTATE_SWITCH_LAST:
> case VIR_TRISTATE_SWITCH_ABSENT:
> @@ -27463,6 +27501,30 @@ virDomainDefFormatInternal(virDomainDefPtr def,
>
> break;
>
> + case VIR_DOMAIN_FEATURE_SMM:
> + if (def->features[i] != VIR_TRISTATE_SWITCH_ABSENT) {
> + virTristateSwitch state = def->features[i];
> + virBuffer attrBuf = VIR_BUFFER_INITIALIZER;
> + virBuffer childBuf = VIR_BUFFER_INITIALIZER;
> +
> + virBufferAsprintf(&attrBuf, " state='%s'",
> + virTristateSwitchTypeToString(state));
> +
> + if (state == VIR_TRISTATE_SWITCH_ON) {
> + const char *unit;
> + unsigned long long short_size = virFormatIntPretty(def->tseg_size,
> + &unit);
> +
> + virBufferSetChildIndent(&childBuf, buf);
> + virBufferAsprintf(&childBuf, "<tseg unit='%s'>%llu</tseg>\n",
> + unit, short_size);
> + }
> +
> + virXMLFormatElement(buf, "smm", &attrBuf, &childBuf);
> + }
> +
> + break;
> +
> case VIR_DOMAIN_FEATURE_APIC:
> if (def->features[i] == VIR_TRISTATE_SWITCH_ON) {
> virBufferAddLit(buf, "<apic");
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 8a8121bf83b2..a41cdce6ff63 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -2421,6 +2421,9 @@ struct _virDomainDef {
> char *hyperv_vendor_id;
> int apic_eoi;
>
> + bool tseg_specified;
> + unsigned long long tseg_size;
> +
> virDomainClockDef clock;
>
> size_t ngraphics;
> diff --git a/tests/genericxml2xmlindata/tseg.xml b/tests/genericxml2xmlindata/tseg.xml
> new file mode 100644
> index 000000000000..49483f874cd4
> --- /dev/null
> +++ b/tests/genericxml2xmlindata/tseg.xml
> @@ -0,0 +1,23 @@
> +<domain type='qemu'>
> + <name>QEMUGuest1</name>
> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
> + <memory unit='KiB'>219100</memory>
> + <currentMemory unit='KiB'>219100</currentMemory>
> + <vcpu placement='static'>1</vcpu>
> + <os>
> + <type arch='x86_64' machine='q35'>hvm</type>
> + <boot dev='hd'/>
> + </os>
> + <features>
> + <smm state='on'>
> + <tseg unit='MiB'>48</tseg>
> + </smm>
> + </features>
> + <clock offset='utc'/>
> + <on_poweroff>destroy</on_poweroff>
> + <on_reboot>restart</on_reboot>
> + <on_crash>destroy</on_crash>
> + <devices>
> + <emulator>/usr/bin/qemu-system-x86_64</emulator>
> + </devices>
> +</domain>
> diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
> index d8270a6cae82..daad6e0f78d8 100644
> --- a/tests/genericxml2xmltest.c
> +++ b/tests/genericxml2xmltest.c
> @@ -141,6 +141,8 @@ mymain(void)
> DO_TEST_FULL("cachetune-colliding-types", false, true,
> TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
>
> + DO_TEST("tseg");
> +
> virObjectUnref(caps);
> virObjectUnref(xmlopt);
>
>
I checked the commit message and the docs; they look OK to me.
Acked-by: Laszlo Ersek <lersek at redhat.com>
Thanks,
Laszlo
More information about the libvir-list
mailing list