diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index c56b739b23..e1e219bcb5 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -8611,6 +8611,13 @@ Example:
mapping larger iova addresses in the guest. :since:`Since 6.5.0` (QEMU/KVM
only)
+ ``dma_translation``
+ The ``dma_translation`` attribute with possible values ``on`` and ``off`` can
+ be used to turn off the dma translation for IOMMU. It is useful when only
+ interrupt remapping is required but dma translation overhead is unwanted, for
+ example to efficiently enable more than 255 vCPUs.
+ :since:`Since 10.7.0` (QEMU/KVM only)
+
The ``virtio`` IOMMU devices can further have ``address`` element as described
in `Device addresses`_ (address has to by type of ``pci``).
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 86b563fbfb..d950921667 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -13931,6 +13931,10 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt,
if (virXMLPropUInt(driver, "aw_bits", 10, VIR_XML_PROP_NONE,
&iommu->aw_bits) < 0)
return NULL;
+
+ if (virXMLPropTristateSwitch(driver, "dma_translation", VIR_XML_PROP_NONE,
+ &iommu->dma_translation) < 0)
+ return NULL;
}
if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt,
@@ -21467,6 +21471,13 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef *src,
dst->aw_bits, src->aw_bits);
return false;
}
+ if (src->dma_translation != dst->dma_translation) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target domain IOMMU device dma translation '%1$s' does not match source '%2$s'"),
+ virTristateSwitchTypeToString(dst->dma_translation),
+ virTristateSwitchTypeToString(src->dma_translation));
+ return false;
+ }
return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info);
}
@@ -27451,6 +27462,10 @@ virDomainIOMMUDefFormat(virBuffer *buf,
virBufferAsprintf(&driverAttrBuf, " aw_bits='%d'",
iommu->aw_bits);
}
+ if (iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT) {
+ virBufferAsprintf(&driverAttrBuf, " dma_translation='%s'",
+ virTristateSwitchTypeToString(iommu->dma_translation));
+ }
virXMLFormatElement(&childBuf, "driver", &driverAttrBuf, NULL);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 95ddf5470e..eae621f900 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2928,6 +2928,7 @@ struct _virDomainIOMMUDef {
virTristateSwitch iotlb;
unsigned int aw_bits;
virDomainDeviceInfo info;
+ virTristateSwitch dma_translation;
};
typedef enum {
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 7d58dce465..05ba697924 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6100,6 +6100,11 @@
+
+
+
+
+
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 0e8f0f977f..b885fe7c77 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -5094,6 +5094,12 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu,
_("iommu: aw_bits is not supported with this QEMU binary"));
return -1;
}
+ if (iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT &&
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_DMA_TRANSLATION)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("iommu: updating dma translation is not supported with this QEMU binary"));
+ return -1;
+ }
return 0;
}
diff --git a/tests/qemuxmlconfdata/intel-iommu-dma-translation.x86_64-latest.args b/tests/qemuxmlconfdata/intel-iommu-dma-translation.x86_64-latest.args
new file mode 100644
index 0000000000..41f30d7fdc
--- /dev/null
+++ b/tests/qemuxmlconfdata/intel-iommu-dma-translation.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=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-device '{"driver":"intel-iommu","id":"iommu0","intremap":"on"}' \
+-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-dma-translation.x86_64-latest.xml b/tests/qemuxmlconfdata/intel-iommu-dma-translation.x86_64-latest.xml
new file mode 120000
index 0000000000..a35a254f7a
--- /dev/null
+++ b/tests/qemuxmlconfdata/intel-iommu-dma-translation.x86_64-latest.xml
@@ -0,0 +1 @@
+intel-iommu-dma-translation.xml
\ No newline at end of file
diff --git a/tests/qemuxmlconfdata/intel-iommu-dma-translation.xml b/tests/qemuxmlconfdata/intel-iommu-dma-translation.xml
new file mode 100644
index 0000000000..9b4debca0a
--- /dev/null
+++ b/tests/qemuxmlconfdata/intel-iommu-dma-translation.xml
@@ -0,0 +1,37 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+
+
+
+ qemu64
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 8aa8efea13..7e47c78150 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -2729,6 +2729,7 @@ mymain(void)
DO_TEST_CAPS_LATEST("intel-iommu-eim");
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_PARSE_ERROR("intel-iommu-wrong-machine");
DO_TEST_CAPS_ARCH_LATEST("iommu-smmuv3", "aarch64");
DO_TEST_CAPS_LATEST("virtio-iommu-x86_64");