From: Nathan Chen <nathanc@nvidia.com>
Open iommufd FD from libvirt backend without exposing
these FDs to XML users, i.e. one per domain for
/dev/iommu, and pass the FD to qemu command line.
Suggested-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
---
src/qemu/qemu_command.c | 11 +++++++++--
src/qemu/qemu_domain.c | 1 +
src/qemu/qemu_domain.h | 2 ++
src/qemu/qemu_process.c | 40 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2a16f9df63..8053f9b453 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5348,9 +5348,13 @@ qemuBuildHostdevCommandLine(virCommand *cmd,
static int
qemuBuildIOMMUFDCommandLine(virCommand *cmd,
- const virDomainDef *def)
+ const virDomainDef *def,
+ virDomainObj *vm)
{
size_t i;
+ qemuDomainObjPrivate *priv = vm->privateData;
+ g_autofree char *fdstr = g_strdup_printf("%d", priv->iommufd);
+
for (i = 0; i < def->nhostdevs; i++) {
virDomainHostdevDef *hostdev = def->hostdevs[i];
@@ -5369,8 +5373,11 @@ qemuBuildIOMMUFDCommandLine(virCommand *cmd,
if (subsys->u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES)
continue;
+ virCommandPassFD(cmd, priv->iommufd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+
if (qemuMonitorCreateObjectProps(&props, "iommufd",
"iommufd0",
+ "S:fd", fdstr,
NULL) < 0)
return -1;
@@ -10996,7 +11003,7 @@ qemuBuildCommandLine(virDomainObj *vm,
if (qemuBuildRedirdevCommandLine(cmd, def, qemuCaps) < 0)
return NULL;
- if (qemuBuildIOMMUFDCommandLine(cmd, def) < 0)
+ if (qemuBuildIOMMUFDCommandLine(cmd, def, vm) < 0)
return NULL;
if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps) < 0)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 85eea1801f..c5e1cd5279 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2042,6 +2042,7 @@ qemuDomainObjPrivateAlloc(void *opaque)
priv->blockjobs = virHashNew(virObjectUnref);
priv->fds = virHashNew(g_object_unref);
+ priv->iommufd = -1;
priv->pidMonitored = -1;
/* agent commands block by default, user can choose different behavior */
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index e91435c062..18ced7ebba 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -264,6 +264,8 @@ struct _qemuDomainObjPrivate {
/* named file descriptor groups associated with the VM */
GHashTable *fds;
+ int iommufd;
+
char *memoryBackingDir;
};
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ab88a6bf62..8863be2cb6 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -10365,6 +10365,37 @@ qemuProcessHandleNbdkitExit(qemuNbdkitProcess *nbdkit,
virObjectUnlock(vm);
}
+/**
+ * qemuProcessOpenIommuFd:
+ * @vm: domain object
+ * @iommuFd: returned file descriptor
+ *
+ * Opens /dev/iommu file descriptor for the VM.
+ *
+ * Returns: FD on success, -1 on failure
+ */
+static int
+qemuProcessOpenIommuFd(virDomainObj *vm)
+{
+ int fd = -1;
+
+ VIR_DEBUG("Opening IOMMU FD for domain %s", vm->def->name);
+
+ if ((fd = open("/dev/iommu", O_RDWR | O_CLOEXEC)) < 0) {
+ if (errno == ENOENT) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("IOMMU FD support requires /dev/iommu device"));
+ } else {
+ virReportSystemError(errno, "%s",
+ _("cannot open /dev/iommu"));
+ }
+ return -1;
+ }
+
+ VIR_DEBUG("Opened IOMMU FD %d for domain %s", fd, vm->def->name);
+ return fd;
+}
+
/**
* qemuProcessOpenVfioDeviceFd:
* @hostdev: host device definition
@@ -10419,6 +10450,7 @@ qemuProcessOpenVfioDeviceFd(virDomainHostdevDef *hostdev)
int
qemuProcessOpenVfioFds(virDomainObj *vm)
{
+ qemuDomainObjPrivate *priv = vm->privateData;
size_t i;
/* Check if we have any hostdevs that need VFIO FDs */
@@ -10430,10 +10462,18 @@ qemuProcessOpenVfioFds(virDomainObj *vm)
hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
hostdev->source.subsys.u.pci.driver.name == VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO &&
hostdev->source.subsys.u.pci.driver.iommufd == VIR_TRISTATE_BOOL_YES) {
+
/* Open VFIO device FD */
hostdevPriv->vfioDeviceFd = qemuProcessOpenVfioDeviceFd(hostdev);
if (hostdevPriv->vfioDeviceFd == -1)
return -1;
+
+ /* Open IOMMU FD */
+ if (priv->iommufd == -1) {
+ priv->iommufd = qemuProcessOpenIommuFd(vm);
+ if (priv->iommufd == -1)
+ return -1;
+ }
}
}
--
2.43.0