Add fsts attribute to iommu to enable/disable first stage translation
support for intel-iommu.

Signed-off-by: Zhenzhong Duan <[email protected]>
---
 docs/formatdomain.rst                         |  4 ++
 src/conf/domain_conf.c                        | 16 ++++++++
 src/conf/domain_conf.h                        |  1 +
 src/conf/domain_validate.c                    |  3 ++
 src/conf/schemas/domaincommon.rng             |  5 +++
 src/qemu/qemu_validate.c                      |  6 +++
 .../intel-iommu-fsts.x86_64-latest.args       | 34 +++++++++++++++++
 .../intel-iommu-fsts.x86_64-latest.xml        | 37 +++++++++++++++++++
 tests/qemuxmlconfdata/intel-iommu-fsts.xml    | 37 +++++++++++++++++++
 tests/qemuxmlconftest.c                       |  1 +
 10 files changed, 144 insertions(+)
 create mode 100644 tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.args
 create mode 100644 tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/intel-iommu-fsts.xml

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 761c5747ed..f376cefc16 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -9486,6 +9486,10 @@ Examples:
       Enable scalable mode DMA translation.
       :since:`Since 12.8.0` (QEMU/KVM and ``intel`` model only)
 
+   ``fsts``
+      Enable first stage translation.
+      :since:`Since 12.8.0` (QEMU/KVM and ``intel`` model only)
+
 In case of ``virtio`` IOMMU device, the ``driver`` element can optionally
 contain ``granule`` subelement that allows to choose which granule will be
 used by default. It is useful when running guests with different page size
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5bcc646deb..b6c3df0404 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -14782,6 +14782,10 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt,
                                      &iommu->scalable_mode) < 0)
             return NULL;
 
+        if (virXMLPropTristateSwitch(driver, "fsts", VIR_XML_PROP_NONE,
+                                     &iommu->fsts) < 0)
+            return NULL;
+
         if ((granule = virXPathNode("./driver/granule", ctxt))) {
             g_autofree char *mode = virXMLPropString(granule, "mode");
             unsigned long long size;
@@ -16893,6 +16897,7 @@ virDomainIOMMUDefEquals(const virDomainIOMMUDef *a,
         a->ssid_size != b->ssid_size ||
         a->oas != b->oas ||
         a->scalable_mode != b->scalable_mode ||
+        a->fsts != b->fsts ||
         a->xtsup != b->xtsup ||
         a->pt != b->pt ||
         a->granule != b->granule)
@@ -22835,6 +22840,13 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef 
*src,
                        virTristateSwitchTypeToString(src->scalable_mode));
         return false;
     }
+    if (src->fsts != dst->fsts) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target domain IOMMU device first stage translation 
support '%1$s' does not match source '%2$s'"),
+                       virTristateSwitchTypeToString(dst->fsts),
+                       virTristateSwitchTypeToString(src->fsts));
+        return false;
+    }
     if (src->pt != dst->pt) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Target domain IOMMU device passthrough '%1$s' does 
not match source '%2$s'"),
@@ -29294,6 +29306,10 @@ virDomainIOMMUDefFormat(virBuffer *buf,
         virBufferAsprintf(&driverAttrBuf, " scalable_mode='%s'",
                           virTristateSwitchTypeToString(iommu->scalable_mode));
     }
+    if (iommu->fsts != VIR_TRISTATE_SWITCH_ABSENT) {
+        virBufferAsprintf(&driverAttrBuf, " fsts='%s'",
+                          virTristateSwitchTypeToString(iommu->fsts));
+    }
     if (iommu->pt != VIR_TRISTATE_SWITCH_ABSENT) {
         virBufferAsprintf(&driverAttrBuf, " passthrough='%s'",
                           virTristateSwitchTypeToString(iommu->pt));
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 2c23a3f65a..e2076e7c36 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3105,6 +3105,7 @@ struct _virDomainIOMMUDef {
     virDomainDeviceInfo info;
     virTristateSwitch dma_translation;
     virTristateSwitch scalable_mode;
+    virTristateSwitch fsts;
     virTristateSwitch xtsup;
     virTristateSwitch pt;
     int granule; /* -1 means 'host', 0 unset, page size in KiB otherwise */
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 10318d89ee..1fae3a04a9 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -3203,6 +3203,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
             iommu->aw_bits != 0 ||
             iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->fsts != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->pt != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->granule != 0) {
@@ -3230,6 +3231,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
             iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->fsts != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->pci_bus >= 0 ||
             iommu->accel != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->cmdqv != VIR_TRISTATE_SWITCH_ABSENT ||
@@ -3259,6 +3261,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
             iommu->aw_bits != 0 ||
             iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->fsts != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->pci_bus >= 0 ||
             iommu->accel != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->cmdqv != VIR_TRISTATE_SWITCH_ABSENT ||
diff --git a/src/conf/schemas/domaincommon.rng 
b/src/conf/schemas/domaincommon.rng
index 01b1766150..ff905c18c2 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6429,6 +6429,11 @@
                 <ref name="virOnOff"/>
               </attribute>
             </optional>
+            <optional>
+              <attribute name="fsts">
+                <ref name="virOnOff"/>
+              </attribute>
+            </optional>
             <optional>
               <attribute name="xtsup">
                 <ref name="virOnOff"/>
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 55513b2691..f2c91a743f 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -5849,6 +5849,12 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef 
*iommu,
                        _("iommu: scalable mode is not supported with this QEMU 
binary"));
         return -1;
     }
+    if (iommu->fsts != VIR_TRISTATE_SWITCH_ABSENT &&
+        !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_FSTS)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("iommu: fsts is not supported with this QEMU 
binary"));
+        return -1;
+    }
 
     /* While QEMU_CAPS_ARM_SMMUV3_ACCEL tracks the .accel attribute of
      * arm-smmuv3 it is also a good indicator of .ats, .ril, .ssidsize, and
diff --git a/tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.args 
b/tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.args
new file mode 100644
index 0000000000..bda776f46a
--- /dev/null
+++ b/tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.args
@@ -0,0 +1,34 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object 
'{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}'
 \
+-machine 
q35,usb=off,kernel_irqchip=split,dump-guest-core=off,memory-backend=pc.ram,acpi=off
 \
+-accel kvm \
+-cpu qemu64 \
+-m size=219136k \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
+-overcommit mem-lock=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=@mon-fd@,server=on,wait=off \
+-object '{"qom-type":"monitor-qmp","id":"monitor","chardev":"charmonitor"}' \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-device '{"driver":"intel-iommu","id":"iommu0","scalable-mode":true}' \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-global ICH9-LPC.noreboot=off \
+-watchdog-action reset \
+-sandbox 
on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.xml 
b/tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.xml
new file mode 100644
index 0000000000..e188008b31
--- /dev/null
+++ b/tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.xml
@@ -0,0 +1,37 @@
+<domain type='kvm'>
+  <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>
+    <ioapic driver='qemu'/>
+  </features>
+  <cpu mode='custom' match='exact' check='none'>
+    <model fallback='forbid'>qemu64</model>
+  </cpu>
+  <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>
+    <controller type='pci' index='0' model='pcie-root'/>
+    <controller type='usb' index='0' model='none'/>
+    <controller type='sata' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' 
function='0x2'/>
+    </controller>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <audio id='1' type='none'/>
+    <watchdog model='itco' action='reset'/>
+    <memballoon model='none'/>
+    <iommu model='intel'>
+      <driver scalable_mode='on' fsts='on'/>
+    </iommu>
+  </devices>
+</domain>
diff --git a/tests/qemuxmlconfdata/intel-iommu-fsts.xml 
b/tests/qemuxmlconfdata/intel-iommu-fsts.xml
new file mode 100644
index 0000000000..e188008b31
--- /dev/null
+++ b/tests/qemuxmlconfdata/intel-iommu-fsts.xml
@@ -0,0 +1,37 @@
+<domain type='kvm'>
+  <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>
+    <ioapic driver='qemu'/>
+  </features>
+  <cpu mode='custom' match='exact' check='none'>
+    <model fallback='forbid'>qemu64</model>
+  </cpu>
+  <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>
+    <controller type='pci' index='0' model='pcie-root'/>
+    <controller type='usb' index='0' model='none'/>
+    <controller type='sata' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' 
function='0x2'/>
+    </controller>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <audio id='1' type='none'/>
+    <watchdog model='itco' action='reset'/>
+    <memballoon model='none'/>
+    <iommu model='intel'>
+      <driver scalable_mode='on' fsts='on'/>
+    </iommu>
+  </devices>
+</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index e77702427f..837bea7b63 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -2990,6 +2990,7 @@ mymain(void)
     DO_TEST_CAPS_LATEST("intel-iommu-aw-bits");
     DO_TEST_CAPS_LATEST("intel-iommu-dma-translation");
     DO_TEST_CAPS_LATEST("intel-iommu-scalable-mode");
+    DO_TEST_CAPS_LATEST("intel-iommu-fsts");
     DO_TEST_CAPS_LATEST_PARSE_ERROR("intel-iommu-wrong-machine");
     DO_TEST_CAPS_LATEST_ABI_UPDATE("intel-iommu-eim-autoadd");
     DO_TEST_CAPS_LATEST_ABI_UPDATE("intel-iommu-eim-autoadd-v2");
-- 
2.52.0

Reply via email to