Part of the resolution to: https://bugzilla.redhat.com/show_bug.cgi?id=1003983 Although most devices available in qemu area defined as PCI devices, and strictly speaking should only be attached via a PCI slot, in practice qemu allows them to be attached to a PCIe slot and sometimes this makes sense. For example, The UHCI and EHCI USB controllers are usually attached directly to the PCIe "root complex" (i.e. PCIe slots) on real hardware, so that should be possible for a Q35-based qemu virtual machine as well. We still want to prefer a standard PCi slot when auto-assigning addresses, though, and in general to disallow attaching PCI devices via PCIe slots. This patch makes that possible by adding a new QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG flag. Three things are done with this flag: 1) It is set for the "pcie-root" controller 2) qemuCollectPCIAddress() now has a set of nested switches that set this "EITHER" flag for devices that we want to allow connecting to pcie-root when specifically requested in the config. 3) qemuDomainPCIAddressFlagsCompatible() adds this new flag to the "flagsMatchMask" if the address being checked came from config rather than being newly auto-allocated by libvirt (this knowledge is conveniently already available in the "fromConfig" arg). Now any device having the EITHER flag set can be connected to pcie-root if explicitly requested, but auto-allocated addresses for those devices will still be standard PCI slots instead. This patch only loosens the restrictions on devices that have been specifically requested, but the setup is such that it should be fairly easy to add new devices. --- src/qemu/qemu_command.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_command.h | 4 ++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2683a9c..280d8d2 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1496,12 +1496,16 @@ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr, { virErrorNumber errType = (fromConfig ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR); + qemuDomainPCIConnectFlags flagsMatchMask = QEMU_PCI_CONNECT_TYPES_MASK; + + if (fromConfig) + flagsMatchMask |= QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG; /* If this bus doesn't allow the type of connection (PCI * vs. PCIe) required by the device, or if the device requires * hot-plug and this bus doesn't have it, return false. */ - if (!(devFlags & busFlags & QEMU_PCI_CONNECT_TYPES_MASK)) { + if (!(devFlags & busFlags & flagsMatchMask)) { if (reportError) { if (devFlags & QEMU_PCI_CONNECT_TYPE_PCI) { virReportError(errType, @@ -1620,8 +1624,12 @@ qemuDomainPCIAddressBusSetModel(qemuDomainPCIAddressBusPtr bus, bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST; break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: - /* slots 1 - 31, PCIe devices only, no hotplug */ - bus->flags = QEMU_PCI_CONNECT_TYPE_PCIE; + /* slots 1 - 31, no hotplug, PCIe only unless the address was + * specified in user config *and* the particular device being + * attached also allows it + */ + bus->flags = (QEMU_PCI_CONNECT_TYPE_PCIE | + QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG); bus->minSlot = 1; bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST; break; @@ -1759,6 +1767,42 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, */ flags = QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE; break; + + case VIR_DOMAIN_CONTROLLER_TYPE_USB: + /* allow UHCI and EHCI controllers to be manually placed on + * the PCIe bus (but don't put them there automatically) + */ + switch (device->data.controller->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI: + flags = (QEMU_PCI_CONNECT_TYPE_PCI | + QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG); + break; + case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI: + /* should this be PCIE-only? Or do we need to allow PCI + * for backward compatibility? + */ + flags = QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI: + case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI: + /* Allow these for PCI only */ + break; + } + } + break; + + case VIR_DOMAIN_DEVICE_SOUND: + switch (device->data.sound->model) { + case VIR_DOMAIN_SOUND_MODEL_ICH6: + flags = (QEMU_PCI_CONNECT_TYPE_PCI | + QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG); + break; } break; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 0e16a3d..2e2acfb 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -239,6 +239,10 @@ typedef enum { /* PCI devices can connect to this bus */ QEMU_PCI_CONNECT_TYPE_PCIE = 1 << 3, /* PCI Express devices can connect to this bus */ + QEMU_PCI_CONNECT_TYPE_EITHER_IF_CONFIG = 1 << 4, + /* PCI *and* PCIe devices allowed, if the address + * was specified in the config by the user + */ } qemuDomainPCIConnectFlags; /* a combination of all bit that describe the type of connections -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list