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];
if (subsys->u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES)
continue;
+ virCommandPassFD(cmd, priv->iommufd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+
+ priv->iommufd = -1;
+
if (qemuMonitorCreateObjectProps(&props, "iommufd",
"iommufd0",
+ "S:fd", fdstr,
NULL) < 0)
return -1;
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)
#include "backup_conf.h"
#include "storage_file_probe.h"
#include "virpci.h"
+#include "viriommufd.h"
#include "logging/log_manager.h"
#include "logging/log_protocol.h"
return 0;
}
+/**
+ * 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(VIR_IOMMU_DEV_PATH, 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;
+ }
+
+ if (virIOMMUFDSetRLimitMode(fd, true) < 0) {
+ VIR_FORCE_CLOSE(fd);
+ return -1;
+ }
+
+ VIR_DEBUG("Opened IOMMU FD %d for domain %s", fd, vm->def->name);
+ return fd;
+}
+
/**
* qemuProcessOpenVfioDeviceFd:
* @hostdev: host device definition
static int
qemuProcessOpenVfioFds(virDomainObj *vm)
{
+ qemuDomainObjPrivate *priv = vm->privateData;
size_t i;
/* Check if we have any hostdevs that need VFIO FDs */
hostdevPriv->vfioDeviceFd = qemuProcessOpenVfioDeviceFd(hostdev);
if (hostdevPriv->vfioDeviceFd == -1)
return -1;
+
+ /* Open IOMMU FD */
+ priv->iommufd = qemuProcessOpenIommuFd(vm);
+ if (priv->iommufd == -1)
+ return -1;
}
}