diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index ba5bd1e502..6912762f28 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> ... @@ -2079,10 +2082,55 @@ Since 1.2.16
smm
-
Depending on the state attribute (values on, +
+

+ Depending on the state attribute (values on, off, default on) enable or disable System Management Mode. Since 2.1.0 +

Optional sub-element tseg 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 + unit can be used to specify the unit of the + aforementioned value (defaults to 'MiB'). If set to 0 the extended + size is not advertised and only the default ones (see above) are + available. +

+ If the VM is booting you should leave this option alone, unless you + are very certain you know what you are doing. +

+ 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 pc-q35-2.9. Starting with + pc-q35-2.10 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. +

+ 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. +

+ 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). +

+ See Memory Allocation + for more details about the unit attribute. + Since 4.5.0 (QEMU only) +

ioapic
Tune the I/O APIC. Possible values for the diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index c5c8c575b8..550fb10159 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4846,6 +4846,11 @@ + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5be773cda4..ab93bb7b45 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,33 @@ 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_specified && + 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 +27486,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 +27502,31 @@ 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 && + def->tseg_specified) { + const char *unit; + unsigned long long short_size = virFormatIntPretty(def->tseg_size, + &unit); + + virBufferSetChildIndent(&childBuf, buf); + virBufferAsprintf(&childBuf, "%llu\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, " + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + + 48 + + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + + diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c index d8270a6cae..daad6e0f78 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);