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 + + + +
+ + + +