]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu_domain: Automagically add IOMMU if needed
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 6 Nov 2024 11:57:21 +0000 (12:57 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 7 Nov 2024 09:46:33 +0000 (10:46 +0100)
If a Q35 domain has huge number of vCPUS (over 255, currently), then
it needs IOMMU with Extended Interrupt Mode enabled (see check in
qemuValidateDomainVCpuTopology()).

Well, we already add some devices and to other tricks when
parsing new domain XML. Might as well add IOMMU device if above
condition is met.

Resolves: https://issues.redhat.com/browse/RHEL-65844
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_domain.c
tests/qemuxmlconfdata/intel-iommu-eim-autoadd.xml

index 39f3e38351eba157a6fc42c4a2f9ef94f08df6e3..562fa76a78f88a3d764012c42edda516789177cc 100644 (file)
@@ -4262,6 +4262,7 @@ qemuDomainDefAddDefaultDevices(virQEMUDriver *driver,
     bool addDefaultUSBMouse = false;
     bool addPanicDevice = false;
     bool addITCOWatchdog = false;
+    bool addIOMMU = false;
 
     /* add implicit input devices */
     if (qemuDomainDefAddImplicitInputDevice(def, qemuCaps) < 0)
@@ -4284,6 +4285,10 @@ qemuDomainDefAddDefaultDevices(virQEMUDriver *driver,
             addImplicitSATA = true;
             addITCOWatchdog = true;
 
+            if (virDomainDefGetVcpusMax(def) > QEMU_MAX_VCPUS_WITHOUT_EIM) {
+                addIOMMU = true;
+            }
+
             /* Prefer adding a USB3 controller if supported, fall back
              * to USB2 if there is no USB3 available, and if that's
              * unavailable don't add anything.
@@ -4530,6 +4535,21 @@ qemuDomainDefAddDefaultDevices(virQEMUDriver *driver,
         }
     }
 
+    if (addIOMMU && !def->iommu &&
+        virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_INTEL_IOMMU) &&
+        virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_INTREMAP) &&
+        virQEMUCapsGet(qemuCaps, QEMU_CAPS_INTEL_IOMMU_EIM)) {
+        g_autoptr(virDomainIOMMUDef) iommu = NULL;
+
+        iommu = virDomainIOMMUDefNew();
+        iommu->model = VIR_DOMAIN_IOMMU_MODEL_INTEL;
+        /* eim requires intremap. */
+        iommu->intremap = VIR_TRISTATE_SWITCH_ON;
+        iommu->eim = VIR_TRISTATE_SWITCH_ON;
+
+        def->iommu = g_steal_pointer(&iommu);
+    }
+
     if (qemuDomainDefAddDefaultAudioBackend(driver, def) < 0)
         return -1;
 
index 7c294fe2f93b3f4236ee3e77b6fbb8a5dc277a17..fa3aaf0d4449593ff217a30370b949ab14d2dfa2 100644 (file)
@@ -30,6 +30,5 @@
     <audio id='1' type='none'/>
     <watchdog model='itco' action='reset'/>
     <memballoon model='none'/>
-    <iommu model='intel'/>
   </devices>
 </domain>