[PATCH v2 00/12] conf, qemu: Add scalable_mode, fsts, pasid_bits, and svm support for intel-iommu
Hi, This series adds support for configuring Intel vIOMMU (VT-d) in domain XML and formatting them onto the QEMU command line: * scalable_mode: Configures scalable mode support ('on'/'off'). * fsts: Enables First-Stage Translation support ('on'/'off'). * pasid_bits: Sets the number of supported PASID bits. * svm: Enables Shared Virtual Memory (SVM) / PRQ support ('on'/'off'). With these attributes, users can configure advanced vIOMMU features for both emulated devices and assigned host devices (e.g., vSVA / nested translation via iommufd and first-stage translation). Example domain XML configuration: <iommu model='intel'> <driver caching_mode='on' iotlb='on' scalable_mode='on' fsts='on' pasid_bits='6' svm='on'/> </iommu> Which formats the following QEMU command line options: -device {"driver":"intel-iommu","id":"iommu0","caching-mode":true,"device-iotlb":true,"scalable-mode":true,"fsts":true,"pasid-bits":6,"svm":true} Testing: - Validated with libvirt test suite (ninja test). - Tested DSA card passthrough and SVM/vSVA with iommufd backend. Changelog: v1: - Added support for 'pasid_bits' and 'svm' attributes. - rebased to master branch newest Thanks, Zhenzhong Zhenzhong Duan (12): qemu_capabilities: Introduce QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE conf: Add scalable_mode attribute to iommu qemu: format scalable-mode on intel-iommu command line qemu_capabilities: Introduce QEMU_CAPS_INTEL_IOMMU_FSTS conf: Add fsts attribute to iommu qemu: format fsts on intel-iommu command line qemu_capabilities: Introduce QEMU_CAPS_INTEL_IOMMU_PASID_BITS conf: add pasid_bits attribute to iommu qemu: format pasid-bits on intel-iommu command line qemu_capabilities: Introduce QEMU_CAPS_INTEL_IOMMU_SVM conf: add svm attribute to iommu qemu: format svm on intel-iommu command line docs/formatdomain.rst | 19 ++++++ src/conf/domain_conf.c | 64 +++++++++++++++++++ src/conf/domain_conf.h | 4 ++ src/conf/domain_validate.c | 12 ++++ src/conf/schemas/domaincommon.rng | 20 ++++++ src/qemu/qemu_capabilities.c | 10 +++ src/qemu/qemu_capabilities.h | 6 ++ src/qemu/qemu_command.c | 4 ++ src/qemu/qemu_validate.c | 31 ++++++++- .../caps_11.0.0_x86_64+sgx.xml | 1 + .../caps_11.0.0_x86_64.xml | 1 + .../caps_11.1.0_x86_64.xml | 4 ++ .../intel-iommu-fsts.x86_64-latest.args | 34 ++++++++++ .../intel-iommu-fsts.x86_64-latest.xml | 37 +++++++++++ tests/qemuxmlconfdata/intel-iommu-fsts.xml | 37 +++++++++++ .../intel-iommu-pasid-bits.x86_64-latest.args | 34 ++++++++++ .../intel-iommu-pasid-bits.x86_64-latest.xml | 37 +++++++++++ .../intel-iommu-pasid-bits.xml | 37 +++++++++++ ...tel-iommu-scalable-mode.x86_64-latest.args | 34 ++++++++++ ...ntel-iommu-scalable-mode.x86_64-latest.xml | 37 +++++++++++ .../intel-iommu-scalable-mode.xml | 37 +++++++++++ .../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 | 4 ++ 25 files changed, 611 insertions(+), 1 deletion(-) 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 create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.xml create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.xml 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 -- 2.52.0
This capability tracks whether intel-iommu device has scalable-mode attribute. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml | 1 + 3 files changed, 4 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index bc2b0412dc..209356a984 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -776,6 +776,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "arm-smmuv3.cmdqv", /* QEMU_CAPS_ARM_SMMUV3_CMDQV */ "iothread.poll-weight", /* QEMU_CAPS_IOTHREAD_POLL_WEIGHT */ "win-dmp.guest-aware", /* QEMU_CAPS_WIN_DMP_GUEST_AWARE */ + "intel-iommu.scalable-mode", /* QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE */ ); @@ -1619,6 +1620,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsIntelIOMMU[] = { { "device-iotlb", QEMU_CAPS_INTEL_IOMMU_DEVICE_IOTLB, NULL }, { "aw-bits", QEMU_CAPS_INTEL_IOMMU_AW_BITS, NULL }, { "dma-translation", QEMU_CAPS_INTEL_IOMMU_DMA_TRANSLATION, NULL }, + { "scalable-mode", QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsMCH[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 28303fd8f0..25695d7982 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -750,6 +750,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_ARM_SMMUV3_CMDQV, /* arm-smmuv3.cmdqv */ QEMU_CAPS_IOTHREAD_POLL_WEIGHT, /* -object iothread.poll-weight */ QEMU_CAPS_WIN_DMP_GUEST_AWARE, /* 'win-dmp' is offered only to a guest that can use it */ + QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE, /* intel-iommu.scalable-mode */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml index 05e6749a17..e228b0f3d1 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml @@ -224,6 +224,7 @@ <flag name='object-monitor-qmp'/> <flag name='iothread.poll-weight'/> <flag name='win-dmp.guest-aware'/> + <flag name='intel-iommu.scalable-mode'/> <version>11001000</version> <microcodeVersion>43100287</microcodeVersion> <package>v11.1.0</package> -- 2.52.0
On Wed, Sep 09, 2026 at 16:29:48 +0800, Zhenzhong Duan wrote:
This capability tracks whether intel-iommu device has scalable-mode attribute.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml | 1 + 3 files changed, 4 insertions(+)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
On Wed, Sep 09, 2026 at 12:22:34 +0200, Peter Krempa via Devel wrote:
On Wed, Sep 09, 2026 at 16:29:48 +0800, Zhenzhong Duan wrote:
This capability tracks whether intel-iommu device has scalable-mode attribute.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml | 1 + 3 files changed, 4 insertions(+)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
You can use this for all capability-adding patches in this series.
Add scalable_mode attribute to iommu to enable/disable scalable mode for intel-iommu. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- 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 | 8 +++- ...tel-iommu-scalable-mode.x86_64-latest.args | 34 +++++++++++++++++ ...ntel-iommu-scalable-mode.x86_64-latest.xml | 37 +++++++++++++++++++ .../intel-iommu-scalable-mode.xml | 37 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 10 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 5a278f3717..761c5747ed 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -9482,6 +9482,10 @@ Examples: default value is used. :since:`Since 12.7.0` (QEMU/KVM and ``smmuv3`` model only) + ``scalable_mode`` + Enable scalable mode DMA 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 34d3b00079..5bcc646deb 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14778,6 +14778,10 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt, &iommu->oas, -1) < 0) return NULL; + if (virXMLPropTristateSwitch(driver, "scalable_mode", VIR_XML_PROP_NONE, + &iommu->scalable_mode) < 0) + return NULL; + if ((granule = virXPathNode("./driver/granule", ctxt))) { g_autofree char *mode = virXMLPropString(granule, "mode"); unsigned long long size; @@ -16888,6 +16892,7 @@ virDomainIOMMUDefEquals(const virDomainIOMMUDef *a, a->ril != b->ril || a->ssid_size != b->ssid_size || a->oas != b->oas || + a->scalable_mode != b->scalable_mode || a->xtsup != b->xtsup || a->pt != b->pt || a->granule != b->granule) @@ -22823,6 +22828,13 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef *src, virTristateSwitchTypeToString(src->dma_translation)); return false; } + if (src->scalable_mode != dst->scalable_mode) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain IOMMU device scalable mode '%1$s' does not match source '%2$s'"), + virTristateSwitchTypeToString(dst->scalable_mode), + virTristateSwitchTypeToString(src->scalable_mode)); + 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'"), @@ -29278,6 +29290,10 @@ virDomainIOMMUDefFormat(virBuffer *buf, virBufferAsprintf(&driverAttrBuf, " dma_translation='%s'", virTristateSwitchTypeToString(iommu->dma_translation)); } + if (iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT) { + virBufferAsprintf(&driverAttrBuf, " scalable_mode='%s'", + virTristateSwitchTypeToString(iommu->scalable_mode)); + } 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 3732525af4..2c23a3f65a 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3104,6 +3104,7 @@ struct _virDomainIOMMUDef { int pci_bus; virDomainDeviceInfo info; virTristateSwitch dma_translation; + virTristateSwitch scalable_mode; 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 15e3bb29e6..10318d89ee 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -3202,6 +3202,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu) iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT || iommu->aw_bits != 0 || iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT || + iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT || iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT || iommu->pt != VIR_TRISTATE_SWITCH_ABSENT || iommu->granule != 0) { @@ -3228,6 +3229,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu) iommu->eim != VIR_TRISTATE_SWITCH_ABSENT || iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT || iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT || + iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT || iommu->pci_bus >= 0 || iommu->accel != VIR_TRISTATE_SWITCH_ABSENT || iommu->cmdqv != VIR_TRISTATE_SWITCH_ABSENT || @@ -3256,6 +3258,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu) iommu->eim != VIR_TRISTATE_SWITCH_ABSENT || iommu->aw_bits != 0 || iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT || + iommu->scalable_mode != 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 887fb8f808..01b1766150 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6424,6 +6424,11 @@ <ref name="virOnOff"/> </attribute> </optional> + <optional> + <attribute name="scalable_mode"> + <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 e946f55351..55513b2691 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5815,7 +5815,7 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu, return -1; } if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_CACHING_MODE)) { + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_CACHING_MODE)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("iommu: caching mode is not supported with this QEMU binary")); return -1; @@ -5843,6 +5843,12 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu, _("iommu: updating dma translation is not supported with this QEMU binary")); return -1; } + if (iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("iommu: scalable mode 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-scalable-mode.x86_64-latest.args b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args new file mode 100644 index 0000000000..c12d76bd89 --- /dev/null +++ b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.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"}' \ +-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-scalable-mode.x86_64-latest.xml b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.xml new file mode 100644 index 0000000000..a8f044ee12 --- /dev/null +++ b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.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'/> + </iommu> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/intel-iommu-scalable-mode.xml b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.xml new file mode 100644 index 0000000000..a8f044ee12 --- /dev/null +++ b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.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'/> + </iommu> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 555c029f58..e77702427f 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -2989,6 +2989,7 @@ mymain(void) DO_TEST_CAPS_LATEST("intel-iommu-device-iotlb"); 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_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
On Wed, Sep 09, 2026 at 16:29:49 +0800, Zhenzhong Duan wrote:
Add scalable_mode attribute to iommu to enable/disable scalable mode for intel-iommu.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- 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 | 8 +++- ...tel-iommu-scalable-mode.x86_64-latest.args | 34 +++++++++++++++++ ...ntel-iommu-scalable-mode.x86_64-latest.xml | 37 +++++++++++++++++++ .../intel-iommu-scalable-mode.xml | 37 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 10 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.xml
[...]
@@ -22823,6 +22828,13 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef *src, virTristateSwitchTypeToString(src->dma_translation)); return false; } + if (src->scalable_mode != dst->scalable_mode) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain IOMMU device scalable mode '%1$s' does not match source '%2$s'"),
The error message should mention the attribute name verbatim: _("Target domain IOMMU device 'scalable_mode' '%1$s' does not match source '%2$s'"), Please apply this change to any further patch in the series.
+ virTristateSwitchTypeToString(dst->scalable_mode), + virTristateSwitchTypeToString(src->scalable_mode)); + 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'"),
[...]
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index e946f55351..55513b2691 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5815,7 +5815,7 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu, return -1; } if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_CACHING_MODE)) { + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_CACHING_MODE)) {
This hunk is unrelated.
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("iommu: caching mode is not supported with this QEMU binary")); return -1; @@ -5843,6 +5843,12 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu, _("iommu: updating dma translation is not supported with this QEMU binary")); return -1; } + if (iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT &&
Missing newline before if.
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("iommu: scalable mode is not supported with this QEMU binary"));
Here also use the verbatim name of the feature: _("iommu: 'scalable_mode' is not supported with this QEMU binary")); and same for all other patches.
+ 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
-----Original Message----- From: Peter Krempa <pkrempa@redhat.com> Subject: Re: [PATCH v2 02/12] conf: Add scalable_mode attribute to iommu
On Wed, Sep 09, 2026 at 16:29:49 +0800, Zhenzhong Duan wrote:
Add scalable_mode attribute to iommu to enable/disable scalable mode for intel-iommu.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- 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 | 8 +++- ...tel-iommu-scalable-mode.x86_64-latest.args | 34 +++++++++++++++++ ...ntel-iommu-scalable-mode.x86_64-latest.xml | 37 +++++++++++++++++++ .../intel-iommu-scalable-mode.xml | 37 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 10 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable- mode.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable- mode.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.xml
[...]
@@ -22823,6 +22828,13 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef *src, virTristateSwitchTypeToString(src->dma_translation)); return false; } + if (src->scalable_mode != dst->scalable_mode) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain IOMMU device scalable mode '%1$s' does not match source '%2$s'"),
The error message should mention the attribute name verbatim:
_("Target domain IOMMU device 'scalable_mode' '%1$s' does not match source '%2$s'"),
The existing code in virDomainIOMMUDefCheckABIStability() formats the attribute without quotes (i.e. ssid_size value rather than 'ssid_size' value). Should I follow existing code style or you prefer 'scalable_mode'?
Please apply this change to any further patch in the series.
Sure.
+ virTristateSwitchTypeToString(dst->scalable_mode), + virTristateSwitchTypeToString(src->scalable_mode)); + 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'"),
[...]
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index e946f55351..55513b2691 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5815,7 +5815,7 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu, return -1; } if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_CACHING_MODE)) { + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_CACHING_MODE)) {
This hunk is unrelated.
Will delete it.
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("iommu: caching mode is not supported with this QEMU
binary"));
return -1; @@ -5843,6 +5843,12 @@ qemuValidateDomainDeviceDefIOMMU(const
virDomainIOMMUDef *iommu,
_("iommu: updating dma translation is not supported with this
QEMU binary"));
return -1; } + if (iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT &&
Missing newline before if.
This is following existing code style in qemuValidateDomainDeviceDefIOMMU(). I'm not sure, should I add new line starting from scalable_mode?
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("iommu: scalable mode is not supported with this QEMU binary"));
Here also use the verbatim name of the feature:
_("iommu: 'scalable_mode' is not supported with this QEMU binary"));
Got it.
and same for all other patches.
Sure. Thanks Zhenzhong
On Thu, Sep 10, 2026 at 05:58:33 +0000, Duan, Zhenzhong wrote:
-----Original Message----- From: Peter Krempa <pkrempa@redhat.com> Subject: Re: [PATCH v2 02/12] conf: Add scalable_mode attribute to iommu
On Wed, Sep 09, 2026 at 16:29:49 +0800, Zhenzhong Duan wrote:
Add scalable_mode attribute to iommu to enable/disable scalable mode for intel-iommu.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- 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 | 8 +++- ...tel-iommu-scalable-mode.x86_64-latest.args | 34 +++++++++++++++++ ...ntel-iommu-scalable-mode.x86_64-latest.xml | 37 +++++++++++++++++++ .../intel-iommu-scalable-mode.xml | 37 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 10 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable- mode.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable- mode.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/intel-iommu-scalable-mode.xml
[...]
@@ -22823,6 +22828,13 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef *src, virTristateSwitchTypeToString(src->dma_translation)); return false; } + if (src->scalable_mode != dst->scalable_mode) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain IOMMU device scalable mode '%1$s' does not match source '%2$s'"),
The error message should mention the attribute name verbatim:
_("Target domain IOMMU device 'scalable_mode' '%1$s' does not match source '%2$s'"),
The existing code in virDomainIOMMUDefCheckABIStability() formats the attribute without quotes (i.e. ssid_size value rather than 'ssid_size' value). Should I follow existing code style or you prefer 'scalable_mode'?
If you want you can fix the existing checks in a separate patch. For the new code please put them into quotes even if you decide to not change the existing code.
Please apply this change to any further patch in the series.
Sure.
+ virTristateSwitchTypeToString(dst->scalable_mode), + virTristateSwitchTypeToString(src->scalable_mode)); + 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'"),
[...]
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index e946f55351..55513b2691 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5815,7 +5815,7 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu, return -1; } if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_CACHING_MODE)) { + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_CACHING_MODE)) {
This hunk is unrelated.
Will delete it.
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("iommu: caching mode is not supported with this QEMU
binary"));
return -1; @@ -5843,6 +5843,12 @@ qemuValidateDomainDeviceDefIOMMU(const
virDomainIOMMUDef *iommu,
_("iommu: updating dma translation is not supported with this
QEMU binary"));
return -1; } + if (iommu->scalable_mode != VIR_TRISTATE_SWITCH_ABSENT &&
Missing newline before if.
This is following existing code style in qemuValidateDomainDeviceDefIOMMU(). I'm not sure, should I add new line starting from scalable_mode?
I see; keep it as is in your patch.
Add scalable-mode attribute to qemu command line if specified in domain conf. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_command.c | 1 + .../intel-iommu-scalable-mode.x86_64-latest.args | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index bcddb9c922..d7afdb4ee4 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6343,6 +6343,7 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, "T:device-iotlb", iommu->iotlb, "p:aw-bits", iommu->aw_bits, "T:dma-translation", iommu->dma_translation, + "T:scalable-mode", iommu->scalable_mode, NULL) < 0) return -1; diff --git a/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args index c12d76bd89..bda776f46a 100644 --- a/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args +++ b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args @@ -26,7 +26,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -rtc base=utc \ -no-shutdown \ -boot strict=on \ --device '{"driver":"intel-iommu","id":"iommu0"}' \ +-device '{"driver":"intel-iommu","id":"iommu0","scalable-mode":true}' \ -audiodev '{"id":"audio1","driver":"none"}' \ -global ICH9-LPC.noreboot=off \ -watchdog-action reset \ -- 2.52.0
On Wed, Sep 09, 2026 at 16:29:50 +0800, Zhenzhong Duan wrote:
Add scalable-mode attribute to qemu command line if specified in domain conf.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_command.c | 1 + .../intel-iommu-scalable-mode.x86_64-latest.args | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index bcddb9c922..d7afdb4ee4 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6343,6 +6343,7 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, "T:device-iotlb", iommu->iotlb, "p:aw-bits", iommu->aw_bits, "T:dma-translation", iommu->dma_translation, + "T:scalable-mode", iommu->scalable_mode, NULL) < 0) return -1;
diff --git a/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args index c12d76bd89..bda776f46a 100644 --- a/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args +++ b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args @@ -26,7 +26,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -rtc base=utc \ -no-shutdown \ -boot strict=on \ --device '{"driver":"intel-iommu","id":"iommu0"}' \ +-device '{"driver":"intel-iommu","id":"iommu0","scalable-mode":true}' \ -audiodev '{"id":"audio1","driver":"none"}' \ -global ICH9-LPC.noreboot=off \ -watchdog-action reset \
Since all code is already added in the patch that adds the 'conf' bits, I don't think this needs to be separate.
-----Original Message----- From: Peter Krempa <pkrempa@redhat.com> Subject: Re: [PATCH v2 03/12] qemu: format scalable-mode on intel-iommu command line
On Wed, Sep 09, 2026 at 16:29:50 +0800, Zhenzhong Duan wrote:
Add scalable-mode attribute to qemu command line if specified in domain conf.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_command.c | 1 + .../intel-iommu-scalable-mode.x86_64-latest.args | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index bcddb9c922..d7afdb4ee4 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6343,6 +6343,7 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, "T:device-iotlb", iommu->iotlb, "p:aw-bits", iommu->aw_bits, "T:dma-translation", iommu->dma_translation, + "T:scalable-mode", iommu->scalable_mode, NULL) < 0) return -1;
diff --git a/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64- latest.args b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64- latest.args index c12d76bd89..bda776f46a 100644 --- a/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args +++ b/tests/qemuxmlconfdata/intel-iommu-scalable-mode.x86_64-latest.args @@ -26,7 +26,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1- QEMUGuest1/.config \ -rtc base=utc \ -no-shutdown \ -boot strict=on \ --device '{"driver":"intel-iommu","id":"iommu0"}' \ +-device '{"driver":"intel-iommu","id":"iommu0","scalable-mode":true}' \ -audiodev '{"id":"audio1","driver":"none"}' \ -global ICH9-LPC.noreboot=off \ -watchdog-action reset \
Since all code is already added in the patch that adds the 'conf' bits, I don't think this needs to be separate.
Got it, will merge each qemu cmdline patch into their 'conf' patch. Thanks Zhenzhong
This capability tracks whether intel-iommu device has fsts attribute. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml | 1 + 3 files changed, 4 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 209356a984..5a4e74180a 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -777,6 +777,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "iothread.poll-weight", /* QEMU_CAPS_IOTHREAD_POLL_WEIGHT */ "win-dmp.guest-aware", /* QEMU_CAPS_WIN_DMP_GUEST_AWARE */ "intel-iommu.scalable-mode", /* QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE */ + "intel-iommu.fsts", /* QEMU_CAPS_INTEL_IOMMU_FSTS */ ); @@ -1621,6 +1622,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsIntelIOMMU[] = { { "aw-bits", QEMU_CAPS_INTEL_IOMMU_AW_BITS, NULL }, { "dma-translation", QEMU_CAPS_INTEL_IOMMU_DMA_TRANSLATION, NULL }, { "scalable-mode", QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE, NULL }, + { "fsts", QEMU_CAPS_INTEL_IOMMU_FSTS, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsMCH[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 25695d7982..38d60b9448 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -751,6 +751,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_IOTHREAD_POLL_WEIGHT, /* -object iothread.poll-weight */ QEMU_CAPS_WIN_DMP_GUEST_AWARE, /* 'win-dmp' is offered only to a guest that can use it */ QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE, /* intel-iommu.scalable-mode */ + QEMU_CAPS_INTEL_IOMMU_FSTS, /* intel-iommu.fsts */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml index e228b0f3d1..e2ad004035 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml @@ -225,6 +225,7 @@ <flag name='iothread.poll-weight'/> <flag name='win-dmp.guest-aware'/> <flag name='intel-iommu.scalable-mode'/> + <flag name='intel-iommu.fsts'/> <version>11001000</version> <microcodeVersion>43100287</microcodeVersion> <package>v11.1.0</package> -- 2.52.0
Add fsts attribute to iommu to enable/disable first stage translation support for intel-iommu. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- 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
Add fsts attribute to qemu command line if specified in domain conf. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_command.c | 1 + tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.args | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d7afdb4ee4..8c59ca4383 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6344,6 +6344,7 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, "p:aw-bits", iommu->aw_bits, "T:dma-translation", iommu->dma_translation, "T:scalable-mode", iommu->scalable_mode, + "T:fsts", iommu->fsts, NULL) < 0) return -1; diff --git a/tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.args b/tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.args index bda776f46a..5db49142e5 100644 --- a/tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.args +++ b/tests/qemuxmlconfdata/intel-iommu-fsts.x86_64-latest.args @@ -26,7 +26,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -rtc base=utc \ -no-shutdown \ -boot strict=on \ --device '{"driver":"intel-iommu","id":"iommu0","scalable-mode":true}' \ +-device '{"driver":"intel-iommu","id":"iommu0","scalable-mode":true,"fsts":true}' \ -audiodev '{"id":"audio1","driver":"none"}' \ -global ICH9-LPC.noreboot=off \ -watchdog-action reset \ -- 2.52.0
This capability tracks whether intel-iommu device has pasid-bits attribute. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 3 +++ tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml | 1 + 3 files changed, 8 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 5a4e74180a..606c5385e9 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -778,6 +778,9 @@ VIR_ENUM_IMPL(virQEMUCaps, "win-dmp.guest-aware", /* QEMU_CAPS_WIN_DMP_GUEST_AWARE */ "intel-iommu.scalable-mode", /* QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE */ "intel-iommu.fsts", /* QEMU_CAPS_INTEL_IOMMU_FSTS */ + + /* 505 */ + "intel-iommu.pasid-bits", /* QEMU_CAPS_INTEL_IOMMU_PASID_BITS */ ); @@ -1623,6 +1626,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsIntelIOMMU[] = { { "dma-translation", QEMU_CAPS_INTEL_IOMMU_DMA_TRANSLATION, NULL }, { "scalable-mode", QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE, NULL }, { "fsts", QEMU_CAPS_INTEL_IOMMU_FSTS, NULL }, + { "pasid-bits", QEMU_CAPS_INTEL_IOMMU_PASID_BITS, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsMCH[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 38d60b9448..30af10da79 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -753,6 +753,9 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE, /* intel-iommu.scalable-mode */ QEMU_CAPS_INTEL_IOMMU_FSTS, /* intel-iommu.fsts */ + /* 505 */ + QEMU_CAPS_INTEL_IOMMU_PASID_BITS, /* intel-iommu.pasid-bits */ + QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml index e2ad004035..38a782b2e3 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml @@ -226,6 +226,7 @@ <flag name='win-dmp.guest-aware'/> <flag name='intel-iommu.scalable-mode'/> <flag name='intel-iommu.fsts'/> + <flag name='intel-iommu.pasid-bits'/> <version>11001000</version> <microcodeVersion>43100287</microcodeVersion> <package>v11.1.0</package> -- 2.52.0
Add pasid_bits attribute to iommu to set pasid bit width or disable pasid capability if 0 for intel-iommu. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- docs/formatdomain.rst | 5 +++ 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 | 11 ++++++ .../intel-iommu-pasid-bits.x86_64-latest.args | 34 +++++++++++++++++ .../intel-iommu-pasid-bits.x86_64-latest.xml | 37 +++++++++++++++++++ .../intel-iommu-pasid-bits.xml | 37 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 10 files changed, 150 insertions(+) create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index f376cefc16..14fe85e817 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -9490,6 +9490,11 @@ Examples: Enable first stage translation. :since:`Since 12.8.0` (QEMU/KVM and ``intel`` model only) + ``pasid-bits`` + The ``pasid-bits`` attribute can be used to set the pasid bit width. + 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) + 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 b6c3df0404..7b8a7e7c68 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14786,6 +14786,10 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt, &iommu->fsts) < 0) return NULL; + if (virXMLPropUInt(driver, "pasid_bits", 10, VIR_XML_PROP_NONE, + &iommu->pasid_bits) < 0) + return NULL; + if ((granule = virXPathNode("./driver/granule", ctxt))) { g_autofree char *mode = virXMLPropString(granule, "mode"); unsigned long long size; @@ -16898,6 +16902,7 @@ virDomainIOMMUDefEquals(const virDomainIOMMUDef *a, a->oas != b->oas || a->scalable_mode != b->scalable_mode || a->fsts != b->fsts || + a->pasid_bits != b->pasid_bits || a->xtsup != b->xtsup || a->pt != b->pt || a->granule != b->granule) @@ -22847,6 +22852,13 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef *src, virTristateSwitchTypeToString(src->fsts)); return false; } + if (src->pasid_bits != dst->pasid_bits) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target domain IOMMU device pasid support '%1$s' does not match source '%2$s'"), + virTristateSwitchTypeToString(dst->pasid_bits), + virTristateSwitchTypeToString(src->pasid_bits)); + 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'"), @@ -29310,6 +29322,10 @@ virDomainIOMMUDefFormat(virBuffer *buf, virBufferAsprintf(&driverAttrBuf, " fsts='%s'", virTristateSwitchTypeToString(iommu->fsts)); } + if (iommu->pasid_bits > 0) { + virBufferAsprintf(&driverAttrBuf, " pasid_bits='%u'", + iommu->pasid_bits); + } 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 e2076e7c36..16d3006c6f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3106,6 +3106,7 @@ struct _virDomainIOMMUDef { virTristateSwitch dma_translation; virTristateSwitch scalable_mode; virTristateSwitch fsts; + virTristateSwitch pasid_bits; 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 1fae3a04a9..fb89dcb8aa 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -3204,6 +3204,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->pasid_bits != 0 || iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT || iommu->pt != VIR_TRISTATE_SWITCH_ABSENT || iommu->granule != 0) { @@ -3232,6 +3233,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->pasid_bits != 0 || iommu->pci_bus >= 0 || iommu->accel != VIR_TRISTATE_SWITCH_ABSENT || iommu->cmdqv != VIR_TRISTATE_SWITCH_ABSENT || @@ -3262,6 +3264,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->pasid_bits != 0 || 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 ff905c18c2..888d0db214 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -6434,6 +6434,11 @@ <ref name="virOnOff"/> </attribute> </optional> + <optional> + <attribute name="pasid_bits"> + <ref name="uint8"/> + </attribute> + </optional> <optional> <attribute name="xtsup"> <ref name="virOnOff"/> diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index f2c91a743f..c343843068 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -5855,6 +5855,17 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu, _("iommu: fsts is not supported with this QEMU binary")); return -1; } + if (iommu->pasid_bits > 0 && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_PASID_BITS)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("iommu: pasid_bits is not supported with this QEMU binary")); + return -1; + } + if (iommu->pasid_bits > 20) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("iommu: unsupported pasid bit width. Max value supported is 20 according to PCI spec")); + 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-pasid-bits.x86_64-latest.args b/tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.args new file mode 100644 index 0000000000..5db49142e5 --- /dev/null +++ b/tests/qemuxmlconfdata/intel-iommu-pasid-bits.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}' \ +-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-pasid-bits.x86_64-latest.xml b/tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.xml new file mode 100644 index 0000000000..cbf5cce48a --- /dev/null +++ b/tests/qemuxmlconfdata/intel-iommu-pasid-bits.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'/> + </iommu> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/intel-iommu-pasid-bits.xml b/tests/qemuxmlconfdata/intel-iommu-pasid-bits.xml new file mode 100644 index 0000000000..cbf5cce48a --- /dev/null +++ b/tests/qemuxmlconfdata/intel-iommu-pasid-bits.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'/> + </iommu> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 837bea7b63..bc83367cd8 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -2991,6 +2991,7 @@ mymain(void) 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("intel-iommu-pasid-bits"); 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
On Wed, Sep 09, 2026 at 16:29:55 +0800, Zhenzhong Duan wrote:
Add pasid_bits attribute to iommu to set pasid bit width or disable pasid capability if 0 for intel-iommu.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- docs/formatdomain.rst | 5 +++ 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 | 11 ++++++ .../intel-iommu-pasid-bits.x86_64-latest.args | 34 +++++++++++++++++ .../intel-iommu-pasid-bits.x86_64-latest.xml | 37 +++++++++++++++++++ .../intel-iommu-pasid-bits.xml | 37 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 10 files changed, 150 insertions(+) create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.xml
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index f376cefc16..14fe85e817 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -9490,6 +9490,11 @@ Examples: Enable first stage translation. :since:`Since 12.8.0` (QEMU/KVM and ``intel`` model only)
+ ``pasid-bits`` + The ``pasid-bits`` attribute can be used to set the pasid bit width.
Both of these have a dash in the name ...
+ 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) + 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 b6c3df0404..7b8a7e7c68 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14786,6 +14786,10 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt, &iommu->fsts) < 0) return NULL;
+ if (virXMLPropUInt(driver, "pasid_bits", 10, VIR_XML_PROP_NONE,
... but the actual parser wants an underscore.
+ &iommu->pasid_bits) < 0) + return NULL; + if ((granule = virXPathNode("./driver/granule", ctxt))) { g_autofree char *mode = virXMLPropString(granule, "mode"); unsigned long long size;
[...]
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e2076e7c36..16d3006c6f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3106,6 +3106,7 @@ struct _virDomainIOMMUDef { virTristateSwitch dma_translation; virTristateSwitch scalable_mode; virTristateSwitch fsts; + virTristateSwitch pasid_bits;
This is parsed as an unsigned integer. I know that it typecasts to an enum cleanly but nevertheless needs to use the correct type.
-----Original Message----- From: Peter Krempa <pkrempa@redhat.com> Subject: Re: [PATCH v2 08/12] conf: add pasid_bits attribute to iommu
On Wed, Sep 09, 2026 at 16:29:55 +0800, Zhenzhong Duan wrote:
Add pasid_bits attribute to iommu to set pasid bit width or disable pasid capability if 0 for intel-iommu.
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- docs/formatdomain.rst | 5 +++ 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 | 11 ++++++ .../intel-iommu-pasid-bits.x86_64-latest.args | 34 +++++++++++++++++ .../intel-iommu-pasid-bits.x86_64-latest.xml | 37 +++++++++++++++++++ .../intel-iommu-pasid-bits.xml | 37 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 10 files changed, 150 insertions(+) create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64- latest.args create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64- latest.xml create mode 100644 tests/qemuxmlconfdata/intel-iommu-pasid-bits.xml
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index f376cefc16..14fe85e817 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -9490,6 +9490,11 @@ Examples: Enable first stage translation. :since:`Since 12.8.0` (QEMU/KVM and ``intel`` model only)
+ ``pasid-bits`` + The ``pasid-bits`` attribute can be used to set the pasid bit width.
Both of these have a dash in the name ...
+ 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) + 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 b6c3df0404..7b8a7e7c68 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14786,6 +14786,10 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt, &iommu->fsts) < 0) return NULL;
+ if (virXMLPropUInt(driver, "pasid_bits", 10, VIR_XML_PROP_NONE,
... but the actual parser wants an underscore.
Oh, will fix.
+ &iommu->pasid_bits) < 0) + return NULL; + if ((granule = virXPathNode("./driver/granule", ctxt))) { g_autofree char *mode = virXMLPropString(granule, "mode"); unsigned long long size;
[...]
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e2076e7c36..16d3006c6f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3106,6 +3106,7 @@ struct _virDomainIOMMUDef { virTristateSwitch dma_translation; virTristateSwitch scalable_mode; virTristateSwitch fsts; + virTristateSwitch pasid_bits;
This is parsed as an unsigned integer. I know that it typecasts to an enum cleanly but nevertheless needs to use the correct type.
Good catch, will fix. Thanks Zhenzhong
Add pasid-bits attribute to qemu command line if specified in domain conf. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_command.c | 1 + tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.args | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8c59ca4383..5ea8337602 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6345,6 +6345,7 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, "T:dma-translation", iommu->dma_translation, "T:scalable-mode", iommu->scalable_mode, "T:fsts", iommu->fsts, + "p:pasid-bits", iommu->pasid_bits, NULL) < 0) return -1; diff --git a/tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.args b/tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.args index 5db49142e5..e2f5adfc93 100644 --- a/tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.args +++ b/tests/qemuxmlconfdata/intel-iommu-pasid-bits.x86_64-latest.args @@ -26,7 +26,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -rtc base=utc \ -no-shutdown \ -boot strict=on \ --device '{"driver":"intel-iommu","id":"iommu0","scalable-mode":true,"fsts":true}' \ +-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 \ -- 2.52.0
This capability tracks whether intel-iommu device has svm attribute. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_11.0.0_x86_64+sgx.xml | 1 + tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml | 1 + 5 files changed, 6 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 606c5385e9..3c3a196b23 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -781,6 +781,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 505 */ "intel-iommu.pasid-bits", /* QEMU_CAPS_INTEL_IOMMU_PASID_BITS */ + "intel-iommu.svm", /* QEMU_CAPS_INTEL_IOMMU_SVM */ ); @@ -1627,6 +1628,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsIntelIOMMU[] = { { "scalable-mode", QEMU_CAPS_INTEL_IOMMU_SCALABLE_MODE, NULL }, { "fsts", QEMU_CAPS_INTEL_IOMMU_FSTS, NULL }, { "pasid-bits", QEMU_CAPS_INTEL_IOMMU_PASID_BITS, NULL }, + { "svm", QEMU_CAPS_INTEL_IOMMU_SVM, NULL }, }; static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsMCH[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 30af10da79..02ea9403a2 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -755,6 +755,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 505 */ QEMU_CAPS_INTEL_IOMMU_PASID_BITS, /* intel-iommu.pasid-bits */ + QEMU_CAPS_INTEL_IOMMU_SVM, /* intel-iommu.svm */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64+sgx.xml b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64+sgx.xml index 108f4b0b86..74628b3c0c 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64+sgx.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64+sgx.xml @@ -222,6 +222,7 @@ <flag name='query-block-flat'/> <flag name='amd-iommu.xtsup'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='intel-iommu.svm'/> <version>11000000</version> <microcodeVersion>43100286</microcodeVersion> <package>v11.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml index 29fdaf20d8..fb01666a16 100644 --- a/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.0.0_x86_64.xml @@ -221,6 +221,7 @@ <flag name='query-block-flat'/> <flag name='amd-iommu.xtsup'/> <flag name='blockdev-mirror.target-is-zero'/> + <flag name='intel-iommu.svm'/> <version>11000000</version> <microcodeVersion>43100286</microcodeVersion> <package>v11.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml index 38a782b2e3..aa66d10a6b 100644 --- a/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_11.1.0_x86_64.xml @@ -227,6 +227,7 @@ <flag name='intel-iommu.scalable-mode'/> <flag name='intel-iommu.fsts'/> <flag name='intel-iommu.pasid-bits'/> + <flag name='intel-iommu.svm'/> <version>11001000</version> <microcodeVersion>43100287</microcodeVersion> <package>v11.1.0</package> -- 2.52.0
Add svm attribute to iommu to enable/disable shared virtual memory capability for intel-iommu. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- 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
Add svm attribute to qemu command line if specified in domain conf. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> --- src/qemu/qemu_command.c | 1 + tests/qemuxmlconfdata/intel-iommu-svm.x86_64-latest.args | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 5ea8337602..f1a1bde3aa 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6346,6 +6346,7 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, "T:scalable-mode", iommu->scalable_mode, "T:fsts", iommu->fsts, "p:pasid-bits", iommu->pasid_bits, + "T:svm", iommu->svm, NULL) < 0) return -1; diff --git a/tests/qemuxmlconfdata/intel-iommu-svm.x86_64-latest.args b/tests/qemuxmlconfdata/intel-iommu-svm.x86_64-latest.args index e2f5adfc93..9cacafe6d3 100644 --- a/tests/qemuxmlconfdata/intel-iommu-svm.x86_64-latest.args +++ b/tests/qemuxmlconfdata/intel-iommu-svm.x86_64-latest.args @@ -26,7 +26,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -rtc base=utc \ -no-shutdown \ -boot strict=on \ --device '{"driver":"intel-iommu","id":"iommu0","scalable-mode":true,"fsts":true,"pasid-bits":6}' \ +-device '{"driver":"intel-iommu","id":"iommu0","scalable-mode":true,"fsts":true,"pasid-bits":6,"svm":true}' \ -audiodev '{"id":"audio1","driver":"none"}' \ -global ICH9-LPC.noreboot=off \ -watchdog-action reset \ -- 2.52.0
On Wed, Sep 09, 2026 at 16:29:47 +0800, Zhenzhong Duan wrote:
Hi,
This series adds support for configuring Intel vIOMMU (VT-d) in domain XML and formatting them onto the QEMU command line:
I've got couple of high-level questions:
* scalable_mode: Configures scalable mode support ('on'/'off'). * fsts: Enables First-Stage Translation support ('on'/'off'). * pasid_bits: Sets the number of supported PASID bits. * svm: Enables Shared Virtual Memory (SVM) / PRQ support ('on'/'off').
Are users actually expected to set these? The libvirt documentation that is added by this series doesn't really describe what the feature does, just names them. So ...
With these attributes, users can configure advanced vIOMMU features for both emulated devices and assigned host devices (e.g., vSVA / nested translation via iommufd and first-stage translation).
... can users meaningfully influence what they get? Arent't the defaults enough? I'll also add some style/code comments inline.
-----Original Message----- From: Peter Krempa <pkrempa@redhat.com> Subject: Re: [PATCH v2 00/12] conf, qemu: Add scalable_mode, fsts, pasid_bits, and svm support for intel-iommu
On Wed, Sep 09, 2026 at 16:29:47 +0800, Zhenzhong Duan wrote:
Hi,
This series adds support for configuring Intel vIOMMU (VT-d) in domain XML and formatting them onto the QEMU command line:
I've got couple of high-level questions:
* scalable_mode: Configures scalable mode support ('on'/'off'). * fsts: Enables First-Stage Translation support ('on'/'off'). * pasid_bits: Sets the number of supported PASID bits. * svm: Enables Shared Virtual Memory (SVM) / PRQ support ('on'/'off').
Are users actually expected to set these? The libvirt documentation that is added by this series doesn't really describe what the feature does, just names them.
So ...
With these attributes, users can configure advanced vIOMMU features for both emulated devices and assigned host devices (e.g., vSVA / nested translation via iommufd and first-stage translation).
... can users meaningfully influence what they get? Arent't the defaults enough?
The default of value of pasid_bits is 0, default of other three properties are 'off' in qemu. So these properties need to be set explicitly to use the advanced vIOMMU features. To summarize: - `scalable_mode='on'`: Required whenever a guest wants to use Intel Scalable Mode (VT-d 3.0+). Legacy mode only supports single address spaces per PCI device; scalable mode allows multiple process address spaces (via PASIDs) and 1st-stage/2nd-stage translation. - `fsts='on'`: Enables first-stage (GVA -> GPA) translation in vIOMMU. This is mandatory for nested translation (FLPT - First Level Page Table) when assigning devices via IOMMUFD and allowing the guest kernel to manage its own stage-1 page tables. - `pasid_bits`: Configures the PASID width supported by the virtual IOMMU (1 to 20 bits). Users need to tune this depending on the guest OS scalability requirements or match the physical host device capabilities during device assignment (e.g., if a host accelerator or physical IOMMU only supports a specific PASID width). - `svm='on'`: Enables Shared Virtual Memory (SVM), which advertises Page Request Interface (PRI) and Page Request Queue (PRQ) capabilities. This allows user-space applications inside the guest to directly submit work to physical/emulated devices using virtual addresses without explicit pinning (shared virtual addressing / SVA). Thanks Zhenzhong
participants (3)
-
Duan, Zhenzhong -
Peter Krempa -
Zhenzhong Duan