diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 8f744871d2..8c998db176 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2757,11 +2757,10 @@ backend, which is compatible with UEFI SecureBoot) or "kvm" (for the legacy device assignment handled directly by the KVM kernel module)Since 1.0.5 (QEMU and KVM - only, requires kernel 3.6 or newer). Currently, "kvm" - is the default used by libvirt when not explicitly provided, - but since the two are functionally equivalent, this default - could be changed in the future with no impact to domains that - don't specify anything. + only, requires kernel 3.6 or newer). The default, when + the driver name is not explicitly specified, is to check wether + VFIO is available and use it if it's the case. If VFIO is not + available, the legacy "kvm" assignment is attempted.
readonly
Indicates that the device is readonly, only supported by SCSI host diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5d5e4431f9..df28fa684d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -399,7 +399,7 @@ enum virDomainHostdevSubsysType { /* the backend driver used for PCI hostdev devices */ typedef enum { - VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, /* currently kvm, could change */ + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, /* detect automaticaly, prefer VFIO */ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM, /* force legacy kvm style */ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO, /* force vfio */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fe40834c0c..cdeb8e06e6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -262,6 +262,7 @@ virDomainHostdevFind; virDomainHostdevInsert; virDomainHostdevModeTypeToString; virDomainHostdevRemove; +virDomainHostdevSubsysPciBackendTypeToString; virDomainHostdevSubsysTypeToString; virDomainHubTypeFromString; virDomainHubTypeToString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 52dc295254..22cc5f227f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5484,10 +5484,10 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) { virBuffer buf = VIR_BUFFER_INITIALIZER; + int backend = dev->source.subsys.u.pci.backend; - switch ((virDomainHostdevSubsysPciBackendType) - dev->source.subsys.u.pci.backend) { - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: + /* caller has to assign proper passthrough backend type */ + switch ((virDomainHostdevSubsysPciBackendType) backend) { case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM: virBufferAddLit(&buf, "pci-assign"); if (configfd && *configfd) @@ -5498,9 +5498,11 @@ qemuBuildPCIHostdevDevStr(virDomainDefPtr def, virBufferAddLit(&buf, "vfio-pci"); break; + case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST: - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("PCI passhthrough type needs to be specified")); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("invalid PCI passthrough type '%s'"), + virDomainHostdevSubsysPciBackendTypeToString(backend)); break; } diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 7f3170d5f8..81e0e8848c 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -564,7 +564,8 @@ qemuHostdevHostSupportsPassthroughLegacy(void) static bool qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs, - size_t nhostdevs) + size_t nhostdevs, + virQEMUCapsPtr qemuCaps) { bool supportsPassthroughKVM = qemuHostdevHostSupportsPassthroughLegacy(); bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO(); @@ -581,6 +582,23 @@ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs, continue; switch ((virDomainHostdevSubsysPciBackendType) *backend) { + case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: + if (supportsPassthroughVFIO && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) { + *backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO; + } else if (supportsPassthroughKVM && + (virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCIDEVICE) || + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE))) { + *backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM; + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("host doesn't support passthrough of " + "host PCI devices")); + return false; + } + + break; + case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO: if (!supportsPassthroughVFIO) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -589,7 +607,6 @@ qemuPrepareHostdevPCICheckSupport(virDomainHostdevDefPtr *hostdevs, } break; - case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT: case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM: if (!supportsPassthroughKVM) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -613,7 +630,8 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, const char *name, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, - int nhostdevs) + int nhostdevs, + virQEMUCapsPtr qemuCaps) { virPCIDeviceListPtr pcidevs; int last_processed_hostdev_vf = -1; @@ -621,7 +639,7 @@ qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, int ret = -1; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); - if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs)) + if (!qemuPrepareHostdevPCICheckSupport(hostdevs, nhostdevs, qemuCaps)) goto cleanup; virObjectLock(driver->activePciHostdevs); @@ -1142,13 +1160,15 @@ cleanup: int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, + virQEMUCapsPtr qemuCaps, bool coldBoot) { if (!def->nhostdevs) return 0; if (qemuPrepareHostdevPCIDevices(driver, def->name, def->uuid, - def->hostdevs, def->nhostdevs) < 0) + def->hostdevs, def->nhostdevs, + qemuCaps) < 0) return -1; if (qemuPrepareHostUSBDevices(driver, def, coldBoot) < 0) diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h index 327d4d5679..272086effa 100644 --- a/src/qemu/qemu_hostdev.h +++ b/src/qemu/qemu_hostdev.h @@ -37,7 +37,8 @@ int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, const char *name, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, - int nhostdevs); + int nhostdevs, + virQEMUCapsPtr qemuCaps); int qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev, bool mandatory, virUSBDevicePtr *usb); @@ -50,6 +51,7 @@ int qemuPrepareHostdevSCSIDevices(virQEMUDriverPtr driver, int nhostdevs); int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, + virQEMUCapsPtr qemuCaps, bool coldBoot); void qemuDomainReAttachHostScsiDevices(virQEMUDriverPtr driver, const char *name, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 71c78226b7..b6ae21870e 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1140,7 +1140,7 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver, return -1; if (qemuPrepareHostdevPCIDevices(driver, vm->def->name, vm->def->uuid, - &hostdev, 1) < 0) + &hostdev, 1, priv->qemuCaps) < 0) return -1; switch ((virDomainHostdevSubsysPciBackendType) backend) { diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 079f062bcd..354e079a75 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3567,6 +3567,12 @@ int qemuProcessStart(virConnectPtr conn, goto cleanup; } + VIR_DEBUG("Determining emulator version"); + virObjectUnref(priv->qemuCaps); + if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache, + vm->def->emulator))) + goto cleanup; + /* network devices must be "prepared" before hostdevs, because * setting up a network device might create a new hostdev that * will need to be setup. @@ -3577,7 +3583,8 @@ int qemuProcessStart(virConnectPtr conn, /* Must be run before security labelling */ VIR_DEBUG("Preparing host devices"); - if (qemuPrepareHostDevices(driver, vm->def, !migrateFrom) < 0) + if (qemuPrepareHostDevices(driver, vm->def, priv->qemuCaps, + !migrateFrom) < 0) goto cleanup; VIR_DEBUG("Preparing chr devices"); @@ -3659,12 +3666,6 @@ int qemuProcessStart(virConnectPtr conn, } } - VIR_DEBUG("Determining emulator version"); - virObjectUnref(priv->qemuCaps); - if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache, - vm->def->emulator))) - goto cleanup; - if (!qemuValidateCpuMax(vm->def, priv->qemuCaps)) goto cleanup; diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 286f1a3628..060acf29ba 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -98,6 +98,7 @@ static int testCompareXMLToArgvFiles(const char *xml, virConnectPtr conn; char *log = NULL; virCommandPtr cmd = NULL; + size_t i; if (!(conn = virGetConnect())) goto out; @@ -154,6 +155,16 @@ static int testCompareXMLToArgvFiles(const char *xml, if (qemuAssignDeviceAliases(vmdef, extraFlags) < 0) goto out; + for (i = 0; i < vmdef->nhostdevs; i++) { + virDomainHostdevDefPtr hostdev = vmdef->hostdevs[i]; + + if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && + hostdev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) { + hostdev->source.subsys.u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM; + } + } + if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr, (flags & FLAG_JSON), extraFlags, migrateFrom, migrateFd, NULL,