From: Pavel Hrdina <[email protected]>

When fdgroup is used for iommufd we will start QEMU with -object iommufd
even if the VM has no host device. When virDomainFDAssociate() is used
the FD libvirt is holding is closed with connection.

Signed-off-by: Pavel Hrdina <[email protected]>
---
 src/qemu/qemu_command.c |  4 +++-
 src/qemu/qemu_hotplug.c |  4 ++--
 src/qemu/qemu_process.c | 47 ++++++++++++++++++++++++++++++++++++++---
 3 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 7286fd8b83..7801d99738 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5367,8 +5367,10 @@ qemuBuildIOMMUFDCommandLine(virCommand *cmd,
     qemuDomainObjPrivate *priv = vm->privateData;
     g_autoptr(virJSONValue) props = NULL;
 
-    if (!virDomainDefHasPCIHostdevWithIOMMUFD(def))
+    if (!virDomainDefHasPCIHostdevWithIOMMUFD(def) &&
+        !def->iommufd_fdgroup) {
         return 0;
+    }
 
     qemuFDPassDirectTransferCommand(priv->iommufd, cmd);
 
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index adae94f0a2..c86ebc59d0 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1615,7 +1615,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriver *driver,
         if (qemuProcessOpenVfioDeviceFd(vm, hostdev) < 0)
             goto error;
 
-        if (!priv->iommufdState) {
+        if (!priv->iommufdState && !vm->def->iommufd_fdgroup) {
             if (qemuProcessOpenIommuFd(vm) < 0)
                 goto error;
 
@@ -5041,7 +5041,7 @@ qemuDomainRemoveHostDevice(virQEMUDriver *driver,
         }
     }
 
-    if (priv->iommufdState &&
+    if (priv->iommufdState && !vm->def->iommufd_fdgroup &&
         !virDomainDefHasPCIHostdevWithIOMMUFD(vm->def)) {
         qemuDomainObjEnterMonitor(vm);
         ignore_value(qemuMonitorDelObject(priv->mon, "iommufd0", false));
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index fed6079ad2..c78fb4273c 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7743,6 +7743,44 @@ qemuProcessOpenIommuFd(virDomainObj *vm)
     return 0;
 }
 
+/**
+ * qemuProcessPrepareIommuFd:
+ * @vm: domain object
+ *
+ * Find passed FD via virDomainFDAssociate() API for the VM.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+static int
+qemuProcessPrepareIommuFd(virDomainObj *vm)
+{
+    qemuDomainObjPrivate *priv = vm->privateData;
+    virDomainFDTuple *fdt = virHashLookup(priv->fds, vm->def->iommufd_fdgroup);
+    VIR_AUTOCLOSE iommufd = -1;
+
+    if (!fdt) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("file descriptor group '%1$s' was not associated with 
the domain"),
+                       vm->def->iommufd_fdgroup);
+        return -1;
+    }
+
+    if (fdt->nfds != 1) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                       _("Only one file descriptor needs to be associated with 
iommufd"));
+        return -1;
+    }
+
+    iommufd = dup(fdt->fds[0]);
+
+    if (qemuSecuritySetImageFDLabel(priv->driver->securityManager, vm->def, 
iommufd) < 0)
+        return -1;
+
+    priv->iommufd = qemuFDPassDirectNew("iommufd", &iommufd);
+
+    return 0;
+}
+
 /**
  * qemuProcessOpenVfioDeviceFd:
  * @hostdev: host device definition
@@ -7798,9 +7836,12 @@ qemuProcessPrepareHostHostdev(virDomainObj *vm)
     }
 
     /* Open IOMMU FD */
-    if (virDomainDefHasPCIHostdevWithIOMMUFD(vm->def) &&
-        qemuProcessOpenIommuFd(vm) < 0) {
-        return -1;
+    if (vm->def->iommufd_fdgroup) {
+        if (qemuProcessPrepareIommuFd(vm) < 0)
+            return -1;
+    } else if (virDomainDefHasPCIHostdevWithIOMMUFD(vm->def)) {
+        if (qemuProcessOpenIommuFd(vm) < 0)
+            return -1;
     }
 
     return 0;
-- 
2.53.0

Reply via email to