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(a)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