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

Christophe Fergeau cfergeau at redhat.com
Wed Oct 9 13:02:36 UTC 2013


If it's not pushed already, there's a typo in the subject: 'availabe'

Christophe

On Tue, Oct 08, 2013 at 05:46:57PM +0200, 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();
> +    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);
> 
> -- 
> 1.8.3.2
> 
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20131009/ee6a51fc/attachment-0001.sig>


More information about the libvir-list mailing list