[libvirt] [PATCH v2 0/8] aggregate multiple pcie-root-ports onto a single slot

This is just a rebase of v1 of the same series, reposted to make it easier for Andrea to review. Laine Stump (8): conf: use struct instead of int for each slot in virDomainPCIAddressBus conf: eliminate concept of "reserveEntireSlot" conf: eliminate repetitive code in virDomainPCIAddressGetNextSlot() conf: start search for next unused PCI address at same slot as previous find conf: new function virDomainPCIAddressIsMulti() qemu: use virDomainPCIAddressIsMulti() to determine multifunction setting conf: aggregate multiple devices on a slot when assigning PCI addresses conf: aggregate multiple pcie-root-ports onto a single slot src/conf/domain_addr.c | 290 ++++++++++++++------- src/conf/domain_addr.h | 48 +++- src/libvirt_private.syms | 1 + src/qemu/qemu_command.c | 16 +- src/qemu/qemu_domain_address.c | 35 ++- .../qemuxml2argv-pcie-root-port.args | 5 +- .../qemuxml2argv-pcie-switch-upstream-port.args | 5 +- .../qemuxml2argv-q35-default-devices-only.args | 7 +- .../qemuxml2argv-q35-multifunction.args | 43 +++ .../qemuxml2argv-q35-multifunction.xml | 51 ++++ .../qemuxml2argv-q35-pcie-autoadd.args | 30 ++- tests/qemuxml2argvdata/qemuxml2argv-q35-pcie.args | 28 +- .../qemuxml2argv-q35-virt-manager-basic.args | 13 +- .../qemuxml2argv-q35-virtio-pci.args | 28 +- tests/qemuxml2argvtest.c | 25 ++ .../qemuxml2xmlout-pcie-root-port.xml | 2 +- .../qemuxml2xmlout-pcie-switch-upstream-port.xml | 4 +- .../qemuxml2xmlout-q35-default-devices-only.xml | 8 +- .../qemuxml2xmlout-q35-multifunction.xml | 120 +++++++++ .../qemuxml2xmlout-q35-pcie-autoadd.xml | 52 ++-- .../qemuxml2xmloutdata/qemuxml2xmlout-q35-pcie.xml | 48 ++-- .../qemuxml2xmlout-q35-virt-manager-basic.xml | 20 +- .../qemuxml2xmlout-q35-virtio-pci.xml | 48 ++-- tests/qemuxml2xmltest.c | 25 ++ 24 files changed, 676 insertions(+), 276 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml -- 2.7.4

When keeping track of which functions of which slots are allocated, we will need to have more information than just the current bitmap with a bit for each function that is currently stored for each slot in a virDomainPCIAddressBus. To prepare for adding more per-slot info, this patch changes "int slots" into "virDomainPCIAddressSlot slot", which currently has a single member named "functions" that serves the same purpose previously served directly by "slots". --- src/conf/domain_addr.c | 15 ++++++++------- src/conf/domain_addr.h | 9 ++++++++- src/qemu/qemu_domain_address.c | 2 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 781050c..adc51f9 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -464,7 +464,7 @@ bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr) { - return !!addrs->buses[addr->bus].slots[addr->slot]; + return !!addrs->buses[addr->bus].slot[addr->slot].functions; } @@ -505,17 +505,17 @@ virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, bus = &addrs->buses[addr->bus]; if (reserveEntireSlot) { - if (bus->slots[addr->slot]) { + if (bus->slot[addr->slot].functions) { virReportError(errType, _("Attempted double use of PCI slot %s " "(may need \"multifunction='on'\" for " "device on function 0)"), addrStr); goto cleanup; } - bus->slots[addr->slot] = 0xFF; /* reserve all functions of slot */ + bus->slot[addr->slot].functions = 0xFF; /* reserve all functions of slot */ VIR_DEBUG("Reserving PCI slot %s (multifunction='off')", addrStr); } else { - if (bus->slots[addr->slot] & (1 << addr->function)) { + if (bus->slot[addr->slot].functions & (1 << addr->function)) { if (addr->function == 0) { virReportError(errType, _("Attempted double use of PCI Address %s"), @@ -528,7 +528,7 @@ virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, } goto cleanup; } - bus->slots[addr->slot] |= (1 << addr->function); + bus->slot[addr->slot].functions |= (1 << addr->function); VIR_DEBUG("Reserving PCI address %s", addrStr); } @@ -595,7 +595,8 @@ int virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr) { - addrs->buses[addr->bus].slots[addr->slot] &= ~(1 << addr->function); + addrs->buses[addr->bus].slot[addr->slot].functions + &= ~(1 << addr->function); return 0; } @@ -616,7 +617,7 @@ virDomainPCIAddressReleaseSlot(virDomainPCIAddressSetPtr addrs, if (!virDomainPCIAddressValidate(addrs, addr, addrStr, flags, false)) goto cleanup; - addrs->buses[addr->bus].slots[addr->slot] = 0; + addrs->buses[addr->bus].slot[addr->slot].functions = 0; ret = 0; cleanup: VIR_FREE(addrStr); diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index bcec2c7..7df0502 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -71,6 +71,13 @@ virDomainPCIConnectFlags virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model); typedef struct { + /* each function is represented by one it, set if that function is + * in use by a device, or clear if it isn't. + */ + uint8_t functions; + } virDomainPCIAddressSlot; + +typedef struct { virDomainControllerModelPCI model; /* flags and min/max can be computed from model, but * having them ready makes life easier. @@ -80,7 +87,7 @@ typedef struct { /* 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[VIR_PCI_ADDRESS_SLOT_LAST + 1]; + virDomainPCIAddressSlot slot[VIR_PCI_ADDRESS_SLOT_LAST + 1]; } virDomainPCIAddressBus; typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 86984fb..a3dfd63 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1462,7 +1462,7 @@ qemuDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus) size_t i; for (i = bus->minSlot; i <= bus->maxSlot; i++) - if (!bus->slots[i]) + if (!bus->slot[i].functions) return false; return true; -- 2.7.4

setting reserveEntireSlot really accomplishes nothing - instead of going to the trouble of computing the value for reserveEntireSlot and then possibly setting *all* functions of the slot as in-use, we can just set the in-use bit only for the specific function being used by a device. Later we will know from the context (the PCI connect flags, and whether we are reserving a specific address or asking for "the next available") whether or not it is okay to allocate other functions on the same slot. Although it's not used yet, we allow specifying "-1" for the function number when looking for the "next available slot" - this is going to end up meaning "return the lowest avaialable function in the slot, but since we currently only provide a function from an otherwise unused slot, "-1" ends up meaning "0". --- src/conf/domain_addr.c | 76 ++++++++++++++++-------------------------- src/conf/domain_addr.h | 4 +-- src/qemu/qemu_domain_address.c | 33 ++++++++---------- 3 files changed, 43 insertions(+), 70 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index adc51f9..e0328f0 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -469,11 +469,9 @@ virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs, /* - * Reserve a slot (or just one function) for a device. If - * reserveEntireSlot is true, all functions for the slot are reserved, - * otherwise only one. If fromConfig is true, the address being - * requested came directly from the config and errors should be worded - * appropriately. If fromConfig is false, the address was + * Reserve a function in a slot. If fromConfig is true, the address + * being requested came directly from the config and errors should be + * worded appropriately. If fromConfig is false, the address was * automatically created by libvirt, so it is an internal error (not * XML). */ @@ -481,7 +479,6 @@ int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, virDomainPCIConnectFlags flags, - bool reserveEntireSlot, bool fromConfig) { int ret = -1; @@ -504,33 +501,13 @@ virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, bus = &addrs->buses[addr->bus]; - if (reserveEntireSlot) { - if (bus->slot[addr->slot].functions) { - virReportError(errType, - _("Attempted double use of PCI slot %s " - "(may need \"multifunction='on'\" for " - "device on function 0)"), addrStr); - goto cleanup; - } - bus->slot[addr->slot].functions = 0xFF; /* reserve all functions of slot */ - VIR_DEBUG("Reserving PCI slot %s (multifunction='off')", addrStr); - } else { - if (bus->slot[addr->slot].functions & (1 << addr->function)) { - if (addr->function == 0) { - virReportError(errType, - _("Attempted double use of PCI Address %s"), - addrStr); - } else { - virReportError(errType, - _("Attempted double use of PCI Address %s " - "(may need \"multifunction='on'\" " - "for device on function 0)"), addrStr); - } - goto cleanup; - } - bus->slot[addr->slot].functions |= (1 << addr->function); - VIR_DEBUG("Reserving PCI address %s", addrStr); + if (bus->slot[addr->slot].functions & (1 << addr->function)) { + virReportError(errType, _("Attempted double use of PCI Address %s"), + addrStr); + goto cleanup; } + bus->slot[addr->slot].functions |= (1 << addr->function); + VIR_DEBUG("Reserving PCI address %s", addrStr); ret = 0; cleanup: @@ -544,7 +521,7 @@ virDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, virDomainPCIConnectFlags flags) { - return virDomainPCIAddressReserveAddr(addrs, addr, flags, true, false); + return virDomainPCIAddressReserveAddr(addrs, addr, flags, false); } int @@ -579,8 +556,8 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs, addrStr, flags, true)) goto cleanup; - ret = virDomainPCIAddressReserveAddr(addrs, &dev->addr.pci, flags, - true, true); + ret = virDomainPCIAddressReserveAddr(addrs, &dev->addr.pci, + flags, true); } else { ret = virDomainPCIAddressReserveNextSlot(addrs, dev, flags); } @@ -659,6 +636,7 @@ virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs) static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr next_addr, + int function, virDomainPCIConnectFlags flags) { /* default to starting the search for a free slot from @@ -686,6 +664,12 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs, a.slot = addrs->buses[0].minSlot; } + /* if the caller asks for "any function", give them function 0 */ + if (function == -1) + a.function = 0; + else + a.function = function; + while (a.bus < addrs->nbuses) { VIR_FREE(addrStr); if (!(addrStr = virDomainPCIAddressAsString(&a))) @@ -764,14 +748,13 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs, * @dev: virDomainDeviceInfo that should get the new address. * @flags: CONNECT_TYPE flags for the device that needs an address. * @function: which function on the slot to mark as reserved - * (if @reserveEntireSlot is false) - * @reserveEntireSlot: true to reserve all functions on the new slot, - * false to reserve just @function * * Find the next *completely unreserved* slot with compatible - * connection @flags, mark either one function or the entire - * slot as in-use (according to @function and @reserveEntireSlot), - * and set @dev->addr.pci with this newly reserved address. + * connection @flags, mark one function of the slot as in-use + * (according to @function), then set @dev->addr.pci with this newly + * reserved address. If @function is -1, then the lowest unused + * function of the slot will be reserved (and since we only look for + * completely unused slots, that means "0"). * * returns 0 on success, or -1 on failure. */ @@ -779,17 +762,14 @@ int virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, virDomainDeviceInfoPtr dev, virDomainPCIConnectFlags flags, - unsigned int function, - bool reserveEntireSlot) + int function) { virPCIDeviceAddress addr; - if (virDomainPCIAddressGetNextSlot(addrs, &addr, flags) < 0) + if (virDomainPCIAddressGetNextSlot(addrs, &addr, function, flags) < 0) return -1; - addr.function = reserveEntireSlot ? 0 : function; - - if (virDomainPCIAddressReserveAddr(addrs, &addr, flags, reserveEntireSlot, false) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &addr, flags, false) < 0) return -1; addrs->lastaddr = addr; @@ -809,7 +789,7 @@ virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs, virDomainDeviceInfoPtr dev, virDomainPCIConnectFlags flags) { - return virDomainPCIAddressReserveNextAddr(addrs, dev, flags, 0, true); + return virDomainPCIAddressReserveNextAddr(addrs, dev, flags, 0); } diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 7df0502..9c08274 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -141,7 +141,6 @@ int virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs, int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, virDomainPCIConnectFlags flags, - bool reserveEntireSlot, bool fromConfig) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); @@ -166,8 +165,7 @@ int virDomainPCIAddressReleaseSlot(virDomainPCIAddressSetPtr addrs, int virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, virDomainDeviceInfoPtr dev, virDomainPCIConnectFlags flags, - unsigned int function, - bool reserveEntireSlot) + int function) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); int virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs, diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index a3dfd63..37ce675 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -863,12 +863,11 @@ qemuDomainFillDevicePCIConnectFlags(virDomainDefPtr def, static int qemuDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs, virDomainDeviceInfoPtr dev, - unsigned int function, - bool reserveEntireSlot) + unsigned int function) { return virDomainPCIAddressReserveNextAddr(addrs, dev, dev->pciConnectFlags, - function, reserveEntireSlot); + function); } @@ -876,7 +875,7 @@ static int qemuDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs, virDomainDeviceInfoPtr dev) { - return qemuDomainPCIAddressReserveNextAddr(addrs, dev, 0, true); + return qemuDomainPCIAddressReserveNextAddr(addrs, dev, 0); } @@ -889,7 +888,6 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, virDomainPCIAddressSetPtr addrs = opaque; int ret = -1; virPCIDeviceAddressPtr addr = &info->addr.pci; - bool entireSlot; if (!virDeviceInfoPCIAddressPresent(info) || ((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) && @@ -961,12 +959,10 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, } } - entireSlot = (addr->function == 0 && - addr->multi != VIR_TRISTATE_SWITCH_ON); - - if (virDomainPCIAddressReserveAddr(addrs, addr, info->pciConnectFlags, - entireSlot, true) < 0) + if (virDomainPCIAddressReserveAddr(addrs, addr, + info->pciConnectFlags, true) < 0) { goto cleanup; + } ret = 0; cleanup: @@ -1287,7 +1283,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, } if (assign) { if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, - flags, false, true) < 0) + flags, true) < 0) goto cleanup; cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; cont->info.addr.pci.domain = 0; @@ -1310,7 +1306,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, tmp_addr.slot = 0x1E; if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) { if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, - flags, true, false) < 0) + flags, false) < 0) goto cleanup; cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; cont->info.addr.pci.domain = 0; @@ -1333,13 +1329,13 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, tmp_addr.slot = 0x1F; tmp_addr.function = 0; tmp_addr.multi = VIR_TRISTATE_SWITCH_ON; - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, - false, false) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, + flags, false) < 0) goto cleanup; tmp_addr.function = 3; tmp_addr.multi = VIR_TRISTATE_SWITCH_ABSENT; - if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags, - false, false) < 0) + if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, + flags, false) < 0) goto cleanup; } @@ -1639,7 +1635,7 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, /* Reserve this function on the slot we found */ if (virDomainPCIAddressReserveAddr(addrs, &addr, cont->info.pciConnectFlags, - false, true) < 0) + true) < 0) goto error; cont->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; @@ -1648,8 +1644,7 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, /* This is the first part of the controller, so need * to find a free slot & then reserve this function */ if (qemuDomainPCIAddressReserveNextAddr(addrs, &cont->info, - addr.function, - false) < 0) { + addr.function) < 0) { goto error; } -- 2.7.4

virDomainPCIAddressGetNextSlot() starts searching from the last allocated address and goes to the end of all the buses, then goes back to the first bus and searchs from there up to the starting point (in case any address has been freed since the last time an address was allocated. The loops for these two are almost, but not exactly, the same, so they have remained as separate loops with the same code inside the loop. To lessen maintenance headaches, the identical code has been moved out into the function virDomainPCIAddressFindUnusedFunctionOnBus(), which is called in place of the loop contents. --- src/conf/domain_addr.c | 92 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index e0328f0..62f60d3 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -633,6 +633,45 @@ virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs) } +static int +virDomainPCIAddressFindUnusedFunctionOnBus(virDomainPCIAddressBusPtr bus, + virPCIDeviceAddressPtr searchAddr, + int function ATTRIBUTE_UNUSED, + virDomainPCIConnectFlags flags, + bool *found) +{ + int ret = -1; + char *addrStr = NULL; + + *found = false; + + if (!(addrStr = virDomainPCIAddressAsString(searchAddr))) + goto cleanup; + + if (!virDomainPCIAddressFlagsCompatible(searchAddr, addrStr, bus->flags, + flags, false, false)) { + VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device", + searchAddr->domain, searchAddr->bus); + } else { + while (searchAddr->slot <= bus->maxSlot) { + if (bus->slot[searchAddr->slot].functions == 0) { + *found = true; + break; + } + + VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use", + searchAddr->domain, searchAddr->bus, searchAddr->slot); + searchAddr->slot++; + } + } + + ret = 0; + cleanup: + VIR_FREE(addrStr); + return ret; +} + + static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr next_addr, @@ -642,8 +681,8 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs, /* default to starting the search for a free slot from * the first slot of domain 0 bus 0... */ - virPCIDeviceAddress a = {0}; - char *addrStr = NULL; + virPCIDeviceAddress a = { 0 }; + bool found = false; if (addrs->nbuses == 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available")); @@ -671,24 +710,16 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs, a.function = function; while (a.bus < addrs->nbuses) { - VIR_FREE(addrStr); - if (!(addrStr = virDomainPCIAddressAsString(&a))) + if (virDomainPCIAddressFindUnusedFunctionOnBus(&addrs->buses[a.bus], + &a, function, + flags, &found) < 0) { goto error; - if (!virDomainPCIAddressFlagsCompatible(&a, addrStr, - addrs->buses[a.bus].flags, - flags, false, false)) { - VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device", - a.domain, a.bus); - } else { - while (a.slot <= addrs->buses[a.bus].maxSlot) { - if (!virDomainPCIAddressSlotInUse(addrs, &a)) - goto success; - - VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use", - a.domain, a.bus, a.slot); - a.slot++; - } } + + if (found) + goto success; + + /* nothing on this bus, go to the next bus */ if (++a.bus < addrs->nbuses) a.slot = addrs->buses[a.bus].minSlot; } @@ -705,38 +736,27 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs, /* Check the buses from 0 up to the last used one */ for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) { a.slot = addrs->buses[a.bus].minSlot; - VIR_FREE(addrStr); - if (!(addrStr = virDomainPCIAddressAsString(&a))) + + if (virDomainPCIAddressFindUnusedFunctionOnBus(&addrs->buses[a.bus], + &a, function, + flags, &found) < 0) { goto error; - if (!virDomainPCIAddressFlagsCompatible(&a, addrStr, - addrs->buses[a.bus].flags, - flags, false, false)) { - VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device", - a.domain, a.bus); - } else { - while (a.slot <= addrs->buses[a.bus].maxSlot) { - if (!virDomainPCIAddressSlotInUse(addrs, &a)) - goto success; - - VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use", - a.domain, a.bus, a.slot); - a.slot++; - } } + + if (found) + goto success; } } virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("No more available PCI slots")); error: - VIR_FREE(addrStr); return -1; success: VIR_DEBUG("Found free PCI slot %.4x:%.2x:%.2x", a.domain, a.bus, a.slot); *next_addr = a; - VIR_FREE(addrStr); return 0; } -- 2.7.4

There is a very slight time advantage to beginning the search for the next unused PCI address at the slot *after* the previous find (which is now used), but if we do that, we will miss allocating the other functions of the same slot (when we implement a VIR_PCI_CONNECT_AGGREGATE_SLOT flag to support that). --- src/conf/domain_addr.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 62f60d3..29d06f1 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -690,18 +690,14 @@ virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs, } /* ...unless this search is for the exact same type of device as - * last time, then continue the search from the next slot after - * the previous match (the "next slot" may possibly be the first - * slot of the next bus). + * last time, then continue the search from the slot where we + * found the previous match (it's possible there will still be a + * function available on that slot). */ - if (flags == addrs->lastFlags) { + if (flags == addrs->lastFlags) a = addrs->lastaddr; - if (++a.slot > addrs->buses[a.bus].maxSlot && - ++a.bus < addrs->nbuses) - a.slot = addrs->buses[a.bus].minSlot; - } else { + else a.slot = addrs->buses[0].minSlot; - } /* if the caller asks for "any function", give them function 0 */ if (function == -1) -- 2.7.4

This function iterates through all the devices in a domain to determine if the address it has been given is part of a "multifunction device" (i.e. multiple devices connected to different functions of the same slot). This implementation may seem a bit inefficient because it has to iterate through all the devices for each device that needs checking, but this really is our only option since the address allocation set isn't always available (and maybe not even exist at the time it's needed). --- src/conf/domain_addr.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 5 ++++ src/libvirt_private.syms | 1 + 3 files changed, 66 insertions(+) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 29d06f1..986d90e 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -809,6 +809,66 @@ virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs, } +typedef struct { + virPCIDeviceAddressPtr addr; + bool isMulti; +} virDomainPCIAddressIsMultiIterData; + + +static int +virDomainPCIAddressIsMultiIter(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, + void *data) +{ + virDomainPCIAddressIsMultiIterData *context = data; + virPCIDeviceAddressPtr testAddr = context->addr; + virPCIDeviceAddressPtr thisAddr; + + if (!info || info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + return 0; + + thisAddr = &info->addr.pci; + + if (thisAddr->domain == testAddr->domain && + thisAddr->bus == testAddr->bus && + thisAddr->slot == testAddr->slot && + thisAddr->function != testAddr->function) { + context->isMulti = true; + return -1; /* finish early, *NOT* an error */ + } + + return 0; +} + + +/** + * virDomainPCIAddressIsMulti(): + * + * @def: the domain definition whose devices need adjusting + * @addr: the address to check + * + * See if there is any PCI device in the domain with the same + * domain/bus/slot but different function. If so, then this address is + * used by a multifunction device. + * + * Returns true if the address is being used by multiple devices, else + * false. + */ +bool +virDomainPCIAddressIsMulti(const virDomainDef *def, + virPCIDeviceAddressPtr addr) +{ + virDomainPCIAddressIsMultiIterData data = { .addr = addr, + .isMulti = false }; + + ignore_value(virDomainDeviceInfoIterate((virDomainDefPtr)def, + virDomainPCIAddressIsMultiIter, + &data)); + return data.isMulti; +} + + static char* virDomainCCWAddressAsString(virDomainDeviceCCWAddressPtr addr) { diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 9c08274..50c4675 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -173,6 +173,11 @@ int virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs, virDomainPCIConnectFlags flags) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +bool +virDomainPCIAddressIsMulti(const virDomainDef *def, + virPCIDeviceAddressPtr addr) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + struct _virDomainCCWAddressSet { virHashTablePtr defined; virDomainDeviceCCWAddress next; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 74dd527..60fb760 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -99,6 +99,7 @@ virDomainPCIAddressAsString; virDomainPCIAddressBusSetModel; virDomainPCIAddressEnsureAddr; virDomainPCIAddressFlagsCompatible; +virDomainPCIAddressIsMulti; virDomainPCIAddressReleaseSlot; virDomainPCIAddressReserveAddr; virDomainPCIAddressReserveNextAddr; -- 2.7.4

If the multifunction attribute isn't set in the config for the device at function 0 of a slot used for multifunction, it would previously have been an error. This patch will instead automatically correct the omission (but only if it hasn't been set at all - if someone explicitly has "multifunction='off'" on function 0, or "multifunction='on'" when function != 0, we have to assume they have a reason for that). This effectively obsoletes the requirement of specifying multifunction='on' in the config, although you're still free to do so. Note that if you migrate a domain that needs an implied "multifunction='on'" back to any older libvirt that doesn't have it, the migration will fail. (Note that this would only be an issue with a domain config that was *created* on a newer libvirt; any config created on an older libvirt and then later migrated to a newer libvirt would necessarily have multifunction explicitly set in the config, and that will not be lost during migration). --- src/qemu/qemu_command.c | 16 +++++- .../qemuxml2argv-q35-multifunction.args | 31 +++++++++++ .../qemuxml2argv-q35-multifunction.xml | 40 +++++++++++++ tests/qemuxml2argvtest.c | 23 ++++++++ .../qemuxml2xmlout-q35-multifunction.xml | 65 ++++++++++++++++++++++ tests/qemuxml2xmltest.c | 23 ++++++++ 6 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 96c4f31..01590da 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -295,6 +295,7 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, int ret = -1; char *devStr = NULL; const char *contAlias = NULL; + virTristateSwitch multi = VIR_TRISTATE_SWITCH_ABSENT; if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { size_t i; @@ -327,6 +328,8 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, goto cleanup; } + multi = info->addr.pci.multi; + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) { if (info->addr.pci.function != 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -340,6 +343,15 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, "this QEMU binary")); goto cleanup; } + } else if (info->addr.pci.function == 0 && + multi == VIR_TRISTATE_SWITCH_ABSENT && + virDomainPCIAddressIsMulti(domainDef, &info->addr.pci)) { + /* Even if the config doesn't tell us, by definition we + * must have multifunction=on in the commandline for the + * device at function 0 if there are any other devices on + * the same slot. + */ + multi = VIR_TRISTATE_SWITCH_ON; } if (info->addr.pci.bus != 0 && @@ -351,9 +363,9 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, } virBufferAsprintf(buf, ",bus=%s", contAlias); - if (info->addr.pci.multi == VIR_TRISTATE_SWITCH_ON) + if (multi == VIR_TRISTATE_SWITCH_ON) virBufferAddLit(buf, ",multifunction=on"); - else if (info->addr.pci.multi == VIR_TRISTATE_SWITCH_OFF) + else if (multi == VIR_TRISTATE_SWITCH_OFF) virBufferAddLit(buf, ",multifunction=off"); virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot); if (info->addr.pci.function != 0) diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args new file mode 100644 index 0000000..de1a4a4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args @@ -0,0 +1,31 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/libexec/qemu-kvm \ +-name q35-test \ +-S \ +-M q35 \ +-m 2048 \ +-smp 2,sockets=2,cores=1,threads=1 \ +-uuid 11dbdcdd-4c3b-482b-8903-9bdb8c0a2774 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-q35-test/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-device ioh3420,port=0x10,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\ +addr=0x2 \ +-device ioh3420,port=0x11,chassis=2,id=pci.2,bus=pcie.0,addr=0x2.0x1 \ +-device ioh3420,port=0x12,chassis=3,id=pci.3,bus=pcie.0,addr=0x2.0x2 \ +-device ioh3420,port=0x18,chassis=4,id=pci.4,bus=pcie.0,multifunction=on,\ +addr=0x3 \ +-device ioh3420,port=0x19,chassis=5,id=pci.5,bus=pcie.0,multifunction=on,\ +addr=0x3.0x1 \ +-device ioh3420,port=0x20,chassis=6,id=pci.6,bus=pcie.0,multifunction=off,\ +addr=0x4 \ +-device ioh3420,port=0x21,chassis=7,id=pci.7,bus=pcie.0,addr=0x4.0x1 \ +-device nec-usb-xhci,id=usb,bus=pci.1,addr=0x0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml new file mode 100644 index 0000000..b1f3c5e --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml @@ -0,0 +1,40 @@ +<domain type='qemu'> + <name>q35-test</name> + <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>2097152</currentMemory> + <vcpu placement='static' cpuset='0-1'>2</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/libexec/qemu-kvm</emulator> + <controller type='pci' model='pcie-root'/> + <controller type='pci' model='pcie-root-port'> + <address type='pci' slot='2' function='0'/> + </controller> + <controller type='pci' model='pcie-root-port'> + <address type='pci' slot='2' function='1'/> + </controller> + <controller type='pci' model='pcie-root-port'> + <address type='pci' slot='2' function='2'/> + </controller> + <controller type='pci' model='pcie-root-port'> + <address type='pci' slot='3' function='0'/> + </controller> + <controller type='pci' model='pcie-root-port'> + <address type='pci' slot='3' function='1' multifunction='on'/> + </controller> + <controller type='pci' model='pcie-root-port'> + <address type='pci' slot='4' function='0' multifunction='off'/> + </controller> + <controller type='pci' model='pcie-root-port'> + <address type='pci' slot='4' function='1'/> + </controller> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 2b6ce10..20ea95b 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1881,6 +1881,29 @@ mymain(void) QEMU_CAPS_ICH9_USB_EHCI1, QEMU_CAPS_NEC_USB_XHCI, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); + DO_TEST("q35-multifunction", + QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY, + QEMU_CAPS_DEVICE_VIRTIO_RNG, + QEMU_CAPS_OBJECT_RNG_RANDOM, + QEMU_CAPS_NETDEV, + QEMU_CAPS_DEVICE_VIRTIO_NET, + QEMU_CAPS_DEVICE_VIRTIO_GPU, + QEMU_CAPS_VIRTIO_GPU_VIRGL, + QEMU_CAPS_VIRTIO_KEYBOARD, + QEMU_CAPS_VIRTIO_MOUSE, + QEMU_CAPS_VIRTIO_TABLET, + QEMU_CAPS_VIRTIO_INPUT_HOST, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_FSDEV, + QEMU_CAPS_FSDEV_WRITEOUT, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_ICH9_AHCI, + QEMU_CAPS_PCI_MULTIFUNCTION, + QEMU_CAPS_ICH9_USB_EHCI1, + QEMU_CAPS_NEC_USB_XHCI, + QEMU_CAPS_DEVICE_VIDEO_PRIMARY); DO_TEST("q35-virt-manager-basic", QEMU_CAPS_KVM, QEMU_CAPS_RTC, diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml new file mode 100644 index 0000000..3d5cd76 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml @@ -0,0 +1,65 @@ +<domain type='qemu'> + <name>q35-test</name> + <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid> + <memory unit='KiB'>2097152</memory> + <currentMemory unit='KiB'>2097152</currentMemory> + <vcpu placement='static' cpuset='0-1'>2</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/libexec/qemu-kvm</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='1' port='0x10'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='2' port='0x11'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> + </controller> + <controller type='pci' index='3' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='3' port='0x12'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/> + </controller> + <controller type='pci' index='4' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='4' port='0x18'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='5' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='5' port='0x19'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x1' multifunction='on'/> + </controller> + <controller type='pci' index='6' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='6' port='0x20'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' multifunction='off'/> + </controller> + <controller type='pci' index='7' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='7' port='0x21'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1'/> + </controller> + <controller type='usb' index='0' model='nec-xhci'> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </controller> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index e22b63f..20b9b17 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -794,6 +794,29 @@ mymain(void) QEMU_CAPS_ICH9_USB_EHCI1, QEMU_CAPS_NEC_USB_XHCI, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); + DO_TEST("q35-multifunction", + QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY, + QEMU_CAPS_DEVICE_VIRTIO_RNG, + QEMU_CAPS_OBJECT_RNG_RANDOM, + QEMU_CAPS_NETDEV, + QEMU_CAPS_DEVICE_VIRTIO_NET, + QEMU_CAPS_DEVICE_VIRTIO_GPU, + QEMU_CAPS_VIRTIO_GPU_VIRGL, + QEMU_CAPS_VIRTIO_KEYBOARD, + QEMU_CAPS_VIRTIO_MOUSE, + QEMU_CAPS_VIRTIO_TABLET, + QEMU_CAPS_VIRTIO_INPUT_HOST, + QEMU_CAPS_VIRTIO_SCSI, + QEMU_CAPS_FSDEV, + QEMU_CAPS_FSDEV_WRITEOUT, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_DEVICE_IOH3420, + QEMU_CAPS_ICH9_AHCI, + QEMU_CAPS_PCI_MULTIFUNCTION, + QEMU_CAPS_ICH9_USB_EHCI1, + QEMU_CAPS_NEC_USB_XHCI, + QEMU_CAPS_DEVICE_VIDEO_PRIMARY); DO_TEST("q35-virt-manager-basic", QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY, QEMU_CAPS_DEVICE_VIRTIO_RNG, -- 2.7.4

If a PCI device has VIR_PCI_CONNECT_AGGREGATE_SLOT set in its pciConnectFlags, then during address assignment we allow multiple instances of this type of device to be auto-assigned to multiple functions on the same device. A slot is used for aggregating multiple devices only if the first device assigned to that slot had VIR_PCI_CONNECT_AGGREGATE_SLOT set. but any device types that have AGGREGATE_SLOT set might be mix/matched on the same slot. (NB: libvirt should never set the AGGREGATE_SLOT flag for a device type that might need to be hotplugged. Currently it is only planned for pcie-root-port and possibly other PCI controller types, and none of those are hotpluggable anyway) There aren't yet any devices that use this flag. That will be in a later patch. --- src/conf/domain_addr.c | 45 +++++++++++++++++++++++++++++++++++++++--- src/conf/domain_addr.h | 30 +++++++++++++++++++--------- src/qemu/qemu_domain_address.c | 2 +- 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 986d90e..1ab9a6d 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -506,8 +506,20 @@ virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs, addrStr); goto cleanup; } + + /* if this is the first function to be reserved on this slot, and + * the device it's being reserved for can aggregate multiples on a + * slot, set the slot's aggregate flag. + */ + if (!bus->slot[addr->slot].functions && + flags & VIR_PCI_CONNECT_AGGREGATE_SLOT) { + bus->slot[addr->slot].aggregate = true; + } + + /* mark the requested function as reserved */ bus->slot[addr->slot].functions |= (1 << addr->function); - VIR_DEBUG("Reserving PCI address %s", addrStr); + VIR_DEBUG("Reserving PCI address %s (aggregate='%s')", addrStr, + bus->slot[addr->slot].aggregate ? "true" : "false"); ret = 0; cleanup: @@ -636,7 +648,7 @@ virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs) static int virDomainPCIAddressFindUnusedFunctionOnBus(virDomainPCIAddressBusPtr bus, virPCIDeviceAddressPtr searchAddr, - int function ATTRIBUTE_UNUSED, + int function, virDomainPCIConnectFlags flags, bool *found) { @@ -659,6 +671,33 @@ virDomainPCIAddressFindUnusedFunctionOnBus(virDomainPCIAddressBusPtr bus, break; } + if (flags & VIR_PCI_CONNECT_AGGREGATE_SLOT && + bus->slot[searchAddr->slot].aggregate) { + /* slot and device are okay with aggregating devices */ + if ((bus->slot[searchAddr->slot].functions & + (1 << searchAddr->function)) == 0) { + *found = true; + break; + } + + /* also check for *any* unused function if caller + * sent function = -1 + */ + if (function == -1) { + while (searchAddr->function < 8) { + if ((bus->slot[searchAddr->slot].functions & + (1 << searchAddr->function)) == 0) { + *found = true; + break; /* out of inner while */ + } + searchAddr->function++; + } + if (*found) + break; /* out of outer while */ + searchAddr->function = 0; /* reset for next try */ + } + } + VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use", searchAddr->domain, searchAddr->bus, searchAddr->slot); searchAddr->slot++; @@ -805,7 +844,7 @@ virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs, virDomainDeviceInfoPtr dev, virDomainPCIConnectFlags flags) { - return virDomainPCIAddressReserveNextAddr(addrs, dev, flags, 0); + return virDomainPCIAddressReserveNextAddr(addrs, dev, flags, -1); } diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 50c4675..dd4cd5b 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -32,18 +32,23 @@ typedef enum { VIR_PCI_CONNECT_HOTPLUGGABLE = 1 << 0, /* is hotplug needed/supported */ + /* set for devices that can share a single slot in auto-assignment + * (by assigning one device to each of the 8 functions on the slot) + */ + VIR_PCI_CONNECT_AGGREGATE_SLOT = 1 << 1, + /* kinds of devices as a bitmap so they can be combined (some PCI * controllers permit connecting multiple types of devices) */ - VIR_PCI_CONNECT_TYPE_PCI_DEVICE = 1 << 1, - VIR_PCI_CONNECT_TYPE_PCIE_DEVICE = 1 << 2, - VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT = 1 << 3, - VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT = 1 << 4, - VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT = 1 << 5, - VIR_PCI_CONNECT_TYPE_DMI_TO_PCI_BRIDGE = 1 << 6, - VIR_PCI_CONNECT_TYPE_PCI_EXPANDER_BUS = 1 << 7, - VIR_PCI_CONNECT_TYPE_PCIE_EXPANDER_BUS = 1 << 8, - VIR_PCI_CONNECT_TYPE_PCI_BRIDGE = 1 << 9, + VIR_PCI_CONNECT_TYPE_PCI_DEVICE = 1 << 2, + VIR_PCI_CONNECT_TYPE_PCIE_DEVICE = 1 << 3, + VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT = 1 << 4, + VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT = 1 << 5, + VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_DOWNSTREAM_PORT = 1 << 6, + VIR_PCI_CONNECT_TYPE_DMI_TO_PCI_BRIDGE = 1 << 7, + VIR_PCI_CONNECT_TYPE_PCI_EXPANDER_BUS = 1 << 8, + VIR_PCI_CONNECT_TYPE_PCIE_EXPANDER_BUS = 1 << 9, + VIR_PCI_CONNECT_TYPE_PCI_BRIDGE = 1 << 10, } virDomainPCIConnectFlags; /* a combination of all bits that describe the type of connections @@ -75,6 +80,13 @@ typedef struct { * in use by a device, or clear if it isn't. */ uint8_t functions; + + /* aggregate is true if this slot has only devices with + * VIR_PCI_CONNECT_AGGREGATE assigned to its functions (meaning + * that other devices with the same flags could also be + * auto-assigned to the other functions) + */ + bool aggregate; } virDomainPCIAddressSlot; typedef struct { diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 37ce675..5b3765f 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -875,7 +875,7 @@ static int qemuDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs, virDomainDeviceInfoPtr dev) { - return qemuDomainPCIAddressReserveNextAddr(addrs, dev, 0); + return qemuDomainPCIAddressReserveNextAddr(addrs, dev, -1); } -- 2.7.4

Set the VIR_PCI_CONNECT_AGGREGATE_SLOT flag for pcie-root-ports so that they will be assigned to all the functions on a slot. Some qemu test case outputs had to be adjusted due to the pcie-root-ports now being put on multiple functions. --- src/conf/domain_addr.c | 2 +- .../qemuxml2argv-pcie-root-port.args | 5 +- .../qemuxml2argv-pcie-switch-upstream-port.args | 5 +- .../qemuxml2argv-q35-default-devices-only.args | 7 +-- .../qemuxml2argv-q35-multifunction.args | 12 +++++ .../qemuxml2argv-q35-multifunction.xml | 11 +++++ .../qemuxml2argv-q35-pcie-autoadd.args | 30 ++++++------ tests/qemuxml2argvdata/qemuxml2argv-q35-pcie.args | 28 ++++++----- .../qemuxml2argv-q35-virt-manager-basic.args | 13 ++--- .../qemuxml2argv-q35-virtio-pci.args | 28 ++++++----- tests/qemuxml2argvtest.c | 2 + .../qemuxml2xmlout-pcie-root-port.xml | 2 +- .../qemuxml2xmlout-pcie-switch-upstream-port.xml | 4 +- .../qemuxml2xmlout-q35-default-devices-only.xml | 8 ++-- .../qemuxml2xmlout-q35-multifunction.xml | 55 ++++++++++++++++++++++ .../qemuxml2xmlout-q35-pcie-autoadd.xml | 52 ++++++++++---------- .../qemuxml2xmloutdata/qemuxml2xmlout-q35-pcie.xml | 48 +++++++++---------- .../qemuxml2xmlout-q35-virt-manager-basic.xml | 20 ++++---- .../qemuxml2xmlout-q35-virtio-pci.xml | 48 +++++++++---------- tests/qemuxml2xmltest.c | 2 + 20 files changed, 237 insertions(+), 145 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 1ab9a6d..56b7f3f 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -63,7 +63,7 @@ virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model) return VIR_PCI_CONNECT_TYPE_DMI_TO_PCI_BRIDGE; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: - return VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT; + return VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT | VIR_PCI_CONNECT_AGGREGATE_SLOT; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: return VIR_PCI_CONNECT_TYPE_PCIE_SWITCH_UPSTREAM_PORT; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.args index 27d5164..9a71281 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.args @@ -18,8 +18,9 @@ QEMU_AUDIO_DRV=none \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ --device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \ --device ioh3420,port=0x1a,chassis=40,id=pci.4,bus=pcie.0,addr=0x3 \ +-device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,multifunction=on,\ +addr=0x2 \ +-device ioh3420,port=0x1a,chassis=40,id=pci.4,bus=pcie.0,addr=0x2.0x1 \ -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-sata0-0-0 \ -device ide-drive,bus=ide.0,drive=drive-sata0-0-0,id=sata0-0-0 \ -device qxl-vga,id=video0,ram_size=67108864,vram_size=33554432,bus=pcie.0,\ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-upstream-port.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-upstream-port.args index 93d16b8..10aedd5 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-upstream-port.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-switch-upstream-port.args @@ -18,8 +18,9 @@ QEMU_AUDIO_DRV=none \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ --device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \ --device ioh3420,port=0x18,chassis=4,id=pci.4,bus=pcie.0,addr=0x3 \ +-device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,multifunction=on,\ +addr=0x2 \ +-device ioh3420,port=0x11,chassis=4,id=pci.4,bus=pcie.0,addr=0x2.0x1 \ -device x3130-upstream,id=pci.5,bus=pci.3,addr=0x0 \ -device x3130-upstream,id=pci.6,bus=pci.4,addr=0x0 \ -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-sata0-0-0 \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-default-devices-only.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-default-devices-only.args index 9d13466..30fc9b7 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-default-devices-only.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-default-devices-only.args @@ -16,8 +16,9 @@ QEMU_AUDIO_DRV=none \ -monitor unix:/tmp/lib/domain--1-q35-test/monitor.sock,server,nowait \ -no-acpi \ -boot c \ --device ioh3420,port=0x8,chassis=1,id=pci.1,bus=pcie.0,addr=0x1 \ --device ioh3420,port=0x10,chassis=2,id=pci.2,bus=pcie.0,addr=0x2 \ --device ioh3420,port=0x18,chassis=3,id=pci.3,bus=pcie.0,addr=0x3 \ +-device ioh3420,port=0x8,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\ +addr=0x1 \ +-device ioh3420,port=0x9,chassis=2,id=pci.2,bus=pcie.0,addr=0x1.0x1 \ +-device ioh3420,port=0xa,chassis=3,id=pci.3,bus=pcie.0,addr=0x1.0x2 \ -device nec-usb-xhci,id=usb,bus=pci.1,addr=0x0 \ -device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args index de1a4a4..1b60744 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.args @@ -27,5 +27,17 @@ addr=0x3.0x1 \ -device ioh3420,port=0x20,chassis=6,id=pci.6,bus=pcie.0,multifunction=off,\ addr=0x4 \ -device ioh3420,port=0x21,chassis=7,id=pci.7,bus=pcie.0,addr=0x4.0x1 \ +-device ioh3420,port=0x8,chassis=8,id=pci.8,bus=pcie.0,multifunction=on,\ +addr=0x1 \ +-device ioh3420,port=0x9,chassis=9,id=pci.9,bus=pcie.0,addr=0x1.0x1 \ +-device ioh3420,port=0xa,chassis=10,id=pci.10,bus=pcie.0,addr=0x1.0x2 \ +-device ioh3420,port=0xb,chassis=11,id=pci.11,bus=pcie.0,addr=0x1.0x3 \ +-device ioh3420,port=0xc,chassis=12,id=pci.12,bus=pcie.0,addr=0x1.0x4 \ +-device ioh3420,port=0xd,chassis=13,id=pci.13,bus=pcie.0,addr=0x1.0x5 \ +-device ioh3420,port=0xe,chassis=14,id=pci.14,bus=pcie.0,addr=0x1.0x6 \ +-device ioh3420,port=0xf,chassis=15,id=pci.15,bus=pcie.0,addr=0x1.0x7 \ +-device ioh3420,port=0x13,chassis=16,id=pci.16,bus=pcie.0,addr=0x2.0x3 \ +-device ioh3420,port=0x14,chassis=17,id=pci.17,bus=pcie.0,addr=0x2.0x4 \ +-device ioh3420,port=0x15,chassis=18,id=pci.18,bus=pcie.0,addr=0x2.0x5 \ -device nec-usb-xhci,id=usb,bus=pci.1,addr=0x0 \ -device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml index b1f3c5e..c1edca1 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-multifunction.xml @@ -36,5 +36,16 @@ <controller type='pci' model='pcie-root-port'> <address type='pci' slot='4' function='1'/> </controller> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> + <controller type='pci' model='pcie-root-port'/> </devices> </domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-pcie-autoadd.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-pcie-autoadd.args index ba26326..f3d44c0 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-pcie-autoadd.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-pcie-autoadd.args @@ -16,20 +16,22 @@ QEMU_AUDIO_DRV=none \ -monitor unix:/tmp/lib/domain--1-q35-test/monitor.sock,server,nowait \ -no-acpi \ -boot c \ --device ioh3420,port=0x10,chassis=1,id=pci.1,bus=pcie.0,addr=0x2 \ --device ioh3420,port=0x18,chassis=2,id=pci.2,bus=pcie.0,addr=0x3 \ --device ioh3420,port=0x20,chassis=3,id=pci.3,bus=pcie.0,addr=0x4 \ --device ioh3420,port=0x28,chassis=4,id=pci.4,bus=pcie.0,addr=0x5 \ --device ioh3420,port=0x30,chassis=5,id=pci.5,bus=pcie.0,addr=0x6 \ --device ioh3420,port=0x38,chassis=6,id=pci.6,bus=pcie.0,addr=0x7 \ --device ioh3420,port=0x40,chassis=7,id=pci.7,bus=pcie.0,addr=0x8 \ --device ioh3420,port=0x48,chassis=8,id=pci.8,bus=pcie.0,addr=0x9 \ --device ioh3420,port=0x50,chassis=9,id=pci.9,bus=pcie.0,addr=0xa \ --device ioh3420,port=0x58,chassis=10,id=pci.10,bus=pcie.0,addr=0xb \ --device ioh3420,port=0x60,chassis=11,id=pci.11,bus=pcie.0,addr=0xc \ --device ioh3420,port=0x68,chassis=12,id=pci.12,bus=pcie.0,addr=0xd \ --device ioh3420,port=0x70,chassis=13,id=pci.13,bus=pcie.0,addr=0xe \ --device ioh3420,port=0x78,chassis=14,id=pci.14,bus=pcie.0,addr=0xf \ +-device ioh3420,port=0x10,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\ +addr=0x2 \ +-device ioh3420,port=0x11,chassis=2,id=pci.2,bus=pcie.0,addr=0x2.0x1 \ +-device ioh3420,port=0x12,chassis=3,id=pci.3,bus=pcie.0,addr=0x2.0x2 \ +-device ioh3420,port=0x13,chassis=4,id=pci.4,bus=pcie.0,addr=0x2.0x3 \ +-device ioh3420,port=0x14,chassis=5,id=pci.5,bus=pcie.0,addr=0x2.0x4 \ +-device ioh3420,port=0x15,chassis=6,id=pci.6,bus=pcie.0,addr=0x2.0x5 \ +-device ioh3420,port=0x16,chassis=7,id=pci.7,bus=pcie.0,addr=0x2.0x6 \ +-device ioh3420,port=0x17,chassis=8,id=pci.8,bus=pcie.0,addr=0x2.0x7 \ +-device ioh3420,port=0x18,chassis=9,id=pci.9,bus=pcie.0,multifunction=on,\ +addr=0x3 \ +-device ioh3420,port=0x19,chassis=10,id=pci.10,bus=pcie.0,addr=0x3.0x1 \ +-device ioh3420,port=0x1a,chassis=11,id=pci.11,bus=pcie.0,addr=0x3.0x2 \ +-device ioh3420,port=0x1b,chassis=12,id=pci.12,bus=pcie.0,addr=0x3.0x3 \ +-device ioh3420,port=0x1c,chassis=13,id=pci.13,bus=pcie.0,addr=0x3.0x4 \ +-device ioh3420,port=0x1d,chassis=14,id=pci.14,bus=pcie.0,addr=0x3.0x5 \ -device nec-usb-xhci,id=usb,bus=pci.6,addr=0x0 \ -device virtio-scsi-pci,id=scsi0,bus=pci.5,addr=0x0 \ -device virtio-serial-pci,id=virtio-serial0,bus=pci.4,addr=0x0 \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-pcie.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-pcie.args index 2738749..3b507f3 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-pcie.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-pcie.args @@ -18,19 +18,21 @@ QEMU_AUDIO_DRV=none \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ --device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \ --device ioh3420,port=0x18,chassis=4,id=pci.4,bus=pcie.0,addr=0x3 \ --device ioh3420,port=0x20,chassis=5,id=pci.5,bus=pcie.0,addr=0x4 \ --device ioh3420,port=0x28,chassis=6,id=pci.6,bus=pcie.0,addr=0x5 \ --device ioh3420,port=0x30,chassis=7,id=pci.7,bus=pcie.0,addr=0x6 \ --device ioh3420,port=0x38,chassis=8,id=pci.8,bus=pcie.0,addr=0x7 \ --device ioh3420,port=0x40,chassis=9,id=pci.9,bus=pcie.0,addr=0x8 \ --device ioh3420,port=0x48,chassis=10,id=pci.10,bus=pcie.0,addr=0x9 \ --device ioh3420,port=0x50,chassis=11,id=pci.11,bus=pcie.0,addr=0xa \ --device ioh3420,port=0x58,chassis=12,id=pci.12,bus=pcie.0,addr=0xb \ --device ioh3420,port=0x60,chassis=13,id=pci.13,bus=pcie.0,addr=0xc \ --device ioh3420,port=0x68,chassis=14,id=pci.14,bus=pcie.0,addr=0xd \ --device ioh3420,port=0x70,chassis=15,id=pci.15,bus=pcie.0,addr=0xe \ +-device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,multifunction=on,\ +addr=0x2 \ +-device ioh3420,port=0x11,chassis=4,id=pci.4,bus=pcie.0,addr=0x2.0x1 \ +-device ioh3420,port=0x12,chassis=5,id=pci.5,bus=pcie.0,addr=0x2.0x2 \ +-device ioh3420,port=0x13,chassis=6,id=pci.6,bus=pcie.0,addr=0x2.0x3 \ +-device ioh3420,port=0x14,chassis=7,id=pci.7,bus=pcie.0,addr=0x2.0x4 \ +-device ioh3420,port=0x15,chassis=8,id=pci.8,bus=pcie.0,addr=0x2.0x5 \ +-device ioh3420,port=0x16,chassis=9,id=pci.9,bus=pcie.0,addr=0x2.0x6 \ +-device ioh3420,port=0x17,chassis=10,id=pci.10,bus=pcie.0,addr=0x2.0x7 \ +-device ioh3420,port=0x18,chassis=11,id=pci.11,bus=pcie.0,multifunction=on,\ +addr=0x3 \ +-device ioh3420,port=0x19,chassis=12,id=pci.12,bus=pcie.0,addr=0x3.0x1 \ +-device ioh3420,port=0x1a,chassis=13,id=pci.13,bus=pcie.0,addr=0x3.0x2 \ +-device ioh3420,port=0x1b,chassis=14,id=pci.14,bus=pcie.0,addr=0x3.0x3 \ +-device ioh3420,port=0x1c,chassis=15,id=pci.15,bus=pcie.0,addr=0x3.0x4 \ -device nec-usb-xhci,id=usb,bus=pci.8,addr=0x0 \ -device virtio-scsi-pci,id=scsi0,bus=pci.7,addr=0x0 \ -device virtio-serial-pci,id=virtio-serial0,bus=pci.6,addr=0x0 \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-virt-manager-basic.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-virt-manager-basic.args index 60af251..e139e52 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-virt-manager-basic.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-virt-manager-basic.args @@ -18,12 +18,13 @@ QEMU_AUDIO_DRV=spice \ -global ICH9-LPC.disable_s3=1 \ -global ICH9-LPC.disable_s4=1 \ -boot c \ --device ioh3420,port=0x10,chassis=1,id=pci.1,bus=pcie.0,addr=0x2 \ --device ioh3420,port=0x18,chassis=2,id=pci.2,bus=pcie.0,addr=0x3 \ --device ioh3420,port=0x20,chassis=3,id=pci.3,bus=pcie.0,addr=0x4 \ --device ioh3420,port=0x28,chassis=4,id=pci.4,bus=pcie.0,addr=0x5 \ --device ioh3420,port=0x30,chassis=5,id=pci.5,bus=pcie.0,addr=0x6 \ --device ioh3420,port=0x38,chassis=6,id=pci.6,bus=pcie.0,addr=0x7 \ +-device ioh3420,port=0x10,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\ +addr=0x2 \ +-device ioh3420,port=0x11,chassis=2,id=pci.2,bus=pcie.0,addr=0x2.0x1 \ +-device ioh3420,port=0x12,chassis=3,id=pci.3,bus=pcie.0,addr=0x2.0x2 \ +-device ioh3420,port=0x13,chassis=4,id=pci.4,bus=pcie.0,addr=0x2.0x3 \ +-device ioh3420,port=0x14,chassis=5,id=pci.5,bus=pcie.0,addr=0x2.0x4 \ +-device ioh3420,port=0x15,chassis=6,id=pci.6,bus=pcie.0,addr=0x2.0x5 \ -device nec-usb-xhci,id=usb,bus=pci.2,addr=0x0 \ -device virtio-serial-pci,id=virtio-serial0,bus=pci.3,addr=0x0 \ -drive file=/var/lib/libvirt/images/basic.qcow2,format=qcow2,if=none,\ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pci.args b/tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pci.args index cada05e..a1025dc 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pci.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35-virtio-pci.args @@ -18,19 +18,21 @@ QEMU_AUDIO_DRV=none \ -boot c \ -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ --device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \ --device ioh3420,port=0x18,chassis=4,id=pci.4,bus=pcie.0,addr=0x3 \ --device ioh3420,port=0x20,chassis=5,id=pci.5,bus=pcie.0,addr=0x4 \ --device ioh3420,port=0x28,chassis=6,id=pci.6,bus=pcie.0,addr=0x5 \ --device ioh3420,port=0x30,chassis=7,id=pci.7,bus=pcie.0,addr=0x6 \ --device ioh3420,port=0x38,chassis=8,id=pci.8,bus=pcie.0,addr=0x7 \ --device ioh3420,port=0x40,chassis=9,id=pci.9,bus=pcie.0,addr=0x8 \ --device ioh3420,port=0x48,chassis=10,id=pci.10,bus=pcie.0,addr=0x9 \ --device ioh3420,port=0x50,chassis=11,id=pci.11,bus=pcie.0,addr=0xa \ --device ioh3420,port=0x58,chassis=12,id=pci.12,bus=pcie.0,addr=0xb \ --device ioh3420,port=0x60,chassis=13,id=pci.13,bus=pcie.0,addr=0xc \ --device ioh3420,port=0x68,chassis=14,id=pci.14,bus=pcie.0,addr=0xd \ --device ioh3420,port=0x70,chassis=15,id=pci.15,bus=pcie.0,addr=0xe \ +-device ioh3420,port=0x10,chassis=3,id=pci.3,bus=pcie.0,multifunction=on,\ +addr=0x2 \ +-device ioh3420,port=0x11,chassis=4,id=pci.4,bus=pcie.0,addr=0x2.0x1 \ +-device ioh3420,port=0x12,chassis=5,id=pci.5,bus=pcie.0,addr=0x2.0x2 \ +-device ioh3420,port=0x13,chassis=6,id=pci.6,bus=pcie.0,addr=0x2.0x3 \ +-device ioh3420,port=0x14,chassis=7,id=pci.7,bus=pcie.0,addr=0x2.0x4 \ +-device ioh3420,port=0x15,chassis=8,id=pci.8,bus=pcie.0,addr=0x2.0x5 \ +-device ioh3420,port=0x16,chassis=9,id=pci.9,bus=pcie.0,addr=0x2.0x6 \ +-device ioh3420,port=0x17,chassis=10,id=pci.10,bus=pcie.0,addr=0x2.0x7 \ +-device ioh3420,port=0x18,chassis=11,id=pci.11,bus=pcie.0,multifunction=on,\ +addr=0x3 \ +-device ioh3420,port=0x19,chassis=12,id=pci.12,bus=pcie.0,addr=0x3.0x1 \ +-device ioh3420,port=0x1a,chassis=13,id=pci.13,bus=pcie.0,addr=0x3.0x2 \ +-device ioh3420,port=0x1b,chassis=14,id=pci.14,bus=pcie.0,addr=0x3.0x3 \ +-device ioh3420,port=0x1c,chassis=15,id=pci.15,bus=pcie.0,addr=0x3.0x4 \ -device nec-usb-xhci,id=usb,bus=pci.4,addr=0x0 \ -device virtio-scsi-pci,id=scsi0,bus=pci.2,addr=0x4 \ -device virtio-serial-pci,id=virtio-serial0,bus=pci.2,addr=0x3 \ diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 20ea95b..3e3c18d 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1943,6 +1943,7 @@ mymain(void) QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, QEMU_CAPS_DEVICE_IOH3420, QEMU_CAPS_ICH9_AHCI, + QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_DEVICE_QXL); DO_TEST("autoindex", @@ -1986,6 +1987,7 @@ mymain(void) QEMU_CAPS_DEVICE_IOH3420, QEMU_CAPS_DEVICE_X3130_UPSTREAM, QEMU_CAPS_ICH9_AHCI, + QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_DEVICE_QXL); DO_TEST("pcie-switch-downstream-port", diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root-port.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root-port.xml index a4ff820..082dd6c 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root-port.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root-port.xml @@ -37,7 +37,7 @@ <controller type='pci' index='4' model='pcie-root-port'> <model name='ioh3420'/> <target chassis='40' port='0x1a'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> </controller> <controller type='sata' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-upstream-port.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-upstream-port.xml index 53e10d0..52c9177 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-upstream-port.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-switch-upstream-port.xml @@ -36,8 +36,8 @@ </controller> <controller type='pci' index='4' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='4' port='0x18'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <target chassis='4' port='0x11'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> </controller> <controller type='pci' index='5' model='pcie-switch-upstream-port'> <model name='x3130-upstream'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-default-devices-only.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-default-devices-only.xml index e64b80c..e8a7d8c 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-default-devices-only.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-default-devices-only.xml @@ -28,13 +28,13 @@ </controller> <controller type='pci' index='2' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='2' port='0x10'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + <target chassis='2' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> </controller> <controller type='pci' index='3' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='3' port='0x18'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <target chassis='3' port='0xa'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> </controller> <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml index 3d5cd76..06b8144 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-multifunction.xml @@ -50,6 +50,61 @@ <target chassis='7' port='0x21'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1'/> </controller> + <controller type='pci' index='8' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='8' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <controller type='pci' index='9' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='9' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='10' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='10' port='0xa'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='11' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='11' port='0xb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x3'/> + </controller> + <controller type='pci' index='12' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='12' port='0xc'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x4'/> + </controller> + <controller type='pci' index='13' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='13' port='0xd'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x5'/> + </controller> + <controller type='pci' index='14' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='14' port='0xe'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x6'/> + </controller> + <controller type='pci' index='15' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='15' port='0xf'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x7'/> + </controller> + <controller type='pci' index='16' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='16' port='0x13'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/> + </controller> + <controller type='pci' index='17' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='17' port='0x14'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/> + </controller> + <controller type='pci' index='18' model='pcie-root-port'> + <model name='ioh3420'/> + <target chassis='18' port='0x15'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/> + </controller> <controller type='usb' index='0' model='nec-xhci'> <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> </controller> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-pcie-autoadd.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-pcie-autoadd.xml index 3742e14..28862c9 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-pcie-autoadd.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-pcie-autoadd.xml @@ -39,68 +39,68 @@ </controller> <controller type='pci' index='2' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='2' port='0x18'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <target chassis='2' port='0x11'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> </controller> <controller type='pci' index='3' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='3' port='0x20'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + <target chassis='3' port='0x12'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/> </controller> <controller type='pci' index='4' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='4' port='0x28'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + <target chassis='4' port='0x13'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/> </controller> <controller type='pci' index='5' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='5' port='0x30'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + <target chassis='5' port='0x14'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/> </controller> <controller type='pci' index='6' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='6' port='0x38'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + <target chassis='6' port='0x15'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/> </controller> <controller type='pci' index='7' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='7' port='0x40'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + <target chassis='7' port='0x16'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x6'/> </controller> <controller type='pci' index='8' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='8' port='0x48'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> + <target chassis='8' port='0x17'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x7'/> </controller> <controller type='pci' index='9' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='9' port='0x50'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + <target chassis='9' port='0x18'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </controller> <controller type='pci' index='10' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='10' port='0x58'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> + <target chassis='10' port='0x19'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x1'/> </controller> <controller type='pci' index='11' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='11' port='0x60'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> + <target chassis='11' port='0x1a'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x2'/> </controller> <controller type='pci' index='12' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='12' port='0x68'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/> + <target chassis='12' port='0x1b'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x3'/> </controller> <controller type='pci' index='13' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='13' port='0x70'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/> + <target chassis='13' port='0x1c'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x4'/> </controller> <controller type='pci' index='14' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='14' port='0x78'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/> + <target chassis='14' port='0x1d'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x5'/> </controller> <filesystem type='mount' accessmode='passthrough'> <source dir='/export/to/guest'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-pcie.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-pcie.xml index 8e727fb..7c74b60 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-pcie.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-pcie.xml @@ -36,63 +36,63 @@ </controller> <controller type='pci' index='4' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='4' port='0x18'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <target chassis='4' port='0x11'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> </controller> <controller type='pci' index='5' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='5' port='0x20'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + <target chassis='5' port='0x12'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/> </controller> <controller type='pci' index='6' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='6' port='0x28'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + <target chassis='6' port='0x13'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/> </controller> <controller type='pci' index='7' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='7' port='0x30'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + <target chassis='7' port='0x14'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/> </controller> <controller type='pci' index='8' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='8' port='0x38'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + <target chassis='8' port='0x15'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/> </controller> <controller type='pci' index='9' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='9' port='0x40'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + <target chassis='9' port='0x16'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x6'/> </controller> <controller type='pci' index='10' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='10' port='0x48'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> + <target chassis='10' port='0x17'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x7'/> </controller> <controller type='pci' index='11' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='11' port='0x50'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + <target chassis='11' port='0x18'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </controller> <controller type='pci' index='12' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='12' port='0x58'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> + <target chassis='12' port='0x19'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x1'/> </controller> <controller type='pci' index='13' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='13' port='0x60'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> + <target chassis='13' port='0x1a'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x2'/> </controller> <controller type='pci' index='14' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='14' port='0x68'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/> + <target chassis='14' port='0x1b'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x3'/> </controller> <controller type='pci' index='15' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='15' port='0x70'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/> + <target chassis='15' port='0x1c'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x4'/> </controller> <controller type='virtio-serial' index='0'> <address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virt-manager-basic.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virt-manager-basic.xml index 236d955..3bbd99f 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virt-manager-basic.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virt-manager-basic.xml @@ -50,28 +50,28 @@ </controller> <controller type='pci' index='2' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='2' port='0x18'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <target chassis='2' port='0x11'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> </controller> <controller type='pci' index='3' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='3' port='0x20'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + <target chassis='3' port='0x12'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/> </controller> <controller type='pci' index='4' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='4' port='0x28'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + <target chassis='4' port='0x13'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/> </controller> <controller type='pci' index='5' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='5' port='0x30'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + <target chassis='5' port='0x14'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/> </controller> <controller type='pci' index='6' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='6' port='0x38'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + <target chassis='6' port='0x15'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/> </controller> <interface type='user'> <mac address='52:54:00:9a:e6:c6'/> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virtio-pci.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virtio-pci.xml index c4bd357..d2fa885 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virtio-pci.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35-virtio-pci.xml @@ -36,63 +36,63 @@ </controller> <controller type='pci' index='4' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='4' port='0x18'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + <target chassis='4' port='0x11'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/> </controller> <controller type='pci' index='5' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='5' port='0x20'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + <target chassis='5' port='0x12'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/> </controller> <controller type='pci' index='6' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='6' port='0x28'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + <target chassis='6' port='0x13'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/> </controller> <controller type='pci' index='7' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='7' port='0x30'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + <target chassis='7' port='0x14'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/> </controller> <controller type='pci' index='8' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='8' port='0x38'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + <target chassis='8' port='0x15'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x5'/> </controller> <controller type='pci' index='9' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='9' port='0x40'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> + <target chassis='9' port='0x16'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x6'/> </controller> <controller type='pci' index='10' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='10' port='0x48'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> + <target chassis='10' port='0x17'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x7'/> </controller> <controller type='pci' index='11' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='11' port='0x50'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + <target chassis='11' port='0x18'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </controller> <controller type='pci' index='12' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='12' port='0x58'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/> + <target chassis='12' port='0x19'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x1'/> </controller> <controller type='pci' index='13' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='13' port='0x60'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> + <target chassis='13' port='0x1a'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x2'/> </controller> <controller type='pci' index='14' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='14' port='0x68'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/> + <target chassis='14' port='0x1b'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x3'/> </controller> <controller type='pci' index='15' model='pcie-root-port'> <model name='ioh3420'/> - <target chassis='15' port='0x70'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/> + <target chassis='15' port='0x1c'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x4'/> </controller> <controller type='virtio-serial' index='0'> <address type='pci' domain='0x0000' bus='0x02' slot='0x03' function='0x0'/> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 20b9b17..bd9ee77 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -849,11 +849,13 @@ mymain(void) DO_TEST("pcie-root-port", QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, QEMU_CAPS_DEVICE_IOH3420, QEMU_CAPS_ICH9_AHCI, + QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_DEVICE_QXL); DO_TEST("pcie-switch-upstream-port", QEMU_CAPS_DEVICE_PCI_BRIDGE, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, QEMU_CAPS_DEVICE_IOH3420, QEMU_CAPS_ICH9_AHCI, + QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_DEVICE_QXL); DO_TEST("pcie-switch-downstream-port", -- 2.7.4
participants (1)
-
Laine Stump