|
|
43fe83 |
From 676f5e9952f7cbc09ad54d77e09d864f61874a6d Mon Sep 17 00:00:00 2001
|
|
|
43fe83 |
Message-Id: <676f5e9952f7cbc09ad54d77e09d864f61874a6d.1382534060.git.jdenemar@redhat.com>
|
|
|
43fe83 |
From: Peter Krempa <pkrempa@redhat.com>
|
|
|
43fe83 |
Date: Thu, 10 Oct 2013 13:56:36 +0200
|
|
|
43fe83 |
Subject: [PATCH] qemu: hostdev: Add checks if PCI passthrough is available in
|
|
|
43fe83 |
the host
|
|
|
43fe83 |
|
|
|
43fe83 |
https://bugzilla.redhat.com/show_bug.cgi?id=1001738
|
|
|
43fe83 |
|
|
|
43fe83 |
Add code to check availability of PCI passhthrough using VFIO and the
|
|
|
43fe83 |
legacy KVM passthrough and use it when starting VMs and hotplugging
|
|
|
43fe83 |
devices to live machine.
|
|
|
43fe83 |
|
|
|
43fe83 |
(cherry picked from commit 467b561ac2ca7cb968d7a1d781e715cdd7bf3d14)
|
|
|
43fe83 |
|
|
|
43fe83 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
43fe83 |
---
|
|
|
43fe83 |
src/qemu/qemu_hostdev.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
43fe83 |
1 file changed, 125 insertions(+)
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
|
|
|
43fe83 |
index 4127abd..7f3170d 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_hostdev.c
|
|
|
43fe83 |
+++ b/src/qemu/qemu_hostdev.c
|
|
|
43fe83 |
@@ -23,6 +23,11 @@
|
|
|
43fe83 |
|
|
|
43fe83 |
#include <config.h>
|
|
|
43fe83 |
|
|
|
43fe83 |
+#include <dirent.h>
|
|
|
43fe83 |
+#include <fcntl.h>
|
|
|
43fe83 |
+#include <sys/ioctl.h>
|
|
|
43fe83 |
+#include <errno.h>
|
|
|
43fe83 |
+
|
|
|
43fe83 |
#include "qemu_hostdev.h"
|
|
|
43fe83 |
#include "virlog.h"
|
|
|
43fe83 |
#include "virerror.h"
|
|
|
43fe83 |
@@ -31,6 +36,7 @@
|
|
|
43fe83 |
#include "virusb.h"
|
|
|
43fe83 |
#include "virscsi.h"
|
|
|
43fe83 |
#include "virnetdev.h"
|
|
|
43fe83 |
+#include "virfile.h"
|
|
|
43fe83 |
|
|
|
43fe83 |
#define VIR_FROM_THIS VIR_FROM_QEMU
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -486,6 +492,122 @@ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
|
|
|
43fe83 |
+static bool
|
|
|
43fe83 |
+qemuHostdevHostSupportsPassthroughVFIO(void)
|
|
|
43fe83 |
+{
|
|
|
43fe83 |
+ DIR *iommuDir = NULL;
|
|
|
43fe83 |
+ struct dirent *iommuGroup = NULL;
|
|
|
43fe83 |
+ bool ret = false;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ /* condition 1 - /sys/kernel/iommu_groups/ contains entries */
|
|
|
43fe83 |
+ if (!(iommuDir = opendir("/sys/kernel/iommu_groups/")))
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ while ((iommuGroup = readdir(iommuDir))) {
|
|
|
43fe83 |
+ /* skip ./ ../ */
|
|
|
43fe83 |
+ if (STRPREFIX(iommuGroup->d_name, "."))
|
|
|
43fe83 |
+ continue;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ /* assume we found a group */
|
|
|
43fe83 |
+ break;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (!iommuGroup)
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ /* okay, iommu is on and recognizes groups */
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ /* condition 2 - /dev/vfio/vfio exists */
|
|
|
43fe83 |
+ if (!virFileExists("/dev/vfio/vfio"))
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ ret = true;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+cleanup:
|
|
|
43fe83 |
+ if (iommuDir)
|
|
|
43fe83 |
+ closedir(iommuDir);
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ return ret;
|
|
|
43fe83 |
+}
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+#if HAVE_LINUX_KVM_H
|
|
|
43fe83 |
+# include <linux/kvm.h>
|
|
|
43fe83 |
+static bool
|
|
|
43fe83 |
+qemuHostdevHostSupportsPassthroughLegacy(void)
|
|
|
43fe83 |
+{
|
|
|
43fe83 |
+ int kvmfd = -1;
|
|
|
43fe83 |
+ bool ret = false;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if ((kvmfd = open("/dev/kvm", O_RDONLY)) < 0)
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+# ifdef KVM_CAP_IOMMU
|
|
|
43fe83 |
+ if ((ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_IOMMU)) <= 0)
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ ret = true;
|
|
|
43fe83 |
+# endif
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+cleanup:
|
|
|
43fe83 |
+ VIR_FORCE_CLOSE(kvmfd);
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ return ret;
|
|
|
43fe83 |
+}
|
|
|
43fe83 |
+#else
|
|
|
43fe83 |
+static bool
|
|
|
43fe83 |
+qemuHostdevHostSupportsPassthroughLegacy(void)
|
|
|
43fe83 |
+{
|
|
|
43fe83 |
+ return false;
|
|
|
43fe83 |
+}
|
|
|
43fe83 |
+#endif
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+static bool
|
|
|
43fe83 |
+qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs,
|
|
|
43fe83 |
+ size_t nhostdevs)
|
|
|
43fe83 |
+{
|
|
|
43fe83 |
+ bool supportsPassthroughKVM = qemuHostdevHostSupportsPassthroughLegacy();
|
|
|
43fe83 |
+ bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO();
|
|
|
43fe83 |
+ size_t i;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ /* assign defaults for hostdev passthrough */
|
|
|
43fe83 |
+ for (i = 0; i < nhostdevs; i++) {
|
|
|
43fe83 |
+ virDomainHostdevDefPtr hostdev = hostdevs[i];
|
|
|
43fe83 |
+ int *backend = &hostdev->source.subsys.u.pci.backend;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
|
43fe83 |
+ continue;
|
|
|
43fe83 |
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
|
|
43fe83 |
+ continue;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ switch ((virDomainHostdevSubsysPciBackendType) *backend) {
|
|
|
43fe83 |
+ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
|
|
|
43fe83 |
+ if (!supportsPassthroughVFIO) {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
43fe83 |
+ _("host doesn't support VFIO PCI passthrough"));
|
|
|
43fe83 |
+ return false;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ break;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
|
|
|
43fe83 |
+ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
|
|
|
43fe83 |
+ if (!supportsPassthroughKVM) {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
43fe83 |
+ _("host doesn't support legacy PCI passthrough"));
|
|
|
43fe83 |
+ return false;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ break;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
|
|
|
43fe83 |
+ break;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ return true;
|
|
|
43fe83 |
+}
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+
|
|
|
43fe83 |
int
|
|
|
43fe83 |
qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
|
|
|
43fe83 |
const char *name,
|
|
|
43fe83 |
@@ -499,6 +621,9 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
|
|
|
43fe83 |
int ret = -1;
|
|
|
43fe83 |
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
|
|
43fe83 |
|
|
|
43fe83 |
+ if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs))
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
virObjectLock(driver->activePciHostdevs);
|
|
|
43fe83 |
virObjectLock(driver->inactivePciHostdevs);
|
|
|
43fe83 |
|
|
|
43fe83 |
--
|
|
|
43fe83 |
1.8.4
|
|
|
43fe83 |
|