Add QEMU_CAPS_AMD_IOMMU_XTSUP capability and enable xtsup
by default for AMD IOMMU when a Q35 domain has >255 vCPUs,
similar to Intel EIM auto-enable logic. Also ensure intremap is
turned on when required.

Signed-off-by: Xiaotian Feng <[email protected]>
Reviewed-by: Ankit Soni <[email protected]>
Tested-by: Ankit Soni <[email protected]>
---
 src/qemu/qemu_capabilities.c |  2 ++
 src/qemu/qemu_capabilities.h |  1 +
 src/qemu/qemu_postparse.c    | 38 ++++++++++++++++++++++++------------
 3 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 5d75c23072..c8667fd77c 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -762,6 +762,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
               "scsi-block.migrate-pr", /* 
QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR */
               "iommufd", /* QEMU_CAPS_OBJECT_IOMMUFD */
               "uefi-vars", /* QEMU_CAPS_DEVICE_UEFI_VARS */
+              "amd-iommu.xtsup", /* QEMU_CAPS_AMD_IOMMU_XTSUP */
     );
 
 
@@ -1632,6 +1633,7 @@ static struct virQEMUCapsDevicePropsFlags 
virQEMUCapsDevicePropsVirtioBlkCCW[] =
 
 static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsAMDIOMMU[] = {
     { "pci-id", QEMU_CAPS_AMD_IOMMU_PCI_ID, NULL },
+    { "xtsup", QEMU_CAPS_AMD_IOMMU_XTSUP, NULL },
 };
 
 /* see documentation for virQEMUQAPISchemaPathGet for the query format */
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index a48e1d0367..5662c81e71 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -736,6 +736,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for 
syntax-check */
     QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR, /* persistent reservation 
migration support */
     QEMU_CAPS_OBJECT_IOMMUFD, /* -object iommufd */
     QEMU_CAPS_DEVICE_UEFI_VARS, /* -device uefi-vars-{x64,sysbus} */
+    QEMU_CAPS_AMD_IOMMU_XTSUP, /* amd-iommu.xtsup */
 
     QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c
index 58bd70c741..79e02e34ac 100644
--- a/src/qemu/qemu_postparse.c
+++ b/src/qemu/qemu_postparse.c
@@ -794,7 +794,7 @@ qemuDomainPstoreDefPostParse(virDomainPstoreDef *pstore,
 
 
 static bool
-qemuDomainNeedsIOMMUWithEIM(const virDomainDef *def)
+qemuDomainNeedsIOMMUWithx2APIC(const virDomainDef *def)
 {
     return ARCH_IS_X86(def->os.arch) &&
            virDomainDefGetVcpusMax(def) > QEMU_MAX_VCPUS_WITHOUT_X2APIC &&
@@ -808,22 +808,34 @@ qemuDomainIOMMUDefPostParse(virDomainIOMMUDef *iommu,
                             virQEMUCaps *qemuCaps,
                             unsigned int parseFlags)
 {
-    /* In case domain has huge number of vCPUS and Extended Interrupt Mode
-     * (EIM) is not explicitly turned off, let's enable it. If we didn't then
+    /* In case domain has huge number of vCPUS and x2APIC (intel EIM or AMD
+     * XTSUP) is not explicitly turned off, let's enable it. If we didn't then
      * guest will have troubles with interrupts. */
     if (parseFlags & VIR_DOMAIN_DEF_PARSE_ABI_UPDATE &&
-        qemuDomainNeedsIOMMUWithEIM(def) &&
-        iommu && iommu->model == VIR_DOMAIN_IOMMU_MODEL_INTEL) {
+        qemuDomainNeedsIOMMUWithx2APIC(def) && iommu) {
+        if (iommu->model == VIR_DOMAIN_IOMMU_MODEL_INTEL) {
+            /* eim requires intremap. */
+            if (iommu->intremap == VIR_TRISTATE_SWITCH_ABSENT &&
+                virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_INTREMAP)) {
+                iommu->intremap = VIR_TRISTATE_SWITCH_ON;
+            }
 
-        /* eim requires intremap. */
-        if (iommu->intremap == VIR_TRISTATE_SWITCH_ABSENT &&
-            virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_INTREMAP)) {
-            iommu->intremap = VIR_TRISTATE_SWITCH_ON;
+            if (iommu->eim == VIR_TRISTATE_SWITCH_ABSENT &&
+                virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_EIM)) {
+                iommu->eim = VIR_TRISTATE_SWITCH_ON;
+            }
         }
 
-        if (iommu->eim == VIR_TRISTATE_SWITCH_ABSENT &&
-            virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_EIM)) {
-            iommu->eim = VIR_TRISTATE_SWITCH_ON;
+        if (iommu->model == VIR_DOMAIN_IOMMU_MODEL_AMD) {
+            if (iommu->intremap == VIR_TRISTATE_SWITCH_ABSENT &&
+                virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_INTREMAP)) {
+                iommu->intremap = VIR_TRISTATE_SWITCH_ON;
+            }
+
+            if (iommu->xtsup == VIR_TRISTATE_SWITCH_ABSENT &&
+                virQEMUCapsGet(qemuCaps, QEMU_CAPS_AMD_IOMMU_XTSUP)) {
+                iommu->xtsup = VIR_TRISTATE_SWITCH_ON;
+            }
         }
     }
 
@@ -1544,7 +1556,7 @@ qemuDomainDefEnableDefaultFeatures(virDomainDef *def,
      * modified so change it now. */
     if (def->iommus && def->iommus[0]->pci_bus < 0 &&
         (def->iommus[0]->intremap == VIR_TRISTATE_SWITCH_ON ||
-         qemuDomainNeedsIOMMUWithEIM(def)) &&
+         qemuDomainNeedsIOMMUWithx2APIC(def)) &&
         def->features[VIR_DOMAIN_FEATURE_IOAPIC] == VIR_DOMAIN_IOAPIC_NONE) {
         def->features[VIR_DOMAIN_FEATURE_IOAPIC] = VIR_DOMAIN_IOAPIC_QEMU;
     }
-- 
2.34.1

Reply via email to