Add code that will be used to check availability of PCI passhthrough
using VFIO and the legacy KVM passthrough. These will be later used to
determine the preferred passthrough option.
---
src/qemu/qemu_hostdev.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_hostdev.h | 3 ++
2 files changed, 79 insertions(+)
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index 21fe47f..1967a47 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -23,6 +23,11 @@
#include <config.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
#include "qemu_hostdev.h"
#include "virlog.h"
#include "virerror.h"
@@ -31,6 +36,7 @@
#include "virusb.h"
#include "virscsi.h"
#include "virnetdev.h"
+#include "virfile.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -1287,3 +1293,73 @@ void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver,
qemuDomainReAttachHostScsiDevices(driver, def->name, def->hostdevs,
def->nhostdevs);
}
+
+
+bool
+qemuHostdevHostSupportsPassthroughVFIO(void)
+{
+ DIR *iommuDir = NULL;
+ struct dirent *iommuGroup = NULL;
+ bool ret = false;
+
+ /* condition 1 - /sys/kernel/iommu_groups/ contains entries */
+ if (!(iommuDir = opendir("/sys/kernel/iommu_groups/")))
+ goto cleanup;
+
+ while ((iommuGroup = readdir(iommuDir))) {
+ /* skip ./ ../ */
+ if (STRPREFIX(iommuGroup->d_name, "."))
+ continue;
+
+ /* assume we found a group */
+ break;
+ }
+
+ if (!iommuGroup)
+ goto cleanup;
+ /* okay, iommu is on and recognizes groups */
+
+ /* condition 2 - /dev/vfio/vfio exists */
+ if (!virFileExists("/dev/vfio/vfio"))
+ goto cleanup;
+
+ ret = true;
+
+cleanup:
+ if (iommuDir)
+ closedir(iommuDir);
+
+ return ret;
+}
+
+
+#if HAVE_LINUX_KVM_H
+# include <linux/kvm.h>
+bool
+qemuHostdevHostSupportsPassthroughLegacy(void)
+{
+ int kvmfd = -1;
+ bool ret = false;
+
+ if ((kvmfd = open("/dev/kvm", O_RDONLY)) < 0)
+ goto cleanup;
+
+# ifdef KVM_CAP_IOMMU
+ if ((ioctl(kvmfd, KVM_CHECK_EXTENSION, KVM_CAP_IOMMU)) <= 0)
+ goto cleanup;
+
+ ret = true;
+# endif
+
+cleanup:
+ VIR_FORCE_CLOSE(kvmfd);
+
+ return ret;
+}
+#else
+bool
+qemuHostdevHostSupportsPassthroughLegacy(void)
+{
+ return false;
+}
+#endif
diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h
index 327d4d5..7f33486 100644
--- a/src/qemu/qemu_hostdev.h
+++ b/src/qemu/qemu_hostdev.h
@@ -69,4 +69,7 @@ int qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
int qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
char *stateDir);
+bool qemuHostdevHostSupportsPassthroughVFIO(void);
+bool qemuHostdevHostSupportsPassthroughLegacy(void);
+
#endif /* __QEMU_HOSTDEV_H__ */
--
1.8.3.2