|
|
43fe83 |
From be42017f858b8227a7a2569eb80adbcb79342145 Mon Sep 17 00:00:00 2001
|
|
|
43fe83 |
Message-Id: <be42017f858b8227a7a2569eb80adbcb79342145.1382534060.git.jdenemar@redhat.com>
|
|
|
43fe83 |
From: Peter Krempa <pkrempa@redhat.com>
|
|
|
43fe83 |
Date: Thu, 10 Oct 2013 13:56:37 +0200
|
|
|
43fe83 |
Subject: [PATCH] qemu: Prefer VFIO for PCI device passthrough
|
|
|
43fe83 |
|
|
|
43fe83 |
https://bugzilla.redhat.com/show_bug.cgi?id=1001738
|
|
|
43fe83 |
|
|
|
43fe83 |
Prefer using VFIO (if available) to the legacy KVM device passthrough.
|
|
|
43fe83 |
|
|
|
43fe83 |
With this patch a PCI passthrough device without the driver configured
|
|
|
43fe83 |
will be started with VFIO if it's available on the host. If not legacy
|
|
|
43fe83 |
KVM passthrough is checked and error is reported if it's not available.
|
|
|
43fe83 |
|
|
|
43fe83 |
(cherry picked from commit f094aaac48a6bbeef87a4df0345dfe2964297298)
|
|
|
43fe83 |
|
|
|
43fe83 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
43fe83 |
---
|
|
|
43fe83 |
docs/formatdomain.html.in | 9 ++++-----
|
|
|
43fe83 |
src/conf/domain_conf.h | 2 +-
|
|
|
43fe83 |
src/libvirt_private.syms | 1 +
|
|
|
43fe83 |
src/qemu/qemu_command.c | 12 +++++++-----
|
|
|
43fe83 |
src/qemu/qemu_hostdev.c | 30 +++++++++++++++++++++++++-----
|
|
|
43fe83 |
src/qemu/qemu_hostdev.h | 4 +++-
|
|
|
43fe83 |
src/qemu/qemu_hotplug.c | 2 +-
|
|
|
43fe83 |
src/qemu/qemu_process.c | 15 ++++++++-------
|
|
|
43fe83 |
tests/qemuxml2argvtest.c | 11 +++++++++++
|
|
|
43fe83 |
9 files changed, 61 insertions(+), 25 deletions(-)
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
|
|
|
43fe83 |
index 4fecdee..512e0df 100644
|
|
|
43fe83 |
--- a/docs/formatdomain.html.in
|
|
|
43fe83 |
+++ b/docs/formatdomain.html.in
|
|
|
43fe83 |
@@ -2704,11 +2704,10 @@
|
|
|
43fe83 |
backend, which is compatible with UEFI SecureBoot) or "kvm"
|
|
|
43fe83 |
(for the legacy device assignment handled directly by the KVM
|
|
|
43fe83 |
kernel module)Since 1.0.5 (QEMU and KVM
|
|
|
43fe83 |
- only, requires kernel 3.6 or newer). Currently, "kvm"
|
|
|
43fe83 |
- is the default used by libvirt when not explicitly provided,
|
|
|
43fe83 |
- but since the two are functionally equivalent, this default
|
|
|
43fe83 |
- could be changed in the future with no impact to domains that
|
|
|
43fe83 |
- don't specify anything.
|
|
|
43fe83 |
+ only, requires kernel 3.6 or newer). The default, when
|
|
|
43fe83 |
+ the driver name is not explicitly specified, is to check wether
|
|
|
43fe83 |
+ VFIO is available and use it if it's the case. If VFIO is not
|
|
|
43fe83 |
+ available, the legacy "kvm" assignment is attempted.
|
|
|
43fe83 |
|
|
|
43fe83 |
readonly
|
|
|
43fe83 |
Indicates that the device is readonly, only supported by SCSI host
|
|
|
43fe83 |
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
|
|
|
43fe83 |
index 5a21576..5ad0318 100644
|
|
|
43fe83 |
--- a/src/conf/domain_conf.h
|
|
|
43fe83 |
+++ b/src/conf/domain_conf.h
|
|
|
43fe83 |
@@ -398,7 +398,7 @@ enum virDomainHostdevSubsysType {
|
|
|
43fe83 |
|
|
|
43fe83 |
/* the backend driver used for PCI hostdev devices */
|
|
|
43fe83 |
typedef enum {
|
|
|
43fe83 |
- VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, /* currently kvm, could change */
|
|
|
43fe83 |
+ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, /* detect automaticaly, prefer VFIO */
|
|
|
43fe83 |
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM, /* force legacy kvm style */
|
|
|
43fe83 |
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO, /* force vfio */
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
43fe83 |
index 5e4de67..9a00dfe 100644
|
|
|
43fe83 |
--- a/src/libvirt_private.syms
|
|
|
43fe83 |
+++ b/src/libvirt_private.syms
|
|
|
43fe83 |
@@ -261,6 +261,7 @@ virDomainHostdevFind;
|
|
|
43fe83 |
virDomainHostdevInsert;
|
|
|
43fe83 |
virDomainHostdevModeTypeToString;
|
|
|
43fe83 |
virDomainHostdevRemove;
|
|
|
43fe83 |
+virDomainHostdevSubsysPciBackendTypeToString;
|
|
|
43fe83 |
virDomainHostdevSubsysTypeToString;
|
|
|
43fe83 |
virDomainHubTypeFromString;
|
|
|
43fe83 |
virDomainHubTypeToString;
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
|
|
|
43fe83 |
index 9c9b956..78f07c8 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_command.c
|
|
|
43fe83 |
+++ b/src/qemu/qemu_command.c
|
|
|
43fe83 |
@@ -5347,10 +5347,10 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
|
|
|
43fe83 |
virQEMUCapsPtr qemuCaps)
|
|
|
43fe83 |
{
|
|
|
43fe83 |
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
43fe83 |
+ int backend = dev->source.subsys.u.pci.backend;
|
|
|
43fe83 |
|
|
|
43fe83 |
- switch ((virDomainHostdevSubsysPciBackendType)
|
|
|
43fe83 |
- dev->source.subsys.u.pci.backend) {
|
|
|
43fe83 |
- case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
|
|
|
43fe83 |
+ /* caller has to assign proper passthrough backend type */
|
|
|
43fe83 |
+ switch ((virDomainHostdevSubsysPciBackendType) backend) {
|
|
|
43fe83 |
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
|
|
|
43fe83 |
virBufferAddLit(&buf, "pci-assign");
|
|
|
43fe83 |
if (configfd && *configfd)
|
|
|
43fe83 |
@@ -5361,9 +5361,11 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
|
|
|
43fe83 |
virBufferAddLit(&buf, "vfio-pci");
|
|
|
43fe83 |
break;
|
|
|
43fe83 |
|
|
|
43fe83 |
+ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
|
|
|
43fe83 |
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
|
|
|
43fe83 |
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
43fe83 |
- _("PCI passhthrough type needs to be specified"));
|
|
|
43fe83 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
43fe83 |
+ _("invalid PCI passthrough type '%s'"),
|
|
|
43fe83 |
+ virDomainHostdevSubsysPciBackendTypeToString(backend));
|
|
|
43fe83 |
break;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
|
|
|
43fe83 |
index 7f3170d..81e0e88 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_hostdev.c
|
|
|
43fe83 |
+++ b/src/qemu/qemu_hostdev.c
|
|
|
43fe83 |
@@ -564,7 +564,8 @@ qemuHostdevHostSupportsPassthroughLegacy(void)
|
|
|
43fe83 |
|
|
|
43fe83 |
static bool
|
|
|
43fe83 |
qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs,
|
|
|
43fe83 |
- size_t nhostdevs)
|
|
|
43fe83 |
+ size_t nhostdevs,
|
|
|
43fe83 |
+ virQEMUCapsPtr qemuCaps)
|
|
|
43fe83 |
{
|
|
|
43fe83 |
bool supportsPassthroughKVM = qemuHostdevHostSupportsPassthroughLegacy();
|
|
|
43fe83 |
bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO();
|
|
|
43fe83 |
@@ -581,6 +582,23 @@ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs,
|
|
|
43fe83 |
continue;
|
|
|
43fe83 |
|
|
|
43fe83 |
switch ((virDomainHostdevSubsysPciBackendType) *backend) {
|
|
|
43fe83 |
+ case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
|
|
|
43fe83 |
+ if (supportsPassthroughVFIO &&
|
|
|
43fe83 |
+ virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
|
|
|
43fe83 |
+ *backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
|
|
|
43fe83 |
+ } else if (supportsPassthroughKVM &&
|
|
|
43fe83 |
+ (virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCIDEVICE) ||
|
|
|
43fe83 |
+ virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE))) {
|
|
|
43fe83 |
+ *backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM;
|
|
|
43fe83 |
+ } else {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
43fe83 |
+ _("host doesn't support passthrough of "
|
|
|
43fe83 |
+ "host PCI devices"));
|
|
|
43fe83 |
+ return false;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ break;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
|
|
|
43fe83 |
if (!supportsPassthroughVFIO) {
|
|
|
43fe83 |
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
43fe83 |
@@ -589,7 +607,6 @@ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs,
|
|
|
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 |
@@ -613,7 +630,8 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
|
|
|
43fe83 |
const char *name,
|
|
|
43fe83 |
const unsigned char *uuid,
|
|
|
43fe83 |
virDomainHostdevDefPtr *hostdevs,
|
|
|
43fe83 |
- int nhostdevs)
|
|
|
43fe83 |
+ int nhostdevs,
|
|
|
43fe83 |
+ virQEMUCapsPtr qemuCaps)
|
|
|
43fe83 |
{
|
|
|
43fe83 |
virPCIDeviceListPtr pcidevs;
|
|
|
43fe83 |
int last_processed_hostdev_vf = -1;
|
|
|
43fe83 |
@@ -621,7 +639,7 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
|
|
|
43fe83 |
int ret = -1;
|
|
|
43fe83 |
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
|
|
43fe83 |
|
|
|
43fe83 |
- if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs))
|
|
|
43fe83 |
+ if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs, qemuCaps))
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
|
|
|
43fe83 |
virObjectLock(driver->activePciHostdevs);
|
|
|
43fe83 |
@@ -1142,13 +1160,15 @@ cleanup:
|
|
|
43fe83 |
int
|
|
|
43fe83 |
qemuPrepareHostDevices(virQEMUDriverPtr driver,
|
|
|
43fe83 |
virDomainDefPtr def,
|
|
|
43fe83 |
+ virQEMUCapsPtr qemuCaps,
|
|
|
43fe83 |
bool coldBoot)
|
|
|
43fe83 |
{
|
|
|
43fe83 |
if (!def->nhostdevs)
|
|
|
43fe83 |
return 0;
|
|
|
43fe83 |
|
|
|
43fe83 |
if (qemuPrepareHostdevPCIDevices(driver, def->name, def->uuid,
|
|
|
43fe83 |
- def->hostdevs, def->nhostdevs) < 0)
|
|
|
43fe83 |
+ def->hostdevs, def->nhostdevs,
|
|
|
43fe83 |
+ qemuCaps) < 0)
|
|
|
43fe83 |
return -1;
|
|
|
43fe83 |
|
|
|
43fe83 |
if (qemuPrepareHostUSBDevices(driver, def, coldBoot) < 0)
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h
|
|
|
43fe83 |
index 327d4d5..272086e 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_hostdev.h
|
|
|
43fe83 |
+++ b/src/qemu/qemu_hostdev.h
|
|
|
43fe83 |
@@ -37,7 +37,8 @@ int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
|
|
|
43fe83 |
const char *name,
|
|
|
43fe83 |
const unsigned char *uuid,
|
|
|
43fe83 |
virDomainHostdevDefPtr *hostdevs,
|
|
|
43fe83 |
- int nhostdevs);
|
|
|
43fe83 |
+ int nhostdevs,
|
|
|
43fe83 |
+ virQEMUCapsPtr qemuCaps);
|
|
|
43fe83 |
int qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev,
|
|
|
43fe83 |
bool mandatory,
|
|
|
43fe83 |
virUSBDevicePtr *usb);
|
|
|
43fe83 |
@@ -50,6 +51,7 @@ int qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver,
|
|
|
43fe83 |
int nhostdevs);
|
|
|
43fe83 |
int qemuPrepareHostDevices(virQEMUDriverPtr driver,
|
|
|
43fe83 |
virDomainDefPtr def,
|
|
|
43fe83 |
+ virQEMUCapsPtr qemuCaps,
|
|
|
43fe83 |
bool coldBoot);
|
|
|
43fe83 |
void qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver,
|
|
|
43fe83 |
const char *name,
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
|
|
|
43fe83 |
index 0c42b0a..cdbafa7 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_hotplug.c
|
|
|
43fe83 |
+++ b/src/qemu/qemu_hotplug.c
|
|
|
43fe83 |
@@ -1018,7 +1018,7 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
|
|
|
43fe83 |
return -1;
|
|
|
43fe83 |
|
|
|
43fe83 |
if (qemuPrepareHostdevPCIDevices(driver, vm->def->name, vm->def->uuid,
|
|
|
43fe83 |
- &hostdev, 1) < 0)
|
|
|
43fe83 |
+ &hostdev, 1, priv->qemuCaps) < 0)
|
|
|
43fe83 |
return -1;
|
|
|
43fe83 |
|
|
|
43fe83 |
switch ((virDomainHostdevSubsysPciBackendType) backend) {
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
|
|
43fe83 |
index f979877..b9f291d 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_process.c
|
|
|
43fe83 |
+++ b/src/qemu/qemu_process.c
|
|
|
43fe83 |
@@ -3540,6 +3540,12 @@ int qemuProcessStart(virConnectPtr conn,
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
+ VIR_DEBUG("Determining emulator version");
|
|
|
43fe83 |
+ virObjectUnref(priv->qemuCaps);
|
|
|
43fe83 |
+ if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
|
|
|
43fe83 |
+ vm->def->emulator)))
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
/* network devices must be "prepared" before hostdevs, because
|
|
|
43fe83 |
* setting up a network device might create a new hostdev that
|
|
|
43fe83 |
* will need to be setup.
|
|
|
43fe83 |
@@ -3550,7 +3556,8 @@ int qemuProcessStart(virConnectPtr conn,
|
|
|
43fe83 |
|
|
|
43fe83 |
/* Must be run before security labelling */
|
|
|
43fe83 |
VIR_DEBUG("Preparing host devices");
|
|
|
43fe83 |
- if (qemuPrepareHostDevices(driver, vm->def, !migrateFrom) < 0)
|
|
|
43fe83 |
+ if (qemuPrepareHostDevices(driver, vm->def, priv->qemuCaps,
|
|
|
43fe83 |
+ !migrateFrom) < 0)
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
|
|
|
43fe83 |
VIR_DEBUG("Preparing chr devices");
|
|
|
43fe83 |
@@ -3632,12 +3639,6 @@ int qemuProcessStart(virConnectPtr conn,
|
|
|
43fe83 |
}
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
- VIR_DEBUG("Determining emulator version");
|
|
|
43fe83 |
- virObjectUnref(priv->qemuCaps);
|
|
|
43fe83 |
- if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
|
|
|
43fe83 |
- vm->def->emulator)))
|
|
|
43fe83 |
- goto cleanup;
|
|
|
43fe83 |
-
|
|
|
43fe83 |
if (!qemuValidateCpuMax(vm->def, priv->qemuCaps))
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
|
|
|
43fe83 |
index 23ea2ee..1d964ce 100644
|
|
|
43fe83 |
--- a/tests/qemuxml2argvtest.c
|
|
|
43fe83 |
+++ b/tests/qemuxml2argvtest.c
|
|
|
43fe83 |
@@ -98,6 +98,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
|
|
|
43fe83 |
virConnectPtr conn;
|
|
|
43fe83 |
char *log = NULL;
|
|
|
43fe83 |
virCommandPtr cmd = NULL;
|
|
|
43fe83 |
+ size_t i;
|
|
|
43fe83 |
|
|
|
43fe83 |
if (!(conn = virGetConnect()))
|
|
|
43fe83 |
goto out;
|
|
|
43fe83 |
@@ -154,6 +155,16 @@ static int testCompareXMLToArgvFiles(const char *xml,
|
|
|
43fe83 |
if (qemuAssignDeviceAliases(vmdef, extraFlags) < 0)
|
|
|
43fe83 |
goto out;
|
|
|
43fe83 |
|
|
|
43fe83 |
+ for (i = 0; i < vmdef->nhostdevs; i++) {
|
|
|
43fe83 |
+ virDomainHostdevDefPtr hostdev = vmdef->hostdevs[i];
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
|
|
43fe83 |
+ hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
|
|
|
43fe83 |
+ hostdev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
|
|
|
43fe83 |
+ hostdev->source.subsys.u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr,
|
|
|
43fe83 |
(flags & FLAG_JSON), extraFlags,
|
|
|
43fe83 |
migrateFrom, migrateFd, NULL,
|
|
|
43fe83 |
--
|
|
|
43fe83 |
1.8.4
|
|
|
43fe83 |
|