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

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to