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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list