diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 6bc9bf5ffab8ef7ebfdd6ed92d8a96bab6c026b3..bd54d17999b61b9c93160c59f11c68baff99aa7e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7295,6 +7295,22 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
return ret;
}
+
+static void
+qemuBuildTSEGCommandLine(virCommandPtr cmd,
+ const virDomainDef *def)
+{
+ if (!def->tseg_specified)
+ return;
+
+ virCommandAddArg(cmd, "-global");
+
+ /* PostParse callback guarantees that the size is divisible by 1 MiB */
+ virCommandAddArgFormat(cmd, "mch.extended-tseg-mbytes=%llu",
+ def->tseg_size >> 20);
+}
+
+
static int
qemuBuildSmpCommandLine(virCommandPtr cmd,
virDomainDefPtr def)
@@ -10108,6 +10124,8 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
if (qemuBuildMachineCommandLine(cmd, cfg, def, qemuCaps) < 0)
goto error;
+ qemuBuildTSEGCommandLine(cmd, def);
+
if (qemuBuildCpuCommandLine(cmd, driver, def, qemuCaps) < 0)
goto error;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index a985e9dd9635239237533d1a8c10880bcc9e11f9..11c261db1a443af7883e3a01a840371e5ed4f1dd 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -3632,6 +3632,38 @@ qemuDomainDefCPUPostParse(virDomainDefPtr def)
}
+static int
+qemuDomainDefTsegPostParse(virDomainDefPtr def,
+ virQEMUCapsPtr qemuCaps)
+{
+ if (def->features[VIR_DOMAIN_FEATURE_SMM] != VIR_TRISTATE_SWITCH_ON)
+ return 0;
+
+ if (!def->tseg_specified)
+ return 0;
+
+ if (!qemuDomainIsQ35(def)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("SMM TSEG is only supported with q35 machine type"));
+ return -1;
+ }
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MCH_EXTENDED_TSEG_MBYTES)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting TSEG size is not supported with this QEMU binary"));
+ return -1;
+ }
+
+ if (def->tseg_size & ((1 << 20) - 1)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("SMM TSEG size must be divisible by 1 MiB"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
qemuDomainDefPostParseBasic(virDomainDefPtr def,
virCapsPtr caps,
@@ -3702,6 +3734,9 @@ qemuDomainDefPostParse(virDomainDefPtr def,
if (qemuDomainDefCPUPostParse(def) < 0)
goto cleanup;
+ if (qemuDomainDefTsegPostParse(def, qemuCaps) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
virObjectUnref(cfg);
diff --git a/tests/qemuxml2argvdata/tseg-explicit-size.x86_64-latest.args b/tests/qemuxml2argvdata/tseg-explicit-size.x86_64-latest.args
new file mode 100644
index 0000000000000000000000000000000000000000..110761b96e0ea31a89ee51ccba1faebde907854a
--- /dev/null
+++ b/tests/qemuxml2argvdata/tseg-explicit-size.x86_64-latest.args
@@ -0,0 +1,35 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object secret,id=masterKey0,format=raw,\
+file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
+-machine pc-q35-2.10,accel=tcg,usb=off,smm=on,dump-guest-core=off \
+-global mch.extended-tseg-mbytes=48 \
+-m 214 \
+-realtime mlock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device pcie-root-port,port=0x8,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\
+addr=0x1 \
+-device pcie-root-port,port=0x9,chassis=2,id=pci.2,bus=pcie.0,addr=0x1.0x1 \
+-device pcie-root-port,port=0xa,chassis=3,id=pci.3,bus=pcie.0,addr=0x1.0x2 \
+-device qemu-xhci,id=usb,bus=pci.1,addr=0x0 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x0 \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
+resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/tseg-explicit-size.xml b/tests/qemuxml2argvdata/tseg-explicit-size.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ae3121048495fa488cd6b82517d114288b1e0d42
--- /dev/null
+++ b/tests/qemuxml2argvdata/tseg-explicit-size.xml
@@ -0,0 +1,23 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+
+ 48
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
diff --git a/tests/qemuxml2argvdata/tseg-i440fx.xml b/tests/qemuxml2argvdata/tseg-i440fx.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5bd832d50829ee3431c3c380d03322237962d662
--- /dev/null
+++ b/tests/qemuxml2argvdata/tseg-i440fx.xml
@@ -0,0 +1,23 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+
+ 48
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
diff --git a/tests/qemuxml2argvdata/tseg-invalid-size.xml b/tests/qemuxml2argvdata/tseg-invalid-size.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3ac8069a81ce043b9e9b5a90e2d8333acdc383a1
--- /dev/null
+++ b/tests/qemuxml2argvdata/tseg-invalid-size.xml
@@ -0,0 +1,23 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+
+ 12345
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 7ad1ae3930902879025f7ab7bf786d3a13392b6d..c81caecdad6b8a40bb5f1234b4c7a5487cf0c0e5 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2854,6 +2854,31 @@ mymain(void)
DO_TEST_CAPS_LATEST("disk-virtio-scsi-reservations");
+ DO_TEST_CAPS_LATEST("tseg-explicit-size");
+ DO_TEST_PARSE_ERROR("tseg-i440fx",
+ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_IOH3420,
+ QEMU_CAPS_ICH9_AHCI,
+ QEMU_CAPS_MACHINE_SMM_OPT,
+ QEMU_CAPS_VIRTIO_SCSI,
+ QEMU_CAPS_MCH_EXTENDED_TSEG_MBYTES);
+ DO_TEST_PARSE_ERROR("tseg-explicit-size",
+ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_IOH3420,
+ QEMU_CAPS_ICH9_AHCI,
+ QEMU_CAPS_MACHINE_SMM_OPT,
+ QEMU_CAPS_VIRTIO_SCSI);
+ DO_TEST_PARSE_ERROR("tseg-invalid-size",
+ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_IOH3420,
+ QEMU_CAPS_ICH9_AHCI,
+ QEMU_CAPS_MACHINE_SMM_OPT,
+ QEMU_CAPS_VIRTIO_SCSI,
+ QEMU_CAPS_MCH_EXTENDED_TSEG_MBYTES);
+
DO_TEST("video-virtio-gpu-ccw", QEMU_CAPS_CCW,
QEMU_CAPS_DEVICE_VIRTIO_GPU,
QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
diff --git a/tests/qemuxml2xmloutdata/tseg-explicit-size.xml b/tests/qemuxml2xmloutdata/tseg-explicit-size.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e1a6e15b610ee100ad0882cba0662a3c95f34939
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/tseg-explicit-size.xml
@@ -0,0 +1,46 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+
+ 48
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmloutdata/tseg-old-machine-type.xml b/tests/qemuxml2xmloutdata/tseg-old-machine-type.xml
new file mode 100644
index 0000000000000000000000000000000000000000..594c5c025d2e17335adf21a78e8a220a4e830615
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/tseg-old-machine-type.xml
@@ -0,0 +1,44 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmloutdata/tseg.xml b/tests/qemuxml2xmloutdata/tseg.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ad80648c73e4cc1cc142ffda01e6b310b3b2c443
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/tseg.xml
@@ -0,0 +1,44 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 689c002b7e1dc7d73e77dc9b16f3df28b6d585e1..f5805c7f508e3f8ed2a0973ea7412d1eb50708a1 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1184,6 +1184,15 @@ mymain(void)
QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW,
QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW);
+ DO_TEST("tseg-explicit-size",
+ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_IOH3420,
+ QEMU_CAPS_ICH9_AHCI,
+ QEMU_CAPS_MACHINE_SMM_OPT,
+ QEMU_CAPS_VIRTIO_SCSI,
+ QEMU_CAPS_MCH_EXTENDED_TSEG_MBYTES);
+
# define DO_TEST_STATUS(name) \
do { \
if (testInfoSetStatus(&info, name, GIC_NONE) < 0) { \