From e0dd452c0cb37af3a8c15bce2f4ac8d624fcee79 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Thu, 17 Jul 2025 12:49:16 +0200 Subject: [PATCH] libvirt-10.10.0-14.el9 - qemu: introduce QEMU_CAPS_AMD_IOMMU (RHEL-50560) - qemu: introduce QEMU_CAPS_PCI_ID (RHEL-50560) - docs: formatdomain: document intel-only IOMMU attributes (RHEL-50560) - qemu: add IOMMU model amd (RHEL-50560) - conf: add passthrough and xtsup attributes for IOMMU (RHEL-50560) - esx: Allow specifying different CA bundle for remote connections (RHEL-97440) Resolves: RHEL-50560, RHEL-97440 --- ...rough-and-xtsup-attributes-for-IOMMU.patch | 198 + ...document-intel-only-IOMMU-attributes.patch | 61 + ...ent-CA-bundle-for-remote-connections.patch | 119 + libvirt-qemu-add-IOMMU-model-amd.patch | 337 ++ ...t-qemu-introduce-QEMU_CAPS_AMD_IOMMU.patch | 253 + libvirt-qemu-introduce-QEMU_CAPS_PCI_ID.patch | 4646 +++++++++++++++++ libvirt.spec | 16 +- 7 files changed, 5629 insertions(+), 1 deletion(-) create mode 100644 libvirt-conf-add-passthrough-and-xtsup-attributes-for-IOMMU.patch create mode 100644 libvirt-docs-formatdomain-document-intel-only-IOMMU-attributes.patch create mode 100644 libvirt-esx-Allow-specifying-different-CA-bundle-for-remote-connections.patch create mode 100644 libvirt-qemu-add-IOMMU-model-amd.patch create mode 100644 libvirt-qemu-introduce-QEMU_CAPS_AMD_IOMMU.patch create mode 100644 libvirt-qemu-introduce-QEMU_CAPS_PCI_ID.patch diff --git a/libvirt-conf-add-passthrough-and-xtsup-attributes-for-IOMMU.patch b/libvirt-conf-add-passthrough-and-xtsup-attributes-for-IOMMU.patch new file mode 100644 index 0000000..d4fc76f --- /dev/null +++ b/libvirt-conf-add-passthrough-and-xtsup-attributes-for-IOMMU.patch @@ -0,0 +1,198 @@ +From 2cd8164cffc5be97e2836862a4fc44578dae2b47 Mon Sep 17 00:00:00 2001 +Message-ID: <2cd8164cffc5be97e2836862a4fc44578dae2b47.1752749355.git.jdenemar@redhat.com> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Fri, 14 Mar 2025 17:13:31 +0100 +Subject: [PATCH] conf: add passthrough and xtsup attributes for IOMMU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For the newly supported AMD device. + +Signed-off-by: Ján Tomko +Reviewed-by: Peter Krempa +(cherry picked from commit 856f667c8a3b44417f3b5bb42db5e8bf971bacd4) + +https://issues.redhat.com/browse/RHEL-50560 + +Signed-off-by: Ján Tomko +--- + docs/formatdomain.rst | 8 +++++ + src/conf/domain_conf.c | 30 +++++++++++++++++++ + src/conf/domain_conf.h | 2 ++ + src/conf/domain_validate.c | 9 ++++++ + src/conf/schemas/domaincommon.rng | 10 +++++++ + src/qemu/qemu_command.c | 2 ++ + .../amd-iommu.x86_64-latest.args | 2 +- + tests/qemuxmlconfdata/amd-iommu.xml | 2 +- + 8 files changed, 63 insertions(+), 2 deletions(-) + +diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst +index ec7bdb07d0..847c9ebc6e 100644 +--- a/docs/formatdomain.rst ++++ b/docs/formatdomain.rst +@@ -8885,6 +8885,14 @@ Example: + example to efficiently enable more than 255 vCPUs. + :since:`Since 10.7.0` (QEMU/KVM and ``intel`` model only) + ++ ``passthrough`` ++ Enable passthrough. In this mode, DMA read/writes are not translated. ++ :since:`Since 11.5.0` (QEMU/KVM and ``amd`` model only) ++ ++ ``xtsup`` ++ Enable x2APIC mode. Useful for higher number of guest CPUs. ++ :since:`Since 11.5.0` (QEMU/KVM and ``amd`` model 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 7c8591e509..286e59a4c7 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -14063,6 +14063,14 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt, + if (virXMLPropTristateSwitch(driver, "dma_translation", VIR_XML_PROP_NONE, + &iommu->dma_translation) < 0) + return NULL; ++ ++ if (virXMLPropTristateSwitch(driver, "xtsup", VIR_XML_PROP_NONE, ++ &iommu->xtsup) < 0) ++ return NULL; ++ ++ if (virXMLPropTristateSwitch(driver, "passthrough", VIR_XML_PROP_NONE, ++ &iommu->pt) < 0) ++ return NULL; + } + + if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, +@@ -21682,6 +21690,20 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef *src, + virTristateSwitchTypeToString(src->dma_translation)); + return false; + } ++ if (src->pt != dst->pt) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("Target domain IOMMU device dma translation '%1$s' does not match source '%2$s'"), ++ virTristateSwitchTypeToString(dst->pt), ++ virTristateSwitchTypeToString(src->pt)); ++ return false; ++ } ++ if (src->xtsup != dst->xtsup) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("Target domain IOMMU device dma translation '%1$s' does not match source '%2$s'"), ++ virTristateSwitchTypeToString(dst->xtsup), ++ virTristateSwitchTypeToString(src->xtsup)); ++ return false; ++ } + + return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info); + } +@@ -27735,6 +27757,14 @@ virDomainIOMMUDefFormat(virBuffer *buf, + virBufferAsprintf(&driverAttrBuf, " dma_translation='%s'", + virTristateSwitchTypeToString(iommu->dma_translation)); + } ++ if (iommu->pt != VIR_TRISTATE_SWITCH_ABSENT) { ++ virBufferAsprintf(&driverAttrBuf, " passthrough='%s'", ++ virTristateSwitchTypeToString(iommu->pt)); ++ } ++ if (iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT) { ++ virBufferAsprintf(&driverAttrBuf, " xtsup='%s'", ++ virTristateSwitchTypeToString(iommu->xtsup)); ++ } + + virXMLFormatElement(&childBuf, "driver", &driverAttrBuf, NULL); + +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 343bb9bae0..e59d2e6c5f 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -2987,6 +2987,8 @@ struct _virDomainIOMMUDef { + unsigned int aw_bits; + virDomainDeviceInfo info; + virTristateSwitch dma_translation; ++ virTristateSwitch xtsup; ++ virTristateSwitch pt; + }; + + typedef enum { +diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c +index 483cfbbe08..522fd0174f 100644 +--- a/src/conf/domain_validate.c ++++ b/src/conf/domain_validate.c +@@ -2999,6 +2999,15 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu) + break; + + case VIR_DOMAIN_IOMMU_MODEL_INTEL: ++ if (iommu->pt != VIR_TRISTATE_SWITCH_ABSENT || ++ iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT) { ++ virReportError(VIR_ERR_XML_ERROR, ++ _("iommu model '%1$s' doesn't support some additional attributes"), ++ virDomainIOMMUModelTypeToString(iommu->model)); ++ return -1; ++ } ++ break; ++ + case VIR_DOMAIN_IOMMU_MODEL_LAST: + break; + } +diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng +index 38a0586f40..1b153acc48 100644 +--- a/src/conf/schemas/domaincommon.rng ++++ b/src/conf/schemas/domaincommon.rng +@@ -6210,6 +6210,16 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c +index de535029a8..fffc8be08a 100644 +--- a/src/qemu/qemu_command.c ++++ b/src/qemu/qemu_command.c +@@ -6113,6 +6113,8 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, + "s:driver", "amd-iommu", + "s:pci-id", iommu->info.alias, + "S:intremap", qemuOnOffAuto(iommu->intremap), ++ "T:pt", iommu->pt, ++ "T:xtsup", iommu->xtsup, + "T:device-iotlb", iommu->iotlb, + NULL) < 0) + return -1; +diff --git a/tests/qemuxmlconfdata/amd-iommu.x86_64-latest.args b/tests/qemuxmlconfdata/amd-iommu.x86_64-latest.args +index 36244edb3a..20d7e379e6 100644 +--- a/tests/qemuxmlconfdata/amd-iommu.x86_64-latest.args ++++ b/tests/qemuxmlconfdata/amd-iommu.x86_64-latest.args +@@ -27,7 +27,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ + -no-shutdown \ + -boot strict=on \ + -device '{"driver":"AMDVI-PCI","id":"iommu0","bus":"pcie.0","addr":"0x1"}' \ +--device '{"driver":"amd-iommu","pci-id":"iommu0","intremap":"on","device-iotlb":true}' \ ++-device '{"driver":"amd-iommu","pci-id":"iommu0","intremap":"on","pt":true,"xtsup":true,"device-iotlb":true}' \ + -audiodev '{"id":"audio1","driver":"none"}' \ + -global ICH9-LPC.noreboot=off \ + -watchdog-action reset \ +diff --git a/tests/qemuxmlconfdata/amd-iommu.xml b/tests/qemuxmlconfdata/amd-iommu.xml +index 0668ed4237..4ad79ce4ae 100644 +--- a/tests/qemuxmlconfdata/amd-iommu.xml ++++ b/tests/qemuxmlconfdata/amd-iommu.xml +@@ -32,7 +32,7 @@ + + + +- ++ +
+ + +-- +2.50.1 diff --git a/libvirt-docs-formatdomain-document-intel-only-IOMMU-attributes.patch b/libvirt-docs-formatdomain-document-intel-only-IOMMU-attributes.patch new file mode 100644 index 0000000..e0038cf --- /dev/null +++ b/libvirt-docs-formatdomain-document-intel-only-IOMMU-attributes.patch @@ -0,0 +1,61 @@ +From 229d362a429fdcf64f91cf2422ab6a402d0af3fa Mon Sep 17 00:00:00 2001 +Message-ID: <229d362a429fdcf64f91cf2422ab6a402d0af3fa.1752749355.git.jdenemar@redhat.com> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Wed, 19 Mar 2025 01:55:02 +0100 +Subject: [PATCH] docs: formatdomain: document intel-only IOMMU attributes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Ján Tomko +Reviewed-by: Peter Krempa +(cherry picked from commit 6291b0af3dd6a34b5a0f5f56dafa881d9c262f57) + +https://issues.redhat.com/browse/RHEL-50560 + +Signed-off-by: Ján Tomko +--- + docs/formatdomain.rst | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst +index 961d20a41d..a950ee1cb4 100644 +--- a/docs/formatdomain.rst ++++ b/docs/formatdomain.rst +@@ -8857,14 +8857,15 @@ Example: + ``caching_mode`` + The ``caching_mode`` attribute with possible values ``on`` and ``off`` can + be used to turn on the VT-d caching mode (useful for assigned devices). +- :since:`Since 3.4.0` (QEMU/KVM only) ++ :since:`Since 3.4.0` (QEMU/KVM and ``intel`` model only) + + ``eim`` + The ``eim`` attribute (with possible values ``on`` and ``off``) can be + used to configure Extended Interrupt Mode. A q35 domain with split I/O + APIC (as described in `Hypervisor features`_), and + both interrupt remapping and EIM turned on for the IOMMU, will be able to +- use more than 255 vCPUs. :since:`Since 3.4.0` (QEMU/KVM only) ++ use more than 255 vCPUs. :since:`Since 3.4.0` (QEMU/KVM and ``intel`` model ++ only) + + ``iotlb`` + The ``iotlb`` attribute with possible values ``on`` and ``off`` can be +@@ -8874,14 +8875,14 @@ Example: + ``aw_bits`` + The ``aw_bits`` attribute can be used to set the address width to allow + mapping larger iova addresses in the guest. :since:`Since 6.5.0` (QEMU/KVM +- only) ++ and ``intel`` model 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) ++ :since:`Since 10.7.0` (QEMU/KVM and ``intel`` model only) + + The ``virtio`` IOMMU devices can further have ``address`` element as described + in `Device addresses`_ (address has to by type of ``pci``). +-- +2.50.1 diff --git a/libvirt-esx-Allow-specifying-different-CA-bundle-for-remote-connections.patch b/libvirt-esx-Allow-specifying-different-CA-bundle-for-remote-connections.patch new file mode 100644 index 0000000..5114e44 --- /dev/null +++ b/libvirt-esx-Allow-specifying-different-CA-bundle-for-remote-connections.patch @@ -0,0 +1,119 @@ +From b554cae09e7870484240b023865bd13fe56878d1 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Martin Kletzander +Date: Mon, 9 Jun 2025 15:40:12 +0200 +Subject: [PATCH] esx: Allow specifying different CA bundle for remote + connections +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add new URI parameter which allows for using non-system CA certificates +to verify remote peers. + +Signed-off-by: Martin Kletzander +Reviewed-by: Ján Tomko +(cherry picked from commit 6c9a0beeca1c6a54eda5d15ba27925c734d51279) + +Resolves: https://issues.redhat.com/browse/RHEL-97440 + +Signed-off-by: Martin Kletzander +--- + docs/drvesx.rst | 16 ++++++++++++++-- + src/esx/esx_util.c | 4 ++++ + src/esx/esx_util.h | 1 + + src/esx/esx_vi.c | 3 +++ + 4 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/docs/drvesx.rst b/docs/drvesx.rst +index 13c2bc37e5..84416562ba 100644 +--- a/docs/drvesx.rst ++++ b/docs/drvesx.rst +@@ -91,7 +91,7 @@ Multiple parameters are separated by ``&``. + + :: + +- ?no_verify=1&auto_answer=1&proxy=socks://example-proxy.com:23456 ++ ?no_verify=1&auto_answer=1&proxy=socks://example-proxy.com:23456&cacert=certs/ca-bundle.pem + + The driver understands the extra parameters shown below. + +@@ -146,6 +146,16 @@ The driver understands the extra parameters shown below. + | | | ``port`` allows to override | + | | | the default port 1080. | + +-----------------+-----------------------------+-----------------------------+ ++| ``cacert`` | Path to a file with one | The specified file will be | ++| | or more certificates | used for verifying the | ++| | | remote host certificate | ++| | | instead of the default | ++| | | system one. | ++| | | :since:`Since 11.5.0`. | ++| | | Does nothing if | ++| | | ``no_verify`` is set | ++| | | to ``1``. | +++-----------------+-----------------------------+-----------------------------+ + + Authentication + ~~~~~~~~~~~~~~ +@@ -181,8 +191,10 @@ error like this one: + + error: internal error curl_easy_perform() returned an error: Peer certificate cannot be authenticated with known CA certificates (60) + +-Where are two ways to solve this problem: ++Where are three ways to solve this problem: + ++- Use the ``cacert`` `Extra parameters`_ to point to a certificate bundle ++ with the CA that signed the SSL certificate used on the ESX server. + - Use the ``no_verify=1`` `Extra parameters`_ to disable server + certificate verification. + - Generate new SSL certificates signed by a CA known to your client computer +diff --git a/src/esx/esx_util.c b/src/esx/esx_util.c +index cb9638f360..7ee0e5f7c0 100644 +--- a/src/esx/esx_util.c ++++ b/src/esx/esx_util.c +@@ -135,6 +135,9 @@ esxUtil_ParseUri(esxUtil_ParsedUri **parsedUri, virURI *uri) + goto cleanup; + } + } ++ } else if (STRCASEEQ(queryParam->name, "cacert")) { ++ g_clear_pointer(&(*parsedUri)->cacert, g_free); ++ (*parsedUri)->cacert = g_strdup(queryParam->value); + } else { + VIR_WARN("Ignoring unexpected query parameter '%s'", + queryParam->name); +@@ -168,6 +171,7 @@ esxUtil_FreeParsedUri(esxUtil_ParsedUri **parsedUri) + g_free((*parsedUri)->vCenter); + g_free((*parsedUri)->proxy_hostname); + g_free((*parsedUri)->path); ++ g_free((*parsedUri)->cacert); + + g_free(*parsedUri); + } +diff --git a/src/esx/esx_util.h b/src/esx/esx_util.h +index 088c943e64..58bc44e744 100644 +--- a/src/esx/esx_util.h ++++ b/src/esx/esx_util.h +@@ -44,6 +44,7 @@ struct _esxUtil_ParsedUri { + char *proxy_hostname; + int proxy_port; + char *path; ++ char *cacert; + }; + + int esxUtil_ParseUri(esxUtil_ParsedUri **parsedUri, virURI *uri); +diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c +index 3ecd406e1d..d49daa5bc6 100644 +--- a/src/esx/esx_vi.c ++++ b/src/esx/esx_vi.c +@@ -343,6 +343,9 @@ esxVI_CURL_Connect(esxVI_CURL *curl, esxUtil_ParsedUri *parsedUri) + parsedUri->proxy_port); + } + ++ if (parsedUri->cacert) ++ curl_easy_setopt(curl->handle, CURLOPT_CAINFO, parsedUri->cacert); ++ + if (virMutexInit(&curl->lock) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not initialize CURL mutex")); +-- +2.50.1 diff --git a/libvirt-qemu-add-IOMMU-model-amd.patch b/libvirt-qemu-add-IOMMU-model-amd.patch new file mode 100644 index 0000000..ba02509 --- /dev/null +++ b/libvirt-qemu-add-IOMMU-model-amd.patch @@ -0,0 +1,337 @@ +From 62862c4c7302758d304dd876f26712a75df26e08 Mon Sep 17 00:00:00 2001 +Message-ID: <62862c4c7302758d304dd876f26712a75df26e08.1752749355.git.jdenemar@redhat.com> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Fri, 14 Mar 2025 17:13:09 +0100 +Subject: [PATCH] qemu: add IOMMU model amd +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce a new IOMMU device model 'amd', both the parser +and the formatter for QEMU because of our enum warnings. + +https://issues.redhat.com/browse/RHEL-50560 + +Signed-off-by: Ján Tomko +Reviewed-by: Peter Krempa +(cherry picked from commit 14760600914ea6b5da778dd470823e734becf630) + +Signed-off-by: Ján Tomko +--- + docs/formatdomain.rst | 5 ++- + src/conf/domain_conf.c | 1 + + src/conf/domain_conf.h | 1 + + src/conf/domain_validate.c | 13 +++++++ + src/conf/schemas/domaincommon.rng | 1 + + src/qemu/qemu_command.c | 28 +++++++++++++ + src/qemu/qemu_domain_address.c | 4 ++ + src/qemu/qemu_validate.c | 22 +++++++++++ + .../amd-iommu.x86_64-latest.args | 35 +++++++++++++++++ + .../amd-iommu.x86_64-latest.xml | 1 + + tests/qemuxmlconfdata/amd-iommu.xml | 39 +++++++++++++++++++ + tests/qemuxmlconftest.c | 2 + + 12 files changed, 150 insertions(+), 2 deletions(-) + create mode 100644 tests/qemuxmlconfdata/amd-iommu.x86_64-latest.args + create mode 120000 tests/qemuxmlconfdata/amd-iommu.x86_64-latest.xml + create mode 100644 tests/qemuxmlconfdata/amd-iommu.xml + +diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst +index a950ee1cb4..ec7bdb07d0 100644 +--- a/docs/formatdomain.rst ++++ b/docs/formatdomain.rst +@@ -8841,8 +8841,9 @@ Example: + + ``model`` + Supported values are ``intel`` (for Q35 guests) ``smmuv3`` +- (:since:`since 5.5.0`, for ARM virt guests), and ``virtio`` +- (:since:`since 8.3.0`, for Q35 and ARM virt guests). ++ (:since:`since 5.5.0`, for ARM virt guests), ``virtio`` ++ (:since:`since 8.3.0`, for Q35 and ARM virt guests) and ++ ``amd`` (:since:`since 11.5.0`). + + ``driver`` + The ``driver`` subelement can be used to configure additional options, some +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 726c3095ed..7c8591e509 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -1349,6 +1349,7 @@ VIR_ENUM_IMPL(virDomainIOMMUModel, + "intel", + "smmuv3", + "virtio", ++ "amd", + ); + + VIR_ENUM_IMPL(virDomainVsockModel, +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 20be6f7c05..343bb9bae0 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -2973,6 +2973,7 @@ typedef enum { + VIR_DOMAIN_IOMMU_MODEL_INTEL, + VIR_DOMAIN_IOMMU_MODEL_SMMUV3, + VIR_DOMAIN_IOMMU_MODEL_VIRTIO, ++ VIR_DOMAIN_IOMMU_MODEL_AMD, + + VIR_DOMAIN_IOMMU_MODEL_LAST + } virDomainIOMMUModel; +diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c +index 9cedc8d6d2..483cfbbe08 100644 +--- a/src/conf/domain_validate.c ++++ b/src/conf/domain_validate.c +@@ -2986,6 +2986,18 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu) + } + break; + ++ case VIR_DOMAIN_IOMMU_MODEL_AMD: ++ if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT || ++ iommu->eim != VIR_TRISTATE_SWITCH_ABSENT || ++ iommu->aw_bits != 0 || ++ iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT) { ++ virReportError(VIR_ERR_XML_ERROR, ++ _("iommu model '%1$s' doesn't support some additional attributes"), ++ virDomainIOMMUModelTypeToString(iommu->model)); ++ return -1; ++ } ++ break; ++ + case VIR_DOMAIN_IOMMU_MODEL_INTEL: + case VIR_DOMAIN_IOMMU_MODEL_LAST: + break; +@@ -3003,6 +3015,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu) + break; + + case VIR_DOMAIN_IOMMU_MODEL_VIRTIO: ++ case VIR_DOMAIN_IOMMU_MODEL_AMD: + case VIR_DOMAIN_IOMMU_MODEL_LAST: + break; + } +diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng +index d46eb44588..38a0586f40 100644 +--- a/src/conf/schemas/domaincommon.rng ++++ b/src/conf/schemas/domaincommon.rng +@@ -6174,6 +6174,7 @@ + intel + smmuv3 + virtio ++ amd + + + +diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c +index fb70c79a94..de535029a8 100644 +--- a/src/qemu/qemu_command.c ++++ b/src/qemu/qemu_command.c +@@ -6051,6 +6051,7 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, + virQEMUCaps *qemuCaps) + { + g_autoptr(virJSONValue) props = NULL; ++ g_autoptr(virJSONValue) wrapperProps = NULL; + const virDomainIOMMUDef *iommu = def->iommu; + + if (!iommu) +@@ -6095,6 +6096,32 @@ qemuBuildIOMMUCommandLine(virCommand *cmd, + /* There is no -device for SMMUv3, so nothing to be done here */ + return 0; + ++ case VIR_DOMAIN_IOMMU_MODEL_AMD: ++ if (virJSONValueObjectAdd(&wrapperProps, ++ "s:driver", "AMDVI-PCI", ++ "s:id", iommu->info.alias, ++ NULL) < 0) ++ return -1; ++ ++ if (qemuBuildDeviceAddressProps(wrapperProps, def, &iommu->info) < 0) ++ return -1; ++ ++ if (qemuBuildDeviceCommandlineFromJSON(cmd, wrapperProps, def, qemuCaps) < 0) ++ return -1; ++ ++ if (virJSONValueObjectAdd(&props, ++ "s:driver", "amd-iommu", ++ "s:pci-id", iommu->info.alias, ++ "S:intremap", qemuOnOffAuto(iommu->intremap), ++ "T:device-iotlb", iommu->iotlb, ++ NULL) < 0) ++ return -1; ++ ++ if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) < 0) ++ return -1; ++ ++ return 0; ++ + case VIR_DOMAIN_IOMMU_MODEL_LAST: + default: + virReportEnumRangeError(virDomainIOMMUModel, iommu->model); +@@ -6921,6 +6948,7 @@ qemuBuildMachineCommandLine(virCommand *cmd, + + case VIR_DOMAIN_IOMMU_MODEL_INTEL: + case VIR_DOMAIN_IOMMU_MODEL_VIRTIO: ++ case VIR_DOMAIN_IOMMU_MODEL_AMD: + /* These IOMMUs are formatted in qemuBuildIOMMUCommandLine */ + break; + +diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c +index b73ac9ebf1..d8ab5a03f7 100644 +--- a/src/qemu/qemu_domain_address.c ++++ b/src/qemu/qemu_domain_address.c +@@ -941,6 +941,9 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, + case VIR_DOMAIN_IOMMU_MODEL_VIRTIO: + return virtioFlags | VIR_PCI_CONNECT_INTEGRATED; + ++ case VIR_DOMAIN_IOMMU_MODEL_AMD: ++ return pciFlags | VIR_PCI_CONNECT_INTEGRATED; ++ + case VIR_DOMAIN_IOMMU_MODEL_INTEL: + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3: + case VIR_DOMAIN_IOMMU_MODEL_LAST: +@@ -2359,6 +2362,7 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def, + + switch (iommu->model) { + case VIR_DOMAIN_IOMMU_MODEL_VIRTIO: ++ case VIR_DOMAIN_IOMMU_MODEL_AMD: + if (virDeviceInfoPCIAddressIsWanted(&iommu->info) && + qemuDomainPCIAddressReserveNextAddr(addrs, &iommu->info) < 0) { + return -1; +diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c +index 97f8f58ffd..ddfb14399a 100644 +--- a/src/qemu/qemu_validate.c ++++ b/src/qemu/qemu_validate.c +@@ -5153,6 +5153,28 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu, + } + break; + ++ case VIR_DOMAIN_IOMMU_MODEL_AMD: ++ if (!qemuDomainIsQ35(def)) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("IOMMU device: '%1$s' is only supported with Q35 machines"), ++ virDomainIOMMUModelTypeToString(iommu->model)); ++ return -1; ++ } ++ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_AMD_IOMMU_PCI_ID)) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("IOMMU device: '%1$s' is not supported with this QEMU binary"), ++ virDomainIOMMUModelTypeToString(iommu->model)); ++ return -1; ++ } ++ if (iommu->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && ++ iommu->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("IOMMU device: '%1$s' needs a PCI address"), ++ virDomainIOMMUModelTypeToString(iommu->model)); ++ return -1; ++ } ++ break; ++ + case VIR_DOMAIN_IOMMU_MODEL_LAST: + default: + virReportEnumRangeError(virDomainIOMMUModel, iommu->model); +diff --git a/tests/qemuxmlconfdata/amd-iommu.x86_64-latest.args b/tests/qemuxmlconfdata/amd-iommu.x86_64-latest.args +new file mode 100644 +index 0000000000..36244edb3a +--- /dev/null ++++ b/tests/qemuxmlconfdata/amd-iommu.x86_64-latest.args +@@ -0,0 +1,35 @@ ++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=on \ ++-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":"AMDVI-PCI","id":"iommu0","bus":"pcie.0","addr":"0x1"}' \ ++-device '{"driver":"amd-iommu","pci-id":"iommu0","intremap":"on","device-iotlb":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/amd-iommu.x86_64-latest.xml b/tests/qemuxmlconfdata/amd-iommu.x86_64-latest.xml +new file mode 120000 +index 0000000000..5ba3d4b91b +--- /dev/null ++++ b/tests/qemuxmlconfdata/amd-iommu.x86_64-latest.xml +@@ -0,0 +1 @@ ++amd-iommu.xml +\ No newline at end of file +diff --git a/tests/qemuxmlconfdata/amd-iommu.xml b/tests/qemuxmlconfdata/amd-iommu.xml +new file mode 100644 +index 0000000000..0668ed4237 +--- /dev/null ++++ b/tests/qemuxmlconfdata/amd-iommu.xml +@@ -0,0 +1,39 @@ ++ ++ QEMUGuest1 ++ c7a5fdbd-edaf-9455-926a-d65c16db1809 ++ 219100 ++ 219100 ++ 1 ++ ++ hvm ++ ++ ++ ++ ++ ++ ++ ++ qemu64 ++ ++ ++ destroy ++ restart ++ destroy ++ ++ /usr/bin/qemu-system-x86_64 ++ ++ ++ ++
++ ++ ++ ++