[libvirt] [PATCH 08/12] qemu-command: Move qemuDomain*Address* functions to qemu_domain.c

John Ferlan jferlan at redhat.com
Mon Feb 15 19:37:22 UTC 2016


Move the functions into qemu_domain.c - additionally move any supporting
static functions.

Make qemuDomainSupportsPCI non static.

Also, move and rename the following:

qemuSetSCSIControllerModel to qemuDomainSetSCSIControllerModel
qemuCollectPCIAddress to qemuDomainCollectPCIAddress
qemuValidateDevicePCISlotsPIIX3 to qemuDomainValidateDevicePCISlotsPIIX3
qemuAssignDevicePCISlots to qemuDomainAssignDevicePCISlots

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/qemu/qemu_command.c | 1597 +----------------------------------------------
 src/qemu/qemu_command.h |   12 -
 src/qemu/qemu_domain.c  | 1592 ++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_domain.h  |   12 +
 4 files changed, 1610 insertions(+), 1603 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d02d7cb..f4b9dcd 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -66,11 +66,6 @@
 
 VIR_LOG_INIT("qemu.qemu_command");
 
-#define VIO_ADDR_NET 0x1000ul
-#define VIO_ADDR_SCSI 0x2000ul
-#define VIO_ADDR_SERIAL 0x30000000ul
-#define VIO_ADDR_NVRAM 0x3000ul
-
 VIR_ENUM_DECL(virDomainDiskQEMUBus)
 VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST,
               "ide",
@@ -500,64 +495,6 @@ static int qemuAssignDeviceDiskAliasFixed(virDomainDiskDefPtr disk)
     return 0;
 }
 
-static int
-qemuSetSCSIControllerModel(virDomainDefPtr def,
-                           virQEMUCapsPtr qemuCaps,
-                           int *model)
-{
-    if (*model > 0) {
-        switch (*model) {
-        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC:
-            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_LSI)) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                               _("This QEMU doesn't support "
-                                 "the LSI 53C895A SCSI controller"));
-                return -1;
-            }
-            break;
-        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI:
-            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_SCSI)) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                               _("This QEMU doesn't support "
-                                 "virtio scsi controller"));
-                return -1;
-            }
-            break;
-        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI:
-            /*TODO: need checking work here if necessary */
-            break;
-        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078:
-            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_MEGASAS)) {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                               _("This QEMU doesn't support "
-                                 "the LSI SAS1078 controller"));
-                return -1;
-            }
-            break;
-        default:
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("Unsupported controller model: %s"),
-                           virDomainControllerModelSCSITypeToString(*model));
-            return -1;
-        }
-    } else {
-        if (ARCH_IS_PPC64(def->os.arch) &&
-            STRPREFIX(def->os.machine, "pseries")) {
-            *model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI;
-        } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_LSI)) {
-            *model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC;
-        } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_SCSI)) {
-            *model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI;
-        } else {
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                           _("Unable to determine model for scsi controller"));
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
 /* Our custom -drive naming scheme used with id= */
 static int
 qemuAssignDeviceDiskAliasCustom(virDomainDefPtr def,
@@ -573,7 +510,8 @@ qemuAssignDeviceDiskAliasCustom(virDomainDefPtr def,
                 virDomainDeviceFindControllerModel(def, &disk->info,
                                                    VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
 
-            if ((qemuSetSCSIControllerModel(def, qemuCaps, &controllerModel)) < 0)
+            if ((qemuDomainSetSCSIControllerModel(def, qemuCaps,
+                                                  &controllerModel)) < 0)
                 return -1;
         }
 
@@ -926,1530 +864,6 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
 }
 
 
-static void
-qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def,
-                                     virDomainDeviceAddressType type)
-{
-    /*
-       declare address-less virtio devices to be of address type 'type'
-       disks, networks, consoles, controllers, memballoon and rng in this
-       order
-       if type is ccw filesystem devices are declared to be of address type ccw
-    */
-    size_t i;
-
-    for (i = 0; i < def->ndisks; i++) {
-        if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_VIRTIO &&
-            def->disks[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            def->disks[i]->info.type = type;
-    }
-
-    for (i = 0; i < def->nnets; i++) {
-        if (STREQ(def->nets[i]->model, "virtio") &&
-            def->nets[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
-            def->nets[i]->info.type = type;
-        }
-    }
-
-    for (i = 0; i < def->ninputs; i++) {
-        if (def->inputs[i]->bus == VIR_DOMAIN_DISK_BUS_VIRTIO &&
-            def->inputs[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            def->inputs[i]->info.type = type;
-    }
-
-    for (i = 0; i < def->ncontrollers; i++) {
-        if ((def->controllers[i]->type ==
-             VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL ||
-             def->controllers[i]->type ==
-             VIR_DOMAIN_CONTROLLER_TYPE_SCSI) &&
-            def->controllers[i]->info.type ==
-            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            def->controllers[i]->info.type = type;
-    }
-
-    if (def->memballoon &&
-        def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
-        def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-        def->memballoon->info.type = type;
-
-    for (i = 0; i < def->nrngs; i++) {
-        if (def->rngs[i]->model == VIR_DOMAIN_RNG_MODEL_VIRTIO &&
-            def->rngs[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            def->rngs[i]->info.type = type;
-    }
-
-    if (type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
-        for (i = 0; i < def->nfss; i++) {
-            if (def->fss[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-                def->fss[i]->info.type = type;
-        }
-    }
-}
-
-
-/*
- * Three steps populating CCW devnos
- * 1. Allocate empty address set
- * 2. Gather addresses with explicit devno
- * 3. Assign defaults to the rest
- */
-static int
-qemuDomainAssignS390Addresses(virDomainDefPtr def,
-                              virQEMUCapsPtr qemuCaps,
-                              virDomainObjPtr obj)
-{
-    int ret = -1;
-    virDomainCCWAddressSetPtr addrs = NULL;
-    qemuDomainObjPrivatePtr priv = NULL;
-
-    if (qemuDomainMachineIsS390CCW(def) &&
-        virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_CCW)) {
-        qemuDomainPrimeVirtioDeviceAddresses(
-            def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW);
-
-        if (!(addrs = virDomainCCWAddressSetCreate()))
-            goto cleanup;
-
-        if (virDomainDeviceInfoIterate(def, virDomainCCWAddressValidate,
-                                       addrs) < 0)
-            goto cleanup;
-
-        if (virDomainDeviceInfoIterate(def, virDomainCCWAddressAllocate,
-                                       addrs) < 0)
-            goto cleanup;
-    } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_S390)) {
-        /* deal with legacy virtio-s390 */
-        qemuDomainPrimeVirtioDeviceAddresses(
-            def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390);
-    }
-
-    if (obj && obj->privateData) {
-        priv = obj->privateData;
-        if (addrs) {
-            /* if this is the live domain object, we persist the CCW addresses*/
-            virDomainCCWAddressSetFree(priv->ccwaddrs);
-            priv->persistentAddrs = 1;
-            priv->ccwaddrs = addrs;
-            addrs = NULL;
-        } else {
-            priv->persistentAddrs = 0;
-        }
-    }
-    ret = 0;
-
- cleanup:
-    virDomainCCWAddressSetFree(addrs);
-
-    return ret;
-}
-
-static int
-qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def,
-                                       virQEMUCapsPtr qemuCaps)
-{
-    if (((def->os.arch == VIR_ARCH_ARMV7L) ||
-        (def->os.arch == VIR_ARCH_AARCH64)) &&
-        (STRPREFIX(def->os.machine, "vexpress-") ||
-            STREQ(def->os.machine, "virt") ||
-            STRPREFIX(def->os.machine, "virt-")) &&
-        virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO)) {
-        qemuDomainPrimeVirtioDeviceAddresses(
-            def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO);
-    }
-    return 0;
-}
-
-static int
-qemuSpaprVIOFindByReg(virDomainDefPtr def ATTRIBUTE_UNUSED,
-                      virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
-                      virDomainDeviceInfoPtr info, void *opaque)
-{
-    virDomainDeviceInfoPtr target = opaque;
-
-    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO)
-        return 0;
-
-    /* Match a dev that has a reg, is not us, and has a matching reg */
-    if (info->addr.spaprvio.has_reg && info != target &&
-        info->addr.spaprvio.reg == target->addr.spaprvio.reg)
-        /* Has to be < 0 so virDomainDeviceInfoIterate() will exit */
-        return -1;
-
-    return 0;
-}
-
-static int
-qemuAssignSpaprVIOAddress(virDomainDefPtr def, virDomainDeviceInfoPtr info,
-                          unsigned long long default_reg)
-{
-    bool user_reg;
-    int ret;
-
-    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO)
-        return 0;
-
-    /* Check if the user has assigned the reg already, if so use it */
-    user_reg = info->addr.spaprvio.has_reg;
-    if (!user_reg) {
-        info->addr.spaprvio.reg = default_reg;
-        info->addr.spaprvio.has_reg = true;
-    }
-
-    ret = virDomainDeviceInfoIterate(def, qemuSpaprVIOFindByReg, info);
-    while (ret != 0) {
-        if (user_reg) {
-            virReportError(VIR_ERR_XML_ERROR,
-                           _("spapr-vio address %#llx already in use"),
-                           info->addr.spaprvio.reg);
-            return -EEXIST;
-        }
-
-        /* We assigned the reg, so try a new value */
-        info->addr.spaprvio.reg += 0x1000;
-        ret = virDomainDeviceInfoIterate(def, qemuSpaprVIOFindByReg, info);
-    }
-
-    return 0;
-}
-
-
-static int
-qemuDomainAssignVirtioSerialAddresses(virDomainDefPtr def,
-                                      virDomainObjPtr obj)
-{
-    int ret = -1;
-    size_t i;
-    virDomainVirtioSerialAddrSetPtr addrs = NULL;
-    qemuDomainObjPrivatePtr priv = NULL;
-
-    if (!(addrs = virDomainVirtioSerialAddrSetCreate()))
-        goto cleanup;
-
-    if (virDomainVirtioSerialAddrSetAddControllers(addrs, def) < 0)
-        goto cleanup;
-
-    if (virDomainDeviceInfoIterate(def, virDomainVirtioSerialAddrReserve,
-                                   addrs) < 0)
-        goto cleanup;
-
-    VIR_DEBUG("Finished reserving existing ports");
-
-    for (i = 0; i < def->nconsoles; i++) {
-        virDomainChrDefPtr chr = def->consoles[i];
-        if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
-            chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO &&
-            !virDomainVirtioSerialAddrIsComplete(&chr->info) &&
-            virDomainVirtioSerialAddrAutoAssign(def, addrs, &chr->info, true) < 0)
-            goto cleanup;
-    }
-
-    for (i = 0; i < def->nchannels; i++) {
-        virDomainChrDefPtr chr = def->channels[i];
-        if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
-            chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
-            !virDomainVirtioSerialAddrIsComplete(&chr->info) &&
-            virDomainVirtioSerialAddrAutoAssign(def, addrs, &chr->info, false) < 0)
-            goto cleanup;
-    }
-
-    if (obj && obj->privateData) {
-        priv = obj->privateData;
-        /* if this is the live domain object, we persist the addresses */
-        virDomainVirtioSerialAddrSetFree(priv->vioserialaddrs);
-        priv->persistentAddrs = 1;
-        priv->vioserialaddrs = addrs;
-        addrs = NULL;
-    }
-    ret = 0;
-
- cleanup:
-    virDomainVirtioSerialAddrSetFree(addrs);
-    return ret;
-}
-
-
-int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def,
-                                      virQEMUCapsPtr qemuCaps)
-{
-    size_t i;
-    int ret = -1;
-    int model;
-
-    /* Default values match QEMU. See spapr_(llan|vscsi|vty).c */
-
-    for (i = 0; i < def->nnets; i++) {
-        if (def->nets[i]->model &&
-            STREQ(def->nets[i]->model, "spapr-vlan"))
-            def->nets[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
-        if (qemuAssignSpaprVIOAddress(def, &def->nets[i]->info,
-                                      VIO_ADDR_NET) < 0)
-            goto cleanup;
-    }
-
-    for (i = 0; i < def->ncontrollers; i++) {
-        model = def->controllers[i]->model;
-        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
-            if (qemuSetSCSIControllerModel(def, qemuCaps, &model) < 0)
-                goto cleanup;
-        }
-
-        if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI &&
-            def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
-            def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
-        if (qemuAssignSpaprVIOAddress(def, &def->controllers[i]->info,
-                                      VIO_ADDR_SCSI) < 0)
-            goto cleanup;
-    }
-
-    for (i = 0; i < def->nserials; i++) {
-        if (def->serials[i]->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
-            ARCH_IS_PPC64(def->os.arch) &&
-            STRPREFIX(def->os.machine, "pseries"))
-            def->serials[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
-        if (qemuAssignSpaprVIOAddress(def, &def->serials[i]->info,
-                                      VIO_ADDR_SERIAL) < 0)
-            goto cleanup;
-    }
-
-    if (def->nvram) {
-        if (ARCH_IS_PPC64(def->os.arch) &&
-            STRPREFIX(def->os.machine, "pseries"))
-            def->nvram->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
-        if (qemuAssignSpaprVIOAddress(def, &def->nvram->info,
-                                      VIO_ADDR_NVRAM) < 0)
-            goto cleanup;
-    }
-
-    /* No other devices are currently supported on spapr-vio */
-
-    ret = 0;
-
- cleanup:
-    return ret;
-}
-
-
-static int
-qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
-                      virDomainDeviceDefPtr device,
-                      virDomainDeviceInfoPtr info,
-                      void *opaque)
-{
-    virDomainPCIAddressSetPtr addrs = opaque;
-    int ret = -1;
-    virDevicePCIAddressPtr addr = &info->addr.pci;
-    bool entireSlot;
-    /* flags may be changed from default below */
-    virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
-                                      VIR_PCI_CONNECT_TYPE_PCI);
-
-    if ((info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
-        || ((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) &&
-            (device->data.hostdev->parent.type != VIR_DOMAIN_DEVICE_NONE))) {
-        /* If a hostdev has a parent, its info will be a part of the
-         * parent, and will have its address collected during the scan
-         * of the parent's device type.
-        */
-        return 0;
-    }
-
-    /* Change flags according to differing requirements of different
-     * devices.
-     */
-    switch (device->type) {
-    case VIR_DOMAIN_DEVICE_CONTROLLER:
-        switch (device->data.controller->type) {
-        case  VIR_DOMAIN_CONTROLLER_TYPE_PCI:
-            switch (device->data.controller->model) {
-            case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
-                /* pci-bridge needs a PCI slot, but it isn't
-                 * hot-pluggable, so it doesn't need a hot-pluggable slot.
-                 */
-                flags = VIR_PCI_CONNECT_TYPE_PCI;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
-                /* pci-bridge needs a PCIe slot, but it isn't
-                 * hot-pluggable, so it doesn't need a hot-pluggable slot.
-                 */
-                flags = VIR_PCI_CONNECT_TYPE_PCIE;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
-                /* pcie-root-port can only connect to pcie-root, isn't
-                 * hot-pluggable
-                 */
-                flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
-                /* pcie-switch can only connect to a true
-                 * pcie bus, and can't be hot-plugged.
-                 */
-                flags = VIR_PCI_CONNECT_TYPE_PCIE_PORT;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
-                /* pcie-switch-downstream-port can only connect to a
-                 * pcie-switch-upstream-port, and can't be hot-plugged.
-                 */
-                flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH;
-                break;
-            default:
-                break;
-            }
-            break;
-
-        case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
-            /* SATA controllers aren't hot-plugged, and can be put in
-             * either a PCI or PCIe slot
-             */
-            flags = VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE;
-            break;
-
-        case VIR_DOMAIN_CONTROLLER_TYPE_USB:
-           /* allow UHCI and EHCI controllers to be manually placed on
-            * the PCIe bus (but don't put them there automatically)
-            */
-           switch (device->data.controller->model) {
-           case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI:
-           case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
-           case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
-           case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
-           case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
-           case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI:
-              flags = VIR_PCI_CONNECT_TYPE_PCI;
-              break;
-           case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI:
-              /* should this be PCIE-only? Or do we need to allow PCI
-               * for backward compatibility?
-               */
-              flags = VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE;
-              break;
-           case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI:
-           case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI:
-           case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI:
-              /* Allow these for PCI only */
-              break;
-           }
-        }
-        break;
-
-    case VIR_DOMAIN_DEVICE_SOUND:
-        switch (device->data.sound->model) {
-        case VIR_DOMAIN_SOUND_MODEL_ICH6:
-        case VIR_DOMAIN_SOUND_MODEL_ICH9:
-            flags = VIR_PCI_CONNECT_TYPE_PCI;
-            break;
-        }
-        break;
-
-    case VIR_DOMAIN_DEVICE_VIDEO:
-        /* video cards aren't hot-plugged, and can be put in either a
-         * PCI or PCIe slot
-         */
-        flags = VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE;
-        break;
-    }
-
-    /* Ignore implicit controllers on slot 0:0:1.0:
-     * implicit IDE controller on 0:0:1.1 (no qemu command line)
-     * implicit USB controller on 0:0:1.2 (-usb)
-     *
-     * If the machine does have a PCI bus, they will get reserved
-     * in qemuAssignDevicePCISlots().
-     */
-
-    /* These are the IDE and USB controllers in the PIIX3, hardcoded
-     * to bus 0 slot 1.  They cannot be attached to a PCIe slot, only
-     * PCI.
-     */
-    if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER && addr->domain == 0 &&
-        addr->bus == 0 && addr->slot == 1) {
-        virDomainControllerDefPtr cont = device->data.controller;
-
-        if ((cont->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE && cont->idx == 0 &&
-             addr->function == 1) ||
-            (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB && cont->idx == 0 &&
-             (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI ||
-              cont->model == -1) && addr->function == 2)) {
-            /* Note the check for nbuses > 0 - if there are no PCI
-             * buses, we skip this check. This is a quirk required for
-             * some machinetypes such as s390, which pretend to have a
-             * PCI bus for long enough to generate the "-usb" on the
-             * commandline, but that don't really care if a PCI bus
-             * actually exists. */
-            if (addrs->nbuses > 0 &&
-                !(addrs->buses[0].flags & VIR_PCI_CONNECT_TYPE_PCI)) {
-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("Bus 0 must be PCI for integrated PIIX3 "
-                                 "USB or IDE controllers"));
-                return -1;
-            } else {
-                return 0;
-            }
-        }
-    }
-
-    entireSlot = (addr->function == 0 &&
-                  addr->multi != VIR_TRISTATE_SWITCH_ON);
-
-    if (virDomainPCIAddressReserveAddr(addrs, addr, flags,
-                                       entireSlot, true) < 0)
-        goto cleanup;
-
-    ret = 0;
- cleanup:
-    return ret;
-}
-
-static bool
-qemuDomainSupportsPCI(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
-{
-    if ((def->os.arch != VIR_ARCH_ARMV7L) && (def->os.arch != VIR_ARCH_AARCH64))
-        return true;
-
-    if (STREQ(def->os.machine, "versatilepb"))
-        return true;
-
-    if ((STREQ(def->os.machine, "virt") ||
-         STRPREFIX(def->os.machine, "virt-")) &&
-        virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_GPEX))
-        return true;
-
-    return false;
-}
-
-static bool
-qemuDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus)
-{
-    size_t i;
-
-    for (i = bus->minSlot; i <= bus->maxSlot; i++)
-        if (!bus->slots[i])
-            return false;
-
-    return true;
-}
-
-
-static int
-qemuAssignDevicePCISlots(virDomainDefPtr def,
-                         virQEMUCapsPtr qemuCaps,
-                         virDomainPCIAddressSetPtr addrs);
-static int
-qemuDomainAssignPCIAddresses(virDomainDefPtr def,
-                             virQEMUCapsPtr qemuCaps,
-                             virDomainObjPtr obj);
-
-
-int qemuDomainAssignAddresses(virDomainDefPtr def,
-                              virQEMUCapsPtr qemuCaps,
-                              virDomainObjPtr obj)
-{
-    int rc;
-
-    rc = qemuDomainAssignVirtioSerialAddresses(def, obj);
-    if (rc)
-        return rc;
-
-    rc = qemuDomainAssignSpaprVIOAddresses(def, qemuCaps);
-    if (rc)
-        return rc;
-
-    rc = qemuDomainAssignS390Addresses(def, qemuCaps, obj);
-    if (rc)
-        return rc;
-
-    rc = qemuDomainAssignARMVirtioMMIOAddresses(def, qemuCaps);
-    if (rc)
-        return rc;
-
-    return qemuDomainAssignPCIAddresses(def, qemuCaps, obj);
-}
-
-
-static virDomainPCIAddressSetPtr
-qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
-                              unsigned int nbuses,
-                              bool dryRun)
-{
-    virDomainPCIAddressSetPtr addrs;
-    size_t i;
-
-    if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
-        return NULL;
-
-    addrs->nbuses = nbuses;
-    addrs->dryRun = dryRun;
-
-    /* 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)
-        virDomainPCIAddressBusSetModel(&addrs->buses[0],
-                                       VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT);
-    for (i = 1; i < nbuses; i++) {
-        virDomainPCIAddressBusSetModel(&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 (virDomainPCIAddressBusSetModel(&addrs->buses[idx],
-                                           def->controllers[i]->model) < 0)
-            goto error;
-        }
-
-    if (virDomainDeviceInfoIterate(def, qemuCollectPCIAddress, addrs) < 0)
-        goto error;
-
-    return addrs;
-
- error:
-    virDomainPCIAddressSetFree(addrs);
-    return NULL;
-}
-
-
-void
-qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
-                               virDomainDeviceInfoPtr info,
-                               const char *devstr)
-{
-    qemuDomainObjPrivatePtr priv = vm->privateData;
-
-    if (!devstr)
-        devstr = info->alias;
-
-    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
-        qemuDomainMachineIsS390CCW(vm->def) &&
-        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW) &&
-        virDomainCCWAddressReleaseAddr(priv->ccwaddrs, info) < 0)
-        VIR_WARN("Unable to release CCW address on %s",
-                 NULLSTR(devstr));
-    else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
-             virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
-             virDomainPCIAddressReleaseSlot(priv->pciaddrs,
-                                            &info->addr.pci) < 0)
-        VIR_WARN("Unable to release PCI address on %s",
-                 NULLSTR(devstr));
-    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL &&
-        virDomainVirtioSerialAddrRelease(priv->vioserialaddrs, info) < 0)
-        VIR_WARN("Unable to release virtio-serial address on %s",
-                 NULLSTR(devstr));
-}
-
-
-#define IS_USB2_CONTROLLER(ctrl) \
-    (((ctrl)->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) && \
-     ((ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1 || \
-      (ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1 || \
-      (ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2 || \
-      (ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3))
-
-
-static int
-qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
-                                virQEMUCapsPtr qemuCaps,
-                                virDomainPCIAddressSetPtr addrs)
-{
-    int ret = -1;
-    size_t i;
-    virDevicePCIAddress tmp_addr;
-    bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
-    char *addrStr = NULL;
-    virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_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++) {
-        /* First IDE controller lives on the PIIX3 at slot=1, function=1 */
-        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE &&
-            def->controllers[i]->idx == 0) {
-            if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
-                if (def->controllers[i]->info.addr.pci.domain != 0 ||
-                    def->controllers[i]->info.addr.pci.bus != 0 ||
-                    def->controllers[i]->info.addr.pci.slot != 1 ||
-                    def->controllers[i]->info.addr.pci.function != 1) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                   _("Primary IDE controller must have PCI address 0:0:1.1"));
-                    goto cleanup;
-                }
-            } else {
-                def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
-                def->controllers[i]->info.addr.pci.domain = 0;
-                def->controllers[i]->info.addr.pci.bus = 0;
-                def->controllers[i]->info.addr.pci.slot = 1;
-                def->controllers[i]->info.addr.pci.function = 1;
-            }
-        } else if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
-                   def->controllers[i]->idx == 0 &&
-                   (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI ||
-                    def->controllers[i]->model == -1)) {
-            if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
-                if (def->controllers[i]->info.addr.pci.domain != 0 ||
-                    def->controllers[i]->info.addr.pci.bus != 0 ||
-                    def->controllers[i]->info.addr.pci.slot != 1 ||
-                    def->controllers[i]->info.addr.pci.function != 2) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                   _("PIIX3 USB controller must have PCI address 0:0:1.2"));
-                    goto cleanup;
-                }
-            } else {
-                def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
-                def->controllers[i]->info.addr.pci.domain = 0;
-                def->controllers[i]->info.addr.pci.bus = 0;
-                def->controllers[i]->info.addr.pci.slot = 1;
-                def->controllers[i]->info.addr.pci.function = 2;
-            }
-        }
-    }
-
-    /* PIIX3 (ISA bridge, IDE controller, something else unknown, USB controller)
-     * hardcoded slot=1, multifunction device
-     */
-    if (addrs->nbuses) {
-        memset(&tmp_addr, 0, sizeof(tmp_addr));
-        tmp_addr.slot = 1;
-        if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
-            goto cleanup;
-    }
-
-    if (def->nvideos > 0) {
-        /* Because the PIIX3 integrated IDE/USB controllers are
-         * already at slot 1, when qemu looks for the first free slot
-         * to place the VGA controller (which is always the first
-         * device added after integrated devices), it *always* ends up
-         * at slot 2.
-         */
-        virDomainVideoDefPtr primaryVideo = def->videos[0];
-        if (primaryVideo->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
-            memset(&tmp_addr, 0, sizeof(tmp_addr));
-            tmp_addr.slot = 2;
-
-            if (!(addrStr = virDomainPCIAddressAsString(&tmp_addr)))
-                goto cleanup;
-            if (!virDomainPCIAddressValidate(addrs, &tmp_addr,
-                                             addrStr, flags, false))
-                goto cleanup;
-
-            if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
-                if (qemuDeviceVideoUsable) {
-                    if (virDomainPCIAddressReserveNextSlot(addrs,
-                                                           &primaryVideo->info,
-                                                           flags) < 0)
-                        goto cleanup;
-                } else {
-                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                   _("PCI address 0:0:2.0 is in use, "
-                                     "QEMU needs it for primary video"));
-                    goto cleanup;
-                }
-            } else {
-                if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
-                    goto cleanup;
-                primaryVideo->info.addr.pci = tmp_addr;
-                primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
-            }
-        } else if (!qemuDeviceVideoUsable) {
-            if (primaryVideo->info.addr.pci.domain != 0 ||
-                primaryVideo->info.addr.pci.bus != 0 ||
-                primaryVideo->info.addr.pci.slot != 2 ||
-                primaryVideo->info.addr.pci.function != 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("Primary video card must have PCI address 0:0:2.0"));
-                goto cleanup;
-            }
-            /* If TYPE == PCI, then qemuCollectPCIAddress() function
-             * has already reserved the address, so we must skip */
-        }
-    } else if (addrs->nbuses && !qemuDeviceVideoUsable) {
-        memset(&tmp_addr, 0, sizeof(tmp_addr));
-        tmp_addr.slot = 2;
-
-        if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
-            VIR_DEBUG("PCI address 0:0:2.0 in use, future addition of a video"
-                      " device will not be possible without manual"
-                      " intervention");
-        } else if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
-            goto cleanup;
-        }
-    }
-    ret = 0;
- cleanup:
-    VIR_FREE(addrStr);
-    return ret;
-}
-
-
-static int
-qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
-                                    virQEMUCapsPtr qemuCaps,
-                                    virDomainPCIAddressSetPtr addrs)
-{
-    int ret = -1;
-    size_t i;
-    virDevicePCIAddress tmp_addr;
-    bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
-    char *addrStr = NULL;
-    virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCIE;
-
-    for (i = 0; i < def->ncontrollers; i++) {
-        switch (def->controllers[i]->type) {
-        case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
-            /* Verify that the first SATA controller is at 00:1F.2 the
-             * q35 machine type *always* has a SATA controller at this
-             * address.
-             */
-            if (def->controllers[i]->idx == 0) {
-                if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
-                    if (def->controllers[i]->info.addr.pci.domain != 0 ||
-                        def->controllers[i]->info.addr.pci.bus != 0 ||
-                        def->controllers[i]->info.addr.pci.slot != 0x1F ||
-                        def->controllers[i]->info.addr.pci.function != 2) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                       _("Primary SATA controller must have PCI address 0:0:1f.2"));
-                        goto cleanup;
-                    }
-                } else {
-                    def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
-                    def->controllers[i]->info.addr.pci.domain = 0;
-                    def->controllers[i]->info.addr.pci.bus = 0;
-                    def->controllers[i]->info.addr.pci.slot = 0x1F;
-                    def->controllers[i]->info.addr.pci.function = 2;
-                }
-            }
-            break;
-
-        case VIR_DOMAIN_CONTROLLER_TYPE_USB:
-            if ((def->controllers[i]->model
-                 == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1) &&
-                (def->controllers[i]->info.type
-                 == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)) {
-                /* Try to assign the first found USB2 controller to
-                 * 00:1D.0 and 2nd to 00:1A.0 (because that is their
-                 * standard location on real Q35 hardware) unless they
-                 * are already taken, but don't insist on it.
-                 *
-                 * (NB: all other controllers at the same index will
-                 * get assigned to the same slot as the UHCI1 when
-                 * addresses are later assigned to all devices.)
-                 */
-                bool assign = false;
-
-                memset(&tmp_addr, 0, sizeof(tmp_addr));
-                tmp_addr.slot = 0x1D;
-                if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
-                    assign = true;
-                } else {
-                    tmp_addr.slot = 0x1A;
-                    if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr))
-                        assign = true;
-                }
-                if (assign) {
-                    if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr,
-                                                       flags, false, true) < 0)
-                        goto cleanup;
-                    def->controllers[i]->info.type
-                        = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
-                    def->controllers[i]->info.addr.pci.domain = 0;
-                    def->controllers[i]->info.addr.pci.bus = 0;
-                    def->controllers[i]->info.addr.pci.slot = tmp_addr.slot;
-                    def->controllers[i]->info.addr.pci.function = 0;
-                    def->controllers[i]->info.addr.pci.multi
-                       = VIR_TRISTATE_SWITCH_ON;
-                }
-            }
-            break;
-
-        case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
-            if (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE &&
-                def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
-                /* Try to assign this bridge to 00:1E.0 (because that
-                * is its standard location on real hardware) unless
-                * it's already taken, but don't insist on it.
-                */
-                memset(&tmp_addr, 0, sizeof(tmp_addr));
-                tmp_addr.slot = 0x1E;
-                if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
-                    if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr,
-                                                       flags, true, false) < 0)
-                        goto cleanup;
-                    def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
-                    def->controllers[i]->info.addr.pci.domain = 0;
-                    def->controllers[i]->info.addr.pci.bus = 0;
-                    def->controllers[i]->info.addr.pci.slot = 0x1E;
-                    def->controllers[i]->info.addr.pci.function = 0;
-                }
-            }
-            break;
-        }
-    }
-
-    /* Reserve slot 0x1F function 0 (ISA bridge, not in config model)
-     * and function 3 (SMBus, also not (yet) in config model). As with
-     * the SATA controller, these devices are always present in a q35
-     * machine; there is no way to not have them.
-     */
-    if (addrs->nbuses) {
-        memset(&tmp_addr, 0, sizeof(tmp_addr));
-        tmp_addr.slot = 0x1F;
-        tmp_addr.function = 0;
-        tmp_addr.multi = VIR_TRISTATE_SWITCH_ON;
-        if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
-                                           false, false) < 0)
-           goto cleanup;
-        tmp_addr.function = 3;
-        tmp_addr.multi = VIR_TRISTATE_SWITCH_ABSENT;
-        if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
-                                           false, false) < 0)
-           goto cleanup;
-    }
-
-    if (def->nvideos > 0) {
-        /* NB: unlike the pc machinetypes, on q35 machinetypes the
-         * integrated devices are at slot 0x1f, so when qemu looks for
-         * the first free lot for the first VGA, it will always be at
-         * slot 1 (which was used up by the integrated PIIX3 devices
-         * on pc machinetypes).
-         */
-        virDomainVideoDefPtr primaryVideo = def->videos[0];
-        if (primaryVideo->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
-            memset(&tmp_addr, 0, sizeof(tmp_addr));
-            tmp_addr.slot = 1;
-
-            if (!(addrStr = virDomainPCIAddressAsString(&tmp_addr)))
-                goto cleanup;
-            if (!virDomainPCIAddressValidate(addrs, &tmp_addr,
-                                             addrStr, flags, false))
-                goto cleanup;
-
-            if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
-                if (qemuDeviceVideoUsable) {
-                    if (virDomainPCIAddressReserveNextSlot(addrs,
-                                                           &primaryVideo->info,
-                                                           flags) < 0)
-                        goto cleanup;
-                } else {
-                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                   _("PCI address 0:0:1.0 is in use, "
-                                     "QEMU needs it for primary video"));
-                    goto cleanup;
-                }
-            } else {
-                if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
-                    goto cleanup;
-                primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
-                primaryVideo->info.addr.pci = tmp_addr;
-            }
-        } else if (!qemuDeviceVideoUsable) {
-            if (primaryVideo->info.addr.pci.domain != 0 ||
-                primaryVideo->info.addr.pci.bus != 0 ||
-                primaryVideo->info.addr.pci.slot != 1 ||
-                primaryVideo->info.addr.pci.function != 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                               _("Primary video card must have PCI address 0:0:1.0"));
-                goto cleanup;
-            }
-            /* If TYPE == PCI, then qemuCollectPCIAddress() function
-             * has already reserved the address, so we must skip */
-        }
-    } else if (addrs->nbuses && !qemuDeviceVideoUsable) {
-        memset(&tmp_addr, 0, sizeof(tmp_addr));
-        tmp_addr.slot = 1;
-
-        if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
-            VIR_DEBUG("PCI address 0:0:1.0 in use, future addition of a video"
-                      " device will not be possible without manual"
-                      " intervention");
-            virResetLastError();
-        } else if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
-            goto cleanup;
-        }
-    }
-    ret = 0;
- cleanup:
-    VIR_FREE(addrStr);
-    return ret;
-}
-
-static int
-qemuValidateDevicePCISlotsChipsets(virDomainDefPtr def,
-                                   virQEMUCapsPtr qemuCaps,
-                                   virDomainPCIAddressSetPtr addrs)
-{
-    if (qemuDomainMachineIsI440FX(def) &&
-        qemuValidateDevicePCISlotsPIIX3(def, qemuCaps, addrs) < 0) {
-        return -1;
-    }
-
-    if (qemuDomainMachineIsQ35(def) &&
-        qemuDomainValidateDevicePCISlotsQ35(def, qemuCaps, addrs) < 0) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static int
-qemuDomainAssignPCIAddresses(virDomainDefPtr def,
-                             virQEMUCapsPtr qemuCaps,
-                             virDomainObjPtr obj)
-{
-    int ret = -1;
-    virDomainPCIAddressSetPtr addrs = NULL;
-    qemuDomainObjPrivatePtr priv = NULL;
-
-    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
-        int max_idx = -1;
-        int nbuses = 0;
-        size_t i;
-        int rv;
-        bool buses_reserved = true;
-
-        virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCI;
-
-        for (i = 0; i < def->ncontrollers; i++) {
-            if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
-                if ((int) def->controllers[i]->idx > max_idx)
-                    max_idx = def->controllers[i]->idx;
-            }
-        }
-
-        nbuses = max_idx + 1;
-
-        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 (qemuValidateDevicePCISlotsChipsets(def, qemuCaps, addrs) < 0)
-                goto cleanup;
-
-            for (i = 0; i < addrs->nbuses; i++) {
-                if (!qemuDomainPCIBusFullyReserved(&addrs->buses[i]))
-                    buses_reserved = false;
-            }
-
-            /* Reserve 1 extra slot for a (potential) bridge only if buses
-             * are not fully reserved yet
-             */
-            if (!buses_reserved &&
-                virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0)
-                goto cleanup;
-
-            if (qemuAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
-                goto cleanup;
-
-            for (i = 1; i < addrs->nbuses; i++) {
-                virDomainPCIAddressBusPtr bus = &addrs->buses[i];
-
-                if ((rv = virDomainDefMaybeAddController(
-                         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 &&
-                    virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0)
-                    goto cleanup;
-            }
-            nbuses = addrs->nbuses;
-            virDomainPCIAddressSetFree(addrs);
-            addrs = NULL;
-
-        } else if (max_idx > 0) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("PCI bridges are not supported "
-                             "by this QEMU binary"));
-            goto cleanup;
-        }
-
-        if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, false)))
-            goto cleanup;
-
-        if (qemuDomainSupportsPCI(def, qemuCaps)) {
-            if (qemuValidateDevicePCISlotsChipsets(def, qemuCaps, addrs) < 0)
-                goto cleanup;
-
-            if (qemuAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
-                goto cleanup;
-
-            for (i = 0; i < def->ncontrollers; i++) {
-                virDomainControllerDefPtr cont = def->controllers[i];
-                int idx = cont->idx;
-                virDevicePCIAddressPtr addr;
-                virDomainPCIControllerOptsPtr options;
-
-                if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI)
-                    continue;
-
-                addr = &cont->info.addr.pci;
-                options = &cont->opts.pciopts;
-
-                /* set defaults for any other auto-generated config
-                 * options for this controller that haven't been
-                 * specified in config.
-                 */
-                switch ((virDomainControllerModelPCI)cont->model) {
-                case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
-                    if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
-                        options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE;
-                    if (options->chassisNr == -1)
-                        options->chassisNr = cont->idx;
-                    break;
-                case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
-                    if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
-                        options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE;
-                    break;
-                case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
-                    if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
-                        options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420;
-                    if (options->chassis == -1)
-                       options->chassis = cont->idx;
-                    if (options->port == -1)
-                       options->port = (addr->slot << 3) + addr->function;
-                    break;
-                case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
-                    if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
-                        options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM;
-                    break;
-                case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
-                    if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
-                        options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM;
-                    if (options->chassis == -1)
-                       options->chassis = cont->idx;
-                    if (options->port == -1)
-                       options->port = addr->slot;
-                    break;
-                case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
-                case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
-                case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
-                    break;
-                }
-
-                /* check if every PCI bridge controller's ID is greater than
-                 * the bus it is placed onto
-                 */
-                if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE &&
-                    idx <= addr->bus) {
-                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                                   _("failed to create PCI bridge "
-                                     "on bus %d: too many devices with fixed "
-                                     "addresses"),
-                                   addr->bus);
-                    goto cleanup;
-                }
-            }
-        }
-    }
-
-    if (obj && obj->privateData) {
-        priv = obj->privateData;
-        if (addrs) {
-            /* if this is the live domain object, we persist the PCI addresses*/
-            virDomainPCIAddressSetFree(priv->pciaddrs);
-            priv->persistentAddrs = 1;
-            priv->pciaddrs = addrs;
-            addrs = NULL;
-        } else {
-            priv->persistentAddrs = 0;
-        }
-    }
-
-    ret = 0;
-
- cleanup:
-    virDomainPCIAddressSetFree(addrs);
-
-    return ret;
-}
-
-
-/*
- * This assigns static PCI slots to all configured devices.
- * The ordering here is chosen to match the ordering used
- * with old QEMU < 0.12, so that if a user updates a QEMU
- * host from old QEMU to QEMU >= 0.12, their guests should
- * get PCI addresses in the same order as before.
- *
- * NB, if they previously hotplugged devices then all bets
- * are off. Hotplug for old QEMU was unfixably broken wrt
- * to stable PCI addressing.
- *
- * Order is:
- *
- *  - Host bridge (slot 0)
- *  - PIIX3 ISA bridge, IDE controller, something else unknown, USB controller (slot 1)
- *  - Video (slot 2)
- *
- *  - These integrated devices were already added by
- *    qemuValidateDevicePCISlotsChipsets invoked right before this function
- *
- * Incrementally assign slots from 3 onwards:
- *
- *  - Net
- *  - Sound
- *  - SCSI controllers
- *  - VirtIO block
- *  - VirtIO balloon
- *  - Host device passthrough
- *  - Watchdog
- *  - pci serial devices
- *
- * Prior to this function being invoked, qemuCollectPCIAddress() will have
- * added all existing PCI addresses from the 'def' to 'addrs'. Thus this
- * function must only try to reserve addresses if info.type == NONE and
- * skip over info.type == PCI
- */
-static int
-qemuAssignDevicePCISlots(virDomainDefPtr def,
-                         virQEMUCapsPtr qemuCaps,
-                         virDomainPCIAddressSetPtr addrs)
-{
-    size_t i, j;
-    virDomainPCIConnectFlags flags;
-    virDevicePCIAddress tmp_addr;
-
-    /* PCI controllers */
-    for (i = 0; i < def->ncontrollers; i++) {
-        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
-            if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-                continue;
-            switch (def->controllers[i]->model) {
-            case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
-            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
-                /* pci-root and pcie-root are implicit in the machine,
-                 * and needs no address */
-                continue;
-            case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
-                /* pci-bridge doesn't require hot-plug
-                 * (although it does provide hot-plug in its slots)
-                 */
-                flags = VIR_PCI_CONNECT_TYPE_PCI;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
-                /* dmi-to-pci-bridge requires a non-hotplug PCIe
-                 * slot
-                 */
-                flags = VIR_PCI_CONNECT_TYPE_PCIE;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
-                /* pcie-root-port can only plug into pcie-root */
-                flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
-                /* pcie-switch really does need a real PCIe
-                 * port, but it doesn't need to be pcie-root
-                 */
-                flags = VIR_PCI_CONNECT_TYPE_PCIE_PORT;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
-                /* pcie-switch-port can only plug into pcie-switch */
-                flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH;
-                break;
-            default:
-                flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI;
-                break;
-            }
-            if (virDomainPCIAddressReserveNextSlot(addrs,
-                                                   &def->controllers[i]->info,
-                                                   flags) < 0)
-                goto error;
-        }
-    }
-
-    flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI;
-
-    for (i = 0; i < def->nfss; i++) {
-        if (def->fss[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            continue;
-
-        /* Only support VirtIO-9p-pci so far. If that changes,
-         * we might need to skip devices here */
-        if (virDomainPCIAddressReserveNextSlot(addrs, &def->fss[i]->info,
-                                               flags) < 0)
-            goto error;
-    }
-
-    /* Network interfaces */
-    for (i = 0; i < def->nnets; i++) {
-        /* type='hostdev' network devices might be USB, and are also
-         * in hostdevs list anyway, so handle them with other hostdevs
-         * instead of here.
-         */
-        if ((def->nets[i]->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
-            (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)) {
-            continue;
-        }
-        if (virDomainPCIAddressReserveNextSlot(addrs, &def->nets[i]->info,
-                                               flags) < 0)
-            goto error;
-    }
-
-    /* Sound cards */
-    for (i = 0; i < def->nsounds; i++) {
-        if (def->sounds[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            continue;
-        /* Skip ISA sound card, PCSPK and usb-audio */
-        if (def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_SB16 ||
-            def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_PCSPK ||
-            def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_USB)
-            continue;
-
-        if (virDomainPCIAddressReserveNextSlot(addrs, &def->sounds[i]->info,
-                                               flags) < 0)
-            goto error;
-    }
-
-    /* Device controllers (SCSI, USB, but not IDE, FDC or CCID) */
-    for (i = 0; i < def->ncontrollers; i++) {
-        /* PCI controllers have been dealt with earlier */
-        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI)
-            continue;
-
-        /* USB controller model 'none' doesn't need a PCI address */
-        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
-            def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE)
-            continue;
-
-        /* FDC lives behind the ISA bridge; CCID is a usb device */
-        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC ||
-            def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_CCID)
-            continue;
-
-        /* First IDE controller lives on the PIIX3 at slot=1, function=1,
-           dealt with earlier on*/
-        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE &&
-            def->controllers[i]->idx == 0)
-            continue;
-
-        if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            continue;
-
-        /* USB2 needs special handling to put all companions in the same slot */
-        if (IS_USB2_CONTROLLER(def->controllers[i])) {
-            virDevicePCIAddress addr = { 0, 0, 0, 0, false };
-            bool foundAddr = false;
-
-            memset(&tmp_addr, 0, sizeof(tmp_addr));
-            for (j = 0; j < def->ncontrollers; j++) {
-                if (IS_USB2_CONTROLLER(def->controllers[j]) &&
-                    def->controllers[j]->idx == def->controllers[i]->idx &&
-                    def->controllers[j]->info.type
-                    == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
-                    addr = def->controllers[j]->info.addr.pci;
-                    foundAddr = true;
-                    break;
-                }
-            }
-
-            switch (def->controllers[i]->model) {
-            case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
-                addr.function = 7;
-                addr.multi = VIR_TRISTATE_SWITCH_ABSENT;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
-                addr.function = 0;
-                addr.multi = VIR_TRISTATE_SWITCH_ON;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
-                addr.function = 1;
-                addr.multi = VIR_TRISTATE_SWITCH_ABSENT;
-                break;
-            case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
-                addr.function = 2;
-                addr.multi = VIR_TRISTATE_SWITCH_ABSENT;
-                break;
-            }
-
-            if (!foundAddr) {
-                /* This is the first part of the controller, so need
-                 * to find a free slot & then reserve a function */
-                if (virDomainPCIAddressGetNextSlot(addrs, &tmp_addr, flags) < 0)
-                    goto error;
-
-                addr.bus = tmp_addr.bus;
-                addr.slot = tmp_addr.slot;
-
-                addrs->lastaddr = addr;
-                addrs->lastaddr.function = 0;
-                addrs->lastaddr.multi = VIR_TRISTATE_SWITCH_ABSENT;
-            }
-            /* Finally we can reserve the slot+function */
-            if (virDomainPCIAddressReserveAddr(addrs, &addr, flags,
-                                               false, foundAddr) < 0)
-                goto error;
-
-            def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
-            def->controllers[i]->info.addr.pci = addr;
-        } else {
-            if (virDomainPCIAddressReserveNextSlot(addrs,
-                                                   &def->controllers[i]->info,
-                                                   flags) < 0)
-                goto error;
-        }
-    }
-
-    /* Disks (VirtIO only for now) */
-    for (i = 0; i < def->ndisks; i++) {
-        /* Only VirtIO disks use PCI addrs */
-        if (def->disks[i]->bus != VIR_DOMAIN_DISK_BUS_VIRTIO)
-            continue;
-
-        /* don't touch s390 devices */
-        if (def->disks[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
-            def->disks[i]->info.type ==
-            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 ||
-            def->disks[i]->info.type ==
-            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)
-            continue;
-
-        /* Also ignore virtio-mmio disks if our machine allows them */
-        if (def->disks[i]->info.type ==
-            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO &&
-            virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO))
-            continue;
-
-        if (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("virtio disk cannot have an address of type '%s'"),
-                           virDomainDeviceAddressTypeToString(def->disks[i]->info.type));
-            goto error;
-        }
-
-        if (virDomainPCIAddressReserveNextSlot(addrs, &def->disks[i]->info,
-                                               flags) < 0)
-            goto error;
-    }
-
-    /* Host PCI devices */
-    for (i = 0; i < def->nhostdevs; i++) {
-        if (def->hostdevs[i]->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            continue;
-        if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
-            def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
-            continue;
-
-        if (virDomainPCIAddressReserveNextSlot(addrs,
-                                               def->hostdevs[i]->info,
-                                               flags) < 0)
-            goto error;
-    }
-
-    /* VirtIO balloon */
-    if (def->memballoon &&
-        def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
-        def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
-        if (virDomainPCIAddressReserveNextSlot(addrs,
-                                               &def->memballoon->info,
-                                               flags) < 0)
-            goto error;
-    }
-
-    /* VirtIO RNG */
-    for (i = 0; i < def->nrngs; i++) {
-        if (def->rngs[i]->model != VIR_DOMAIN_RNG_MODEL_VIRTIO ||
-            def->rngs[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            continue;
-
-        if (virDomainPCIAddressReserveNextSlot(addrs,
-                                               &def->rngs[i]->info, flags) < 0)
-            goto error;
-    }
-
-    /* A watchdog - check if it is a PCI device */
-    if (def->watchdog &&
-        def->watchdog->model == VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB &&
-        def->watchdog->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
-        if (virDomainPCIAddressReserveNextSlot(addrs, &def->watchdog->info,
-                                               flags) < 0)
-            goto error;
-    }
-
-    /* Assign a PCI slot to the primary video card if there is not an
-     * assigned address. */
-    if (def->nvideos > 0 &&
-        def->videos[0]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
-        if (virDomainPCIAddressReserveNextSlot(addrs, &def->videos[0]->info,
-                                               flags) < 0)
-            goto error;
-    }
-
-    /* Further non-primary video cards which have to be qxl type */
-    for (i = 1; i < def->nvideos; i++) {
-        if (def->videos[i]->type != VIR_DOMAIN_VIDEO_TYPE_QXL) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("non-primary video device must be type of 'qxl'"));
-            goto error;
-        }
-        if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            continue;
-        if (virDomainPCIAddressReserveNextSlot(addrs, &def->videos[i]->info,
-                                               flags) < 0)
-            goto error;
-    }
-
-    /* Shared Memory */
-    for (i = 0; i < def->nshmems; i++) {
-        if (def->shmems[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            continue;
-
-        if (virDomainPCIAddressReserveNextSlot(addrs,
-                                               &def->shmems[i]->info, flags) < 0)
-            goto error;
-    }
-    for (i = 0; i < def->ninputs; i++) {
-        if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_VIRTIO)
-            continue;
-        if (def->inputs[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            continue;
-
-        if (virDomainPCIAddressReserveNextSlot(addrs,
-                                               &def->inputs[i]->info, flags) < 0)
-            goto error;
-    }
-    for (i = 0; i < def->nparallels; i++) {
-        /* Nada - none are PCI based (yet) */
-    }
-    for (i = 0; i < def->nserials; i++) {
-        virDomainChrDefPtr chr = def->serials[i];
-
-        if (chr->targetType != VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI)
-            continue;
-
-        if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            continue;
-
-        if (virDomainPCIAddressReserveNextSlot(addrs, &chr->info, flags) < 0)
-            goto error;
-    }
-    for (i = 0; i < def->nchannels; i++) {
-        /* Nada - none are PCI based (yet) */
-    }
-    for (i = 0; i < def->nhubs; i++) {
-        /* Nada - none are PCI based (yet) */
-    }
-
-    return 0;
-
- error:
-    return -1;
-}
-
 static int
 qemuBuildDeviceAddressStr(virBufferPtr buf,
                           virDomainDefPtr domainDef,
@@ -3741,7 +2155,8 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
         controllerModel =
             virDomainDeviceFindControllerModel(def, &disk->info,
                                                VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
-        if ((qemuSetSCSIControllerModel(def, qemuCaps, &controllerModel)) < 0)
+        if ((qemuDomainSetSCSIControllerModel(def, qemuCaps,
+                                              &controllerModel)) < 0)
             goto error;
 
         if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
@@ -4131,7 +2546,7 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
         return NULL;
 
     if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
-        if ((qemuSetSCSIControllerModel(domainDef, qemuCaps, &model)) < 0)
+        if ((qemuDomainSetSCSIControllerModel(domainDef, qemuCaps, &model)) < 0)
             return NULL;
     }
 
@@ -5965,7 +4380,7 @@ qemuBuildSCSIHostdevDevStr(virDomainDefPtr def,
     model = virDomainDeviceFindControllerModel(def, dev->info,
                                                VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
 
-    if (qemuSetSCSIControllerModel(def, qemuCaps, &model) < 0)
+    if (qemuDomainSetSCSIControllerModel(def, qemuCaps, &model) < 0)
         goto error;
 
     if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC) {
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 5fb91e5..e523054 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -232,18 +232,6 @@ int qemuOpenVhostNet(virDomainDefPtr def,
 
 int qemuNetworkPrepareDevices(virDomainDefPtr def);
 
-int qemuDomainAssignAddresses(virDomainDefPtr def,
-                              virQEMUCapsPtr qemuCaps,
-                              virDomainObjPtr obj)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
-int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def,
-                                      virQEMUCapsPtr qemuCaps);
-
-void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
-                                    virDomainDeviceInfoPtr info,
-                                    const char *devstr);
-
-
 int qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps);
 int qemuDomainNetVLAN(virDomainNetDefPtr def);
 int qemuAssignDeviceNetAlias(virDomainDefPtr def, virDomainNetDefPtr net, int idx);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 686c9e4..0616574 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -56,6 +56,12 @@
 
 VIR_LOG_INIT("qemu.qemu_domain");
 
+#define VIO_ADDR_NET 0x1000ul
+#define VIO_ADDR_SCSI 0x2000ul
+#define VIO_ADDR_SERIAL 0x30000000ul
+#define VIO_ADDR_NVRAM 0x3000ul
+
+
 #define QEMU_NAMESPACE_HREF "http://libvirt.org/schemas/domain/qemu/1.0"
 
 VIR_ENUM_IMPL(qemuDomainJob, QEMU_JOB_LAST,
@@ -4395,3 +4401,1589 @@ qemuDomainSupportsNetdev(virDomainDefPtr def,
         return false;
     return virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV);
 }
+
+
+int
+qemuDomainSetSCSIControllerModel(virDomainDefPtr def,
+                                 virQEMUCapsPtr qemuCaps,
+                                 int *model)
+{
+    if (*model > 0) {
+        switch (*model) {
+        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC:
+            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_LSI)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("This QEMU doesn't support "
+                                 "the LSI 53C895A SCSI controller"));
+                return -1;
+            }
+            break;
+        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI:
+            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_SCSI)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("This QEMU doesn't support "
+                                 "virtio scsi controller"));
+                return -1;
+            }
+            break;
+        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI:
+            /*TODO: need checking work here if necessary */
+            break;
+        case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078:
+            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_MEGASAS)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("This QEMU doesn't support "
+                                 "the LSI SAS1078 controller"));
+                return -1;
+            }
+            break;
+        default:
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("Unsupported controller model: %s"),
+                           virDomainControllerModelSCSITypeToString(*model));
+            return -1;
+        }
+    } else {
+        if (ARCH_IS_PPC64(def->os.arch) &&
+            STRPREFIX(def->os.machine, "pseries")) {
+            *model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI;
+        } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_LSI)) {
+            *model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC;
+        } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_SCSI)) {
+            *model = VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI;
+        } else {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Unable to determine model for scsi controller"));
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+static int
+qemuDomainAssignVirtioSerialAddresses(virDomainDefPtr def,
+                                      virDomainObjPtr obj)
+{
+    int ret = -1;
+    size_t i;
+    virDomainVirtioSerialAddrSetPtr addrs = NULL;
+    qemuDomainObjPrivatePtr priv = NULL;
+
+    if (!(addrs = virDomainVirtioSerialAddrSetCreate()))
+        goto cleanup;
+
+    if (virDomainVirtioSerialAddrSetAddControllers(addrs, def) < 0)
+        goto cleanup;
+
+    if (virDomainDeviceInfoIterate(def, virDomainVirtioSerialAddrReserve,
+                                   addrs) < 0)
+        goto cleanup;
+
+    VIR_DEBUG("Finished reserving existing ports");
+
+    for (i = 0; i < def->nconsoles; i++) {
+        virDomainChrDefPtr chr = def->consoles[i];
+        if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
+            chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO &&
+            !virDomainVirtioSerialAddrIsComplete(&chr->info) &&
+            virDomainVirtioSerialAddrAutoAssign(def, addrs, &chr->info, true) < 0)
+            goto cleanup;
+    }
+
+    for (i = 0; i < def->nchannels; i++) {
+        virDomainChrDefPtr chr = def->channels[i];
+        if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
+            chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
+            !virDomainVirtioSerialAddrIsComplete(&chr->info) &&
+            virDomainVirtioSerialAddrAutoAssign(def, addrs, &chr->info, false) < 0)
+            goto cleanup;
+    }
+
+    if (obj && obj->privateData) {
+        priv = obj->privateData;
+        /* if this is the live domain object, we persist the addresses */
+        virDomainVirtioSerialAddrSetFree(priv->vioserialaddrs);
+        priv->persistentAddrs = 1;
+        priv->vioserialaddrs = addrs;
+        addrs = NULL;
+    }
+    ret = 0;
+
+ cleanup:
+    virDomainVirtioSerialAddrSetFree(addrs);
+    return ret;
+}
+
+
+static int
+qemuDomainSpaprVIOFindByReg(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                            virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
+                            virDomainDeviceInfoPtr info, void *opaque)
+{
+    virDomainDeviceInfoPtr target = opaque;
+
+    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO)
+        return 0;
+
+    /* Match a dev that has a reg, is not us, and has a matching reg */
+    if (info->addr.spaprvio.has_reg && info != target &&
+        info->addr.spaprvio.reg == target->addr.spaprvio.reg)
+        /* Has to be < 0 so virDomainDeviceInfoIterate() will exit */
+        return -1;
+
+    return 0;
+}
+
+
+static int
+qemuDomainAssignSpaprVIOAddress(virDomainDefPtr def,
+                                virDomainDeviceInfoPtr info,
+                                unsigned long long default_reg)
+{
+    bool user_reg;
+    int ret;
+
+    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO)
+        return 0;
+
+    /* Check if the user has assigned the reg already, if so use it */
+    user_reg = info->addr.spaprvio.has_reg;
+    if (!user_reg) {
+        info->addr.spaprvio.reg = default_reg;
+        info->addr.spaprvio.has_reg = true;
+    }
+
+    ret = virDomainDeviceInfoIterate(def, qemuDomainSpaprVIOFindByReg, info);
+    while (ret != 0) {
+        if (user_reg) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("spapr-vio address %#llx already in use"),
+                           info->addr.spaprvio.reg);
+            return -EEXIST;
+        }
+
+        /* We assigned the reg, so try a new value */
+        info->addr.spaprvio.reg += 0x1000;
+        ret = virDomainDeviceInfoIterate(def, qemuDomainSpaprVIOFindByReg,
+                                         info);
+    }
+
+    return 0;
+}
+
+
+static int
+qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def,
+                                  virQEMUCapsPtr qemuCaps)
+{
+    size_t i;
+    int ret = -1;
+    int model;
+
+    /* Default values match QEMU. See spapr_(llan|vscsi|vty).c */
+
+    for (i = 0; i < def->nnets; i++) {
+        if (def->nets[i]->model &&
+            STREQ(def->nets[i]->model, "spapr-vlan"))
+            def->nets[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
+        if (qemuDomainAssignSpaprVIOAddress(def, &def->nets[i]->info,
+                                            VIO_ADDR_NET) < 0)
+            goto cleanup;
+    }
+
+    for (i = 0; i < def->ncontrollers; i++) {
+        model = def->controllers[i]->model;
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
+            if (qemuDomainSetSCSIControllerModel(def, qemuCaps, &model) < 0)
+                goto cleanup;
+        }
+
+        if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI &&
+            def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
+            def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
+        if (qemuDomainAssignSpaprVIOAddress(def, &def->controllers[i]->info,
+                                            VIO_ADDR_SCSI) < 0)
+            goto cleanup;
+    }
+
+    for (i = 0; i < def->nserials; i++) {
+        if (def->serials[i]->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
+            ARCH_IS_PPC64(def->os.arch) &&
+            STRPREFIX(def->os.machine, "pseries"))
+            def->serials[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
+        if (qemuDomainAssignSpaprVIOAddress(def, &def->serials[i]->info,
+                                            VIO_ADDR_SERIAL) < 0)
+            goto cleanup;
+    }
+
+    if (def->nvram) {
+        if (ARCH_IS_PPC64(def->os.arch) &&
+            STRPREFIX(def->os.machine, "pseries"))
+            def->nvram->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
+        if (qemuDomainAssignSpaprVIOAddress(def, &def->nvram->info,
+                                            VIO_ADDR_NVRAM) < 0)
+            goto cleanup;
+    }
+
+    /* No other devices are currently supported on spapr-vio */
+
+    ret = 0;
+
+ cleanup:
+    return ret;
+}
+
+
+static void
+qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def,
+                                     virDomainDeviceAddressType type)
+{
+    /*
+       declare address-less virtio devices to be of address type 'type'
+       disks, networks, consoles, controllers, memballoon and rng in this
+       order
+       if type is ccw filesystem devices are declared to be of address type ccw
+    */
+    size_t i;
+
+    for (i = 0; i < def->ndisks; i++) {
+        if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_VIRTIO &&
+            def->disks[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            def->disks[i]->info.type = type;
+    }
+
+    for (i = 0; i < def->nnets; i++) {
+        if (STREQ(def->nets[i]->model, "virtio") &&
+            def->nets[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+            def->nets[i]->info.type = type;
+        }
+    }
+
+    for (i = 0; i < def->ninputs; i++) {
+        if (def->inputs[i]->bus == VIR_DOMAIN_DISK_BUS_VIRTIO &&
+            def->inputs[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            def->inputs[i]->info.type = type;
+    }
+
+    for (i = 0; i < def->ncontrollers; i++) {
+        if ((def->controllers[i]->type ==
+             VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL ||
+             def->controllers[i]->type ==
+             VIR_DOMAIN_CONTROLLER_TYPE_SCSI) &&
+            def->controllers[i]->info.type ==
+            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            def->controllers[i]->info.type = type;
+    }
+
+    if (def->memballoon &&
+        def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
+        def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+        def->memballoon->info.type = type;
+
+    for (i = 0; i < def->nrngs; i++) {
+        if (def->rngs[i]->model == VIR_DOMAIN_RNG_MODEL_VIRTIO &&
+            def->rngs[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            def->rngs[i]->info.type = type;
+    }
+
+    if (type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
+        for (i = 0; i < def->nfss; i++) {
+            if (def->fss[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+                def->fss[i]->info.type = type;
+        }
+    }
+}
+
+
+/*
+ * Three steps populating CCW devnos
+ * 1. Allocate empty address set
+ * 2. Gather addresses with explicit devno
+ * 3. Assign defaults to the rest
+ */
+static int
+qemuDomainAssignS390Addresses(virDomainDefPtr def,
+                              virQEMUCapsPtr qemuCaps,
+                              virDomainObjPtr obj)
+{
+    int ret = -1;
+    virDomainCCWAddressSetPtr addrs = NULL;
+    qemuDomainObjPrivatePtr priv = NULL;
+
+    if (qemuDomainMachineIsS390CCW(def) &&
+        virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_CCW)) {
+        qemuDomainPrimeVirtioDeviceAddresses(
+            def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW);
+
+        if (!(addrs = virDomainCCWAddressSetCreate()))
+            goto cleanup;
+
+        if (virDomainDeviceInfoIterate(def, virDomainCCWAddressValidate,
+                                       addrs) < 0)
+            goto cleanup;
+
+        if (virDomainDeviceInfoIterate(def, virDomainCCWAddressAllocate,
+                                       addrs) < 0)
+            goto cleanup;
+    } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_S390)) {
+        /* deal with legacy virtio-s390 */
+        qemuDomainPrimeVirtioDeviceAddresses(
+            def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390);
+    }
+
+    if (obj && obj->privateData) {
+        priv = obj->privateData;
+        if (addrs) {
+            /* if this is the live domain object, we persist the CCW addresses*/
+            virDomainCCWAddressSetFree(priv->ccwaddrs);
+            priv->persistentAddrs = 1;
+            priv->ccwaddrs = addrs;
+            addrs = NULL;
+        } else {
+            priv->persistentAddrs = 0;
+        }
+    }
+    ret = 0;
+
+ cleanup:
+    virDomainCCWAddressSetFree(addrs);
+
+    return ret;
+}
+
+
+static int
+qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def,
+                                       virQEMUCapsPtr qemuCaps)
+{
+    if (((def->os.arch == VIR_ARCH_ARMV7L) ||
+        (def->os.arch == VIR_ARCH_AARCH64)) &&
+        (STRPREFIX(def->os.machine, "vexpress-") ||
+            STREQ(def->os.machine, "virt") ||
+            STRPREFIX(def->os.machine, "virt-")) &&
+        virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO)) {
+        qemuDomainPrimeVirtioDeviceAddresses(
+            def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO);
+    }
+    return 0;
+}
+
+
+static int
+qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                            virDomainDeviceDefPtr device,
+                            virDomainDeviceInfoPtr info,
+                            void *opaque)
+{
+    virDomainPCIAddressSetPtr addrs = opaque;
+    int ret = -1;
+    virDevicePCIAddressPtr addr = &info->addr.pci;
+    bool entireSlot;
+    /* flags may be changed from default below */
+    virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
+                                      VIR_PCI_CONNECT_TYPE_PCI);
+
+    if ((info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
+        || ((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) &&
+            (device->data.hostdev->parent.type != VIR_DOMAIN_DEVICE_NONE))) {
+        /* If a hostdev has a parent, its info will be a part of the
+         * parent, and will have its address collected during the scan
+         * of the parent's device type.
+        */
+        return 0;
+    }
+
+    /* Change flags according to differing requirements of different
+     * devices.
+     */
+    switch (device->type) {
+    case VIR_DOMAIN_DEVICE_CONTROLLER:
+        switch (device->data.controller->type) {
+        case  VIR_DOMAIN_CONTROLLER_TYPE_PCI:
+            switch (device->data.controller->model) {
+            case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
+                /* pci-bridge needs a PCI slot, but it isn't
+                 * hot-pluggable, so it doesn't need a hot-pluggable slot.
+                 */
+                flags = VIR_PCI_CONNECT_TYPE_PCI;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+                /* pci-bridge needs a PCIe slot, but it isn't
+                 * hot-pluggable, so it doesn't need a hot-pluggable slot.
+                 */
+                flags = VIR_PCI_CONNECT_TYPE_PCIE;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
+                /* pcie-root-port can only connect to pcie-root, isn't
+                 * hot-pluggable
+                 */
+                flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
+                /* pcie-switch can only connect to a true
+                 * pcie bus, and can't be hot-plugged.
+                 */
+                flags = VIR_PCI_CONNECT_TYPE_PCIE_PORT;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
+                /* pcie-switch-downstream-port can only connect to a
+                 * pcie-switch-upstream-port, and can't be hot-plugged.
+                 */
+                flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH;
+                break;
+            default:
+                break;
+            }
+            break;
+
+        case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
+            /* SATA controllers aren't hot-plugged, and can be put in
+             * either a PCI or PCIe slot
+             */
+            flags = VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE;
+            break;
+
+        case VIR_DOMAIN_CONTROLLER_TYPE_USB:
+           /* allow UHCI and EHCI controllers to be manually placed on
+            * the PCIe bus (but don't put them there automatically)
+            */
+           switch (device->data.controller->model) {
+           case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI:
+           case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
+           case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
+           case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
+           case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
+           case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI:
+              flags = VIR_PCI_CONNECT_TYPE_PCI;
+              break;
+           case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI:
+              /* should this be PCIE-only? Or do we need to allow PCI
+               * for backward compatibility?
+               */
+              flags = VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE;
+              break;
+           case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI:
+           case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI:
+           case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI:
+              /* Allow these for PCI only */
+              break;
+           }
+        }
+        break;
+
+    case VIR_DOMAIN_DEVICE_SOUND:
+        switch (device->data.sound->model) {
+        case VIR_DOMAIN_SOUND_MODEL_ICH6:
+        case VIR_DOMAIN_SOUND_MODEL_ICH9:
+            flags = VIR_PCI_CONNECT_TYPE_PCI;
+            break;
+        }
+        break;
+
+    case VIR_DOMAIN_DEVICE_VIDEO:
+        /* video cards aren't hot-plugged, and can be put in either a
+         * PCI or PCIe slot
+         */
+        flags = VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE;
+        break;
+    }
+
+    /* Ignore implicit controllers on slot 0:0:1.0:
+     * implicit IDE controller on 0:0:1.1 (no qemu command line)
+     * implicit USB controller on 0:0:1.2 (-usb)
+     *
+     * If the machine does have a PCI bus, they will get reserved
+     * in qemuDomainAssignDevicePCISlots().
+     */
+
+    /* These are the IDE and USB controllers in the PIIX3, hardcoded
+     * to bus 0 slot 1.  They cannot be attached to a PCIe slot, only
+     * PCI.
+     */
+    if (device->type == VIR_DOMAIN_DEVICE_CONTROLLER && addr->domain == 0 &&
+        addr->bus == 0 && addr->slot == 1) {
+        virDomainControllerDefPtr cont = device->data.controller;
+
+        if ((cont->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE && cont->idx == 0 &&
+             addr->function == 1) ||
+            (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB && cont->idx == 0 &&
+             (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI ||
+              cont->model == -1) && addr->function == 2)) {
+            /* Note the check for nbuses > 0 - if there are no PCI
+             * buses, we skip this check. This is a quirk required for
+             * some machinetypes such as s390, which pretend to have a
+             * PCI bus for long enough to generate the "-usb" on the
+             * commandline, but that don't really care if a PCI bus
+             * actually exists. */
+            if (addrs->nbuses > 0 &&
+                !(addrs->buses[0].flags & VIR_PCI_CONNECT_TYPE_PCI)) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Bus 0 must be PCI for integrated PIIX3 "
+                                 "USB or IDE controllers"));
+                return -1;
+            } else {
+                return 0;
+            }
+        }
+    }
+
+    entireSlot = (addr->function == 0 &&
+                  addr->multi != VIR_TRISTATE_SWITCH_ON);
+
+    if (virDomainPCIAddressReserveAddr(addrs, addr, flags,
+                                       entireSlot, true) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    return ret;
+}
+
+static virDomainPCIAddressSetPtr
+qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
+                              unsigned int nbuses,
+                              bool dryRun)
+{
+    virDomainPCIAddressSetPtr addrs;
+    size_t i;
+
+    if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
+        return NULL;
+
+    addrs->nbuses = nbuses;
+    addrs->dryRun = dryRun;
+
+    /* 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)
+        virDomainPCIAddressBusSetModel(&addrs->buses[0],
+                                       VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT);
+    for (i = 1; i < nbuses; i++) {
+        virDomainPCIAddressBusSetModel(&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 (virDomainPCIAddressBusSetModel(&addrs->buses[idx],
+                                           def->controllers[i]->model) < 0)
+            goto error;
+        }
+
+    if (virDomainDeviceInfoIterate(def, qemuDomainCollectPCIAddress, addrs) < 0)
+        goto error;
+
+    return addrs;
+
+ error:
+    virDomainPCIAddressSetFree(addrs);
+    return NULL;
+}
+
+
+static int
+qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
+                                      virQEMUCapsPtr qemuCaps,
+                                      virDomainPCIAddressSetPtr addrs)
+{
+    int ret = -1;
+    size_t i;
+    virDevicePCIAddress tmp_addr;
+    bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
+    char *addrStr = NULL;
+    virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_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++) {
+        /* First IDE controller lives on the PIIX3 at slot=1, function=1 */
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE &&
+            def->controllers[i]->idx == 0) {
+            if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+                if (def->controllers[i]->info.addr.pci.domain != 0 ||
+                    def->controllers[i]->info.addr.pci.bus != 0 ||
+                    def->controllers[i]->info.addr.pci.slot != 1 ||
+                    def->controllers[i]->info.addr.pci.function != 1) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                   _("Primary IDE controller must have PCI address 0:0:1.1"));
+                    goto cleanup;
+                }
+            } else {
+                def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+                def->controllers[i]->info.addr.pci.domain = 0;
+                def->controllers[i]->info.addr.pci.bus = 0;
+                def->controllers[i]->info.addr.pci.slot = 1;
+                def->controllers[i]->info.addr.pci.function = 1;
+            }
+        } else if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
+                   def->controllers[i]->idx == 0 &&
+                   (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI ||
+                    def->controllers[i]->model == -1)) {
+            if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+                if (def->controllers[i]->info.addr.pci.domain != 0 ||
+                    def->controllers[i]->info.addr.pci.bus != 0 ||
+                    def->controllers[i]->info.addr.pci.slot != 1 ||
+                    def->controllers[i]->info.addr.pci.function != 2) {
+                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                   _("PIIX3 USB controller must have PCI address 0:0:1.2"));
+                    goto cleanup;
+                }
+            } else {
+                def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+                def->controllers[i]->info.addr.pci.domain = 0;
+                def->controllers[i]->info.addr.pci.bus = 0;
+                def->controllers[i]->info.addr.pci.slot = 1;
+                def->controllers[i]->info.addr.pci.function = 2;
+            }
+        }
+    }
+
+    /* PIIX3 (ISA bridge, IDE controller, something else unknown, USB controller)
+     * hardcoded slot=1, multifunction device
+     */
+    if (addrs->nbuses) {
+        memset(&tmp_addr, 0, sizeof(tmp_addr));
+        tmp_addr.slot = 1;
+        if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
+            goto cleanup;
+    }
+
+    if (def->nvideos > 0) {
+        /* Because the PIIX3 integrated IDE/USB controllers are
+         * already at slot 1, when qemu looks for the first free slot
+         * to place the VGA controller (which is always the first
+         * device added after integrated devices), it *always* ends up
+         * at slot 2.
+         */
+        virDomainVideoDefPtr primaryVideo = def->videos[0];
+        if (primaryVideo->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+            memset(&tmp_addr, 0, sizeof(tmp_addr));
+            tmp_addr.slot = 2;
+
+            if (!(addrStr = virDomainPCIAddressAsString(&tmp_addr)))
+                goto cleanup;
+            if (!virDomainPCIAddressValidate(addrs, &tmp_addr,
+                                             addrStr, flags, false))
+                goto cleanup;
+
+            if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
+                if (qemuDeviceVideoUsable) {
+                    if (virDomainPCIAddressReserveNextSlot(addrs,
+                                                           &primaryVideo->info,
+                                                           flags) < 0)
+                        goto cleanup;
+                } else {
+                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                   _("PCI address 0:0:2.0 is in use, "
+                                     "QEMU needs it for primary video"));
+                    goto cleanup;
+                }
+            } else {
+                if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
+                    goto cleanup;
+                primaryVideo->info.addr.pci = tmp_addr;
+                primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+            }
+        } else if (!qemuDeviceVideoUsable) {
+            if (primaryVideo->info.addr.pci.domain != 0 ||
+                primaryVideo->info.addr.pci.bus != 0 ||
+                primaryVideo->info.addr.pci.slot != 2 ||
+                primaryVideo->info.addr.pci.function != 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Primary video card must have PCI address 0:0:2.0"));
+                goto cleanup;
+            }
+            /* If TYPE == PCI, then qemuDomainCollectPCIAddress() function
+             * has already reserved the address, so we must skip */
+        }
+    } else if (addrs->nbuses && !qemuDeviceVideoUsable) {
+        memset(&tmp_addr, 0, sizeof(tmp_addr));
+        tmp_addr.slot = 2;
+
+        if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
+            VIR_DEBUG("PCI address 0:0:2.0 in use, future addition of a video"
+                      " device will not be possible without manual"
+                      " intervention");
+        } else if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
+            goto cleanup;
+        }
+    }
+    ret = 0;
+ cleanup:
+    VIR_FREE(addrStr);
+    return ret;
+}
+
+
+static int
+qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
+                                    virQEMUCapsPtr qemuCaps,
+                                    virDomainPCIAddressSetPtr addrs)
+{
+    int ret = -1;
+    size_t i;
+    virDevicePCIAddress tmp_addr;
+    bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
+    char *addrStr = NULL;
+    virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCIE;
+
+    for (i = 0; i < def->ncontrollers; i++) {
+        switch (def->controllers[i]->type) {
+        case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
+            /* Verify that the first SATA controller is at 00:1F.2 the
+             * q35 machine type *always* has a SATA controller at this
+             * address.
+             */
+            if (def->controllers[i]->idx == 0) {
+                if (def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+                    if (def->controllers[i]->info.addr.pci.domain != 0 ||
+                        def->controllers[i]->info.addr.pci.bus != 0 ||
+                        def->controllers[i]->info.addr.pci.slot != 0x1F ||
+                        def->controllers[i]->info.addr.pci.function != 2) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                       _("Primary SATA controller must have PCI address 0:0:1f.2"));
+                        goto cleanup;
+                    }
+                } else {
+                    def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+                    def->controllers[i]->info.addr.pci.domain = 0;
+                    def->controllers[i]->info.addr.pci.bus = 0;
+                    def->controllers[i]->info.addr.pci.slot = 0x1F;
+                    def->controllers[i]->info.addr.pci.function = 2;
+                }
+            }
+            break;
+
+        case VIR_DOMAIN_CONTROLLER_TYPE_USB:
+            if ((def->controllers[i]->model
+                 == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1) &&
+                (def->controllers[i]->info.type
+                 == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)) {
+                /* Try to assign the first found USB2 controller to
+                 * 00:1D.0 and 2nd to 00:1A.0 (because that is their
+                 * standard location on real Q35 hardware) unless they
+                 * are already taken, but don't insist on it.
+                 *
+                 * (NB: all other controllers at the same index will
+                 * get assigned to the same slot as the UHCI1 when
+                 * addresses are later assigned to all devices.)
+                 */
+                bool assign = false;
+
+                memset(&tmp_addr, 0, sizeof(tmp_addr));
+                tmp_addr.slot = 0x1D;
+                if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
+                    assign = true;
+                } else {
+                    tmp_addr.slot = 0x1A;
+                    if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr))
+                        assign = true;
+                }
+                if (assign) {
+                    if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr,
+                                                       flags, false, true) < 0)
+                        goto cleanup;
+                    def->controllers[i]->info.type
+                        = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+                    def->controllers[i]->info.addr.pci.domain = 0;
+                    def->controllers[i]->info.addr.pci.bus = 0;
+                    def->controllers[i]->info.addr.pci.slot = tmp_addr.slot;
+                    def->controllers[i]->info.addr.pci.function = 0;
+                    def->controllers[i]->info.addr.pci.multi
+                       = VIR_TRISTATE_SWITCH_ON;
+                }
+            }
+            break;
+
+        case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
+            if (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE &&
+                def->controllers[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+                /* Try to assign this bridge to 00:1E.0 (because that
+                * is its standard location on real hardware) unless
+                * it's already taken, but don't insist on it.
+                */
+                memset(&tmp_addr, 0, sizeof(tmp_addr));
+                tmp_addr.slot = 0x1E;
+                if (!virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
+                    if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr,
+                                                       flags, true, false) < 0)
+                        goto cleanup;
+                    def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+                    def->controllers[i]->info.addr.pci.domain = 0;
+                    def->controllers[i]->info.addr.pci.bus = 0;
+                    def->controllers[i]->info.addr.pci.slot = 0x1E;
+                    def->controllers[i]->info.addr.pci.function = 0;
+                }
+            }
+            break;
+        }
+    }
+
+    /* Reserve slot 0x1F function 0 (ISA bridge, not in config model)
+     * and function 3 (SMBus, also not (yet) in config model). As with
+     * the SATA controller, these devices are always present in a q35
+     * machine; there is no way to not have them.
+     */
+    if (addrs->nbuses) {
+        memset(&tmp_addr, 0, sizeof(tmp_addr));
+        tmp_addr.slot = 0x1F;
+        tmp_addr.function = 0;
+        tmp_addr.multi = VIR_TRISTATE_SWITCH_ON;
+        if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
+                                           false, false) < 0)
+           goto cleanup;
+        tmp_addr.function = 3;
+        tmp_addr.multi = VIR_TRISTATE_SWITCH_ABSENT;
+        if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
+                                           false, false) < 0)
+           goto cleanup;
+    }
+
+    if (def->nvideos > 0) {
+        /* NB: unlike the pc machinetypes, on q35 machinetypes the
+         * integrated devices are at slot 0x1f, so when qemu looks for
+         * the first free lot for the first VGA, it will always be at
+         * slot 1 (which was used up by the integrated PIIX3 devices
+         * on pc machinetypes).
+         */
+        virDomainVideoDefPtr primaryVideo = def->videos[0];
+        if (primaryVideo->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+            memset(&tmp_addr, 0, sizeof(tmp_addr));
+            tmp_addr.slot = 1;
+
+            if (!(addrStr = virDomainPCIAddressAsString(&tmp_addr)))
+                goto cleanup;
+            if (!virDomainPCIAddressValidate(addrs, &tmp_addr,
+                                             addrStr, flags, false))
+                goto cleanup;
+
+            if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
+                if (qemuDeviceVideoUsable) {
+                    if (virDomainPCIAddressReserveNextSlot(addrs,
+                                                           &primaryVideo->info,
+                                                           flags) < 0)
+                        goto cleanup;
+                } else {
+                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                   _("PCI address 0:0:1.0 is in use, "
+                                     "QEMU needs it for primary video"));
+                    goto cleanup;
+                }
+            } else {
+                if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
+                    goto cleanup;
+                primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+                primaryVideo->info.addr.pci = tmp_addr;
+            }
+        } else if (!qemuDeviceVideoUsable) {
+            if (primaryVideo->info.addr.pci.domain != 0 ||
+                primaryVideo->info.addr.pci.bus != 0 ||
+                primaryVideo->info.addr.pci.slot != 1 ||
+                primaryVideo->info.addr.pci.function != 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Primary video card must have PCI address 0:0:1.0"));
+                goto cleanup;
+            }
+            /* If TYPE == PCI, then qemuDomainCollectPCIAddress() function
+             * has already reserved the address, so we must skip */
+        }
+    } else if (addrs->nbuses && !qemuDeviceVideoUsable) {
+        memset(&tmp_addr, 0, sizeof(tmp_addr));
+        tmp_addr.slot = 1;
+
+        if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
+            VIR_DEBUG("PCI address 0:0:1.0 in use, future addition of a video"
+                      " device will not be possible without manual"
+                      " intervention");
+            virResetLastError();
+        } else if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
+            goto cleanup;
+        }
+    }
+    ret = 0;
+ cleanup:
+    VIR_FREE(addrStr);
+    return ret;
+}
+
+
+static int
+qemuDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def,
+                                         virQEMUCapsPtr qemuCaps,
+                                         virDomainPCIAddressSetPtr addrs)
+{
+    if (qemuDomainMachineIsI440FX(def) &&
+        qemuDomainValidateDevicePCISlotsPIIX3(def, qemuCaps, addrs) < 0) {
+        return -1;
+    }
+
+    if (qemuDomainMachineIsQ35(def) &&
+        qemuDomainValidateDevicePCISlotsQ35(def, qemuCaps, addrs) < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static bool
+qemuDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus)
+{
+    size_t i;
+
+    for (i = bus->minSlot; i <= bus->maxSlot; i++)
+        if (!bus->slots[i])
+            return false;
+
+    return true;
+}
+
+
+#define IS_USB2_CONTROLLER(ctrl) \
+    (((ctrl)->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) && \
+     ((ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1 || \
+      (ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1 || \
+      (ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2 || \
+      (ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3))
+
+/*
+ * This assigns static PCI slots to all configured devices.
+ * The ordering here is chosen to match the ordering used
+ * with old QEMU < 0.12, so that if a user updates a QEMU
+ * host from old QEMU to QEMU >= 0.12, their guests should
+ * get PCI addresses in the same order as before.
+ *
+ * NB, if they previously hotplugged devices then all bets
+ * are off. Hotplug for old QEMU was unfixably broken wrt
+ * to stable PCI addressing.
+ *
+ * Order is:
+ *
+ *  - Host bridge (slot 0)
+ *  - PIIX3 ISA bridge, IDE controller, something else unknown, USB controller (slot 1)
+ *  - Video (slot 2)
+ *
+ *  - These integrated devices were already added by
+ *    qemuValidateDevicePCISlotsChipsets invoked right before this function
+ *
+ * Incrementally assign slots from 3 onwards:
+ *
+ *  - Net
+ *  - Sound
+ *  - SCSI controllers
+ *  - VirtIO block
+ *  - VirtIO balloon
+ *  - Host device passthrough
+ *  - Watchdog
+ *  - pci serial devices
+ *
+ * Prior to this function being invoked, qemuDomainCollectPCIAddress() will have
+ * added all existing PCI addresses from the 'def' to 'addrs'. Thus this
+ * function must only try to reserve addresses if info.type == NONE and
+ * skip over info.type == PCI
+ */
+static int
+qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
+                               virQEMUCapsPtr qemuCaps,
+                               virDomainPCIAddressSetPtr addrs)
+{
+    size_t i, j;
+    virDomainPCIConnectFlags flags;
+    virDevicePCIAddress tmp_addr;
+
+    /* PCI controllers */
+    for (i = 0; i < def->ncontrollers; i++) {
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
+            if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+                continue;
+            switch (def->controllers[i]->model) {
+            case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
+            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
+                /* pci-root and pcie-root are implicit in the machine,
+                 * and needs no address */
+                continue;
+            case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
+                /* pci-bridge doesn't require hot-plug
+                 * (although it does provide hot-plug in its slots)
+                 */
+                flags = VIR_PCI_CONNECT_TYPE_PCI;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+                /* dmi-to-pci-bridge requires a non-hotplug PCIe
+                 * slot
+                 */
+                flags = VIR_PCI_CONNECT_TYPE_PCIE;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
+                /* pcie-root-port can only plug into pcie-root */
+                flags = VIR_PCI_CONNECT_TYPE_PCIE_ROOT;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
+                /* pcie-switch really does need a real PCIe
+                 * port, but it doesn't need to be pcie-root
+                 */
+                flags = VIR_PCI_CONNECT_TYPE_PCIE_PORT;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
+                /* pcie-switch-port can only plug into pcie-switch */
+                flags = VIR_PCI_CONNECT_TYPE_PCIE_SWITCH;
+                break;
+            default:
+                flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI;
+                break;
+            }
+            if (virDomainPCIAddressReserveNextSlot(addrs,
+                                                   &def->controllers[i]->info,
+                                                   flags) < 0)
+                goto error;
+        }
+    }
+
+    flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI;
+
+    for (i = 0; i < def->nfss; i++) {
+        if (def->fss[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            continue;
+
+        /* Only support VirtIO-9p-pci so far. If that changes,
+         * we might need to skip devices here */
+        if (virDomainPCIAddressReserveNextSlot(addrs, &def->fss[i]->info,
+                                               flags) < 0)
+            goto error;
+    }
+
+    /* Network interfaces */
+    for (i = 0; i < def->nnets; i++) {
+        /* type='hostdev' network devices might be USB, and are also
+         * in hostdevs list anyway, so handle them with other hostdevs
+         * instead of here.
+         */
+        if ((def->nets[i]->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+            (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)) {
+            continue;
+        }
+        if (virDomainPCIAddressReserveNextSlot(addrs, &def->nets[i]->info,
+                                               flags) < 0)
+            goto error;
+    }
+
+    /* Sound cards */
+    for (i = 0; i < def->nsounds; i++) {
+        if (def->sounds[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            continue;
+        /* Skip ISA sound card, PCSPK and usb-audio */
+        if (def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_SB16 ||
+            def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_PCSPK ||
+            def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_USB)
+            continue;
+
+        if (virDomainPCIAddressReserveNextSlot(addrs, &def->sounds[i]->info,
+                                               flags) < 0)
+            goto error;
+    }
+
+    /* Device controllers (SCSI, USB, but not IDE, FDC or CCID) */
+    for (i = 0; i < def->ncontrollers; i++) {
+        /* PCI controllers have been dealt with earlier */
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI)
+            continue;
+
+        /* USB controller model 'none' doesn't need a PCI address */
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
+            def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE)
+            continue;
+
+        /* FDC lives behind the ISA bridge; CCID is a usb device */
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC ||
+            def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_CCID)
+            continue;
+
+        /* First IDE controller lives on the PIIX3 at slot=1, function=1,
+           dealt with earlier on*/
+        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE &&
+            def->controllers[i]->idx == 0)
+            continue;
+
+        if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            continue;
+
+        /* USB2 needs special handling to put all companions in the same slot */
+        if (IS_USB2_CONTROLLER(def->controllers[i])) {
+            virDevicePCIAddress addr = { 0, 0, 0, 0, false };
+            bool foundAddr = false;
+
+            memset(&tmp_addr, 0, sizeof(tmp_addr));
+            for (j = 0; j < def->ncontrollers; j++) {
+                if (IS_USB2_CONTROLLER(def->controllers[j]) &&
+                    def->controllers[j]->idx == def->controllers[i]->idx &&
+                    def->controllers[j]->info.type
+                    == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+                    addr = def->controllers[j]->info.addr.pci;
+                    foundAddr = true;
+                    break;
+                }
+            }
+
+            switch (def->controllers[i]->model) {
+            case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
+                addr.function = 7;
+                addr.multi = VIR_TRISTATE_SWITCH_ABSENT;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
+                addr.function = 0;
+                addr.multi = VIR_TRISTATE_SWITCH_ON;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
+                addr.function = 1;
+                addr.multi = VIR_TRISTATE_SWITCH_ABSENT;
+                break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
+                addr.function = 2;
+                addr.multi = VIR_TRISTATE_SWITCH_ABSENT;
+                break;
+            }
+
+            if (!foundAddr) {
+                /* This is the first part of the controller, so need
+                 * to find a free slot & then reserve a function */
+                if (virDomainPCIAddressGetNextSlot(addrs, &tmp_addr, flags) < 0)
+                    goto error;
+
+                addr.bus = tmp_addr.bus;
+                addr.slot = tmp_addr.slot;
+
+                addrs->lastaddr = addr;
+                addrs->lastaddr.function = 0;
+                addrs->lastaddr.multi = VIR_TRISTATE_SWITCH_ABSENT;
+            }
+            /* Finally we can reserve the slot+function */
+            if (virDomainPCIAddressReserveAddr(addrs, &addr, flags,
+                                               false, foundAddr) < 0)
+                goto error;
+
+            def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+            def->controllers[i]->info.addr.pci = addr;
+        } else {
+            if (virDomainPCIAddressReserveNextSlot(addrs,
+                                                   &def->controllers[i]->info,
+                                                   flags) < 0)
+                goto error;
+        }
+    }
+
+    /* Disks (VirtIO only for now) */
+    for (i = 0; i < def->ndisks; i++) {
+        /* Only VirtIO disks use PCI addrs */
+        if (def->disks[i]->bus != VIR_DOMAIN_DISK_BUS_VIRTIO)
+            continue;
+
+        /* don't touch s390 devices */
+        if (def->disks[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
+            def->disks[i]->info.type ==
+            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 ||
+            def->disks[i]->info.type ==
+            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)
+            continue;
+
+        /* Also ignore virtio-mmio disks if our machine allows them */
+        if (def->disks[i]->info.type ==
+            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO &&
+            virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO))
+            continue;
+
+        if (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("virtio disk cannot have an address of type '%s'"),
+                           virDomainDeviceAddressTypeToString(def->disks[i]->info.type));
+            goto error;
+        }
+
+        if (virDomainPCIAddressReserveNextSlot(addrs, &def->disks[i]->info,
+                                               flags) < 0)
+            goto error;
+    }
+
+    /* Host PCI devices */
+    for (i = 0; i < def->nhostdevs; i++) {
+        if (def->hostdevs[i]->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            continue;
+        if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
+            def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+            continue;
+
+        if (virDomainPCIAddressReserveNextSlot(addrs,
+                                               def->hostdevs[i]->info,
+                                               flags) < 0)
+            goto error;
+    }
+
+    /* VirtIO balloon */
+    if (def->memballoon &&
+        def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
+        def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+        if (virDomainPCIAddressReserveNextSlot(addrs,
+                                               &def->memballoon->info,
+                                               flags) < 0)
+            goto error;
+    }
+
+    /* VirtIO RNG */
+    for (i = 0; i < def->nrngs; i++) {
+        if (def->rngs[i]->model != VIR_DOMAIN_RNG_MODEL_VIRTIO ||
+            def->rngs[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            continue;
+
+        if (virDomainPCIAddressReserveNextSlot(addrs,
+                                               &def->rngs[i]->info, flags) < 0)
+            goto error;
+    }
+
+    /* A watchdog - check if it is a PCI device */
+    if (def->watchdog &&
+        def->watchdog->model == VIR_DOMAIN_WATCHDOG_MODEL_I6300ESB &&
+        def->watchdog->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+        if (virDomainPCIAddressReserveNextSlot(addrs, &def->watchdog->info,
+                                               flags) < 0)
+            goto error;
+    }
+
+    /* Assign a PCI slot to the primary video card if there is not an
+     * assigned address. */
+    if (def->nvideos > 0 &&
+        def->videos[0]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+        if (virDomainPCIAddressReserveNextSlot(addrs, &def->videos[0]->info,
+                                               flags) < 0)
+            goto error;
+    }
+
+    /* Further non-primary video cards which have to be qxl type */
+    for (i = 1; i < def->nvideos; i++) {
+        if (def->videos[i]->type != VIR_DOMAIN_VIDEO_TYPE_QXL) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("non-primary video device must be type of 'qxl'"));
+            goto error;
+        }
+        if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            continue;
+        if (virDomainPCIAddressReserveNextSlot(addrs, &def->videos[i]->info,
+                                               flags) < 0)
+            goto error;
+    }
+
+    /* Shared Memory */
+    for (i = 0; i < def->nshmems; i++) {
+        if (def->shmems[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            continue;
+
+        if (virDomainPCIAddressReserveNextSlot(addrs,
+                                               &def->shmems[i]->info, flags) < 0)
+            goto error;
+    }
+    for (i = 0; i < def->ninputs; i++) {
+        if (def->inputs[i]->bus != VIR_DOMAIN_INPUT_BUS_VIRTIO)
+            continue;
+        if (def->inputs[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            continue;
+
+        if (virDomainPCIAddressReserveNextSlot(addrs,
+                                               &def->inputs[i]->info, flags) < 0)
+            goto error;
+    }
+    for (i = 0; i < def->nparallels; i++) {
+        /* Nada - none are PCI based (yet) */
+    }
+    for (i = 0; i < def->nserials; i++) {
+        virDomainChrDefPtr chr = def->serials[i];
+
+        if (chr->targetType != VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI)
+            continue;
+
+        if (chr->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+            continue;
+
+        if (virDomainPCIAddressReserveNextSlot(addrs, &chr->info, flags) < 0)
+            goto error;
+    }
+    for (i = 0; i < def->nchannels; i++) {
+        /* Nada - none are PCI based (yet) */
+    }
+    for (i = 0; i < def->nhubs; i++) {
+        /* Nada - none are PCI based (yet) */
+    }
+
+    return 0;
+
+ error:
+    return -1;
+}
+
+
+static bool
+qemuDomainSupportsPCI(virDomainDefPtr def,
+                      virQEMUCapsPtr qemuCaps)
+{
+    if ((def->os.arch != VIR_ARCH_ARMV7L) && (def->os.arch != VIR_ARCH_AARCH64))
+        return true;
+
+    if (STREQ(def->os.machine, "versatilepb"))
+        return true;
+
+    if ((STREQ(def->os.machine, "virt") ||
+         STRPREFIX(def->os.machine, "virt-")) &&
+        virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_GPEX))
+        return true;
+
+    return false;
+}
+
+
+static int
+qemuDomainAssignPCIAddresses(virDomainDefPtr def,
+                             virQEMUCapsPtr qemuCaps,
+                             virDomainObjPtr obj)
+{
+    int ret = -1;
+    virDomainPCIAddressSetPtr addrs = NULL;
+    qemuDomainObjPrivatePtr priv = NULL;
+
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
+        int max_idx = -1;
+        int nbuses = 0;
+        size_t i;
+        int rv;
+        bool buses_reserved = true;
+
+        virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCI;
+
+        for (i = 0; i < def->ncontrollers; i++) {
+            if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
+                if ((int) def->controllers[i]->idx > max_idx)
+                    max_idx = def->controllers[i]->idx;
+            }
+        }
+
+        nbuses = max_idx + 1;
+
+        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 (qemuDomainValidateDevicePCISlotsChipsets(def, qemuCaps,
+                                                         addrs) < 0)
+                goto cleanup;
+
+            for (i = 0; i < addrs->nbuses; i++) {
+                if (!qemuDomainPCIBusFullyReserved(&addrs->buses[i]))
+                    buses_reserved = false;
+            }
+
+            /* Reserve 1 extra slot for a (potential) bridge only if buses
+             * are not fully reserved yet
+             */
+            if (!buses_reserved &&
+                virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0)
+                goto cleanup;
+
+            if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
+                goto cleanup;
+
+            for (i = 1; i < addrs->nbuses; i++) {
+                virDomainPCIAddressBusPtr bus = &addrs->buses[i];
+
+                if ((rv = virDomainDefMaybeAddController(
+                         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 &&
+                    virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0)
+                    goto cleanup;
+            }
+            nbuses = addrs->nbuses;
+            virDomainPCIAddressSetFree(addrs);
+            addrs = NULL;
+
+        } else if (max_idx > 0) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("PCI bridges are not supported "
+                             "by this QEMU binary"));
+            goto cleanup;
+        }
+
+        if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, false)))
+            goto cleanup;
+
+        if (qemuDomainSupportsPCI(def, qemuCaps)) {
+            if (qemuDomainValidateDevicePCISlotsChipsets(def, qemuCaps,
+                                                         addrs) < 0)
+                goto cleanup;
+
+            if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
+                goto cleanup;
+
+            for (i = 0; i < def->ncontrollers; i++) {
+                virDomainControllerDefPtr cont = def->controllers[i];
+                int idx = cont->idx;
+                virDevicePCIAddressPtr addr;
+                virDomainPCIControllerOptsPtr options;
+
+                if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI)
+                    continue;
+
+                addr = &cont->info.addr.pci;
+                options = &cont->opts.pciopts;
+
+                /* set defaults for any other auto-generated config
+                 * options for this controller that haven't been
+                 * specified in config.
+                 */
+                switch ((virDomainControllerModelPCI)cont->model) {
+                case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
+                    if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
+                        options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE;
+                    if (options->chassisNr == -1)
+                        options->chassisNr = cont->idx;
+                    break;
+                case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+                    if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
+                        options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE;
+                    break;
+                case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
+                    if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
+                        options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420;
+                    if (options->chassis == -1)
+                       options->chassis = cont->idx;
+                    if (options->port == -1)
+                       options->port = (addr->slot << 3) + addr->function;
+                    break;
+                case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
+                    if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
+                        options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM;
+                    break;
+                case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
+                    if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
+                        options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM;
+                    if (options->chassis == -1)
+                       options->chassis = cont->idx;
+                    if (options->port == -1)
+                       options->port = addr->slot;
+                    break;
+                case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
+                case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
+                case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
+                    break;
+                }
+
+                /* check if every PCI bridge controller's ID is greater than
+                 * the bus it is placed onto
+                 */
+                if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE &&
+                    idx <= addr->bus) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                   _("failed to create PCI bridge "
+                                     "on bus %d: too many devices with fixed "
+                                     "addresses"),
+                                   addr->bus);
+                    goto cleanup;
+                }
+            }
+        }
+    }
+
+    if (obj && obj->privateData) {
+        priv = obj->privateData;
+        if (addrs) {
+            /* if this is the live domain object, we persist the PCI addresses*/
+            virDomainPCIAddressSetFree(priv->pciaddrs);
+            priv->persistentAddrs = 1;
+            priv->pciaddrs = addrs;
+            addrs = NULL;
+        } else {
+            priv->persistentAddrs = 0;
+        }
+    }
+
+    ret = 0;
+
+ cleanup:
+    virDomainPCIAddressSetFree(addrs);
+
+    return ret;
+}
+
+
+int
+qemuDomainAssignAddresses(virDomainDefPtr def,
+                          virQEMUCapsPtr qemuCaps,
+                          virDomainObjPtr obj)
+{
+    int rc;
+
+    rc = qemuDomainAssignVirtioSerialAddresses(def, obj);
+    if (rc)
+        return rc;
+
+    rc = qemuDomainAssignSpaprVIOAddresses(def, qemuCaps);
+    if (rc)
+        return rc;
+
+    rc = qemuDomainAssignS390Addresses(def, qemuCaps, obj);
+    if (rc)
+        return rc;
+
+    rc = qemuDomainAssignARMVirtioMMIOAddresses(def, qemuCaps);
+    if (rc)
+        return rc;
+
+    return qemuDomainAssignPCIAddresses(def, qemuCaps, obj);
+}
+
+
+void
+qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
+                               virDomainDeviceInfoPtr info,
+                               const char *devstr)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+
+    if (!devstr)
+        devstr = info->alias;
+
+    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
+        qemuDomainMachineIsS390CCW(vm->def) &&
+        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW) &&
+        virDomainCCWAddressReleaseAddr(priv->ccwaddrs, info) < 0)
+        VIR_WARN("Unable to release CCW address on %s",
+                 NULLSTR(devstr));
+    else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
+             virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
+             virDomainPCIAddressReleaseSlot(priv->pciaddrs,
+                                            &info->addr.pci) < 0)
+        VIR_WARN("Unable to release PCI address on %s",
+                 NULLSTR(devstr));
+    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL &&
+        virDomainVirtioSerialAddrRelease(priv->vioserialaddrs, info) < 0)
+        VIR_WARN("Unable to release virtio-serial address on %s",
+                 NULLSTR(devstr));
+}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 95b2e9d..88a991e 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -521,5 +521,17 @@ bool qemuDomainSupportsNetdev(virDomainDefPtr def,
                               virQEMUCapsPtr qemuCaps,
                               virDomainNetDefPtr net);
 
+int qemuDomainSetSCSIControllerModel(virDomainDefPtr def,
+                                     virQEMUCapsPtr qemuCaps,
+                                     int *model);
+
+int qemuDomainAssignAddresses(virDomainDefPtr def,
+                              virQEMUCapsPtr qemuCaps,
+                              virDomainObjPtr obj)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
+                                    virDomainDeviceInfoPtr info,
+                                    const char *devstr);
 
 #endif /* __QEMU_DOMAIN_H__ */
-- 
2.5.0




More information about the libvir-list mailing list