|
|
43fe83 |
From efc2b6dc182a0d5a36b3791114f844bcc29e5e45 Mon Sep 17 00:00:00 2001
|
|
|
43fe83 |
Message-Id: <efc2b6dc182a0d5a36b3791114f844bcc29e5e45.1377873636.git.jdenemar@redhat.com>
|
|
|
43fe83 |
From: Laine Stump <laine@laine.org>
|
|
|
43fe83 |
Date: Tue, 6 Aug 2013 13:23:21 -0600
|
|
|
43fe83 |
Subject: [PATCH] qemu: enable auto-allocate of all PCI addresses
|
|
|
43fe83 |
|
|
|
43fe83 |
This patch is part of the resolution to:
|
|
|
43fe83 |
|
|
|
43fe83 |
https://bugzilla.redhat.com/show_bug.cgi?id=819968
|
|
|
43fe83 |
|
|
|
43fe83 |
Previous refactoring of the guest PCI address reservation/allocation
|
|
|
43fe83 |
code allowed for slot types other than basic PCI (e.g. PCI express,
|
|
|
43fe83 |
non-hotpluggable slots, etc) but would not auto-allocate a slot for a
|
|
|
43fe83 |
device that required any type other than a basic hot-pluggable
|
|
|
43fe83 |
PCI slot.
|
|
|
43fe83 |
|
|
|
43fe83 |
This patch refactors the code to be aware of different slot types
|
|
|
43fe83 |
during auto-allocation of addresses as well - as long as there is an
|
|
|
43fe83 |
empty slot of the required type, it will be found and used.
|
|
|
43fe83 |
|
|
|
43fe83 |
The piece that *wasn't* added is that we don't auto-create a new PCI
|
|
|
43fe83 |
bus when needed for anything except basic PCI devices. This is because
|
|
|
43fe83 |
there are multiple different types of controllers that can provide,
|
|
|
43fe83 |
for example, a PCI express slot (in addition to the pcie-root
|
|
|
43fe83 |
controller, these can also be found on a "root-port" or on a
|
|
|
43fe83 |
"downstream-switch-port"). Since we currently don't support any PCIe
|
|
|
43fe83 |
devices (except pending support for dmi-to-pci-bridge), we can defer
|
|
|
43fe83 |
any decision on what to do about this.
|
|
|
43fe83 |
(cherry picked from commit c305783c65f2b552a08fc0e03e1d9b98157d91ca)
|
|
|
43fe83 |
---
|
|
|
43fe83 |
src/qemu/qemu_command.c | 115 +++++++++++++++++++++++++++++++++++++++---------
|
|
|
43fe83 |
1 file changed, 93 insertions(+), 22 deletions(-)
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
|
|
|
43fe83 |
index abc973a..2886e01 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_command.c
|
|
|
43fe83 |
+++ b/src/qemu/qemu_command.c
|
|
|
43fe83 |
@@ -1429,6 +1429,7 @@ struct _qemuDomainPCIAddressSet {
|
|
|
43fe83 |
qemuDomainPCIAddressBus *buses;
|
|
|
43fe83 |
size_t nbuses;
|
|
|
43fe83 |
virDevicePCIAddress lastaddr;
|
|
|
43fe83 |
+ qemuDomainPCIConnectFlags lastFlags;
|
|
|
43fe83 |
bool dryRun; /* on a dry run, new buses are auto-added
|
|
|
43fe83 |
and addresses aren't saved in device infos */
|
|
|
43fe83 |
};
|
|
|
43fe83 |
@@ -1630,7 +1631,7 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
|
|
43fe83 |
int ret = -1;
|
|
|
43fe83 |
virDevicePCIAddressPtr addr = &info->addr.pci;
|
|
|
43fe83 |
bool entireSlot;
|
|
|
43fe83 |
- /* FIXME: flags should be set according to the requirements of @device */
|
|
|
43fe83 |
+ /* flags may be changed from default below */
|
|
|
43fe83 |
qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE |
|
|
|
43fe83 |
QEMU_PCI_CONNECT_TYPE_PCI);
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -1644,28 +1645,60 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
|
|
43fe83 |
return 0;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
+ /* Change flags according to differing requirements of different
|
|
|
43fe83 |
+ * devices.
|
|
|
43fe83 |
+ */
|
|
|
43fe83 |
+ if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER &&
|
|
|
43fe83 |
+ device->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
|
|
|
43fe83 |
+ switch (device->data.controller->model) {
|
|
|
43fe83 |
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
|
|
|
43fe83 |
+ /* pci-bridge needs a PCI slot, but it isn't
|
|
|
43fe83 |
+ * hot-pluggable, so it doesn't need a hot-pluggable slot.
|
|
|
43fe83 |
+ */
|
|
|
43fe83 |
+ flags = QEMU_PCI_CONNECT_TYPE_PCI;
|
|
|
43fe83 |
+ break;
|
|
|
43fe83 |
+ default:
|
|
|
43fe83 |
+ break;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
/* Ignore implicit controllers on slot 0:0:1.0:
|
|
|
43fe83 |
* implicit IDE controller on 0:0:1.1 (no qemu command line)
|
|
|
43fe83 |
* implicit USB controller on 0:0:1.2 (-usb)
|
|
|
43fe83 |
*
|
|
|
43fe83 |
* If the machine does have a PCI bus, they will get reserved
|
|
|
43fe83 |
* in qemuAssignDevicePCISlots().
|
|
|
43fe83 |
- *
|
|
|
43fe83 |
- * FIXME: When we have support for a pcie-root controller at bus
|
|
|
43fe83 |
- * 0, we will no longer be able to skip checking of these devices,
|
|
|
43fe83 |
- * as they are PCI, and thus can't be connected to bus 0 if it is
|
|
|
43fe83 |
- * PCIe rather than PCI.
|
|
|
43fe83 |
+ */
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ /* These are the IDE and USB controllers in the PIIX3, hardcoded
|
|
|
43fe83 |
+ * to bus 0 slot 1. They cannot be attached to a PCIe slot, only
|
|
|
43fe83 |
+ * PCI.
|
|
|
43fe83 |
*/
|
|
|
43fe83 |
if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER && addr->domain == 0 &&
|
|
|
43fe83 |
addr->bus == 0 && addr->slot == 1) {
|
|
|
43fe83 |
virDomainControllerDefPtr cont = device->data.controller;
|
|
|
43fe83 |
- if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE && cont->idx == 0 &&
|
|
|
43fe83 |
- addr->function == 1)
|
|
|
43fe83 |
- return 0;
|
|
|
43fe83 |
- if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB && cont->idx == 0 &&
|
|
|
43fe83 |
- (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI ||
|
|
|
43fe83 |
- cont->model == -1) && addr->function == 2)
|
|
|
43fe83 |
- return 0;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ if ((cont->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE && cont->idx == 0 &&
|
|
|
43fe83 |
+ addr->function == 1) ||
|
|
|
43fe83 |
+ (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB && cont->idx == 0 &&
|
|
|
43fe83 |
+ (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI ||
|
|
|
43fe83 |
+ cont->model == -1) && addr->function == 2)) {
|
|
|
43fe83 |
+ /* Note the check for nbuses > 0 - if there are no PCI
|
|
|
43fe83 |
+ * buses, we skip this check. This is a quirk required for
|
|
|
43fe83 |
+ * some machinetypes such as s390, which pretend to have a
|
|
|
43fe83 |
+ * PCI bus for long enough to generate the "-usb" on the
|
|
|
43fe83 |
+ * commandline, but that don't really care if a PCI bus
|
|
|
43fe83 |
+ * actually exists. */
|
|
|
43fe83 |
+ if (addrs->nbuses > 0 &&
|
|
|
43fe83 |
+ !(addrs->buses[0].flags & QEMU_PCI_CONNECT_TYPE_PCI)) {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
43fe83 |
+ _("Bus 0 must be PCI for integrated PIIX3 "
|
|
|
43fe83 |
+ "USB or IDE controllers"));
|
|
|
43fe83 |
+ return -1;
|
|
|
43fe83 |
+ } else {
|
|
|
43fe83 |
+ return 0;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
entireSlot = (addr->function == 0 &&
|
|
|
43fe83 |
@@ -1695,8 +1728,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
|
|
|
43fe83 |
int nbuses = 0;
|
|
|
43fe83 |
size_t i;
|
|
|
43fe83 |
int rv;
|
|
|
43fe83 |
- qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE |
|
|
|
43fe83 |
- QEMU_PCI_CONNECT_TYPE_PCI);
|
|
|
43fe83 |
+ qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_TYPE_PCI;
|
|
|
43fe83 |
|
|
|
43fe83 |
for (i = 0; i < def->ncontrollers; i++) {
|
|
|
43fe83 |
if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
|
|
|
43fe83 |
@@ -1941,7 +1973,11 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs,
|
|
|
43fe83 |
virDomainDeviceInfoPtr dev)
|
|
|
43fe83 |
{
|
|
|
43fe83 |
int ret = 0;
|
|
|
43fe83 |
- /* FIXME: flags should be set according to the particular device */
|
|
|
43fe83 |
+ /* Flags should be set according to the particular device,
|
|
|
43fe83 |
+ * but only the caller knows the type of device. Currently this
|
|
|
43fe83 |
+ * function is only used for hot-plug, though, and hot-plug is
|
|
|
43fe83 |
+ * only supported for standard PCI devices, so we can safely use
|
|
|
43fe83 |
+ * the setting below */
|
|
|
43fe83 |
qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE |
|
|
|
43fe83 |
QEMU_PCI_CONNECT_TYPE_PCI);
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -2005,7 +2041,16 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
|
|
|
43fe83 |
virDevicePCIAddressPtr next_addr,
|
|
|
43fe83 |
qemuDomainPCIConnectFlags flags)
|
|
|
43fe83 |
{
|
|
|
43fe83 |
- virDevicePCIAddress a = addrs->lastaddr;
|
|
|
43fe83 |
+ /* default to starting the search for a free slot from
|
|
|
43fe83 |
+ * 0000:00:00.0
|
|
|
43fe83 |
+ */
|
|
|
43fe83 |
+ virDevicePCIAddress a = { 0, 0, 0, 0, false };
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+ /* except if this search is for the exact same type of device as
|
|
|
43fe83 |
+ * last time, continue the search from the previous match
|
|
|
43fe83 |
+ */
|
|
|
43fe83 |
+ if (flags == addrs->lastFlags)
|
|
|
43fe83 |
+ a = addrs->lastaddr;
|
|
|
43fe83 |
|
|
|
43fe83 |
if (addrs->nbuses == 0) {
|
|
|
43fe83 |
virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
|
|
|
43fe83 |
@@ -2014,6 +2059,12 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
|
|
|
43fe83 |
|
|
|
43fe83 |
/* Start the search at the last used bus and slot */
|
|
|
43fe83 |
for (a.slot++; a.bus < addrs->nbuses; a.bus++) {
|
|
|
43fe83 |
+ if (!qemuDomainPCIAddressFlagsCompatible(&a, addrs->buses[a.bus].flags,
|
|
|
43fe83 |
+ flags, false)) {
|
|
|
43fe83 |
+ VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
|
|
|
43fe83 |
+ a.domain, a.bus);
|
|
|
43fe83 |
+ continue;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
for (; a.slot <= QEMU_PCI_ADDRESS_SLOT_LAST; a.slot++) {
|
|
|
43fe83 |
if (!qemuDomainPCIAddressSlotInUse(addrs, &a))
|
|
|
43fe83 |
goto success;
|
|
|
43fe83 |
@@ -2030,9 +2081,15 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs,
|
|
|
43fe83 |
if (qemuDomainPCIAddressSetGrow(addrs, &a, flags) < 0)
|
|
|
43fe83 |
return -1;
|
|
|
43fe83 |
goto success;
|
|
|
43fe83 |
- } else {
|
|
|
43fe83 |
+ } else if (flags == addrs->lastFlags) {
|
|
|
43fe83 |
/* Check the buses from 0 up to the last used one */
|
|
|
43fe83 |
for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) {
|
|
|
43fe83 |
+ if (!qemuDomainPCIAddressFlagsCompatible(&a, addrs->buses[a.bus].flags,
|
|
|
43fe83 |
+ flags, false)) {
|
|
|
43fe83 |
+ VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
|
|
|
43fe83 |
+ a.domain, a.bus);
|
|
|
43fe83 |
+ continue;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
for (a.slot = 1; a.slot <= QEMU_PCI_ADDRESS_SLOT_LAST; a.slot++) {
|
|
|
43fe83 |
if (!qemuDomainPCIAddressSlotInUse(addrs, &a))
|
|
|
43fe83 |
goto success;
|
|
|
43fe83 |
@@ -2072,6 +2129,7 @@ qemuDomainPCIAddressReserveNextSlot(qemuDomainPCIAddressSetPtr addrs,
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
addrs->lastaddr = addr;
|
|
|
43fe83 |
+ addrs->lastFlags = flags;
|
|
|
43fe83 |
return 0;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -2285,15 +2343,26 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
|
|
|
43fe83 |
goto error;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
- flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
|
|
|
43fe83 |
-
|
|
|
43fe83 |
/* PCI controllers */
|
|
|
43fe83 |
for (i = 0; i < def->ncontrollers; i++) {
|
|
|
43fe83 |
if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
|
|
|
43fe83 |
- if (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT)
|
|
|
43fe83 |
- continue;
|
|
|
43fe83 |
if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
|
|
|
43fe83 |
continue;
|
|
|
43fe83 |
+ switch (def->controllers[i]->model) {
|
|
|
43fe83 |
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
|
|
|
43fe83 |
+ /* pci-root is implicit in the machine,
|
|
|
43fe83 |
+ * and needs no address */
|
|
|
43fe83 |
+ continue;
|
|
|
43fe83 |
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
|
|
|
43fe83 |
+ /* pci-bridge doesn't require hot-plug
|
|
|
43fe83 |
+ * (although it does provide hot-plug in its slots)
|
|
|
43fe83 |
+ */
|
|
|
43fe83 |
+ flags = QEMU_PCI_CONNECT_TYPE_PCI;
|
|
|
43fe83 |
+ break;
|
|
|
43fe83 |
+ default:
|
|
|
43fe83 |
+ flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
|
|
|
43fe83 |
+ break;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
if (qemuDomainPCIAddressReserveNextSlot(addrs,
|
|
|
43fe83 |
&def->controllers[i]->info,
|
|
|
43fe83 |
flags) < 0)
|
|
|
43fe83 |
@@ -2301,6 +2370,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
|
|
|
43fe83 |
}
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
+ flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
for (i = 0; i < def->nfss; i++) {
|
|
|
43fe83 |
if (def->fss[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
|
|
|
43fe83 |
continue;
|
|
|
43fe83 |
--
|
|
|
43fe83 |
1.8.3.2
|
|
|
43fe83 |
|