Add svm attribute to iommu to enable/disable shared virtual memory
capability for intel-iommu.

Signed-off-by: Zhenzhong Duan <[email protected]>
---
 docs/formatdomain.rst                         |  6 +++
 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-svm.x86_64-latest.args        | 34 +++++++++++++++++
 .../intel-iommu-svm.x86_64-latest.xml         | 37 +++++++++++++++++++
 tests/qemuxmlconfdata/intel-iommu-svm.xml     | 37 +++++++++++++++++++
 tests/qemuxmlconftest.c                       |  1 +
 10 files changed, 146 insertions(+)
 create mode 100644 tests/qemuxmlconfdata/intel-iommu-svm.x86_64-latest.args
 create mode 100644 tests/qemuxmlconfdata/intel-iommu-svm.x86_64-latest.xml
 create mode 100644 tests/qemuxmlconfdata/intel-iommu-svm.xml

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 14fe85e817..8ca6aa02b3 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -9495,6 +9495,12 @@ Examples:
       Max supported value is 20 according to PCI spec, pasid is disabled if 0.
       :since:`Since 12.8.0` (QEMU/KVM and ``intel`` model only)
 
+   ``svm``
+      Enable shared virtual memory, it exposes the necessary hardware
+      capabilities to the guest operating system so that devices can share
+      the exact same virtual address space as user-space applications.
+      :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 7b8a7e7c68..462873bfb9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -14790,6 +14790,10 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt,
                            &iommu->pasid_bits) < 0)
             return NULL;
 
+        if (virXMLPropTristateSwitch(driver, "svm", VIR_XML_PROP_NONE,
+                                     &iommu->svm) < 0)
+            return NULL;
+
         if ((granule = virXPathNode("./driver/granule", ctxt))) {
             g_autofree char *mode = virXMLPropString(granule, "mode");
             unsigned long long size;
@@ -16903,6 +16907,7 @@ virDomainIOMMUDefEquals(const virDomainIOMMUDef *a,
         a->scalable_mode != b->scalable_mode ||
         a->fsts != b->fsts ||
         a->pasid_bits != b->pasid_bits ||
+        a->svm != b->svm ||
         a->xtsup != b->xtsup ||
         a->pt != b->pt ||
         a->granule != b->granule)
@@ -22859,6 +22864,13 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef 
*src,
                        virTristateSwitchTypeToString(src->pasid_bits));
         return false;
     }
+    if (src->svm != dst->svm) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target domain IOMMU device shared virtual memory 
'%1$s' does not match source '%2$s'"),
+                       virTristateSwitchTypeToString(dst->svm),
+                       virTristateSwitchTypeToString(src->svm));
+        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'"),
@@ -29326,6 +29338,10 @@ virDomainIOMMUDefFormat(virBuffer *buf,
         virBufferAsprintf(&driverAttrBuf, " pasid_bits='%u'",
                           iommu->pasid_bits);
     }
+    if (iommu->svm != VIR_TRISTATE_SWITCH_ABSENT) {
+        virBufferAsprintf(&driverAttrBuf, " svm='%s'",
+                          virTristateSwitchTypeToString(iommu->svm));
+    }
     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 16d3006c6f..87767e30f9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3107,6 +3107,7 @@ struct _virDomainIOMMUDef {
     virTristateSwitch scalable_mode;
     virTristateSwitch fsts;
     virTristateSwitch pasid_bits;
+    virTristateSwitch svm;
     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 fb89dcb8aa..524d0559ae 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -3205,6 +3205,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
             iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->fsts != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->pasid_bits != 0 ||
+            iommu->svm != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->pt != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->granule != 0) {
@@ -3234,6 +3235,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
             iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->fsts != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->pasid_bits != 0 ||
+            iommu->svm != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->pci_bus >= 0 ||
             iommu->accel != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->cmdqv != VIR_TRISTATE_SWITCH_ABSENT ||
@@ -3264,6 +3266,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
             iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->fsts != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->svm != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->pasid_bits != 0 ||
             iommu->pci_bus >= 0 ||
             iommu->accel != VIR_TRISTATE_SWITCH_ABSENT ||
diff --git a/src/conf/schemas/domaincommon.rng 
b/src/conf/schemas/domaincommon.rng
index 888d0db214..afd506af60 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6439,6 +6439,11 @@
                 <ref name="uint8"/>
               </attribute>
             </optional>
+            <optional>
+              <attribute name="svm">
+                <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 c343843068..b81ea7f6eb 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -5866,6 +5866,12 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef 
*iommu,
                            _("iommu: unsupported pasid bit width. Max value 
supported is 20 according to PCI spec"));
             return -1;
     }
+    if (iommu->svm != VIR_TRISTATE_SWITCH_ABSENT &&
+        !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_SVM)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("iommu: svm 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-svm.x86_64-latest.args 
b/tests/qemuxmlconfdata/intel-iommu-svm.x86_64-latest.args
new file mode 100644
index 0000000000..e2f5adfc93
--- /dev/null
+++ b/tests/qemuxmlconfdata/intel-iommu-svm.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,"fsts":true,"pasid-bits":6}'
 \
+-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-svm.x86_64-latest.xml 
b/tests/qemuxmlconfdata/intel-iommu-svm.x86_64-latest.xml
new file mode 100644
index 0000000000..05361ececd
--- /dev/null
+++ b/tests/qemuxmlconfdata/intel-iommu-svm.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' pasid_bits='6' svm='on'/>
+    </iommu>
+  </devices>
+</domain>
diff --git a/tests/qemuxmlconfdata/intel-iommu-svm.xml 
b/tests/qemuxmlconfdata/intel-iommu-svm.xml
new file mode 100644
index 0000000000..05361ececd
--- /dev/null
+++ b/tests/qemuxmlconfdata/intel-iommu-svm.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' pasid_bits='6' svm='on'/>
+    </iommu>
+  </devices>
+</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index bc83367cd8..39b6749a18 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -2992,6 +2992,7 @@ mymain(void)
     DO_TEST_CAPS_LATEST("intel-iommu-scalable-mode");
     DO_TEST_CAPS_LATEST("intel-iommu-fsts");
     DO_TEST_CAPS_LATEST("intel-iommu-pasid-bits");
+    DO_TEST_CAPS_LATEST("intel-iommu-svm");
     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