Re: [PATCHv4 2/3] qemu: hostdev: Add checks if PCI passthrough is availabe in the host

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/08/2013 06:46 PM, Peter Krempa wrote:
> Add code to check availability of PCI passhthrough using VFIO and the
> legacy KVM passthrough and use it when starting VMs and hotplugging
> devices to live machine.
> ---
>
> Notes:
>     Version 4:
>     - moved this function so that it can be called from qemuPrepareHostdevPCIDevices()
>     - now caching the support for passthrough types right away
>
>  src/qemu/qemu_hostdev.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 125 insertions(+)
>
> diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
> index 4127abd..7f3170d 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
>
> @@ -486,6 +492,122 @@ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
>  }
>
>
> +static 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>
> +static 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
> +static bool
> +qemuHostdevHostSupportsPassthroughLegacy(void)
> +{
> +    return false;
> +}
> +#endif
> +
> +
> +static bool
> +qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs,
> +                                  size_t nhostdevs)
> +{
> +    bool supportsPassthroughKVM = qemuHostdevHostSupportsPassthroughLegacy();
> +    bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO();


I just double checked, and these two calls won't ever be done
unnecessarily, because qemuPrepareHostdevPCIDevices() is never called
unless there will be at least one hostdev added.


> +    size_t i;
> +
> +    /* assign defaults for hostdev passthrough */
> +    for (i = 0; i < nhostdevs; i++) {
> +        virDomainHostdevDefPtr hostdev = hostdevs[i];
> +        int *backend = &hostdev->source.subsys.u.pci.backend;
> +
> +        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
> +            continue;
> +        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
> +            continue;
> +
> +        switch ((virDomainHostdevSubsysPciBackendType) *backend) {
> +        case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
> +            if (!supportsPassthroughVFIO) {
> +                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                               _("host doesn't support VFIO PCI passthrough"));
> +                return false;
> +            }
> +            break;
> +
> +        case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
> +        case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
> +            if (!supportsPassthroughKVM) {
> +                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                               _("host doesn't support legacy PCI passthrough"));
> +                return false;
> +            }
> +
> +            break;
> +
> +        case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
> +            break;
> +        }
> +    }
> +
> +    return true;
> +}
> +
> +
>  int
>  qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
>                               const char *name,
> @@ -499,6 +621,9 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
>      int ret = -1;
>      virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
>
> +    if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs))
> +        goto cleanup;
> +
>      virObjectLock(driver->activePciHostdevs);
>      virObjectLock(driver->inactivePciHostdevs);
>

ACK.

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




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]