[libvirt] [PATCH 00/13] Move functions from qemu_domain_address.c to domain_addr.c

This series depends on another one: https://www.redhat.com/archives/libvir-list/2016-July/msg00696.html Because the address sets are no longer cached, it's possible to move functions that don't depend on qemu anymore from qemu_domain_address.c to domain_addr.c. I did that with virtioSerial and PCI. To make some functions not dependent on qemuCaps, their parameters were changed to booleans. These changes are in [PATCH 02/13]. If you are satisfied with this approach, I can do the same with the rest of the functions or just some of them. Tomasz Flendrich (13): Move and rename qemuDomainAssignVirtioSerialAddresses make pci address handling functions qemu-agnostic Move and rename qemuDomainCollectPCIAddress Move and rename qemuDomainMachineIsQ35 et al Move and rename qemuDomainValidateDevicePCISlotsPIIX3 Move and rename qemuDomainValidateDevicePCISlotsQ35 Move and rename qemuDomainValidateDevicePCISlotsChipsets Move and rename qemuDomainAddressFindNewBusNr et al Move and rename qemuDomainMachineIsVirt Move and rename qemuDomainSupportsPCI Move and rename qemuDomainPCIAddrSetCreateFromDomain Move and rename qemuDomainAssignPCIAddresses et al Make functions in qemu_domain_address static src/conf/domain_addr.c | 1315 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 28 + src/libvirt_private.syms | 6 + src/qemu/qemu_alias.c | 2 +- src/qemu/qemu_capabilities.c | 6 +- src/qemu/qemu_command.c | 20 +- src/qemu/qemu_domain.c | 55 +- src/qemu/qemu_domain.h | 3 - src/qemu/qemu_domain_address.c | 1284 +-------------------------------------- src/qemu/qemu_domain_address.h | 4 - src/qemu/qemu_hotplug.c | 33 +- 11 files changed, 1406 insertions(+), 1350 deletions(-) -- 2.7.4 (Apple Git-66)

qemuDomainAssignVirtioSerialAddresses is renamed to virDomainAssignVirtioSerialAddresses and moved from qemu_domain_address.c to domain_addr.c All these functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 38 ++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 4 ++++ src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 40 +--------------------------------------- 4 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 67c12a4..4b7fead 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -1190,3 +1190,41 @@ virDomainVirtioSerialAddrReserve(virDomainDefPtr def ATTRIBUTE_UNUSED, VIR_FREE(str); return ret; } + + +int +virDomainAssignVirtioSerialAddresses(virDomainDefPtr def) +{ + int ret = -1; + size_t i; + virDomainVirtioSerialAddrSetPtr addrs = NULL; + + if (!(addrs = virDomainVirtioSerialAddrSetCreateFromDomain(def))) + 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; + } + + ret = 0; + + cleanup: + virDomainVirtioSerialAddrSetFree(addrs); + return ret; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index a060683..74ae3ab 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -228,4 +228,8 @@ virDomainVirtioSerialAddrReserve(virDomainDefPtr def, void *data) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); +int +virDomainAssignVirtioSerialAddresses(virDomainDefPtr def) + ATTRIBUTE_NONNULL(1); + #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bdf8304..e1bfce9 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -85,6 +85,7 @@ virPCIDeviceAddressParseXML; # conf/domain_addr.h +virDomainAssignVirtioSerialAddresses; virDomainCCWAddressAllocate; virDomainCCWAddressAssign; virDomainCCWAddressSetCreate; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index df36349..c0a96ba 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -106,44 +106,6 @@ qemuDomainSetSCSIControllerModel(const virDomainDef *def, static int -qemuDomainAssignVirtioSerialAddresses(virDomainDefPtr def) -{ - int ret = -1; - size_t i; - virDomainVirtioSerialAddrSetPtr addrs = NULL; - - if (!(addrs = virDomainVirtioSerialAddrSetCreateFromDomain(def))) - 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; - } - - ret = 0; - - cleanup: - virDomainVirtioSerialAddrSetFree(addrs); - return ret; -} - - -static int qemuDomainSpaprVIOFindByReg(virDomainDefPtr def ATTRIBUTE_UNUSED, virDomainDeviceDefPtr device ATTRIBUTE_UNUSED, virDomainDeviceInfoPtr info, void *opaque) @@ -1638,7 +1600,7 @@ qemuDomainAssignAddresses(virDomainDefPtr def, virDomainObjPtr obj ATTRIBUTE_UNUSED, bool newDomain ATTRIBUTE_UNUSED) { - if (qemuDomainAssignVirtioSerialAddresses(def) < 0) + if (virDomainAssignVirtioSerialAddresses(def) < 0) return -1; if (qemuDomainAssignSpaprVIOAddresses(def, qemuCaps) < 0) -- 2.7.4 (Apple Git-66)

Change functions in qemu_domain_address.c to accept boolean parameters instead of qemuCaps. Thanks to this, they can be moved to domain_addr.c and have the potential to be reused for more hypervisors in the future. --- src/qemu/qemu_domain_address.c | 80 ++++++++++++++++++++++++------------------ src/qemu/qemu_domain_address.h | 6 ++-- src/qemu/qemu_hotplug.c | 27 ++++++++++---- 3 files changed, 71 insertions(+), 42 deletions(-) diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index c0a96ba..b6a0b83 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -560,13 +560,12 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def, static int qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, - virQEMUCapsPtr qemuCaps, - virDomainPCIAddressSetPtr addrs) + virDomainPCIAddressSetPtr addrs, + bool videoPrimaryEnabled) { int ret = -1; size_t i; virPCIDeviceAddress 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_DEVICE); @@ -644,7 +643,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, goto cleanup; if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) { - if (qemuDeviceVideoUsable) { + if (videoPrimaryEnabled) { if (virDomainPCIAddressReserveNextSlot(addrs, &primaryVideo->info, flags) < 0) @@ -661,7 +660,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, primaryVideo->info.addr.pci = tmp_addr; primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; } - } else if (!qemuDeviceVideoUsable) { + } else if (!videoPrimaryEnabled) { if (primaryVideo->info.addr.pci.domain != 0 || primaryVideo->info.addr.pci.bus != 0 || primaryVideo->info.addr.pci.slot != 2 || @@ -673,7 +672,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, /* If TYPE == PCI, then qemuDomainCollectPCIAddress() function * has already reserved the address, so we must skip */ } - } else if (addrs->nbuses && !qemuDeviceVideoUsable) { + } else if (addrs->nbuses && !videoPrimaryEnabled) { memset(&tmp_addr, 0, sizeof(tmp_addr)); tmp_addr.slot = 2; @@ -694,13 +693,12 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, static int qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, - virQEMUCapsPtr qemuCaps, - virDomainPCIAddressSetPtr addrs) + virDomainPCIAddressSetPtr addrs, + bool videoPrimaryEnabled) { int ret = -1; size_t i; virPCIDeviceAddress tmp_addr; - bool qemuDeviceVideoUsable = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); char *addrStr = NULL; virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; @@ -835,7 +833,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, goto cleanup; if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) { - if (qemuDeviceVideoUsable) { + if (videoPrimaryEnabled) { if (virDomainPCIAddressReserveNextSlot(addrs, &primaryVideo->info, flags) < 0) @@ -852,7 +850,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; primaryVideo->info.addr.pci = tmp_addr; } - } else if (!qemuDeviceVideoUsable) { + } else if (!videoPrimaryEnabled) { if (primaryVideo->info.addr.pci.domain != 0 || primaryVideo->info.addr.pci.bus != 0 || primaryVideo->info.addr.pci.slot != 1 || @@ -864,7 +862,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, /* If TYPE == PCI, then qemuDomainCollectPCIAddress() function * has already reserved the address, so we must skip */ } - } else if (addrs->nbuses && !qemuDeviceVideoUsable) { + } else if (addrs->nbuses && !videoPrimaryEnabled) { memset(&tmp_addr, 0, sizeof(tmp_addr)); tmp_addr.slot = 1; @@ -886,16 +884,16 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, static int qemuDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, - virQEMUCapsPtr qemuCaps, - virDomainPCIAddressSetPtr addrs) + virDomainPCIAddressSetPtr addrs, + bool videoPrimaryEnabled) { if (qemuDomainMachineIsI440FX(def) && - qemuDomainValidateDevicePCISlotsPIIX3(def, qemuCaps, addrs) < 0) { + qemuDomainValidateDevicePCISlotsPIIX3(def, addrs, videoPrimaryEnabled) < 0) { return -1; } if (qemuDomainMachineIsQ35(def) && - qemuDomainValidateDevicePCISlotsQ35(def, qemuCaps, addrs) < 0) { + qemuDomainValidateDevicePCISlotsQ35(def, addrs, videoPrimaryEnabled) < 0) { return -1; } @@ -954,8 +952,8 @@ qemuDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus) */ static int qemuDomainAssignDevicePCISlots(virDomainDefPtr def, - virQEMUCapsPtr qemuCaps, - virDomainPCIAddressSetPtr addrs) + virDomainPCIAddressSetPtr addrs, + bool virtioMMIOEnabled) { size_t i, j; virDomainPCIConnectFlags flags = 0; /* initialize to quiet gcc warning */ @@ -1136,7 +1134,7 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, /* 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)) + virtioMMIOEnabled) continue; if (!virDeviceInfoPCIAddressWanted(&def->disks[i]->info)) { @@ -1265,7 +1263,7 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def, static bool qemuDomainSupportsPCI(virDomainDefPtr def, - virQEMUCapsPtr qemuCaps) + bool gpexEnabled) { if ((def->os.arch != VIR_ARCH_ARMV7L) && (def->os.arch != VIR_ARCH_AARCH64)) return true; @@ -1274,7 +1272,7 @@ qemuDomainSupportsPCI(virDomainDefPtr def, return true; if (qemuDomainMachineIsVirt(def) && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_GPEX)) + gpexEnabled) return true; return false; @@ -1388,7 +1386,9 @@ qemuDomainAddressFindNewBusNr(virDomainDefPtr def) virDomainPCIAddressSetPtr qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, - virQEMUCapsPtr qemuCaps) + bool virtioMMIOEnabled, + bool videoPrimaryEnabled, + bool gpexEnabled) { virDomainPCIAddressSetPtr addrs = NULL; int max_idx = -1; @@ -1408,12 +1408,12 @@ qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, false))) goto cleanup; - if (qemuDomainSupportsPCI(def, qemuCaps)) { - if (qemuDomainValidateDevicePCISlotsChipsets(def, qemuCaps, - addrs) < 0) + if (qemuDomainSupportsPCI(def, gpexEnabled)) { + if (qemuDomainValidateDevicePCISlotsChipsets(def, addrs, + videoPrimaryEnabled) < 0) goto cleanup; - if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0) + if (qemuDomainAssignDevicePCISlots(def, addrs, virtioMMIOEnabled) < 0) goto cleanup; } @@ -1428,7 +1428,10 @@ qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, static int qemuDomainAssignPCIAddresses(virDomainDefPtr def, - virQEMUCapsPtr qemuCaps) + bool pciBridgeEnabled, + bool virtioMMIOEnabled, + bool videoPrimaryEnabled, + bool gpexEnabled) { int ret = -1; virDomainPCIAddressSetPtr addrs = NULL; @@ -1450,15 +1453,15 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, nbuses = max_idx + 1; if (nbuses > 0 && - virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PCI_BRIDGE)) { + pciBridgeEnabled) { 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) + if (qemuDomainValidateDevicePCISlotsChipsets(def, addrs, + videoPrimaryEnabled) < 0) goto cleanup; for (i = 0; i < addrs->nbuses; i++) { @@ -1479,7 +1482,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0) goto cleanup; - if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0) + if (qemuDomainAssignDevicePCISlots(def, addrs, virtioMMIOEnabled) < 0) goto cleanup; for (i = 1; i < addrs->nbuses; i++) { @@ -1505,10 +1508,13 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, goto cleanup; } - if (!(addrs = qemuDomainPCIAddrSetCreateFromDomain(def, qemuCaps))) + if (!(addrs = qemuDomainPCIAddrSetCreateFromDomain(def, + virtioMMIOEnabled, + videoPrimaryEnabled, + gpexEnabled))) goto cleanup; - if (qemuDomainSupportsPCI(def, qemuCaps)) { + if (qemuDomainSupportsPCI(def, gpexEnabled)) { for (i = 0; i < def->ncontrollers; i++) { virDomainControllerDefPtr cont = def->controllers[i]; int idx = cont->idx; @@ -1600,6 +1606,11 @@ qemuDomainAssignAddresses(virDomainDefPtr def, virDomainObjPtr obj ATTRIBUTE_UNUSED, bool newDomain ATTRIBUTE_UNUSED) { + bool pciBridgeEnabled = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PCI_BRIDGE); + bool virtioMMIOEnabled = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO); + bool videoPrimaryEnabled = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); + bool gpexEnabled = virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_GPEX); + if (virDomainAssignVirtioSerialAddresses(def) < 0) return -1; @@ -1611,7 +1622,8 @@ qemuDomainAssignAddresses(virDomainDefPtr def, qemuDomainAssignARMVirtioMMIOAddresses(def, qemuCaps); - if (qemuDomainAssignPCIAddresses(def, qemuCaps) < 0) + if (qemuDomainAssignPCIAddresses(def, pciBridgeEnabled, virtioMMIOEnabled, + videoPrimaryEnabled, gpexEnabled) < 0) return -1; return 0; diff --git a/src/qemu/qemu_domain_address.h b/src/qemu/qemu_domain_address.h index 5f35a92..77a5541 100644 --- a/src/qemu/qemu_domain_address.h +++ b/src/qemu/qemu_domain_address.h @@ -43,8 +43,10 @@ qemuDomainCCWAddrSetCreateFromDomain(virDomainDefPtr def) virDomainPCIAddressSetPtr qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, - virQEMUCapsPtr qemuCaps) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + bool virtioMMIOEnabled, + bool videoPrimaryEnabled, + bool gpexEnabled) + ATTRIBUTE_NONNULL(1); # define __QEMU_DOMAIN_ADDRESS_H__ diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index a6404d8..fa7a8e9 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -335,7 +335,9 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, } else if (!disk->info.type || disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, - priv->qemuCaps))) + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) goto error; if (virDomainPCIAddressEnsureAddr(pciaddrs, &disk->info) < 0) goto error; @@ -455,7 +457,9 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, - priv->qemuCaps))) + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) goto cleanup; if (virDomainPCIAddressEnsureAddr(pciaddrs, &controller->info) < 0) goto cleanup; @@ -973,7 +977,9 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, goto cleanup; } else { if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, - priv->qemuCaps))) + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) goto cleanup; if (virDomainPCIAddressEnsureAddr(pciaddrs, &net->info) < 0) goto cleanup; @@ -1252,7 +1258,10 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0) goto error; - if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, priv->qemuCaps))) + if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) goto cleanup; if (virDomainPCIAddressEnsureAddr(pciaddrs, hostdev->info) < 0) goto error; @@ -1498,7 +1507,10 @@ qemuDomainAttachChrDeviceAssignAddr(virDomainDefPtr def, } else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL && chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI) { - if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(def, priv->qemuCaps))) + if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(def, + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) goto cleanup; if (virDomainPCIAddressEnsureAddr(pciaddrs, &chr->info) < 0) goto cleanup; @@ -1626,7 +1638,10 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver, if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { - if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, priv->qemuCaps))) + if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) goto cleanup; if (virDomainPCIAddressEnsureAddr(pciaddrs, &rng->info) < 0) goto cleanup; -- 2.7.4 (Apple Git-66)

qemuDomainCollectPCIAddress is renamed to virDomainCollectPCIAddress and moved from qemu_domain_address.c to domain_addr.c All these functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 141 +++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 6 ++ src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 148 ++--------------------------------------- 4 files changed, 152 insertions(+), 144 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 4b7fead..fcfd84a 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -1228,3 +1228,144 @@ virDomainAssignVirtioSerialAddresses(virDomainDefPtr def) virDomainVirtioSerialAddrSetFree(addrs); return ret; } + + +int +virDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceDefPtr device, + virDomainDeviceInfoPtr info, + void *opaque) +{ + virDomainPCIAddressSetPtr addrs = opaque; + int ret = -1; + virPCIDeviceAddressPtr addr = &info->addr.pci; + bool entireSlot; + /* flags may be changed from default below */ + virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE | + VIR_PCI_CONNECT_TYPE_PCI_DEVICE); + + if (!virDeviceInfoPCIAddressPresent(info) || + ((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: + flags = virDomainPCIControllerModelToConnectType(device->data.controller->model); + 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_DEVICE + | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE); + 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_DEVICE; + 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_DEVICE + | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE); + 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_DEVICE; + 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_DEVICE + | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE); + 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_DEVICE)) { + 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; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 74ae3ab..273ec0d 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -232,4 +232,10 @@ int virDomainAssignVirtioSerialAddresses(virDomainDefPtr def) ATTRIBUTE_NONNULL(1); +int +virDomainCollectPCIAddress(virDomainDefPtr def, + virDomainDeviceDefPtr device, + virDomainDeviceInfoPtr info, + void *opaque); + #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e1bfce9..51b3a3f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -91,6 +91,7 @@ virDomainCCWAddressAssign; virDomainCCWAddressSetCreate; virDomainCCWAddressSetFree; virDomainCCWAddressValidate; +virDomainCollectPCIAddress; virDomainGetBlkioParametersAssignFromDef; virDomainPCIAddressAsString; virDomainPCIAddressBusSetModel; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index b6a0b83..777aab5 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -360,146 +360,6 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def, } -static int -qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, - virDomainDeviceDefPtr device, - virDomainDeviceInfoPtr info, - void *opaque) -{ - virDomainPCIAddressSetPtr addrs = opaque; - int ret = -1; - virPCIDeviceAddressPtr addr = &info->addr.pci; - bool entireSlot; - /* flags may be changed from default below */ - virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE | - VIR_PCI_CONNECT_TYPE_PCI_DEVICE); - - if (!virDeviceInfoPCIAddressPresent(info) || - ((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: - flags = virDomainPCIControllerModelToConnectType(device->data.controller->model); - 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_DEVICE - | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE); - 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_DEVICE; - 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_DEVICE - | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE); - 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_DEVICE; - 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_DEVICE - | VIR_PCI_CONNECT_TYPE_PCIE_DEVICE); - 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_DEVICE)) { - 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, @@ -547,7 +407,7 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def, goto error; } - if (virDomainDeviceInfoIterate(def, qemuDomainCollectPCIAddress, addrs) < 0) + if (virDomainDeviceInfoIterate(def, virDomainCollectPCIAddress, addrs) < 0) goto error; return addrs; @@ -669,7 +529,7 @@ qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, _("Primary video card must have PCI address 0:0:2.0")); goto cleanup; } - /* If TYPE == PCI, then qemuDomainCollectPCIAddress() function + /* If TYPE == PCI, then virDomainCollectPCIAddress() function * has already reserved the address, so we must skip */ } } else if (addrs->nbuses && !videoPrimaryEnabled) { @@ -859,7 +719,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, _("Primary video card must have PCI address 0:0:1.0")); goto cleanup; } - /* If TYPE == PCI, then qemuDomainCollectPCIAddress() function + /* If TYPE == PCI, then virDomainCollectPCIAddress() function * has already reserved the address, so we must skip */ } } else if (addrs->nbuses && !videoPrimaryEnabled) { @@ -945,7 +805,7 @@ qemuDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus) * - Watchdog * - pci serial devices * - * Prior to this function being invoked, qemuDomainCollectPCIAddress() will have + * Prior to this function being invoked, virDomainCollectPCIAddress() 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 -- 2.7.4 (Apple Git-66)

qemuDomainMachineIsQ35 is renamed to virDomainMachineIsQ35, qemuDomainMachineIsI440FX is renamed to virDomainMachineIsI440FX, both are moved from qemu_domain_address.c to domain_addr.c All these functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 19 +++++++++++++++++++ src/conf/domain_addr.h | 8 ++++++++ src/libvirt_private.syms | 2 ++ src/qemu/qemu_alias.c | 2 +- src/qemu/qemu_capabilities.c | 4 ++-- src/qemu/qemu_command.c | 16 ++++++++-------- src/qemu/qemu_domain.c | 31 ++++++------------------------- src/qemu/qemu_domain.h | 2 -- src/qemu/qemu_domain_address.c | 4 ++-- 9 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index fcfd84a..f3a75a0 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -1369,3 +1369,22 @@ virDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, cleanup: return ret; } + + +bool +virDomainMachineIsQ35(const virDomainDef *def) +{ + return (STRPREFIX(def->os.machine, "pc-q35") || + STREQ(def->os.machine, "q35")); +} + + +bool +virDomainMachineIsI440FX(const virDomainDef *def) +{ + return (STREQ(def->os.machine, "pc") || + STRPREFIX(def->os.machine, "pc-0.") || + STRPREFIX(def->os.machine, "pc-1.") || + STRPREFIX(def->os.machine, "pc-i440") || + STRPREFIX(def->os.machine, "rhel")); +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 273ec0d..fb90ec9 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -238,4 +238,12 @@ virDomainCollectPCIAddress(virDomainDefPtr def, virDomainDeviceInfoPtr info, void *opaque); +bool +virDomainMachineIsQ35(const virDomainDef *def); + +bool +virDomainMachineIsI440FX(const virDomainDef *def); + + + #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 51b3a3f..2697afa 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -93,6 +93,8 @@ virDomainCCWAddressSetFree; virDomainCCWAddressValidate; virDomainCollectPCIAddress; virDomainGetBlkioParametersAssignFromDef; +virDomainMachineIsI440FX; +virDomainMachineIsQ35; virDomainPCIAddressAsString; virDomainPCIAddressBusSetModel; virDomainPCIAddressEnsureAddr; diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index d624071..9e4e03c 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -157,7 +157,7 @@ qemuAssignDeviceControllerAlias(virDomainDefPtr domainDef, /* for any Q35 machine, the first SATA controller is the * integrated one, and it too is hardcoded with id "ide" */ - if (qemuDomainMachineIsQ35(domainDef) && controller->idx == 0) + if (virDomainMachineIsQ35(domainDef) && controller->idx == 0) return VIR_STRDUP(controller->info.alias, "ide"); } else if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) { /* first USB device is "usb", others are normal "usb%d" */ diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f600ce9..6989a87 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -4045,8 +4045,8 @@ virQEMUCapsSupportsVmport(virQEMUCapsPtr qemuCaps, if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_VMPORT_OPT)) return false; - return qemuDomainMachineIsI440FX(def) || - qemuDomainMachineIsQ35(def) || + return virDomainMachineIsI440FX(def) || + virDomainMachineIsQ35(def) || STREQ(def->os.machine, "isapc"); } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index fe4bb88..24295bd 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2823,7 +2823,7 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd, /* first SATA controller on Q35 machines is implicit */ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_SATA && - cont->idx == 0 && qemuDomainMachineIsQ35(def)) + cont->idx == 0 && virDomainMachineIsQ35(def)) continue; /* first IDE controller is implicit on various machines */ @@ -2833,7 +2833,7 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd, if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB && cont->model == -1 && - !qemuDomainMachineIsQ35(def)) { + !virDomainMachineIsQ35(def)) { bool need_legacy = false; /* We're not using legacy usb controller for q35 */ @@ -2869,7 +2869,7 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd, } if (usbcontroller == 0 && - !qemuDomainMachineIsQ35(def) && + !virDomainMachineIsQ35(def) && !qemuDomainMachineIsVirt(def) && !ARCH_IS_S390(def->os.arch)) virCommandAddArg(cmd, "-usb"); @@ -5979,7 +5979,7 @@ qemuBuildPMCommandLine(virCommandPtr cmd, if (def->pm.s3) { const char *pm_object = "PIIX4_PM"; - if (qemuDomainMachineIsQ35(def) && + if (virDomainMachineIsQ35(def) && virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S3)) { pm_object = "ICH9-LPC"; } else if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX_DISABLE_S3)) { @@ -5996,7 +5996,7 @@ qemuBuildPMCommandLine(virCommandPtr cmd, if (def->pm.s4) { const char *pm_object = "PIIX4_PM"; - if (qemuDomainMachineIsQ35(def) && + if (virDomainMachineIsQ35(def) && virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_DISABLE_S4)) { pm_object = "ICH9-LPC"; } else if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX_DISABLE_S4)) { @@ -6178,7 +6178,7 @@ qemuBuildIOMMUCommandLine(virCommandPtr cmd, virDomainIOMMUModelTypeToString(def->iommu->model)); return -1; } - if (!qemuDomainMachineIsQ35(def)) { + if (!virDomainMachineIsQ35(def)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("IOMMU device: '%s' is only supported with " "Q35 machines"), @@ -6212,13 +6212,13 @@ qemuBuildGlobalControllerCommandLine(virCommandPtr cmd, case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: hoststr = "i440FX-pcihost"; cap = virQEMUCapsGet(qemuCaps, QEMU_CAPS_I440FX_PCI_HOLE64_SIZE); - machine = qemuDomainMachineIsI440FX(def); + machine = virDomainMachineIsI440FX(def); break; case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: hoststr = "q35-pcihost"; cap = virQEMUCapsGet(qemuCaps, QEMU_CAPS_Q35_PCI_HOLE64_SIZE); - machine = qemuDomainMachineIsQ35(def); + machine = virDomainMachineIsQ35(def); break; default: diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index e51584e..8c23157 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1936,7 +1936,7 @@ qemuDomainDefAddDefaultDevices(virDomainDefPtr def, addDefaultUSB = false; break; } - if (qemuDomainMachineIsQ35(def)) { + if (virDomainMachineIsQ35(def)) { addPCIeRoot = true; addImplicitSATA = true; @@ -1949,7 +1949,7 @@ qemuDomainDefAddDefaultDevices(virDomainDefPtr def, addDefaultUSB = false; break; } - if (qemuDomainMachineIsI440FX(def)) + if (virDomainMachineIsI440FX(def)) addPCIRoot = true; break; @@ -2499,14 +2499,14 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS && - !qemuDomainMachineIsI440FX(def)) { + !virDomainMachineIsI440FX(def)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("pci-expander-bus controllers are only supported " "on 440fx-based machinetypes")); goto cleanup; } if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS && - !qemuDomainMachineIsQ35(def)) { + !virDomainMachineIsQ35(def)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("pcie-expander-bus controllers are only supported " "on q35-based machinetypes")); @@ -3213,7 +3213,7 @@ qemuDomainDefFormatBuf(virQEMUDriverPtr driver, * with libvirt <= 0.9.4. Limitation doesn't apply to other archs * and can cause problems on PPC64. */ - if (ARCH_IS_X86(def->os.arch) && qemuDomainMachineIsI440FX(def) && + if (ARCH_IS_X86(def->os.arch) && virDomainMachineIsI440FX(def) && usb && usb->idx == 0 && usb->model == -1) { VIR_DEBUG("Removing default USB controller from domain '%s'" " for migration compatibility", def->name); @@ -4992,25 +4992,6 @@ qemuFindAgentConfig(virDomainDefPtr def) bool -qemuDomainMachineIsQ35(const virDomainDef *def) -{ - return (STRPREFIX(def->os.machine, "pc-q35") || - STREQ(def->os.machine, "q35")); -} - - -bool -qemuDomainMachineIsI440FX(const virDomainDef *def) -{ - return (STREQ(def->os.machine, "pc") || - STRPREFIX(def->os.machine, "pc-0.") || - STRPREFIX(def->os.machine, "pc-1.") || - STRPREFIX(def->os.machine, "pc-i440") || - STRPREFIX(def->os.machine, "rhel")); -} - - -bool qemuDomainMachineNeedsFDC(const virDomainDef *def) { char *p = STRSKIP(def->os.machine, "pc-q35-"); @@ -5238,7 +5219,7 @@ qemuDomainDefValidateMemoryHotplug(const virDomainDef *def, bool qemuDomainMachineHasBuiltinIDE(const virDomainDef *def) { - return qemuDomainMachineIsI440FX(def) || + return virDomainMachineIsI440FX(def) || STREQ(def->os.machine, "malta") || STREQ(def->os.machine, "sun4u") || STREQ(def->os.machine, "g3beige"); diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index bf96ad3..81086d9 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -622,8 +622,6 @@ void qemuDomainMemoryDeviceAlignSize(virDomainDefPtr def, virDomainChrDefPtr qemuFindAgentConfig(virDomainDefPtr def); -bool qemuDomainMachineIsQ35(const virDomainDef *def); -bool qemuDomainMachineIsI440FX(const virDomainDef *def); bool qemuDomainMachineNeedsFDC(const virDomainDef *def); bool qemuDomainMachineIsS390CCW(const virDomainDef *def); bool qemuDomainMachineIsVirt(const virDomainDef *def); diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 777aab5..02642f9 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -747,12 +747,12 @@ qemuDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, virDomainPCIAddressSetPtr addrs, bool videoPrimaryEnabled) { - if (qemuDomainMachineIsI440FX(def) && + if (virDomainMachineIsI440FX(def) && qemuDomainValidateDevicePCISlotsPIIX3(def, addrs, videoPrimaryEnabled) < 0) { return -1; } - if (qemuDomainMachineIsQ35(def) && + if (virDomainMachineIsQ35(def) && qemuDomainValidateDevicePCISlotsQ35(def, addrs, videoPrimaryEnabled) < 0) { return -1; } -- 2.7.4 (Apple Git-66)

qemuDomainValidateDevicePCISlotsPIIX3 is renamed to virDomainValidateDevicePCISlotsPIIX3 and moved from qemu_domain_addr.c to domain_addr.c All these functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 133 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 6 ++ src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 135 +---------------------------------------- 4 files changed, 141 insertions(+), 134 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index f3a75a0..17b60e4 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -1388,3 +1388,136 @@ virDomainMachineIsI440FX(const virDomainDef *def) STRPREFIX(def->os.machine, "pc-i440") || STRPREFIX(def->os.machine, "rhel")); } + + +int +virDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, + virDomainPCIAddressSetPtr addrs, + bool videoPrimaryEnabled) +{ + int ret = -1; + size_t i; + virPCIDeviceAddress tmp_addr; + char *addrStr = NULL; + virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE + | VIR_PCI_CONNECT_TYPE_PCI_DEVICE); + + /* 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 (virDeviceInfoPCIAddressPresent(&def->controllers[i]->info)) { + 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 (virDeviceInfoPCIAddressPresent(&def->controllers[i]->info)) { + 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 (virDeviceInfoPCIAddressWanted(&primaryVideo->info)) { + 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 (videoPrimaryEnabled) { + 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 (!videoPrimaryEnabled) { + 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 virDomainCollectPCIAddress() function + * has already reserved the address, so we must skip */ + } + } else if (addrs->nbuses && !videoPrimaryEnabled) { + 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; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index fb90ec9..0995e7b 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -244,6 +244,12 @@ virDomainMachineIsQ35(const virDomainDef *def); bool virDomainMachineIsI440FX(const virDomainDef *def); +int +virDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, + virDomainPCIAddressSetPtr addrs, + bool videoPrimaryEnabled) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2697afa..c154a83 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -109,6 +109,7 @@ virDomainPCIAddressSetGrow; virDomainPCIAddressSlotInUse; virDomainPCIAddressValidate; virDomainPCIControllerModelToConnectType; +virDomainValidateDevicePCISlotsPIIX3; virDomainVirtioSerialAddrAssign; virDomainVirtioSerialAddrAutoAssign; virDomainVirtioSerialAddrIsComplete; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 02642f9..abf1a26 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -419,139 +419,6 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def, static int -qemuDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, - virDomainPCIAddressSetPtr addrs, - bool videoPrimaryEnabled) -{ - int ret = -1; - size_t i; - virPCIDeviceAddress tmp_addr; - char *addrStr = NULL; - virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE - | VIR_PCI_CONNECT_TYPE_PCI_DEVICE); - - /* 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 (virDeviceInfoPCIAddressPresent(&def->controllers[i]->info)) { - 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 (virDeviceInfoPCIAddressPresent(&def->controllers[i]->info)) { - 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 (virDeviceInfoPCIAddressWanted(&primaryVideo->info)) { - 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 (videoPrimaryEnabled) { - 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 (!videoPrimaryEnabled) { - 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 virDomainCollectPCIAddress() function - * has already reserved the address, so we must skip */ - } - } else if (addrs->nbuses && !videoPrimaryEnabled) { - 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, virDomainPCIAddressSetPtr addrs, bool videoPrimaryEnabled) @@ -748,7 +615,7 @@ qemuDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, bool videoPrimaryEnabled) { if (virDomainMachineIsI440FX(def) && - qemuDomainValidateDevicePCISlotsPIIX3(def, addrs, videoPrimaryEnabled) < 0) { + virDomainValidateDevicePCISlotsPIIX3(def, addrs, videoPrimaryEnabled) < 0) { return -1; } -- 2.7.4 (Apple Git-66)

qemuDomainValidateDevicePCISlotsQ35 is renamed to virDomainValidateDevicePCISlotsQ35 and moved from qemu_domain_addr.c to domain_addr.c All these functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 191 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 6 ++ src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 193 +---------------------------------------- 4 files changed, 199 insertions(+), 192 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 17b60e4..aecad04 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -1521,3 +1521,194 @@ virDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, VIR_FREE(addrStr); return ret; } + + +int +virDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, + virDomainPCIAddressSetPtr addrs, + bool videoPrimaryEnabled) +{ + int ret = -1; + size_t i; + virPCIDeviceAddress tmp_addr; + char *addrStr = NULL; + virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; + + 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 (virDeviceInfoPCIAddressPresent(&def->controllers[i]->info)) { + 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 (virDeviceInfoPCIAddressWanted(&primaryVideo->info)) { + 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 (videoPrimaryEnabled) { + 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 (!videoPrimaryEnabled) { + 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 virDomainCollectPCIAddress() function + * has already reserved the address, so we must skip */ + } + } else if (addrs->nbuses && !videoPrimaryEnabled) { + 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; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 0995e7b..55c4e83 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -250,6 +250,12 @@ virDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, bool videoPrimaryEnabled) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int +virDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, + virDomainPCIAddressSetPtr addrs, + bool videoPrimaryEnabled) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c154a83..89c1710 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -110,6 +110,7 @@ virDomainPCIAddressSlotInUse; virDomainPCIAddressValidate; virDomainPCIControllerModelToConnectType; virDomainValidateDevicePCISlotsPIIX3; +virDomainValidateDevicePCISlotsQ35; virDomainVirtioSerialAddrAssign; virDomainVirtioSerialAddrAutoAssign; virDomainVirtioSerialAddrIsComplete; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index abf1a26..dcdd4e2 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -419,197 +419,6 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def, static int -qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, - virDomainPCIAddressSetPtr addrs, - bool videoPrimaryEnabled) -{ - int ret = -1; - size_t i; - virPCIDeviceAddress tmp_addr; - char *addrStr = NULL; - virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCIE_DEVICE; - - 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 (virDeviceInfoPCIAddressPresent(&def->controllers[i]->info)) { - 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 (virDeviceInfoPCIAddressWanted(&primaryVideo->info)) { - 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 (videoPrimaryEnabled) { - 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 (!videoPrimaryEnabled) { - 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 virDomainCollectPCIAddress() function - * has already reserved the address, so we must skip */ - } - } else if (addrs->nbuses && !videoPrimaryEnabled) { - 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, virDomainPCIAddressSetPtr addrs, bool videoPrimaryEnabled) @@ -620,7 +429,7 @@ qemuDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, } if (virDomainMachineIsQ35(def) && - qemuDomainValidateDevicePCISlotsQ35(def, addrs, videoPrimaryEnabled) < 0) { + virDomainValidateDevicePCISlotsQ35(def, addrs, videoPrimaryEnabled) < 0) { return -1; } -- 2.7.4 (Apple Git-66)

qemuDomainValidateDevicePCISlotsChipsets is renamed to virDomainValidateDevicePCISlotsChipsets and moved from qemu_domain_addr.c to domain_addr.c All these functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 19 +++++++++++++++++++ src/conf/domain_addr.h | 6 +++++- src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 23 ++--------------------- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index aecad04..0659842 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -1712,3 +1712,22 @@ virDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, VIR_FREE(addrStr); return ret; } + + +int +virDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, + virDomainPCIAddressSetPtr addrs, + bool videoPrimaryEnabled) +{ + if (virDomainMachineIsI440FX(def) && + virDomainValidateDevicePCISlotsPIIX3(def, addrs, videoPrimaryEnabled) < 0) { + return -1; + } + + if (virDomainMachineIsQ35(def) && + virDomainValidateDevicePCISlotsQ35(def, addrs, videoPrimaryEnabled) < 0) { + return -1; + } + + return 0; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 55c4e83..42424f9 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -256,6 +256,10 @@ virDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, bool videoPrimaryEnabled) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - +int +virDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, + virDomainPCIAddressSetPtr addrs, + bool videoPrimaryEnabled) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 89c1710..3e468b5 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -109,6 +109,7 @@ virDomainPCIAddressSetGrow; virDomainPCIAddressSlotInUse; virDomainPCIAddressValidate; virDomainPCIControllerModelToConnectType; +virDomainValidateDevicePCISlotsChipsets; virDomainValidateDevicePCISlotsPIIX3; virDomainValidateDevicePCISlotsQ35; virDomainVirtioSerialAddrAssign; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index dcdd4e2..ec67e37 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -418,25 +418,6 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def, } -static int -qemuDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, - virDomainPCIAddressSetPtr addrs, - bool videoPrimaryEnabled) -{ - if (virDomainMachineIsI440FX(def) && - virDomainValidateDevicePCISlotsPIIX3(def, addrs, videoPrimaryEnabled) < 0) { - return -1; - } - - if (virDomainMachineIsQ35(def) && - virDomainValidateDevicePCISlotsQ35(def, addrs, videoPrimaryEnabled) < 0) { - return -1; - } - - return 0; -} - - static bool qemuDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus) { @@ -945,7 +926,7 @@ qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, goto cleanup; if (qemuDomainSupportsPCI(def, gpexEnabled)) { - if (qemuDomainValidateDevicePCISlotsChipsets(def, addrs, + if (virDomainValidateDevicePCISlotsChipsets(def, addrs, videoPrimaryEnabled) < 0) goto cleanup; @@ -996,7 +977,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, true))) goto cleanup; - if (qemuDomainValidateDevicePCISlotsChipsets(def, addrs, + if (virDomainValidateDevicePCISlotsChipsets(def, addrs, videoPrimaryEnabled) < 0) goto cleanup; -- 2.7.4 (Apple Git-66)

qemuDomainAddressFindNewBusNr is renamed to virDomainAddressFindNewBusNr qemuDomainPCIAddressSetCreate is renamed to virDomainPCIAddressSetCreate qemuDomainPCIBusFullyReserved is renamed to virDomainPCIBusFullyReserved qemuDomainAssignDevicePCISlots is renamed to virDomainAssignDevicePCISlots All of these are moved from qemu_domain_addr.c to domain_addr.c These functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 486 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 20 ++ src/libvirt_private.syms | 4 + src/qemu/qemu_domain_address.c | 498 +---------------------------------------- 4 files changed, 516 insertions(+), 492 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 0659842..32943e8 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -1731,3 +1731,489 @@ virDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, return 0; } + + +int +virDomainAddressFindNewBusNr(virDomainDefPtr def) +{ +/* Try to find a nice default for busNr for a new pci-expander-bus. + * This is a bit tricky, since you need to satisfy the following: + * + * 1) There need to be enough unused bus numbers between busNr of this + * bus and busNr of the next highest bus for the guest to assign a + * unique bus number to each PCI bus that is a child of this + * bus. Each PCI controller. On top of this, the pxb device (which + * implements the pci-expander-bus) includes a pci-bridge within + * it, and that bridge also uses one bus number (so each pxb device + * requires at least 2 bus numbers). + * + * 2) There need to be enough bus numbers *below* this for all the + * child controllers of the pci-expander-bus with the next lower + * busNr (or the pci-root bus if there are no lower + * pci-expander-buses). + * + * 3) If at all possible, we want to avoid needing to change the busNr + * of a bus in the future, as that changes the guest's device ABI, + * which could potentially lead to issues with a guest OS that is + * picky about such things. + * + * Due to the impossibility of predicting what might be added to the + * config in the future, we can't make a foolproof choice, but since + * a pci-expander-bus (pxb) has slots for 32 devices, and the only + * practical use for it is to assign real devices on a particular + * NUMA node in the host, it's reasonably safe to assume it should + * never need any additional child buses (probably only a few of the + * 32 will ever be used). So for pci-expander-bus we find the lowest + * existing busNr, and set this one to the current lowest - 2 (one + * for the pxb, one for the intergrated pci-bridge), thus leaving the + * maximum possible bus numbers available for other buses plugged + * into pci-root (i.e. pci-bridges and other + * pci-expander-buses). Anyone who needs more than 32 devices + * descended from one pci-expander-bus should set the busNr manually + * in the config. + * + * There is room for more error checking here - in particular we + * can/should determine the ultimate parent (root-bus) of each PCI + * controller and determine if there is enough space for all the + * buses within the current range allotted to the bus just prior to + * this one. + */ + size_t i; + int lowestBusNr = 256; + + for (i = 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { + int thisBusNr = def->controllers[i]->opts.pciopts.busNr; + + if (thisBusNr >= 0 && thisBusNr < lowestBusNr) + lowestBusNr = thisBusNr; + } + } + + /* If we already have a busNR = 1, then we can't auto-assign (0 is + * the pci[e]-root, and the others may have been assigned + * purposefully). + */ + if (lowestBusNr <= 2) + return -1; + + return lowestBusNr - 2; +} + + +virDomainPCIAddressSetPtr +virDomainPCIAddressSetCreate(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, virDomainCollectPCIAddress, addrs) < 0) + goto error; + + return addrs; + + error: + virDomainPCIAddressSetFree(addrs); + return NULL; +} + + +bool +virDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus) +{ + size_t i; + + for (i = bus->minSlot; i <= bus->maxSlot; i++) + if (!bus->slots[i]) + return false; + + return true; +} + + +/* + * 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, virDomainCollectPCIAddress() 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 + */ +int +virDomainAssignDevicePCISlots(virDomainDefPtr def, + virDomainPCIAddressSetPtr addrs, + bool virtioMMIOEnabled) +{ + size_t i, j; + virDomainPCIConnectFlags flags = 0; /* initialize to quiet gcc warning */ + virPCIDeviceAddress tmp_addr; + + /* PCI controllers */ + for (i = 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { + virDomainControllerModelPCI model = def->controllers[i]->model; + + if (model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || + model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT || + !virDeviceInfoPCIAddressWanted(&def->controllers[i]->info)) + continue; + + /* convert the type of controller into a "CONNECT_TYPE" + * flag to use when searching for the proper + * controller/bus to connect it to on the upstream side. + */ + flags = virDomainPCIControllerModelToConnectType(model); + if (virDomainPCIAddressReserveNextSlot(addrs, + &def->controllers[i]->info, + flags) < 0) + goto error; + } + } + + /* all other devices that plug into a PCI slot are treated as a + * PCI endpoint devices that require a hotplug-capable slot + * (except for some special cases which have specific handling + * below) + */ + flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + + for (i = 0; i < def->nfss; i++) { + if (!virDeviceInfoPCIAddressWanted(&def->fss[i]->info)) + 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) || + !virDeviceInfoPCIAddressWanted(&def->nets[i]->info)) { + continue; + } + if (virDomainPCIAddressReserveNextSlot(addrs, &def->nets[i]->info, + flags) < 0) + goto error; + } + + /* Sound cards */ + for (i = 0; i < def->nsounds; i++) { + if (!virDeviceInfoPCIAddressWanted(&def->sounds[i]->info)) + 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 (!virDeviceInfoPCIAddressWanted(&def->controllers[i]->info)) + continue; + + /* USB2 needs special handling to put all companions in the same slot */ + if (IS_USB2_CONTROLLER(def->controllers[i])) { + virPCIDeviceAddress 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 && + virDeviceInfoPCIAddressPresent(&def->controllers[j]->info)) { + 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 (virDeviceInfoPCIAddressPresent(&def->disks[i]->info) || + 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 && + virtioMMIOEnabled) + continue; + + if (!virDeviceInfoPCIAddressWanted(&def->disks[i]->info)) { + 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 (!virDeviceInfoPCIAddressWanted(def->hostdevs[i]->info)) + 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 && + virDeviceInfoPCIAddressWanted(&def->memballoon->info)) { + 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 || + !virDeviceInfoPCIAddressWanted(&def->rngs[i]->info)) + 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 && + virDeviceInfoPCIAddressWanted(&def->watchdog->info)) { + 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 && + virDeviceInfoPCIAddressWanted(&def->videos[0]->info)) { + 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 (!virDeviceInfoPCIAddressWanted(&def->videos[i]->info)) + continue; + if (virDomainPCIAddressReserveNextSlot(addrs, &def->videos[i]->info, + flags) < 0) + goto error; + } + + /* Shared Memory */ + for (i = 0; i < def->nshmems; i++) { + if (!virDeviceInfoPCIAddressWanted(&def->shmems[i]->info)) + 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 || + !virDeviceInfoPCIAddressWanted(&def->inputs[i]->info)) + 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 || + !virDeviceInfoPCIAddressWanted(&chr->info)) + 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; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 42424f9..a1e572b 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -262,4 +262,24 @@ virDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, bool videoPrimaryEnabled) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int +virDomainAddressFindNewBusNr(virDomainDefPtr def) + ATTRIBUTE_NONNULL(1); + +virDomainPCIAddressSetPtr +virDomainPCIAddressSetCreate(virDomainDefPtr def, + unsigned int nbuses, + bool dryRun) + ATTRIBUTE_NONNULL(1); + +bool +virDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus) + ATTRIBUTE_NONNULL(1); + +int +virDomainAssignDevicePCISlots(virDomainDefPtr def, + virDomainPCIAddressSetPtr addrs, + bool virtioMMIOEnabled) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 3e468b5..66144fd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -85,6 +85,8 @@ virPCIDeviceAddressParseXML; # conf/domain_addr.h +virDomainAddressFindNewBusNr; +virDomainAssignDevicePCISlots; virDomainAssignVirtioSerialAddresses; virDomainCCWAddressAllocate; virDomainCCWAddressAssign; @@ -104,10 +106,12 @@ virDomainPCIAddressReserveAddr; virDomainPCIAddressReserveNextSlot; virDomainPCIAddressReserveSlot; virDomainPCIAddressSetAlloc; +virDomainPCIAddressSetCreate; virDomainPCIAddressSetFree; virDomainPCIAddressSetGrow; virDomainPCIAddressSlotInUse; virDomainPCIAddressValidate; +virDomainPCIBusFullyReserved; virDomainPCIControllerModelToConnectType; virDomainValidateDevicePCISlotsChipsets; virDomainValidateDevicePCISlotsPIIX3; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index ec67e37..a0bc752 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -360,424 +360,6 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def, } -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, virDomainCollectPCIAddress, addrs) < 0) - goto error; - - return addrs; - - error: - virDomainPCIAddressSetFree(addrs); - return NULL; -} - - -static bool -qemuDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus) -{ - size_t i; - - for (i = bus->minSlot; i <= bus->maxSlot; i++) - if (!bus->slots[i]) - return false; - - return true; -} - - -/* - * 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, virDomainCollectPCIAddress() 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, - virDomainPCIAddressSetPtr addrs, - bool virtioMMIOEnabled) -{ - size_t i, j; - virDomainPCIConnectFlags flags = 0; /* initialize to quiet gcc warning */ - virPCIDeviceAddress tmp_addr; - - /* PCI controllers */ - for (i = 0; i < def->ncontrollers; i++) { - if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { - virDomainControllerModelPCI model = def->controllers[i]->model; - - if (model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || - model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT || - !virDeviceInfoPCIAddressWanted(&def->controllers[i]->info)) - continue; - - /* convert the type of controller into a "CONNECT_TYPE" - * flag to use when searching for the proper - * controller/bus to connect it to on the upstream side. - */ - flags = virDomainPCIControllerModelToConnectType(model); - if (virDomainPCIAddressReserveNextSlot(addrs, - &def->controllers[i]->info, - flags) < 0) - goto error; - } - } - - /* all other devices that plug into a PCI slot are treated as a - * PCI endpoint devices that require a hotplug-capable slot - * (except for some special cases which have specific handling - * below) - */ - flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI_DEVICE; - - for (i = 0; i < def->nfss; i++) { - if (!virDeviceInfoPCIAddressWanted(&def->fss[i]->info)) - 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) || - !virDeviceInfoPCIAddressWanted(&def->nets[i]->info)) { - continue; - } - if (virDomainPCIAddressReserveNextSlot(addrs, &def->nets[i]->info, - flags) < 0) - goto error; - } - - /* Sound cards */ - for (i = 0; i < def->nsounds; i++) { - if (!virDeviceInfoPCIAddressWanted(&def->sounds[i]->info)) - 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 (!virDeviceInfoPCIAddressWanted(&def->controllers[i]->info)) - continue; - - /* USB2 needs special handling to put all companions in the same slot */ - if (IS_USB2_CONTROLLER(def->controllers[i])) { - virPCIDeviceAddress 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 && - virDeviceInfoPCIAddressPresent(&def->controllers[j]->info)) { - 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 (virDeviceInfoPCIAddressPresent(&def->disks[i]->info) || - 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 && - virtioMMIOEnabled) - continue; - - if (!virDeviceInfoPCIAddressWanted(&def->disks[i]->info)) { - 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 (!virDeviceInfoPCIAddressWanted(def->hostdevs[i]->info)) - 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 && - virDeviceInfoPCIAddressWanted(&def->memballoon->info)) { - 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 || - !virDeviceInfoPCIAddressWanted(&def->rngs[i]->info)) - 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 && - virDeviceInfoPCIAddressWanted(&def->watchdog->info)) { - 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 && - virDeviceInfoPCIAddressWanted(&def->videos[0]->info)) { - 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 (!virDeviceInfoPCIAddressWanted(&def->videos[i]->info)) - continue; - if (virDomainPCIAddressReserveNextSlot(addrs, &def->videos[i]->info, - flags) < 0) - goto error; - } - - /* Shared Memory */ - for (i = 0; i < def->nshmems; i++) { - if (!virDeviceInfoPCIAddressWanted(&def->shmems[i]->info)) - 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 || - !virDeviceInfoPCIAddressWanted(&def->inputs[i]->info)) - 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 || - !virDeviceInfoPCIAddressWanted(&chr->info)) - 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, bool gpexEnabled) @@ -833,74 +415,6 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) } } - -static int -qemuDomainAddressFindNewBusNr(virDomainDefPtr def) -{ -/* Try to find a nice default for busNr for a new pci-expander-bus. - * This is a bit tricky, since you need to satisfy the following: - * - * 1) There need to be enough unused bus numbers between busNr of this - * bus and busNr of the next highest bus for the guest to assign a - * unique bus number to each PCI bus that is a child of this - * bus. Each PCI controller. On top of this, the pxb device (which - * implements the pci-expander-bus) includes a pci-bridge within - * it, and that bridge also uses one bus number (so each pxb device - * requires at least 2 bus numbers). - * - * 2) There need to be enough bus numbers *below* this for all the - * child controllers of the pci-expander-bus with the next lower - * busNr (or the pci-root bus if there are no lower - * pci-expander-buses). - * - * 3) If at all possible, we want to avoid needing to change the busNr - * of a bus in the future, as that changes the guest's device ABI, - * which could potentially lead to issues with a guest OS that is - * picky about such things. - * - * Due to the impossibility of predicting what might be added to the - * config in the future, we can't make a foolproof choice, but since - * a pci-expander-bus (pxb) has slots for 32 devices, and the only - * practical use for it is to assign real devices on a particular - * NUMA node in the host, it's reasonably safe to assume it should - * never need any additional child buses (probably only a few of the - * 32 will ever be used). So for pci-expander-bus we find the lowest - * existing busNr, and set this one to the current lowest - 2 (one - * for the pxb, one for the intergrated pci-bridge), thus leaving the - * maximum possible bus numbers available for other buses plugged - * into pci-root (i.e. pci-bridges and other - * pci-expander-buses). Anyone who needs more than 32 devices - * descended from one pci-expander-bus should set the busNr manually - * in the config. - * - * There is room for more error checking here - in particular we - * can/should determine the ultimate parent (root-bus) of each PCI - * controller and determine if there is enough space for all the - * buses within the current range allotted to the bus just prior to - * this one. - */ - size_t i; - int lowestBusNr = 256; - - for (i = 0; i < def->ncontrollers; i++) { - if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) { - int thisBusNr = def->controllers[i]->opts.pciopts.busNr; - - if (thisBusNr >= 0 && thisBusNr < lowestBusNr) - lowestBusNr = thisBusNr; - } - } - - /* If we already have a busNR = 1, then we can't auto-assign (0 is - * the pci[e]-root, and the others may have been assigned - * purposefully). - */ - if (lowestBusNr <= 2) - return -1; - - return lowestBusNr - 2; -} - virDomainPCIAddressSetPtr qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, bool virtioMMIOEnabled, @@ -922,7 +436,7 @@ qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, nbuses = max_idx + 1; - if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, false))) + if (!(addrs = virDomainPCIAddressSetCreate(def, nbuses, false))) goto cleanup; if (qemuDomainSupportsPCI(def, gpexEnabled)) { @@ -930,7 +444,7 @@ qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, videoPrimaryEnabled) < 0) goto cleanup; - if (qemuDomainAssignDevicePCISlots(def, addrs, virtioMMIOEnabled) < 0) + if (virDomainAssignDevicePCISlots(def, addrs, virtioMMIOEnabled) < 0) goto cleanup; } @@ -974,7 +488,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, virDomainDeviceInfo info; /* 1st pass to figure out how many PCI bridges we need */ - if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses, true))) + if (!(addrs = virDomainPCIAddressSetCreate(def, nbuses, true))) goto cleanup; if (virDomainValidateDevicePCISlotsChipsets(def, addrs, @@ -982,7 +496,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, goto cleanup; for (i = 0; i < addrs->nbuses; i++) { - if (!qemuDomainPCIBusFullyReserved(&addrs->buses[i])) + if (!virDomainPCIBusFullyReserved(&addrs->buses[i])) buses_reserved = false; } @@ -999,7 +513,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0) goto cleanup; - if (qemuDomainAssignDevicePCISlots(def, addrs, virtioMMIOEnabled) < 0) + if (virDomainAssignDevicePCISlots(def, addrs, virtioMMIOEnabled) < 0) goto cleanup; for (i = 1; i < addrs->nbuses; i++) { @@ -1074,7 +588,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: if (options->busNr == -1) - options->busNr = qemuDomainAddressFindNewBusNr(def); + options->busNr = virDomainAddressFindNewBusNr(def); if (options->busNr == -1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("No free busNr lower than current " -- 2.7.4 (Apple Git-66)

qemuDomainMachineIsVirt is renamed to virDomainMachineIsVirt and moved from qemu_domain_addr.c to domain_addr.c All these functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 15 +++++++++++++++ src/conf/domain_addr.h | 3 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 2 +- src/qemu/qemu_command.c | 4 ++-- src/qemu/qemu_domain.c | 24 ++++-------------------- src/qemu/qemu_domain.h | 1 - src/qemu/qemu_domain_address.c | 6 +++--- 8 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 32943e8..3a9c44d 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -2217,3 +2217,18 @@ virDomainAssignDevicePCISlots(virDomainDefPtr def, error: return -1; } + + +bool +virDomainMachineIsVirt(const virDomainDef *def) +{ + if (def->os.arch != VIR_ARCH_ARMV7L && + def->os.arch != VIR_ARCH_AARCH64) + return false; + + if (STRNEQ(def->os.machine, "virt") && + !STRPREFIX(def->os.machine, "virt-")) + return false; + + return true; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index a1e572b..7ecdac3 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -282,4 +282,7 @@ virDomainAssignDevicePCISlots(virDomainDefPtr def, bool virtioMMIOEnabled) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +bool +virDomainMachineIsVirt(const virDomainDef *def); + #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 66144fd..e02f453 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -97,6 +97,7 @@ virDomainCollectPCIAddress; virDomainGetBlkioParametersAssignFromDef; virDomainMachineIsI440FX; virDomainMachineIsQ35; +virDomainMachineIsVirt; virDomainPCIAddressAsString; virDomainPCIAddressBusSetModel; virDomainPCIAddressEnsureAddr; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 6989a87..464262d 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2179,7 +2179,7 @@ bool virQEMUCapsHasPCIMultiBus(virQEMUCapsPtr qemuCaps, /* If 'virt' supports PCI, it supports multibus. * No extra conditions here for simplicity. */ - if (qemuDomainMachineIsVirt(def)) + if (virDomainMachineIsVirt(def)) return true; return false; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 24295bd..512c926 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2870,7 +2870,7 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd, if (usbcontroller == 0 && !virDomainMachineIsQ35(def) && - !qemuDomainMachineIsVirt(def) && + !virDomainMachineIsVirt(def) && !ARCH_IS_S390(def->os.arch)) virCommandAddArg(cmd, "-usb"); @@ -6855,7 +6855,7 @@ qemuBuildMachineCommandLine(virCommandPtr cmd, if (def->features[VIR_DOMAIN_FEATURE_GIC] == VIR_TRISTATE_SWITCH_ON) { if (def->gic_version != VIR_GIC_VERSION_NONE) { - if (!qemuDomainMachineIsVirt(def)) { + if (!virDomainMachineIsVirt(def)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("gic-version option is available " "only for ARM virt machine")); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 8c23157..6270c8e 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1957,7 +1957,7 @@ qemuDomainDefAddDefaultDevices(virDomainDefPtr def, case VIR_ARCH_AARCH64: addDefaultUSB = false; addDefaultMemballoon = false; - if (qemuDomainMachineIsVirt(def)) + if (virDomainMachineIsVirt(def)) addPCIeRoot = virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_GPEX); break; @@ -2056,7 +2056,7 @@ qemuDomainDefAddDefaultDevices(virDomainDefPtr def, * be able to have a pure virtio-mmio topology */ if (virDomainControllerFind(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 1) < 0 && - !qemuDomainMachineIsVirt(def) && + !virDomainMachineIsVirt(def) && !virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 1, VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE)) goto cleanup; @@ -2131,7 +2131,7 @@ qemuDomainDefEnableDefaultFeatures(virDomainDefPtr def, * was not included in the domain XML, we need to choose a suitable * GIC version ourselves */ if (def->features[VIR_DOMAIN_FEATURE_GIC] == VIR_TRISTATE_SWITCH_ABSENT && - qemuDomainMachineIsVirt(def)) { + virDomainMachineIsVirt(def)) { VIR_DEBUG("Looking for usable GIC version in domain capabilities"); for (version = VIR_GIC_VERSION_LAST - 1; @@ -2334,7 +2334,7 @@ qemuDomainDefaultNetModel(const virDomainDef *def, if (STREQ(def->os.machine, "versatilepb")) return "smc91c111"; - if (qemuDomainMachineIsVirt(def)) + if (virDomainMachineIsVirt(def)) return "virtio"; /* Incomplete. vexpress (and a few others) use this, but not all @@ -5015,22 +5015,6 @@ qemuDomainMachineIsS390CCW(const virDomainDef *def) return STRPREFIX(def->os.machine, "s390-ccw"); } - -bool -qemuDomainMachineIsVirt(const virDomainDef *def) -{ - if (def->os.arch != VIR_ARCH_ARMV7L && - def->os.arch != VIR_ARCH_AARCH64) - return false; - - if (STRNEQ(def->os.machine, "virt") && - !STRPREFIX(def->os.machine, "virt-")) - return false; - - return true; -} - - bool qemuDomainMachineIsPSeries(const virDomainDef *def) { diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 81086d9..99f265e 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -624,7 +624,6 @@ virDomainChrDefPtr qemuFindAgentConfig(virDomainDefPtr def); bool qemuDomainMachineNeedsFDC(const virDomainDef *def); bool qemuDomainMachineIsS390CCW(const virDomainDef *def); -bool qemuDomainMachineIsVirt(const virDomainDef *def); bool qemuDomainMachineIsPSeries(const virDomainDef *def); bool qemuDomainMachineHasBuiltinIDE(const virDomainDef *def); diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index a0bc752..be790ec 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -350,7 +350,7 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def, return; if (!(STRPREFIX(def->os.machine, "vexpress-") || - qemuDomainMachineIsVirt(def))) + virDomainMachineIsVirt(def))) return; if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO)) { @@ -370,7 +370,7 @@ qemuDomainSupportsPCI(virDomainDefPtr def, if (STREQ(def->os.machine, "versatilepb")) return true; - if (qemuDomainMachineIsVirt(def) && + if (virDomainMachineIsVirt(def) && gpexEnabled) return true; @@ -509,7 +509,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, * a dmi-to-pci-bridge to an otherwise PCI-free topology */ if (!buses_reserved && - !qemuDomainMachineIsVirt(def) && + !virDomainMachineIsVirt(def) && virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0) goto cleanup; -- 2.7.4 (Apple Git-66)

qemuDomainSupportsPCI is renamed to virDomainSupportsPCI and moved from qemu_domain_address.c to domain_addr.c All these functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 18 ++++++++++++++++++ src/conf/domain_addr.h | 5 +++++ src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 22 ++-------------------- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 3a9c44d..3ac7d3f 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -2232,3 +2232,21 @@ virDomainMachineIsVirt(const virDomainDef *def) return true; } + + +bool +virDomainSupportsPCI(virDomainDefPtr def, + bool gpexEnabled) +{ + if ((def->os.arch != VIR_ARCH_ARMV7L) && (def->os.arch != VIR_ARCH_AARCH64)) + return true; + + if (STREQ(def->os.machine, "versatilepb")) + return true; + + if (virDomainMachineIsVirt(def) && + gpexEnabled) + return true; + + return false; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 7ecdac3..f06ae46 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -285,4 +285,9 @@ virDomainAssignDevicePCISlots(virDomainDefPtr def, bool virDomainMachineIsVirt(const virDomainDef *def); +bool +virDomainSupportsPCI(virDomainDefPtr def, + bool gpexEnabled) + ATTRIBUTE_NONNULL(1); + #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e02f453..9d1024b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -114,6 +114,7 @@ virDomainPCIAddressSlotInUse; virDomainPCIAddressValidate; virDomainPCIBusFullyReserved; virDomainPCIControllerModelToConnectType; +virDomainSupportsPCI; virDomainValidateDevicePCISlotsChipsets; virDomainValidateDevicePCISlotsPIIX3; virDomainValidateDevicePCISlotsQ35; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index be790ec..795fcd0 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -360,24 +360,6 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def, } -static bool -qemuDomainSupportsPCI(virDomainDefPtr def, - bool gpexEnabled) -{ - if ((def->os.arch != VIR_ARCH_ARMV7L) && (def->os.arch != VIR_ARCH_AARCH64)) - return true; - - if (STREQ(def->os.machine, "versatilepb")) - return true; - - if (virDomainMachineIsVirt(def) && - gpexEnabled) - return true; - - return false; -} - - static void qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) { @@ -439,7 +421,7 @@ qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, if (!(addrs = virDomainPCIAddressSetCreate(def, nbuses, false))) goto cleanup; - if (qemuDomainSupportsPCI(def, gpexEnabled)) { + if (virDomainSupportsPCI(def, gpexEnabled)) { if (virDomainValidateDevicePCISlotsChipsets(def, addrs, videoPrimaryEnabled) < 0) goto cleanup; @@ -545,7 +527,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, gpexEnabled))) goto cleanup; - if (qemuDomainSupportsPCI(def, gpexEnabled)) { + if (virDomainSupportsPCI(def, gpexEnabled)) { for (i = 0; i < def->ncontrollers; i++) { virDomainControllerDefPtr cont = def->controllers[i]; int idx = cont->idx; -- 2.7.4 (Apple Git-66)

qemuDomainPCIAddrSetCreateFromDomain is renamed to virDomainPCIAddrSetCreateFromDomain and moved from qemu_domain_address.c to domain_addr.c All these functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 43 ++++++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 7 +++++++ src/libvirt_private.syms | 1 + src/qemu/qemu_domain_address.c | 43 +----------------------------------------- src/qemu/qemu_domain_address.h | 6 ------ src/qemu/qemu_hotplug.c | 12 ++++++------ 6 files changed, 58 insertions(+), 54 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 3ac7d3f..ec68ca0 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -2250,3 +2250,46 @@ virDomainSupportsPCI(virDomainDefPtr def, return false; } + + +virDomainPCIAddressSetPtr +virDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, + bool virtioMMIOEnabled, + bool videoPrimaryEnabled, + bool gpexEnabled) +{ + virDomainPCIAddressSetPtr addrs = NULL; + int max_idx = -1; + int nbuses = 0; + virDomainPCIAddressSetPtr ret = NULL; + size_t i; + + 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 (!(addrs = virDomainPCIAddressSetCreate(def, nbuses, false))) + goto cleanup; + + if (virDomainSupportsPCI(def, gpexEnabled)) { + if (virDomainValidateDevicePCISlotsChipsets(def, addrs, + videoPrimaryEnabled) < 0) + goto cleanup; + + if (virDomainAssignDevicePCISlots(def, addrs, virtioMMIOEnabled) < 0) + goto cleanup; + } + + ret = addrs; + addrs = NULL; + + cleanup: + virDomainPCIAddressSetFree(addrs); + + return ret; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index f06ae46..5bfec3b 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -290,4 +290,11 @@ virDomainSupportsPCI(virDomainDefPtr def, bool gpexEnabled) ATTRIBUTE_NONNULL(1); +virDomainPCIAddressSetPtr +virDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, + bool virtioMMIOEnabled, + bool videoPrimaryEnabled, + bool gpexEnabled) + ATTRIBUTE_NONNULL(1); + #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 9d1024b..a111f02 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -112,6 +112,7 @@ virDomainPCIAddressSetFree; virDomainPCIAddressSetGrow; virDomainPCIAddressSlotInUse; virDomainPCIAddressValidate; +virDomainPCIAddrSetCreateFromDomain; virDomainPCIBusFullyReserved; virDomainPCIControllerModelToConnectType; virDomainSupportsPCI; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 795fcd0..2754623 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -397,47 +397,6 @@ qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) } } -virDomainPCIAddressSetPtr -qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, - bool virtioMMIOEnabled, - bool videoPrimaryEnabled, - bool gpexEnabled) -{ - virDomainPCIAddressSetPtr addrs = NULL; - int max_idx = -1; - int nbuses = 0; - virDomainPCIAddressSetPtr ret = NULL; - size_t i; - - 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 (!(addrs = virDomainPCIAddressSetCreate(def, nbuses, false))) - goto cleanup; - - if (virDomainSupportsPCI(def, gpexEnabled)) { - if (virDomainValidateDevicePCISlotsChipsets(def, addrs, - videoPrimaryEnabled) < 0) - goto cleanup; - - if (virDomainAssignDevicePCISlots(def, addrs, virtioMMIOEnabled) < 0) - goto cleanup; - } - - ret = addrs; - addrs = NULL; - - cleanup: - virDomainPCIAddressSetFree(addrs); - - return ret; -} static int qemuDomainAssignPCIAddresses(virDomainDefPtr def, @@ -521,7 +480,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def, goto cleanup; } - if (!(addrs = qemuDomainPCIAddrSetCreateFromDomain(def, + if (!(addrs = virDomainPCIAddrSetCreateFromDomain(def, virtioMMIOEnabled, videoPrimaryEnabled, gpexEnabled))) diff --git a/src/qemu/qemu_domain_address.h b/src/qemu/qemu_domain_address.h index 77a5541..b6ef65d 100644 --- a/src/qemu/qemu_domain_address.h +++ b/src/qemu/qemu_domain_address.h @@ -41,12 +41,6 @@ virDomainCCWAddressSetPtr qemuDomainCCWAddrSetCreateFromDomain(virDomainDefPtr def) ATTRIBUTE_NONNULL(1); -virDomainPCIAddressSetPtr -qemuDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, - bool virtioMMIOEnabled, - bool videoPrimaryEnabled, - bool gpexEnabled) - ATTRIBUTE_NONNULL(1); # define __QEMU_DOMAIN_ADDRESS_H__ diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index fa7a8e9..a193cc0 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -334,7 +334,7 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn, goto error; } else if (!disk->info.type || disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { - if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, + if (!(pciaddrs = virDomainPCIAddrSetCreateFromDomain(vm->def, virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) @@ -456,7 +456,7 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { - if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, + if (!(pciaddrs = virDomainPCIAddrSetCreateFromDomain(vm->def, virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) @@ -976,7 +976,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, _("virtio-s390 net device cannot be hotplugged.")); goto cleanup; } else { - if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, + if (!(pciaddrs = virDomainPCIAddrSetCreateFromDomain(vm->def, virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) @@ -1258,7 +1258,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0) goto error; - if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, + if (!(pciaddrs = virDomainPCIAddrSetCreateFromDomain(vm->def, virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) @@ -1507,7 +1507,7 @@ qemuDomainAttachChrDeviceAssignAddr(virDomainDefPtr def, } else if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL && chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI) { - if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(def, + if (!(pciaddrs = virDomainPCIAddrSetCreateFromDomain(def, virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) @@ -1638,7 +1638,7 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver, if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { - if (!(pciaddrs = qemuDomainPCIAddrSetCreateFromDomain(vm->def, + if (!(pciaddrs = virDomainPCIAddrSetCreateFromDomain(vm->def, virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_MMIO), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY), virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_GPEX)))) -- 2.7.4 (Apple Git-66)

qemuDomainPCIControllerSetDefaultModelName is renamed to qemuDomainAssignPCIAddresses is renamed to virDomainAssignPCIAddresses Both are moved from qemu_domain_addr.c to domain_addr.c All these functions are being moved because they don't depend on qemu, so they have the potential to be reused for more hypervisors. --- src/conf/domain_addr.c | 212 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 12 +++ src/libvirt_private.syms | 2 + src/qemu/qemu_domain_address.c | 214 +---------------------------------------- 4 files changed, 227 insertions(+), 213 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index ec68ca0..fa25272 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -2293,3 +2293,215 @@ virDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, return ret; } + + +void +virDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) +{ + int *modelName = &cont->opts.pciopts.modelName; + + /* make sure it's not already set */ + if (*modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) + return; + switch ((virDomainControllerModelPCI)cont->model) { + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: + break; + } +} + + +int +virDomainAssignPCIAddresses(virDomainDefPtr def, + bool pciBridgeEnabled, + bool virtioMMIOEnabled, + bool videoPrimaryEnabled, + bool gpexEnabled) +{ + int ret = -1; + virDomainPCIAddressSetPtr addrs = NULL; + int max_idx = -1; + int nbuses = 0; + size_t i; + int rv; + bool buses_reserved = true; + + virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; + + 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 && + pciBridgeEnabled) { + virDomainDeviceInfo info; + + /* 1st pass to figure out how many PCI bridges we need */ + if (!(addrs = virDomainPCIAddressSetCreate(def, nbuses, true))) + goto cleanup; + + if (virDomainValidateDevicePCISlotsChipsets(def, addrs, + videoPrimaryEnabled) < 0) + goto cleanup; + + for (i = 0; i < addrs->nbuses; i++) { + if (!virDomainPCIBusFullyReserved(&addrs->buses[i])) + buses_reserved = false; + } + + /* Reserve 1 extra slot for a (potential) bridge only if buses + * are not fully reserved yet. + * + * We don't reserve the extra slot for aarch64 mach-virt guests + * either because we want to be able to have pure virtio-mmio + * guests, and reserving this slot would force us to add at least + * a dmi-to-pci-bridge to an otherwise PCI-free topology + */ + if (!buses_reserved && + !virDomainMachineIsVirt(def) && + virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0) + goto cleanup; + + if (virDomainAssignDevicePCISlots(def, addrs, virtioMMIOEnabled) < 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 = virDomainPCIAddrSetCreateFromDomain(def, + virtioMMIOEnabled, + videoPrimaryEnabled, + gpexEnabled))) + goto cleanup; + + if (virDomainSupportsPCI(def, gpexEnabled)) { + for (i = 0; i < def->ncontrollers; i++) { + virDomainControllerDefPtr cont = def->controllers[i]; + int idx = cont->idx; + virPCIDeviceAddressPtr addr; + virDomainPCIControllerOptsPtr options; + + if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI) + continue; + + addr = &cont->info.addr.pci; + options = &cont->opts.pciopts; + + /* set default model name (the actual name of the + * device in qemu) for any controller that doesn't yet + * have it set. + */ + virDomainPCIControllerSetDefaultModelName(cont); + + /* 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->chassisNr == -1) + options->chassisNr = cont->idx; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: + 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_DOWNSTREAM_PORT: + if (options->chassis == -1) + options->chassis = cont->idx; + if (options->port == -1) + options->port = addr->slot; + break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: + if (options->busNr == -1) + options->busNr = virDomainAddressFindNewBusNr(def); + if (options->busNr == -1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("No free busNr lower than current " + "lowest busNr is available to " + "auto-assign to bus %d. Must be " + "manually assigned"), + addr->bus); + goto cleanup; + } + break; + case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: + 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 index is larger than + * the bus it is placed onto + */ + if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE && + idx <= addr->bus) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("PCI controller at index %d (0x%02x) has " + "bus='0x%02x', but index must be " + "larger than bus"), + idx, idx, addr->bus); + goto cleanup; + } + } + } + + ret = 0; + + cleanup: + virDomainPCIAddressSetFree(addrs); + + return ret; +} diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 5bfec3b..49ddf09 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -297,4 +297,16 @@ virDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, bool gpexEnabled) ATTRIBUTE_NONNULL(1); +int +virDomainAssignPCIAddresses(virDomainDefPtr def, + bool pciBridgeEnabled, + bool virtioMMIOEnabled, + bool videoPrimaryEnabled, + bool gpexEnabled) + ATTRIBUTE_NONNULL(1); + +void +virDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) + ATTRIBUTE_NONNULL(1); + #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a111f02..f4e7b45 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -87,6 +87,7 @@ virPCIDeviceAddressParseXML; # conf/domain_addr.h virDomainAddressFindNewBusNr; virDomainAssignDevicePCISlots; +virDomainAssignPCIAddresses; virDomainAssignVirtioSerialAddresses; virDomainCCWAddressAllocate; virDomainCCWAddressAssign; @@ -115,6 +116,7 @@ virDomainPCIAddressValidate; virDomainPCIAddrSetCreateFromDomain; virDomainPCIBusFullyReserved; virDomainPCIControllerModelToConnectType; +virDomainPCIControllerSetDefaultModelName; virDomainSupportsPCI; virDomainValidateDevicePCISlotsChipsets; virDomainValidateDevicePCISlotsPIIX3; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 2754623..0e54f43 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -360,218 +360,6 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def, } -static void -qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) -{ - int *modelName = &cont->opts.pciopts.modelName; - - /* make sure it's not already set */ - if (*modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE) - return; - switch ((virDomainControllerModelPCI)cont->model) { - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: - *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: - *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: - *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_X3130_UPSTREAM; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT: - *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_XIO3130_DOWNSTREAM; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: - *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: - *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST: - break; - } -} - - -static int -qemuDomainAssignPCIAddresses(virDomainDefPtr def, - bool pciBridgeEnabled, - bool virtioMMIOEnabled, - bool videoPrimaryEnabled, - bool gpexEnabled) -{ - int ret = -1; - virDomainPCIAddressSetPtr addrs = NULL; - int max_idx = -1; - int nbuses = 0; - size_t i; - int rv; - bool buses_reserved = true; - - virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE; - - 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 && - pciBridgeEnabled) { - virDomainDeviceInfo info; - - /* 1st pass to figure out how many PCI bridges we need */ - if (!(addrs = virDomainPCIAddressSetCreate(def, nbuses, true))) - goto cleanup; - - if (virDomainValidateDevicePCISlotsChipsets(def, addrs, - videoPrimaryEnabled) < 0) - goto cleanup; - - for (i = 0; i < addrs->nbuses; i++) { - if (!virDomainPCIBusFullyReserved(&addrs->buses[i])) - buses_reserved = false; - } - - /* Reserve 1 extra slot for a (potential) bridge only if buses - * are not fully reserved yet. - * - * We don't reserve the extra slot for aarch64 mach-virt guests - * either because we want to be able to have pure virtio-mmio - * guests, and reserving this slot would force us to add at least - * a dmi-to-pci-bridge to an otherwise PCI-free topology - */ - if (!buses_reserved && - !virDomainMachineIsVirt(def) && - virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0) - goto cleanup; - - if (virDomainAssignDevicePCISlots(def, addrs, virtioMMIOEnabled) < 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 = virDomainPCIAddrSetCreateFromDomain(def, - virtioMMIOEnabled, - videoPrimaryEnabled, - gpexEnabled))) - goto cleanup; - - if (virDomainSupportsPCI(def, gpexEnabled)) { - for (i = 0; i < def->ncontrollers; i++) { - virDomainControllerDefPtr cont = def->controllers[i]; - int idx = cont->idx; - virPCIDeviceAddressPtr addr; - virDomainPCIControllerOptsPtr options; - - if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI) - continue; - - addr = &cont->info.addr.pci; - options = &cont->opts.pciopts; - - /* set default model name (the actual name of the - * device in qemu) for any controller that doesn't yet - * have it set. - */ - qemuDomainPCIControllerSetDefaultModelName(cont); - - /* 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->chassisNr == -1) - options->chassisNr = cont->idx; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: - 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_DOWNSTREAM_PORT: - if (options->chassis == -1) - options->chassis = cont->idx; - if (options->port == -1) - options->port = addr->slot; - break; - case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS: - if (options->busNr == -1) - options->busNr = virDomainAddressFindNewBusNr(def); - if (options->busNr == -1) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("No free busNr lower than current " - "lowest busNr is available to " - "auto-assign to bus %d. Must be " - "manually assigned"), - addr->bus); - goto cleanup; - } - break; - case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE: - case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT: - 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 index is larger than - * the bus it is placed onto - */ - if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE && - idx <= addr->bus) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("PCI controller at index %d (0x%02x) has " - "bus='0x%02x', but index must be " - "larger than bus"), - idx, idx, addr->bus); - goto cleanup; - } - } - } - - ret = 0; - - cleanup: - virDomainPCIAddressSetFree(addrs); - - return ret; -} - - int qemuDomainAssignAddresses(virDomainDefPtr def, virQEMUCapsPtr qemuCaps, @@ -594,7 +382,7 @@ qemuDomainAssignAddresses(virDomainDefPtr def, qemuDomainAssignARMVirtioMMIOAddresses(def, qemuCaps); - if (qemuDomainAssignPCIAddresses(def, pciBridgeEnabled, virtioMMIOEnabled, + if (virDomainAssignPCIAddresses(def, pciBridgeEnabled, virtioMMIOEnabled, videoPrimaryEnabled, gpexEnabled) < 0) return -1; -- 2.7.4 (Apple Git-66)

The process of moving functions from qemu_domain_address.c to domain_addr.c is finished, so some of these functions can be declared static if they aren't used anywhere outside. --- src/conf/domain_addr.c | 20 +++++++++--------- src/conf/domain_addr.h | 53 ------------------------------------------------ src/libvirt_private.syms | 10 --------- 3 files changed, 10 insertions(+), 73 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index fa25272..7abe44c 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -1230,7 +1230,7 @@ virDomainAssignVirtioSerialAddresses(virDomainDefPtr def) } -int +static int virDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, virDomainDeviceDefPtr device, virDomainDeviceInfoPtr info, @@ -1390,7 +1390,7 @@ virDomainMachineIsI440FX(const virDomainDef *def) } -int +static int virDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, virDomainPCIAddressSetPtr addrs, bool videoPrimaryEnabled) @@ -1523,7 +1523,7 @@ virDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, } -int +static int virDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, virDomainPCIAddressSetPtr addrs, bool videoPrimaryEnabled) @@ -1714,7 +1714,7 @@ virDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, } -int +static int virDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, virDomainPCIAddressSetPtr addrs, bool videoPrimaryEnabled) @@ -1733,7 +1733,7 @@ virDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, } -int +static int virDomainAddressFindNewBusNr(virDomainDefPtr def) { /* Try to find a nice default for busNr for a new pci-expander-bus. @@ -1801,7 +1801,7 @@ virDomainAddressFindNewBusNr(virDomainDefPtr def) } -virDomainPCIAddressSetPtr +static virDomainPCIAddressSetPtr virDomainPCIAddressSetCreate(virDomainDefPtr def, unsigned int nbuses, bool dryRun) @@ -1859,7 +1859,7 @@ virDomainPCIAddressSetCreate(virDomainDefPtr def, } -bool +static bool virDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus) { size_t i; @@ -1908,7 +1908,7 @@ virDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus) * function must only try to reserve addresses if info.type == NONE and * skip over info.type == PCI */ -int +static int virDomainAssignDevicePCISlots(virDomainDefPtr def, virDomainPCIAddressSetPtr addrs, bool virtioMMIOEnabled) @@ -2234,7 +2234,7 @@ virDomainMachineIsVirt(const virDomainDef *def) } -bool +static bool virDomainSupportsPCI(virDomainDefPtr def, bool gpexEnabled) { @@ -2295,7 +2295,7 @@ virDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, } -void +static void virDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) { int *modelName = &cont->opts.pciopts.modelName; diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 49ddf09..8fa6f60 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -232,64 +232,15 @@ int virDomainAssignVirtioSerialAddresses(virDomainDefPtr def) ATTRIBUTE_NONNULL(1); -int -virDomainCollectPCIAddress(virDomainDefPtr def, - virDomainDeviceDefPtr device, - virDomainDeviceInfoPtr info, - void *opaque); - bool virDomainMachineIsQ35(const virDomainDef *def); bool virDomainMachineIsI440FX(const virDomainDef *def); -int -virDomainValidateDevicePCISlotsPIIX3(virDomainDefPtr def, - virDomainPCIAddressSetPtr addrs, - bool videoPrimaryEnabled) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - -int -virDomainValidateDevicePCISlotsQ35(virDomainDefPtr def, - virDomainPCIAddressSetPtr addrs, - bool videoPrimaryEnabled) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - -int -virDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, - virDomainPCIAddressSetPtr addrs, - bool videoPrimaryEnabled) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - -int -virDomainAddressFindNewBusNr(virDomainDefPtr def) - ATTRIBUTE_NONNULL(1); - -virDomainPCIAddressSetPtr -virDomainPCIAddressSetCreate(virDomainDefPtr def, - unsigned int nbuses, - bool dryRun) - ATTRIBUTE_NONNULL(1); - -bool -virDomainPCIBusFullyReserved(virDomainPCIAddressBusPtr bus) - ATTRIBUTE_NONNULL(1); - -int -virDomainAssignDevicePCISlots(virDomainDefPtr def, - virDomainPCIAddressSetPtr addrs, - bool virtioMMIOEnabled) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - bool virDomainMachineIsVirt(const virDomainDef *def); -bool -virDomainSupportsPCI(virDomainDefPtr def, - bool gpexEnabled) - ATTRIBUTE_NONNULL(1); - virDomainPCIAddressSetPtr virDomainPCIAddrSetCreateFromDomain(virDomainDefPtr def, bool virtioMMIOEnabled, @@ -305,8 +256,4 @@ virDomainAssignPCIAddresses(virDomainDefPtr def, bool gpexEnabled) ATTRIBUTE_NONNULL(1); -void -virDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont) - ATTRIBUTE_NONNULL(1); - #endif /* __DOMAIN_ADDR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f4e7b45..b3f1ded 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -85,8 +85,6 @@ virPCIDeviceAddressParseXML; # conf/domain_addr.h -virDomainAddressFindNewBusNr; -virDomainAssignDevicePCISlots; virDomainAssignPCIAddresses; virDomainAssignVirtioSerialAddresses; virDomainCCWAddressAllocate; @@ -94,7 +92,6 @@ virDomainCCWAddressAssign; virDomainCCWAddressSetCreate; virDomainCCWAddressSetFree; virDomainCCWAddressValidate; -virDomainCollectPCIAddress; virDomainGetBlkioParametersAssignFromDef; virDomainMachineIsI440FX; virDomainMachineIsQ35; @@ -108,19 +105,12 @@ virDomainPCIAddressReserveAddr; virDomainPCIAddressReserveNextSlot; virDomainPCIAddressReserveSlot; virDomainPCIAddressSetAlloc; -virDomainPCIAddressSetCreate; virDomainPCIAddressSetFree; virDomainPCIAddressSetGrow; virDomainPCIAddressSlotInUse; virDomainPCIAddressValidate; virDomainPCIAddrSetCreateFromDomain; -virDomainPCIBusFullyReserved; virDomainPCIControllerModelToConnectType; -virDomainPCIControllerSetDefaultModelName; -virDomainSupportsPCI; -virDomainValidateDevicePCISlotsChipsets; -virDomainValidateDevicePCISlotsPIIX3; -virDomainValidateDevicePCISlotsQ35; virDomainVirtioSerialAddrAssign; virDomainVirtioSerialAddrAutoAssign; virDomainVirtioSerialAddrIsComplete; -- 2.7.4 (Apple Git-66)

On 07/19/2016 08:07 PM, Tomasz Flendrich wrote:
This series depends on another one: https://www.redhat.com/archives/libvir-list/2016-July/msg00696.html
Because the address sets are no longer cached, it's possible to move functions that don't depend on qemu anymore from qemu_domain_address.c to domain_addr.c. I did that with virtioSerial and PCI.
To make some functions not dependent on qemuCaps, their parameters were changed to booleans. These changes are in [PATCH 02/13].
If you are satisfied with this approach, I can do the same with the rest of the functions or just some of them.
The problem is that many/most these functions are by definition qemu-specific - only the qemu driver has any concept of a Q35 machinetype or a PIIX3 controller (actually that function should probably have used "i440fx" instead of PIIX3) or an aarch64 "virt" machinetype, or any use for a "busNr" etc etc. So moving them from qemu into conf is busy-work that is counter-productive. I guess you're wanting to move these into conf because they are related to and used by functions that are assigning/allocating PCI addresses, and you want that to be done in a driver-agnostic place. I don't think simply moving all these driver-specific functions into driver-agnostic files and declaring them driver-agnostic is the right approach though. The "pre-loading/validation" of addresses in these functions based on hardware and qemu capabilities should either be called from qemu-specific code prior to calling a driver-agnostic address allocation/assignment function, or the driver-agnostic function should do a callback back into qemu to pre-load/validate the addresses. Beyond that, each PCI controller needs flags to indicate what type of slots (and how many) it provides, which is driver-specific and so needs to be provided by a callback into a driver-specific function, and as each device is assigned we need to determine what type of slot it can plug into, which will also be driver-specific and thus require a callback into a driver-specific function. This (functions to provide the slot-type-compatibility flags for controllers and devices) was something I was about to work on before I left for a two week vacation that turned into 3 due to "social unrest" (and I've now spent nearly a week just catching up on email). I have a lot of accumulated bits of knowledge about this in my brain that I need to dump into code, the sooner the better.
Tomasz Flendrich (13): Move and rename qemuDomainAssignVirtioSerialAddresses make pci address handling functions qemu-agnostic Move and rename qemuDomainCollectPCIAddress Move and rename qemuDomainMachineIsQ35 et al Move and rename qemuDomainValidateDevicePCISlotsPIIX3 Move and rename qemuDomainValidateDevicePCISlotsQ35 Move and rename qemuDomainValidateDevicePCISlotsChipsets Move and rename qemuDomainAddressFindNewBusNr et al Move and rename qemuDomainMachineIsVirt Move and rename qemuDomainSupportsPCI Move and rename qemuDomainPCIAddrSetCreateFromDomain Move and rename qemuDomainAssignPCIAddresses et al Make functions in qemu_domain_address static
src/conf/domain_addr.c | 1315 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_addr.h | 28 + src/libvirt_private.syms | 6 + src/qemu/qemu_alias.c | 2 +- src/qemu/qemu_capabilities.c | 6 +- src/qemu/qemu_command.c | 20 +- src/qemu/qemu_domain.c | 55 +- src/qemu/qemu_domain.h | 3 - src/qemu/qemu_domain_address.c | 1284 +-------------------------------------- src/qemu/qemu_domain_address.h | 4 - src/qemu/qemu_hotplug.c | 33 +- 11 files changed, 1406 insertions(+), 1350 deletions(-)

On Thu, Jul 28, 2016 at 07:00:40PM -0400, Laine Stump wrote:
On 07/19/2016 08:07 PM, Tomasz Flendrich wrote:
This series depends on another one: https://www.redhat.com/archives/libvir-list/2016-July/msg00696.html
Because the address sets are no longer cached, it's possible to move functions that don't depend on qemu anymore from qemu_domain_address.c to domain_addr.c. I did that with virtioSerial and PCI.
To make some functions not dependent on qemuCaps, their parameters were changed to booleans. These changes are in [PATCH 02/13].
If you are satisfied with this approach, I can do the same with the rest of the functions or just some of them.
The problem is that many/most these functions are by definition qemu-specific - only the qemu driver has any concept of a Q35 machinetype or a PIIX3 controller (actually that function should probably have used "i440fx" instead of PIIX3) or an aarch64 "virt" machinetype, or any use for a "busNr" etc etc. So moving them from qemu into conf is busy-work that is counter-productive.
Agreed, I would consider it to be mandatary to separate the general address handling logic (which could be in conf) from the logic that assigns addresses for specific QEMU machine types (which should always remain in the QEMU drive dir). Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (3)
-
Daniel P. Berrange
-
Laine Stump
-
Tomasz Flendrich