conf: add dma_translation attribute to iommu

Add dma_translation attribute to iommu to enable/disable dma traslation
for intel-iommu

Signed-off-by: Sandesh Patel <sandesh.patel@nutanix.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Sandesh Patel 2024-08-07 07:37:50 +00:00 committed by Michal Privoznik
parent b2cc19e5fd
commit 6866f958c1
9 changed files with 107 additions and 0 deletions

View File

@ -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``).

View File

@ -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);

View File

@ -2928,6 +2928,7 @@ struct _virDomainIOMMUDef {
virTristateSwitch iotlb;
unsigned int aw_bits;
virDomainDeviceInfo info;
virTristateSwitch dma_translation;
};
typedef enum {

View File

@ -6100,6 +6100,11 @@
<ref name="uint8"/>
</attribute>
</optional>
<optional>
<attribute name="dma_translation">
<ref name="virOnOff"/>
</attribute>
</optional>
</element>
</optional>
<optional>

View File

@ -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;
}

View File

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

View File

@ -0,0 +1 @@
intel-iommu-dma-translation.xml

View File

@ -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 intremap='on' dma_translation='off'/>
</iommu>
</devices>
</domain>

View File

@ -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");