]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu_hotplug: Add support to hotplug host device with IOMMUFD
authorPavel Hrdina <phrdina@redhat.com>
Sun, 15 Feb 2026 20:21:53 +0000 (21:21 +0100)
committerPavel Hrdina <phrdina@redhat.com>
Mon, 16 Feb 2026 14:50:39 +0000 (15:50 +0100)
For first host device we need to add iommufd object as well.

Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/qemu/qemu_hotplug.c
src/qemu/qemu_process.c
src/qemu/qemu_process.h

index 24fbccccf03cb4a5b734f1a5d493ace46ec9ce4e..bede4e3ccd22af9300b08f923f8c52d7aa77436d 100644 (file)
@@ -1553,13 +1553,16 @@ qemuDomainAttachHostPCIDevice(virQEMUDriver *driver,
     virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
                                { .hostdev = hostdev } };
     virDomainDeviceInfo *info = hostdev->info;
+    qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
     int ret;
     g_autoptr(virJSONValue) devprops = NULL;
+    g_autoptr(virJSONValue) objprops = NULL;
     bool releaseaddr = false;
     bool teardowncgroup = false;
     bool teardownlabel = false;
     bool teardowndevice = false;
     bool teardownmemlock = false;
+    bool removeiommufd = false;
     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
     unsigned int flags = 0;
 
@@ -1609,11 +1612,38 @@ qemuDomainAttachHostPCIDevice(virQEMUDriver *driver,
         goto error;
     }
 
+    if (virHostdevIsPCIDeviceWithIOMMUFD(hostdev)) {
+        if (qemuProcessOpenVfioDeviceFd(hostdev) < 0)
+            goto error;
+
+        if (!priv->iommufdState) {
+            if (qemuProcessOpenIommuFd(vm) < 0)
+                goto error;
+
+            if (!(objprops = qemuBuildIOMMUFDProps(priv->iommufd)))
+                goto error;
+        }
+    }
+
     if (!(devprops = qemuBuildPCIHostdevDevProps(vm->def, hostdev)))
         goto error;
 
     qemuDomainObjEnterMonitor(vm);
 
+    if (objprops) {
+        if ((ret = qemuFDPassDirectTransferMonitor(priv->iommufd, priv->mon)) < 0)
+            goto exit_monitor;
+
+        if ((ret = qemuMonitorAddObject(priv->mon, &objprops, NULL)) < 0)
+            goto exit_monitor;
+
+        priv->iommufdState = true;
+        removeiommufd = true;
+    }
+
+    if ((ret = qemuFDPassDirectTransferMonitor(hostdevPriv->vfioDeviceFd, priv->mon)) < 0)
+        goto exit_monitor;
+
     if ((ret = qemuDomainAttachExtensionDevice(priv->mon, hostdev->info)) < 0)
         goto exit_monitor;
 
@@ -1644,6 +1674,15 @@ qemuDomainAttachHostPCIDevice(virQEMUDriver *driver,
     if (teardownmemlock && qemuDomainAdjustMaxMemLock(vm) < 0)
         VIR_WARN("Unable to reset maximum locked memory on hotplug fail");
 
+    if (removeiommufd) {
+        qemuDomainObjEnterMonitor(vm);
+        ignore_value(qemuMonitorDelObject(priv->mon, "iommufd0", false));
+        qemuDomainObjExitMonitor(vm);
+    }
+
+    qemuFDPassDirectTransferMonitorRollback(hostdevPriv->vfioDeviceFd, priv->mon);
+    qemuFDPassDirectTransferMonitorRollback(priv->iommufd, priv->mon);
+
     if (releaseaddr)
         qemuDomainReleaseDeviceAddress(vm, info);
 
index fc7e7bc98011368f05e8d00d2d1aa8605f4a4353..371b64faaca505ffef3602c0a8b7f88e04429ddc 100644 (file)
@@ -7685,7 +7685,7 @@ qemuProcessPrepareHostBackendChardevHotplug(virDomainObj *vm,
  *
  * Returns: 0 on success, -1 on failure
  */
-static int
+int
 qemuProcessOpenIommuFd(virDomainObj *vm)
 {
     qemuDomainObjPrivate *priv = vm->privateData;
@@ -7709,7 +7709,7 @@ qemuProcessOpenIommuFd(virDomainObj *vm)
  *
  * Returns: 0 on success, -1 on failure
  */
-static int
+int
 qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev)
 {
     qemuDomainHostdevPrivate *hostdevPriv = QEMU_DOMAIN_HOSTDEV_PRIVATE(hostdev);
index 6ba846b7b19af22269656058225bf72f784a3295..fccd41e1a67272469eb4fa9c92c32821ae248a12 100644 (file)
@@ -134,6 +134,9 @@ int qemuProcessPrepareHostBackendChardevHotplug(virDomainObj *vm,
                                                 virDomainDeviceDef *dev)
     ATTRIBUTE_MOCKABLE;
 
+int qemuProcessOpenIommuFd(virDomainObj *vm);
+
+int qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev);
 
 int qemuProcessPrepareHost(virQEMUDriver *driver,
                            virDomainObj *vm,