diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f26596645a..abf024c7b2 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -766,12 +766,12 @@ enum virDomainControllerType { }; -enum virDomainControllerModelPCI { +typedef enum { VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT, VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST -}; +} virDomainControllerModelPCI; enum virDomainControllerModelSCSI { VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5a5d1129ca..22c2f25688 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -139,6 +139,7 @@ virDomainControllerDefFree; virDomainControllerFind; virDomainControllerInsert; virDomainControllerInsertPreAlloced; +virDomainControllerModelPCITypeToString; virDomainControllerModelSCSITypeFromString; virDomainControllerModelSCSITypeToString; virDomainControllerModelUSBTypeFromString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9bba9d04a2..aa3a2fd691 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1412,7 +1412,15 @@ cleanup: #define QEMU_PCI_ADDRESS_FUNCTION_LAST 7 typedef struct { - /* Each bit in a slot represents one function on that slot */ + virDomainControllerModelPCI model; + /* flags an min/max can be computed from model, but + * having them ready makes life easier. + */ + qemuDomainPCIConnectFlags flags; + size_t minSlot, maxSlot; /* usually 0,0 or 1,31 */ + /* Each bit in a slot represents one function on that slot. If the + * bit is set, that function is in use by a device. + */ uint8_t slots[QEMU_PCI_ADDRESS_SLOT_LAST + 1]; } qemuDomainPCIAddressBus; typedef qemuDomainPCIAddressBus *qemuDomainPCIAddressBusPtr; @@ -1430,9 +1438,13 @@ struct _qemuDomainPCIAddressSet { * Check that the PCI address is valid for use * with the specified PCI address set. */ -static bool qemuPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs ATTRIBUTE_UNUSED, - virDevicePCIAddressPtr addr) +static bool +qemuPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs ATTRIBUTE_UNUSED, + virDevicePCIAddressPtr addr, + qemuDomainPCIConnectFlags flags) { + qemuDomainPCIAddressBusPtr bus; + if (addrs->nbuses == 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available")); return false; @@ -1448,32 +1460,81 @@ static bool qemuPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs ATTRIBUTE_UN addrs->nbuses - 1); return false; } + + bus = &addrs->buses[addr->bus]; + + /* assure that at least one of the requested connection types is + * provided by this bus + */ + if (!(flags & bus->flags & QEMU_PCI_CONNECT_TYPES_MASK)) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid PCI address: The PCI controller " + "providing bus %04x doesn't support " + "connections appropriate for the device " + "(%x required vs. %x provided by bus)"), + addr->bus, flags & QEMU_PCI_CONNECT_TYPES_MASK, + bus->flags & QEMU_PCI_CONNECT_TYPES_MASK); + return false; + } + /* make sure this bus allows hot-plug if the caller demands it */ + if ((flags & QEMU_PCI_CONNECT_HOTPLUGGABLE) && + !(bus->flags & QEMU_PCI_CONNECT_HOTPLUGGABLE)) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid PCI address: hot-pluggable slot requested, " + "but bus %04x doesn't support hot-plug"), addr->bus); + return false; + } + /* some "buses" are really just a single port */ + if (bus->minSlot && addr->slot < bus->minSlot) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid PCI address: slot must be >= %zu"), + bus->minSlot); + return false; + } + if (addr->slot > bus->maxSlot) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid PCI address: slot must be <= %zu"), + bus->maxSlot); + return false; + } if (addr->function > QEMU_PCI_ADDRESS_FUNCTION_LAST) { virReportError(VIR_ERR_XML_ERROR, _("Invalid PCI address: function must be <= %u"), QEMU_PCI_ADDRESS_FUNCTION_LAST); return false; } - if (addr->slot > QEMU_PCI_ADDRESS_SLOT_LAST) { - virReportError(VIR_ERR_XML_ERROR, - _("Invalid PCI address: slot must be <= %u"), - QEMU_PCI_ADDRESS_SLOT_LAST); - return false; - } - if (addr->slot == 0) { - if (addr->bus) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Slot 0 is unusable on PCI bridges")); - } else { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Slot 0 on bus 0 is reserved for the host bridge")); - } - return false; - } return true; } + +static int +qemuDomainPCIAddressBusSetModel(qemuDomainPCIAddressBusPtr bus, + virDomainControllerModelPCI model) +{ + switch (model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + bus->flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE | + QEMU_PCI_CONNECT_TYPE_PCI); + bus->minSlot = 1; + bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST; + break; + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid PCI controller model %d"), model); + return -1; + } + + bus->model = model; + return 0; +} + + /* Ensure addr fits in the address set, by expanding it if needed. + * This will only grow if the flags say that we need a normal + * hot-pluggable PCI slot. If we need a different type of slot, it + * will fail. + * * Return value: * -1 = OOM * 0 = no action performed @@ -1481,7 +1542,8 @@ static bool qemuPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs ATTRIBUTE_UN */ static int qemuDomainPCIAddressSetGrow(qemuDomainPCIAddressSetPtr addrs, - virDevicePCIAddressPtr addr) + virDevicePCIAddressPtr addr, + qemuDomainPCIConnectFlags flags) { int add; size_t i; @@ -1490,16 +1552,33 @@ qemuDomainPCIAddressSetGrow(qemuDomainPCIAddressSetPtr addrs, i = addrs->nbuses; if (add <= 0) return 0; + + /* auto-grow only works when we're adding plain PCI devices */ + if (!(flags & QEMU_PCI_CONNECT_TYPE_PCI)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot automatically add a new PCI bus for a " + "device requiring a slot other than standard PCI.")); + return -1; + } + if (VIR_EXPAND_N(addrs->buses, addrs->nbuses, add) < 0) return -1; - /* reserve slot 0 on the new buses */ - for (; i < addrs->nbuses; i++) - addrs->buses[i].slots[0] = 0xFF; + + for (; i < addrs->nbuses; i++) { + /* Any time we auto-add a bus, we will want a multi-slot + * bus. Currently the only type of bus we will auto-add is a + * pci-bridge, which is hot-pluggable and provides standard + * PCI slots. + */ + qemuDomainPCIAddressBusSetModel(&addrs->buses[i], + VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE); + } return add; } -static char *qemuPCIAddressAsString(virDevicePCIAddressPtr addr) +static char * +qemuPCIAddressAsString(virDevicePCIAddressPtr addr) { char *str; @@ -1512,15 +1591,19 @@ static char *qemuPCIAddressAsString(virDevicePCIAddressPtr addr) } -static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, - virDomainDeviceDefPtr device, - virDomainDeviceInfoPtr info, - void *opaque) +static int +qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr device, + virDomainDeviceInfoPtr info, + void *opaque) { int ret = -1; char *str = NULL; virDevicePCIAddressPtr addr = &info->addr.pci; qemuDomainPCIAddressSetPtr addrs = opaque; + /* FIXME: flags should be set according to the requirements of @device */ + qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE | + QEMU_PCI_CONNECT_TYPE_PCI); if ((info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) || ((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) && @@ -1538,6 +1621,11 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, * * If the machine does have a PCI bus, they will get reserved * in qemuAssignDevicePCISlots(). + * + * FIXME: When we have support for a pcie-root controller at bus + * 0, we will no longer be able to skip checking of these devices, + * as they are PCI, and thus can't be connected to bus 0 if it is + * PCIe rather than PCI. */ if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER && addr->domain == 0 && addr->bus == 0 && addr->slot == 1) { @@ -1551,15 +1639,22 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, return 0; } - if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr) < 0) + /* add an additional bus of the correct type if needed */ + if (addrs->dryRun && + qemuDomainPCIAddressSetGrow(addrs, addr, flags) < 0) return -1; - if (!qemuPCIAddressValidate(addrs, addr)) + /* verify that the address is in bounds for the chosen bus, and + * that the bus is of the correct type for the device (via + * comparing the flags). + */ + if (!qemuPCIAddressValidate(addrs, addr, flags)) return -1; if (!(str = qemuPCIAddressAsString(addr))) goto cleanup; + /* check if already in use */ if (addrs->buses[addr->bus].slots[addr->slot] & (1 << addr->function)) { if (info->addr.pci.function != 0) { virReportError(VIR_ERR_XML_ERROR, @@ -1573,6 +1668,7 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, goto cleanup; } + /* mark as in use */ if ((info->addr.pci.function == 0) && (info->addr.pci.multi != VIR_DEVICE_ADDRESS_PCI_MULTI_ON)) { /* a function 0 w/o multifunction=on must reserve the entire slot */ @@ -1611,6 +1707,8 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, int nbuses = 0; size_t i; int rv; + qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE | + QEMU_PCI_CONNECT_TYPE_PCI); for (i = 0; i < def->ncontrollers; i++) { if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { @@ -1624,22 +1722,25 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, if (nbuses > 0 && virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PCI_BRIDGE)) { virDomainDeviceInfo info; + /* 1st pass to figure out how many PCI bridges we need */ if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, true))) goto cleanup; if (qemuAssignDevicePCISlots(def, qemuCaps, addrs) < 0) goto cleanup; /* Reserve 1 extra slot for a (potential) bridge */ - if (qemuDomainPCIAddressSetNextAddr(addrs, &info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &info, flags) < 0) goto cleanup; for (i = 1; i < addrs->nbuses; i++) { + qemuDomainPCIAddressBusPtr bus = &addrs->buses[i]; + if ((rv = virDomainDefMaybeAddController( - def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, - i, VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE)) < 0) + def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, + i, bus->model)) < 0) goto cleanup; /* If we added a new bridge, we will need one more address */ - if (rv > 0 && qemuDomainPCIAddressSetNextAddr(addrs, &info) < 0) + if (rv > 0 && qemuDomainPCIAddressSetNextAddr(addrs, &info, flags) < 0) goto cleanup; } nbuses = addrs->nbuses; @@ -1698,9 +1799,11 @@ int qemuDomainAssignAddresses(virDomainDefPtr def, return qemuDomainAssignPCIAddresses(def, qemuCaps, obj); } -qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def, - unsigned int nbuses, - bool dryRun) + +qemuDomainPCIAddressSetPtr +qemuDomainPCIAddressSetCreate(virDomainDefPtr def, + unsigned int nbuses, + bool dryRun) { qemuDomainPCIAddressSetPtr addrs; size_t i; @@ -1714,10 +1817,38 @@ qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def, addrs->nbuses = nbuses; addrs->dryRun = dryRun; - /* reserve slot 0 in every bus - it's used by the host bridge on bus 0 - * and unusable on PCI bridges */ - for (i = 0; i < nbuses; i++) - addrs->buses[i].slots[0] = 0xFF; + /* As a safety measure, set default model='pci-root' for first pci + * controller and 'pci-bridge' for all subsequent. After setting + * those defaults, then scan the config and set the actual model + * for all addrs[idx]->bus that already have a corresponding + * controller in the config. + * + */ + if (nbuses > 0) + qemuDomainPCIAddressBusSetModel(&addrs->buses[0], + VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT); + for (i = 1; i < nbuses; i++) { + qemuDomainPCIAddressBusSetModel(&addrs->buses[i], + VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE); + } + + for (i = 0; i < def->ncontrollers; i++) { + size_t idx = def->controllers[i]->idx; + + if (def->controllers[i]->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI) + continue; + + if (idx >= addrs->nbuses) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Inappropriate new pci controller index %zu " + "not found in addrs"), idx); + goto error; + } + + if (qemuDomainPCIAddressBusSetModel(&addrs->buses[idx], + def->controllers[i]->model) < 0) + goto error; + } if (virDomainDeviceInfoIterate(def, qemuCollectPCIAddress, addrs) < 0) goto error; @@ -1738,12 +1869,16 @@ static bool qemuDomainPCIAddressSlotInUse(qemuDomainPCIAddressSetPtr addrs, return !!addrs->buses[addr->bus].slots[addr->slot]; } -int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs, - virDevicePCIAddressPtr addr) + +int +qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs, + virDevicePCIAddressPtr addr, + qemuDomainPCIConnectFlags flags) { char *str; + qemuDomainPCIAddressBusPtr bus; - if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr) < 0) + if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr, flags) < 0) return -1; if (!(str = qemuPCIAddressAsString(addr))) @@ -1751,9 +1886,19 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs, VIR_DEBUG("Reserving PCI addr %s", str); - if (addrs->buses[addr->bus].slots[addr->slot] & (1 << addr->function)) { + bus = &addrs->buses[addr->bus]; + if ((bus->minSlot && addr->slot < bus->minSlot) || + addr->slot > bus->maxSlot) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("unable to reserve PCI address %s"), str); + _("Unable to reserve PCI address %s. " + "Slot %02x can't be used on bus %04x, " + "only slots %02zx - %02zx are permitted on this bus."), + str, addr->slot, addr->bus, bus->minSlot, bus->maxSlot); + } + + if (bus->slots[addr->slot] & (1 << addr->function)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unable to reserve PCI address %s already in use"), str); VIR_FREE(str); return -1; } @@ -1763,16 +1908,19 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs, addrs->lastaddr = *addr; addrs->lastaddr.function = 0; addrs->lastaddr.multi = 0; - addrs->buses[addr->bus].slots[addr->slot] |= 1 << addr->function; + bus->slots[addr->slot] |= 1 << addr->function; return 0; } -int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs, - virDevicePCIAddressPtr addr) + +int +qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs, + virDevicePCIAddressPtr addr, + qemuDomainPCIConnectFlags flags) { char *str; - if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr) < 0) + if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr, flags) < 0) return -1; if (!(str = qemuPCIAddressAsString(addr))) @@ -1796,6 +1944,10 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs, virDomainDeviceInfoPtr dev) { int ret = 0; + /* FIXME: flags should be set according to the particular device */ + qemuDomainPCIConnectFlags flags = (QEMU_PCI_CONNECT_HOTPLUGGABLE | + QEMU_PCI_CONNECT_TYPE_PCI); + if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { /* We do not support hotplug multi-function PCI device now, so we should * reserve the whole slot. The function of the PCI device must be 0. @@ -1807,12 +1959,12 @@ int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs, return -1; } - if (!qemuPCIAddressValidate(addrs, &dev->addr.pci)) + if (!qemuPCIAddressValidate(addrs, &dev->addr.pci, flags)) return -1; - ret = qemuDomainPCIAddressReserveSlot(addrs, &dev->addr.pci); + ret = qemuDomainPCIAddressReserveSlot(addrs, &dev->addr.pci, flags); } else { - ret = qemuDomainPCIAddressSetNextAddr(addrs, dev); + ret = qemuDomainPCIAddressSetNextAddr(addrs, dev, flags); } return ret; } @@ -1829,7 +1981,12 @@ static int qemuDomainPCIAddressReleaseSlot(qemuDomainPCIAddressSetPtr addrs, virDevicePCIAddressPtr addr) { - if (!qemuPCIAddressValidate(addrs, addr)) + /* permit any kind of connection type in validation, since we + * already had it, and are giving it back. + */ + qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_TYPES_MASK; + + if (!qemuPCIAddressValidate(addrs, addr, flags)) return -1; addrs->buses[addr->bus].slots[addr->slot] = 0; @@ -1848,7 +2005,8 @@ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs) static int qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs, - virDevicePCIAddressPtr next_addr) + virDevicePCIAddressPtr next_addr, + qemuDomainPCIConnectFlags flags) { virDevicePCIAddress a = addrs->lastaddr; @@ -1872,7 +2030,7 @@ qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs, /* There were no free slots after the last used one */ if (addrs->dryRun) { /* a is already set to the first new bus and slot 1 */ - if (qemuDomainPCIAddressSetGrow(addrs, &a) < 0) + if (qemuDomainPCIAddressSetGrow(addrs, &a, flags) < 0) return -1; goto success; } else { @@ -1900,14 +2058,16 @@ success: return 0; } -int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs, - virDomainDeviceInfoPtr dev) +int +qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs, + virDomainDeviceInfoPtr dev, + qemuDomainPCIConnectFlags flags) { virDevicePCIAddress addr; - if (qemuDomainPCIAddressGetNextSlot(addrs, &addr) < 0) + if (qemuDomainPCIAddressGetNextSlot(addrs, &addr, flags) < 0) return -1; - if (qemuDomainPCIAddressReserveSlot(addrs, &addr) < 0) + if (qemuDomainPCIAddressReserveSlot(addrs, &addr, flags) < 0) return -1; if (!addrs->dryRun) { @@ -1962,6 +2122,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def, virDevicePCIAddress tmp_addr; bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); virDevicePCIAddressPtr addrptr; + qemuDomainPCIConnectFlags flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI; /* Verify that first IDE and USB controllers (if any) is on the PIIX3, fn 1 */ for (i = 0; i < def->ncontrollers; i++) { @@ -2013,7 +2174,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def, if (addrs->nbuses) { memset(&tmp_addr, 0, sizeof(tmp_addr)); tmp_addr.slot = 1; - if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr) < 0) + if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) goto error; } @@ -2027,21 +2188,21 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def, primaryVideo->info.addr.pci.function = 0; addrptr = &primaryVideo->info.addr.pci; - if (!qemuPCIAddressValidate(addrs, addrptr)) + if (!qemuPCIAddressValidate(addrs, addrptr, flags)) goto error; if (qemuDomainPCIAddressSlotInUse(addrs, addrptr)) { if (qemuDeviceVideoUsable) { virResetLastError(); - if (qemuDomainPCIAddressSetNextAddr(addrs, &primaryVideo->info) < 0) - goto error; + if (qemuDomainPCIAddressSetNextAddr(addrs, &primaryVideo->info, flags) < 0) + goto error;; } else { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("PCI address 0:0:2.0 is in use, " "QEMU needs it for primary video")); goto error; } - } else if (qemuDomainPCIAddressReserveSlot(addrs, addrptr) < 0) { + } else if (qemuDomainPCIAddressReserveSlot(addrs, addrptr, flags) < 0) { goto error; } } else if (!qemuDeviceVideoUsable) { @@ -2065,7 +2226,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def, " device will not be possible without manual" " intervention"); virResetLastError(); - } else if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr) < 0) { + } else if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) { goto error; } } @@ -2114,6 +2275,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) { size_t i, j; + qemuDomainPCIConnectFlags flags; virDevicePCIAddress tmp_addr; if ((STRPREFIX(def->os.machine, "pc-0.") || @@ -2125,6 +2287,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, goto error; } + flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI; + /* PCI controllers */ for (i = 0; i < def->ncontrollers; i++) { if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { @@ -2132,7 +2296,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, continue; if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) continue; - if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info, flags) < 0) goto error; } } @@ -2143,7 +2307,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, /* Only support VirtIO-9p-pci so far. If that changes, * we might need to skip devices here */ - if (qemuDomainPCIAddressSetNextAddr(addrs, &def->fss[i]->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->fss[i]->info, flags) < 0) goto error; } @@ -2157,7 +2321,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)) { continue; } - if (qemuDomainPCIAddressSetNextAddr(addrs, &def->nets[i]->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->nets[i]->info, flags) < 0) goto error; } @@ -2170,7 +2334,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_PCSPK) continue; - if (qemuDomainPCIAddressSetNextAddr(addrs, &def->sounds[i]->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->sounds[i]->info, flags) < 0) goto error; } @@ -2232,20 +2396,20 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, if (addr.slot == 0) { /* This is the first part of the controller, so need * to find a free slot & then reserve a function */ - if (qemuDomainPCIAddressGetNextSlot(addrs, &tmp_addr) < 0) + if (qemuDomainPCIAddressGetNextSlot(addrs, &tmp_addr, flags) < 0) goto error; addr.bus = tmp_addr.bus; addr.slot = tmp_addr.slot; } /* Finally we can reserve the slot+function */ - if (qemuDomainPCIAddressReserveAddr(addrs, &addr) < 0) + if (qemuDomainPCIAddressReserveAddr(addrs, &addr, flags) < 0) goto error; def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; def->controllers[i]->info.addr.pci = addr; } else { - if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info, flags) < 0) goto error; } } @@ -2270,7 +2434,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, goto error; } - if (qemuDomainPCIAddressSetNextAddr(addrs, &def->disks[i]->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->disks[i]->info, flags) < 0) goto error; } @@ -2282,7 +2446,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) continue; - if (qemuDomainPCIAddressSetNextAddr(addrs, def->hostdevs[i]->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, def->hostdevs[i]->info, flags) < 0) goto error; } @@ -2290,7 +2454,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, if (def->memballoon && def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO && def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { - if (qemuDomainPCIAddressSetNextAddr(addrs, &def->memballoon->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->memballoon->info, flags) < 0) goto error; } @@ -2298,7 +2462,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, if (def->rng && def->rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO && def->rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { - if (qemuDomainPCIAddressSetNextAddr(addrs, &def->rng->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->rng->info, flags) < 0) goto error; } @@ -2306,7 +2470,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, if (def->watchdog && def->watchdog->model != VIR_DOMAIN_WATCHDOG_MODEL_IB700 && def->watchdog->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { - if (qemuDomainPCIAddressSetNextAddr(addrs, &def->watchdog->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->watchdog->info, flags) < 0) goto error; } @@ -2319,7 +2483,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, } if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) continue; - if (qemuDomainPCIAddressSetNextAddr(addrs, &def->videos[i]->info) < 0) + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->videos[i]->info, flags) < 0) goto error; } for (i = 0; i < def->ninputs; i++) { diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index e15fe647fe..2b02d6eaf0 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -225,6 +225,23 @@ void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm, virDomainDeviceInfoPtr info, const char *devstr); +typedef enum { + QEMU_PCI_CONNECT_HOTPLUGGABLE = 1 << 0, + /* This bus supports hot-plug */ + QEMU_PCI_CONNECT_SINGLESLOT = 1 << 1, + /* This "bus" has only a single downstream slot/port */ + + QEMU_PCI_CONNECT_TYPE_PCI = 1 << 2, + /* PCI devices can connect to this bus */ +} qemuDomainPCIConnectFlags; + +/* a combination of all bit that describe the type of connections + * allowed, e.g. PCI, PCIe, switch + */ +# define QEMU_PCI_CONNECT_TYPES_MASK \ + QEMU_PCI_CONNECT_TYPE_PCI + + int qemuDomainAssignPCIAddresses(virDomainDefPtr def, virQEMUCapsPtr qemuCaps, virDomainObjPtr obj); @@ -232,11 +249,14 @@ qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def, unsigned int nbuses, bool dryRun); int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs, - virDevicePCIAddressPtr addr); + virDevicePCIAddressPtr addr, + qemuDomainPCIConnectFlags flags); int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs, - virDevicePCIAddressPtr addr); + virDevicePCIAddressPtr addr, + qemuDomainPCIConnectFlags flags); int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs, - virDomainDeviceInfoPtr dev); + virDomainDeviceInfoPtr dev, + qemuDomainPCIConnectFlags flags); int qemuDomainPCIAddressEnsureAddr(qemuDomainPCIAddressSetPtr addrs, virDomainDeviceInfoPtr dev); int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs, diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-bridge-many-disks.args b/tests/qemuxml2argvdata/qemuxml2argv-pci-bridge-many-disks.args new file mode 100644 index 0000000000..b2cf685fb4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-bridge-many-disks.args @@ -0,0 +1,217 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu-kvm \ +-S -M pc-i440fx-1.4 -cpu qemu64,-kvmclock -bios /usr/share/seabios/bios.bin \ +-m 3907 -smp 1 -nographic -nodefaults \ +-monitor unix:/tmp/test-monitor,server,nowait -boot c \ +-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x3 \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.0,addr=0x4 \ +-device pci-bridge,chassis_nr=3,id=pci.3,bus=pci.0,addr=0x5 \ +-usb -drive file=/var/lib/libvirt/images/test.img,if=none,id=drive-virtio-disk0 \ +-device virtio-blk-pci,bus=pci.0,addr=0x6,drive=drive-virtio-disk0,id=virtio-disk0 \ +-drive file=/var/lib/libvirt/images/disk-a-a.img,if=none,id=drive-virtio-disk0 \ +-device virtio-blk-pci,bus=pci.0,addr=0x7,drive=drive-virtio-disk0,id=virtio-disk0 \ +-drive file=/var/lib/libvirt/images/disk-a-b.img,if=none,id=drive-virtio-disk27 \ +-device virtio-blk-pci,bus=pci.0,addr=0x8,drive=drive-virtio-disk27,id=virtio-disk27 \ +-drive file=/var/lib/libvirt/images/disk-a-c.img,if=none,id=drive-virtio-disk28 \ +-device virtio-blk-pci,bus=pci.0,addr=0x9,drive=drive-virtio-disk28,id=virtio-disk28 \ +-drive file=/var/lib/libvirt/images/disk-a-d.img,if=none,id=drive-virtio-disk29 \ +-device virtio-blk-pci,bus=pci.0,addr=0xa,drive=drive-virtio-disk29,id=virtio-disk29 \ +-drive file=/var/lib/libvirt/images/disk-b-a.img,if=none,id=drive-virtio-disk52 \ +-device virtio-blk-pci,bus=pci.0,addr=0xb,drive=drive-virtio-disk52,id=virtio-disk52 \ +-drive file=/var/lib/libvirt/images/disk-b-b.img,if=none,id=drive-virtio-disk53 \ +-device virtio-blk-pci,bus=pci.0,addr=0xc,drive=drive-virtio-disk53,id=virtio-disk53 \ +-drive file=/var/lib/libvirt/images/disk-b-c.img,if=none,id=drive-virtio-disk54 \ +-device virtio-blk-pci,bus=pci.0,addr=0xd,drive=drive-virtio-disk54,id=virtio-disk54 \ +-drive file=/var/lib/libvirt/images/disk-b-d.img,if=none,id=drive-virtio-disk55 \ +-device virtio-blk-pci,bus=pci.0,addr=0xe,drive=drive-virtio-disk55,id=virtio-disk55 \ +-drive file=/var/lib/libvirt/images/disk-c-a.img,if=none,id=drive-virtio-disk78 \ +-device virtio-blk-pci,bus=pci.0,addr=0xf,drive=drive-virtio-disk78,id=virtio-disk78 \ +-drive file=/var/lib/libvirt/images/disk-c-b.img,if=none,id=drive-virtio-disk79 \ +-device virtio-blk-pci,bus=pci.0,addr=0x10,drive=drive-virtio-disk79,id=virtio-disk79 \ +-drive file=/var/lib/libvirt/images/disk-c-c.img,if=none,id=drive-virtio-disk80 \ +-device virtio-blk-pci,bus=pci.0,addr=0x11,drive=drive-virtio-disk80,id=virtio-disk80 \ +-drive file=/var/lib/libvirt/images/disk-c-d.img,if=none,id=drive-virtio-disk81 \ +-device virtio-blk-pci,bus=pci.0,addr=0x12,drive=drive-virtio-disk81,id=virtio-disk81 \ +-drive file=/var/lib/libvirt/images/disk-d-a.img,if=none,id=drive-virtio-disk104 \ +-device virtio-blk-pci,bus=pci.0,addr=0x13,drive=drive-virtio-disk104,id=virtio-disk104 \ +-drive file=/var/lib/libvirt/images/disk-d-b.img,if=none,id=drive-virtio-disk105 \ +-device virtio-blk-pci,bus=pci.0,addr=0x14,drive=drive-virtio-disk105,id=virtio-disk105 \ +-drive file=/var/lib/libvirt/images/disk-d-c.img,if=none,id=drive-virtio-disk106 \ +-device virtio-blk-pci,bus=pci.0,addr=0x15,drive=drive-virtio-disk106,id=virtio-disk106 \ +-drive file=/var/lib/libvirt/images/disk-d-d.img,if=none,id=drive-virtio-disk107 \ +-device virtio-blk-pci,bus=pci.0,addr=0x16,drive=drive-virtio-disk107,id=virtio-disk107 \ +-drive file=/var/lib/libvirt/images/disk-e-a.img,if=none,id=drive-virtio-disk130 \ +-device virtio-blk-pci,bus=pci.0,addr=0x17,drive=drive-virtio-disk130,id=virtio-disk130 \ +-drive file=/var/lib/libvirt/images/disk-e-b.img,if=none,id=drive-virtio-disk131 \ +-device virtio-blk-pci,bus=pci.0,addr=0x18,drive=drive-virtio-disk131,id=virtio-disk131 \ +-drive file=/var/lib/libvirt/images/disk-e-c.img,if=none,id=drive-virtio-disk132 \ +-device virtio-blk-pci,bus=pci.0,addr=0x19,drive=drive-virtio-disk132,id=virtio-disk132 \ +-drive file=/var/lib/libvirt/images/disk-e-d.img,if=none,id=drive-virtio-disk133 \ +-device virtio-blk-pci,bus=pci.0,addr=0x1a,drive=drive-virtio-disk133,id=virtio-disk133 \ +-drive file=/var/lib/libvirt/images/disk-f-a.img,if=none,id=drive-virtio-disk156 \ +-device virtio-blk-pci,bus=pci.0,addr=0x1b,drive=drive-virtio-disk156,id=virtio-disk156 \ +-drive file=/var/lib/libvirt/images/disk-f-b.img,if=none,id=drive-virtio-disk157 \ +-device virtio-blk-pci,bus=pci.0,addr=0x1c,drive=drive-virtio-disk157,id=virtio-disk157 \ +-drive file=/var/lib/libvirt/images/disk-f-c.img,if=none,id=drive-virtio-disk158 \ +-device virtio-blk-pci,bus=pci.0,addr=0x1d,drive=drive-virtio-disk158,id=virtio-disk158 \ +-drive file=/var/lib/libvirt/images/disk-f-d.img,if=none,id=drive-virtio-disk159 \ +-device virtio-blk-pci,bus=pci.0,addr=0x1e,drive=drive-virtio-disk159,id=virtio-disk159 \ +-drive file=/var/lib/libvirt/images/disk-g-a.img,if=none,id=drive-virtio-disk182 \ +-device virtio-blk-pci,bus=pci.0,addr=0x1f,drive=drive-virtio-disk182,id=virtio-disk182 \ +-drive file=/var/lib/libvirt/images/disk-g-b.img,if=none,id=drive-virtio-disk183 \ +-device virtio-blk-pci,bus=pci.1,addr=0x1,drive=drive-virtio-disk183,id=virtio-disk183 \ +-drive file=/var/lib/libvirt/images/disk-g-c.img,if=none,id=drive-virtio-disk184 \ +-device virtio-blk-pci,bus=pci.1,addr=0x2,drive=drive-virtio-disk184,id=virtio-disk184 \ +-drive file=/var/lib/libvirt/images/disk-g-d.img,if=none,id=drive-virtio-disk185 \ +-device virtio-blk-pci,bus=pci.1,addr=0x3,drive=drive-virtio-disk185,id=virtio-disk185 \ +-drive file=/var/lib/libvirt/images/disk-h-a.img,if=none,id=drive-virtio-disk208 \ +-device virtio-blk-pci,bus=pci.1,addr=0x4,drive=drive-virtio-disk208,id=virtio-disk208 \ +-drive file=/var/lib/libvirt/images/disk-h-b.img,if=none,id=drive-virtio-disk209 \ +-device virtio-blk-pci,bus=pci.1,addr=0x5,drive=drive-virtio-disk209,id=virtio-disk209 \ +-drive file=/var/lib/libvirt/images/disk-h-c.img,if=none,id=drive-virtio-disk210 \ +-device virtio-blk-pci,bus=pci.1,addr=0x6,drive=drive-virtio-disk210,id=virtio-disk210 \ +-drive file=/var/lib/libvirt/images/disk-h-d.img,if=none,id=drive-virtio-disk211 \ +-device virtio-blk-pci,bus=pci.1,addr=0x7,drive=drive-virtio-disk211,id=virtio-disk211 \ +-drive file=/var/lib/libvirt/images/disk-i-a.img,if=none,id=drive-virtio-disk234 \ +-device virtio-blk-pci,bus=pci.1,addr=0x8,drive=drive-virtio-disk234,id=virtio-disk234 \ +-drive file=/var/lib/libvirt/images/disk-i-b.img,if=none,id=drive-virtio-disk235 \ +-device virtio-blk-pci,bus=pci.1,addr=0x9,drive=drive-virtio-disk235,id=virtio-disk235 \ +-drive file=/var/lib/libvirt/images/disk-i-c.img,if=none,id=drive-virtio-disk236 \ +-device virtio-blk-pci,bus=pci.1,addr=0xa,drive=drive-virtio-disk236,id=virtio-disk236 \ +-drive file=/var/lib/libvirt/images/disk-i-d.img,if=none,id=drive-virtio-disk237 \ +-device virtio-blk-pci,bus=pci.1,addr=0xb,drive=drive-virtio-disk237,id=virtio-disk237 \ +-drive file=/var/lib/libvirt/images/disk-j-a.img,if=none,id=drive-virtio-disk260 \ +-device virtio-blk-pci,bus=pci.1,addr=0xc,drive=drive-virtio-disk260,id=virtio-disk260 \ +-drive file=/var/lib/libvirt/images/disk-j-b.img,if=none,id=drive-virtio-disk261 \ +-device virtio-blk-pci,bus=pci.1,addr=0xd,drive=drive-virtio-disk261,id=virtio-disk261 \ +-drive file=/var/lib/libvirt/images/disk-j-c.img,if=none,id=drive-virtio-disk262 \ +-device virtio-blk-pci,bus=pci.1,addr=0xe,drive=drive-virtio-disk262,id=virtio-disk262 \ +-drive file=/var/lib/libvirt/images/disk-j-d.img,if=none,id=drive-virtio-disk263 \ +-device virtio-blk-pci,bus=pci.1,addr=0xf,drive=drive-virtio-disk263,id=virtio-disk263 \ +-drive file=/var/lib/libvirt/images/disk-k-a.img,if=none,id=drive-virtio-disk286 \ +-device virtio-blk-pci,bus=pci.1,addr=0x10,drive=drive-virtio-disk286,id=virtio-disk286 \ +-drive file=/var/lib/libvirt/images/disk-k-b.img,if=none,id=drive-virtio-disk287 \ +-device virtio-blk-pci,bus=pci.1,addr=0x11,drive=drive-virtio-disk287,id=virtio-disk287 \ +-drive file=/var/lib/libvirt/images/disk-k-c.img,if=none,id=drive-virtio-disk288 \ +-device virtio-blk-pci,bus=pci.1,addr=0x12,drive=drive-virtio-disk288,id=virtio-disk288 \ +-drive file=/var/lib/libvirt/images/disk-k-d.img,if=none,id=drive-virtio-disk289 \ +-device virtio-blk-pci,bus=pci.1,addr=0x13,drive=drive-virtio-disk289,id=virtio-disk289 \ +-drive file=/var/lib/libvirt/images/disk-l-a.img,if=none,id=drive-virtio-disk312 \ +-device virtio-blk-pci,bus=pci.1,addr=0x14,drive=drive-virtio-disk312,id=virtio-disk312 \ +-drive file=/var/lib/libvirt/images/disk-l-b.img,if=none,id=drive-virtio-disk313 \ +-device virtio-blk-pci,bus=pci.1,addr=0x15,drive=drive-virtio-disk313,id=virtio-disk313 \ +-drive file=/var/lib/libvirt/images/disk-l-c.img,if=none,id=drive-virtio-disk314 \ +-device virtio-blk-pci,bus=pci.1,addr=0x16,drive=drive-virtio-disk314,id=virtio-disk314 \ +-drive file=/var/lib/libvirt/images/disk-l-d.img,if=none,id=drive-virtio-disk315 \ +-device virtio-blk-pci,bus=pci.1,addr=0x17,drive=drive-virtio-disk315,id=virtio-disk315 \ +-drive file=/var/lib/libvirt/images/disk-m-a.img,if=none,id=drive-virtio-disk338 \ +-device virtio-blk-pci,bus=pci.1,addr=0x18,drive=drive-virtio-disk338,id=virtio-disk338 \ +-drive file=/var/lib/libvirt/images/disk-m-b.img,if=none,id=drive-virtio-disk339 \ +-device virtio-blk-pci,bus=pci.1,addr=0x19,drive=drive-virtio-disk339,id=virtio-disk339 \ +-drive file=/var/lib/libvirt/images/disk-m-c.img,if=none,id=drive-virtio-disk340 \ +-device virtio-blk-pci,bus=pci.1,addr=0x1a,drive=drive-virtio-disk340,id=virtio-disk340 \ +-drive file=/var/lib/libvirt/images/disk-m-d.img,if=none,id=drive-virtio-disk341 \ +-device virtio-blk-pci,bus=pci.1,addr=0x1b,drive=drive-virtio-disk341,id=virtio-disk341 \ +-drive file=/var/lib/libvirt/images/disk-n-a.img,if=none,id=drive-virtio-disk364 \ +-device virtio-blk-pci,bus=pci.1,addr=0x1c,drive=drive-virtio-disk364,id=virtio-disk364 \ +-drive file=/var/lib/libvirt/images/disk-n-b.img,if=none,id=drive-virtio-disk365 \ +-device virtio-blk-pci,bus=pci.1,addr=0x1d,drive=drive-virtio-disk365,id=virtio-disk365 \ +-drive file=/var/lib/libvirt/images/disk-n-c.img,if=none,id=drive-virtio-disk366 \ +-device virtio-blk-pci,bus=pci.1,addr=0x1e,drive=drive-virtio-disk366,id=virtio-disk366 \ +-drive file=/var/lib/libvirt/images/disk-n-d.img,if=none,id=drive-virtio-disk367 \ +-device virtio-blk-pci,bus=pci.1,addr=0x1f,drive=drive-virtio-disk367,id=virtio-disk367 \ +-drive file=/var/lib/libvirt/images/disk-o-a.img,if=none,id=drive-virtio-disk390 \ +-device virtio-blk-pci,bus=pci.2,addr=0x1,drive=drive-virtio-disk390,id=virtio-disk390 \ +-drive file=/var/lib/libvirt/images/disk-o-b.img,if=none,id=drive-virtio-disk391 \ +-device virtio-blk-pci,bus=pci.2,addr=0x2,drive=drive-virtio-disk391,id=virtio-disk391 \ +-drive file=/var/lib/libvirt/images/disk-o-c.img,if=none,id=drive-virtio-disk392 \ +-device virtio-blk-pci,bus=pci.2,addr=0x3,drive=drive-virtio-disk392,id=virtio-disk392 \ +-drive file=/var/lib/libvirt/images/disk-o-d.img,if=none,id=drive-virtio-disk393 \ +-device virtio-blk-pci,bus=pci.2,addr=0x4,drive=drive-virtio-disk393,id=virtio-disk393 \ +-drive file=/var/lib/libvirt/images/disk-p-a.img,if=none,id=drive-virtio-disk416 \ +-device virtio-blk-pci,bus=pci.2,addr=0x5,drive=drive-virtio-disk416,id=virtio-disk416 \ +-drive file=/var/lib/libvirt/images/disk-p-b.img,if=none,id=drive-virtio-disk417 \ +-device virtio-blk-pci,bus=pci.2,addr=0x6,drive=drive-virtio-disk417,id=virtio-disk417 \ +-drive file=/var/lib/libvirt/images/disk-p-c.img,if=none,id=drive-virtio-disk418 \ +-device virtio-blk-pci,bus=pci.2,addr=0x7,drive=drive-virtio-disk418,id=virtio-disk418 \ +-drive file=/var/lib/libvirt/images/disk-p-d.img,if=none,id=drive-virtio-disk419 \ +-device virtio-blk-pci,bus=pci.2,addr=0x8,drive=drive-virtio-disk419,id=virtio-disk419 \ +-drive file=/var/lib/libvirt/images/disk-q-a.img,if=none,id=drive-virtio-disk442 \ +-device virtio-blk-pci,bus=pci.2,addr=0x9,drive=drive-virtio-disk442,id=virtio-disk442 \ +-drive file=/var/lib/libvirt/images/disk-q-b.img,if=none,id=drive-virtio-disk443 \ +-device virtio-blk-pci,bus=pci.2,addr=0xa,drive=drive-virtio-disk443,id=virtio-disk443 \ +-drive file=/var/lib/libvirt/images/disk-q-c.img,if=none,id=drive-virtio-disk444 \ +-device virtio-blk-pci,bus=pci.2,addr=0xb,drive=drive-virtio-disk444,id=virtio-disk444 \ +-drive file=/var/lib/libvirt/images/disk-q-d.img,if=none,id=drive-virtio-disk445 \ +-device virtio-blk-pci,bus=pci.2,addr=0xc,drive=drive-virtio-disk445,id=virtio-disk445 \ +-drive file=/var/lib/libvirt/images/disk-r-a.img,if=none,id=drive-virtio-disk468 \ +-device virtio-blk-pci,bus=pci.2,addr=0xd,drive=drive-virtio-disk468,id=virtio-disk468 \ +-drive file=/var/lib/libvirt/images/disk-r-b.img,if=none,id=drive-virtio-disk469 \ +-device virtio-blk-pci,bus=pci.2,addr=0xe,drive=drive-virtio-disk469,id=virtio-disk469 \ +-drive file=/var/lib/libvirt/images/disk-r-c.img,if=none,id=drive-virtio-disk470 \ +-device virtio-blk-pci,bus=pci.2,addr=0xf,drive=drive-virtio-disk470,id=virtio-disk470 \ +-drive file=/var/lib/libvirt/images/disk-r-d.img,if=none,id=drive-virtio-disk471 \ +-device virtio-blk-pci,bus=pci.2,addr=0x10,drive=drive-virtio-disk471,id=virtio-disk471 \ +-drive file=/var/lib/libvirt/images/disk-s-a.img,if=none,id=drive-virtio-disk494 \ +-device virtio-blk-pci,bus=pci.2,addr=0x11,drive=drive-virtio-disk494,id=virtio-disk494 \ +-drive file=/var/lib/libvirt/images/disk-s-b.img,if=none,id=drive-virtio-disk495 \ +-device virtio-blk-pci,bus=pci.2,addr=0x12,drive=drive-virtio-disk495,id=virtio-disk495 \ +-drive file=/var/lib/libvirt/images/disk-s-c.img,if=none,id=drive-virtio-disk496 \ +-device virtio-blk-pci,bus=pci.2,addr=0x13,drive=drive-virtio-disk496,id=virtio-disk496 \ +-drive file=/var/lib/libvirt/images/disk-s-d.img,if=none,id=drive-virtio-disk497 \ +-device virtio-blk-pci,bus=pci.2,addr=0x14,drive=drive-virtio-disk497,id=virtio-disk497 \ +-drive file=/var/lib/libvirt/images/disk-t-a.img,if=none,id=drive-virtio-disk520 \ +-device virtio-blk-pci,bus=pci.2,addr=0x15,drive=drive-virtio-disk520,id=virtio-disk520 \ +-drive file=/var/lib/libvirt/images/disk-t-b.img,if=none,id=drive-virtio-disk521 \ +-device virtio-blk-pci,bus=pci.2,addr=0x16,drive=drive-virtio-disk521,id=virtio-disk521 \ +-drive file=/var/lib/libvirt/images/disk-t-c.img,if=none,id=drive-virtio-disk522 \ +-device virtio-blk-pci,bus=pci.2,addr=0x17,drive=drive-virtio-disk522,id=virtio-disk522 \ +-drive file=/var/lib/libvirt/images/disk-t-d.img,if=none,id=drive-virtio-disk523 \ +-device virtio-blk-pci,bus=pci.2,addr=0x18,drive=drive-virtio-disk523,id=virtio-disk523 \ +-drive file=/var/lib/libvirt/images/disk-u-a.img,if=none,id=drive-virtio-disk546 \ +-device virtio-blk-pci,bus=pci.2,addr=0x19,drive=drive-virtio-disk546,id=virtio-disk546 \ +-drive file=/var/lib/libvirt/images/disk-u-b.img,if=none,id=drive-virtio-disk547 \ +-device virtio-blk-pci,bus=pci.2,addr=0x1a,drive=drive-virtio-disk547,id=virtio-disk547 \ +-drive file=/var/lib/libvirt/images/disk-u-c.img,if=none,id=drive-virtio-disk548 \ +-device virtio-blk-pci,bus=pci.2,addr=0x1b,drive=drive-virtio-disk548,id=virtio-disk548 \ +-drive file=/var/lib/libvirt/images/disk-u-d.img,if=none,id=drive-virtio-disk549 \ +-device virtio-blk-pci,bus=pci.2,addr=0x1c,drive=drive-virtio-disk549,id=virtio-disk549 \ +-drive file=/var/lib/libvirt/images/disk-v-a.img,if=none,id=drive-virtio-disk572 \ +-device virtio-blk-pci,bus=pci.2,addr=0x1d,drive=drive-virtio-disk572,id=virtio-disk572 \ +-drive file=/var/lib/libvirt/images/disk-v-b.img,if=none,id=drive-virtio-disk573 \ +-device virtio-blk-pci,bus=pci.2,addr=0x1e,drive=drive-virtio-disk573,id=virtio-disk573 \ +-drive file=/var/lib/libvirt/images/disk-v-c.img,if=none,id=drive-virtio-disk574 \ +-device virtio-blk-pci,bus=pci.2,addr=0x1f,drive=drive-virtio-disk574,id=virtio-disk574 \ +-drive file=/var/lib/libvirt/images/disk-v-d.img,if=none,id=drive-virtio-disk575 \ +-device virtio-blk-pci,bus=pci.3,addr=0x1,drive=drive-virtio-disk575,id=virtio-disk575 \ +-drive file=/var/lib/libvirt/images/disk-w-a.img,if=none,id=drive-virtio-disk598 \ +-device virtio-blk-pci,bus=pci.3,addr=0x2,drive=drive-virtio-disk598,id=virtio-disk598 \ +-drive file=/var/lib/libvirt/images/disk-w-b.img,if=none,id=drive-virtio-disk599 \ +-device virtio-blk-pci,bus=pci.3,addr=0x3,drive=drive-virtio-disk599,id=virtio-disk599 \ +-drive file=/var/lib/libvirt/images/disk-w-c.img,if=none,id=drive-virtio-disk600 \ +-device virtio-blk-pci,bus=pci.3,addr=0x4,drive=drive-virtio-disk600,id=virtio-disk600 \ +-drive file=/var/lib/libvirt/images/disk-w-d.img,if=none,id=drive-virtio-disk601 \ +-device virtio-blk-pci,bus=pci.3,addr=0x5,drive=drive-virtio-disk601,id=virtio-disk601 \ +-drive file=/var/lib/libvirt/images/disk-x-a.img,if=none,id=drive-virtio-disk624 \ +-device virtio-blk-pci,bus=pci.3,addr=0x6,drive=drive-virtio-disk624,id=virtio-disk624 \ +-drive file=/var/lib/libvirt/images/disk-x-b.img,if=none,id=drive-virtio-disk625 \ +-device virtio-blk-pci,bus=pci.3,addr=0x7,drive=drive-virtio-disk625,id=virtio-disk625 \ +-drive file=/var/lib/libvirt/images/disk-x-c.img,if=none,id=drive-virtio-disk626 \ +-device virtio-blk-pci,bus=pci.3,addr=0x8,drive=drive-virtio-disk626,id=virtio-disk626 \ +-drive file=/var/lib/libvirt/images/disk-x-d.img,if=none,id=drive-virtio-disk627 \ +-device virtio-blk-pci,bus=pci.3,addr=0x9,drive=drive-virtio-disk627,id=virtio-disk627 \ +-drive file=/var/lib/libvirt/images/disk-y-a.img,if=none,id=drive-virtio-disk650 \ +-device virtio-blk-pci,bus=pci.3,addr=0xa,drive=drive-virtio-disk650,id=virtio-disk650 \ +-drive file=/var/lib/libvirt/images/disk-y-b.img,if=none,id=drive-virtio-disk651 \ +-device virtio-blk-pci,bus=pci.3,addr=0xb,drive=drive-virtio-disk651,id=virtio-disk651 \ +-drive file=/var/lib/libvirt/images/disk-y-c.img,if=none,id=drive-virtio-disk652 \ +-device virtio-blk-pci,bus=pci.3,addr=0xc,drive=drive-virtio-disk652,id=virtio-disk652 \ +-drive file=/var/lib/libvirt/images/disk-y-d.img,if=none,id=drive-virtio-disk653 \ +-device virtio-blk-pci,bus=pci.3,addr=0xd,drive=drive-virtio-disk653,id=virtio-disk653 \ +-drive file=/var/lib/libvirt/images/disk-z-a.img,if=none,id=drive-virtio-disk676 \ +-device virtio-blk-pci,bus=pci.3,addr=0xe,drive=drive-virtio-disk676,id=virtio-disk676 \ +-drive file=/var/lib/libvirt/images/disk-z-b.img,if=none,id=drive-virtio-disk677 \ +-device virtio-blk-pci,bus=pci.3,addr=0xf,drive=drive-virtio-disk677,id=virtio-disk677 \ +-drive file=/var/lib/libvirt/images/disk-z-c.img,if=none,id=drive-virtio-disk678 \ +-device virtio-blk-pci,bus=pci.3,addr=0x10,drive=drive-virtio-disk678,id=virtio-disk678 \ +-drive file=/var/lib/libvirt/images/disk-z-d.img,if=none,id=drive-virtio-disk679 \ +-device virtio-blk-pci,bus=pci.3,addr=0x11,drive=drive-virtio-disk679,id=virtio-disk679 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-bridge-many-disks.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-bridge-many-disks.xml new file mode 100644 index 0000000000..1f3ad6ecbc --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-bridge-many-disks.xml @@ -0,0 +1,551 @@ + + lots-of-disks + 04872dc1-e1de-434b-ab21-e3e80e416349 + 4000768 + 4000000 + + hvm + /usr/share/seabios/bios.bin + + + + + + + + + + + destroy + restart + restart + + /usr/bin/qemu-kvm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 0f96eef91e..8185c541b9 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -992,6 +992,8 @@ mymain(void) DO_TEST("pci-autoadd-addr", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE); DO_TEST("pci-autoadd-idx", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE); + DO_TEST("pci-bridge-many-disks", + QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE_PCI_BRIDGE); DO_TEST("hostdev-scsi-lsi", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-bridge-many-disks.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-bridge-many-disks.xml new file mode 100644 index 0000000000..d469b8b568 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-bridge-many-disks.xml @@ -0,0 +1,554 @@ + + lots-of-disks + 04872dc1-e1de-434b-ab21-e3e80e416349 + 4000768 + 4000000 + 1 + + hvm + /usr/share/seabios/bios.bin + + + + + + + + + + + destroy + restart + restart + + /usr/bin/qemu-kvm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 77cac3f687..66be40e648 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -291,6 +291,7 @@ mymain(void) DO_TEST("tpm-passthrough"); DO_TEST("pci-bridge"); + DO_TEST_DIFFERENT("pci-bridge-many-disks"); DO_TEST_DIFFERENT("pci-autoadd-addr"); DO_TEST_DIFFERENT("pci-autoadd-idx");