[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