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