Move sharable PCI handling functions to domain_addr.[ch], and
change theirs prefix from 'qemu' to 'vir':
- virDomainPCIAddressAsString;
- virDomainPCIAddressBusSetModel;
- virDomainPCIAddressEnsureAddr;
- virDomainPCIAddressFlagsCompatible;
- virDomainPCIAddressGetNextSlot;
- virDomainPCIAddressReleaseSlot;
- virDomainPCIAddressReserveAddr;
- virDomainPCIAddressReserveNextSlot;
- virDomainPCIAddressReserveSlot;
- virDomainPCIAddressSetFree;
- virDomainPCIAddressSetGrow;
- virDomainPCIAddressSlotInUse;
- virDomainPCIAddressValidate;
The only change here is function names, the implementation itself
stays untouched.
Extract common allocation code from DomainPCIAddressSetCreate
into virDomainPCIAddressSetAlloc.
---
po/POTFILES.in | 1 +
src/conf/domain_addr.c | 542 ++++++++++++++++++++++++++++++++++++++
src/conf/domain_addr.h | 70 +++++
src/libvirt_private.syms | 17 ++
src/qemu/qemu_command.c | 671 ++++++-----------------------------------------
src/qemu/qemu_command.h | 18 +-
src/qemu/qemu_domain.c | 3 +-
src/qemu/qemu_hotplug.c | 8 +-
src/qemu/qemu_process.c | 2 +-
9 files changed, 718 insertions(+), 614 deletions(-)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e35eb82..6e8d465 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -14,6 +14,7 @@ src/bhyve/bhyve_process.c
src/conf/capabilities.c
src/conf/cpu_conf.c
src/conf/device_conf.c
+src/conf/domain_addr.c
src/conf/domain_conf.c
src/conf/domain_event.c
src/conf/interface_conf.c
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 73e17aa..34a3fac 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -22,3 +22,545 @@
*/
#include <config.h>
+
+#include "viralloc.h"
+#include "virlog.h"
+#include "virstring.h"
+#include "domain_addr.h"
+
+#define VIR_FROM_THIS VIR_FROM_DOMAIN
+
+VIR_LOG_INIT("conf.domain_addr");
+
+bool
+virDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
+ const char *addrStr,
+ virDomainPCIConnectFlags busFlags,
+ virDomainPCIConnectFlags devFlags,
+ bool reportError,
+ bool fromConfig)
+{
+ virErrorNumber errType = (fromConfig
+ ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
+ virDomainPCIConnectFlags flagsMatchMask = VIR_PCI_CONNECT_TYPES_MASK;
+
+ if (fromConfig)
+ flagsMatchMask |= VIR_PCI_CONNECT_TYPE_EITHER_IF_CONFIG;
+
+ /* If this bus doesn't allow the type of connection (PCI
+ * vs. PCIe) required by the device, or if the device requires
+ * hot-plug and this bus doesn't have it, return false.
+ */
+ if (!(devFlags & busFlags & flagsMatchMask)) {
+ if (reportError) {
+ if (devFlags & VIR_PCI_CONNECT_TYPE_PCI) {
+ virReportError(errType,
+ _("PCI bus is not compatible with the device "
+ "at %s. Device requires a standard PCI slot,
"
+ "which is not provided by bus %.4x:%.2x"),
+ addrStr, addr->domain, addr->bus);
+ } else if (devFlags & VIR_PCI_CONNECT_TYPE_PCIE) {
+ virReportError(errType,
+ _("PCI bus is not compatible with the device "
+ "at %s. Device requires a PCI Express slot, "
+ "which is not provided by bus %.4x:%.2x"),
+ addrStr, addr->domain, addr->bus);
+ } else {
+ /* this should never happen. If it does, there is a
+ * bug in the code that sets the flag bits for devices.
+ */
+ virReportError(errType,
+ _("The device information for %s has no PCI "
+ "connection types listed"), addrStr);
+ }
+ }
+ return false;
+ }
+ if ((devFlags & VIR_PCI_CONNECT_HOTPLUGGABLE) &&
+ !(busFlags & VIR_PCI_CONNECT_HOTPLUGGABLE)) {
+ if (reportError) {
+ virReportError(errType,
+ _("PCI bus is not compatible with the device "
+ "at %s. Device requires hot-plug capability, "
+ "which is not provided by bus %.4x:%.2x"),
+ addrStr, addr->domain, addr->bus);
+ }
+ return false;
+ }
+ return true;
+}
+
+
+/* Verify that the address is in bounds for the chosen bus, and
+ * that the bus is of the correct type for the device (via
+ * comparing the flags).
+ */
+bool
+virDomainPCIAddressValidate(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+ const char *addrStr,
+ virDomainPCIConnectFlags flags,
+ bool fromConfig)
+{
+ virDomainPCIAddressBusPtr bus;
+ virErrorNumber errType = (fromConfig
+ ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
+
+ if (addrs->nbuses == 0) {
+ virReportError(errType, "%s", _("No PCI buses available"));
+ return false;
+ }
+ if (addr->domain != 0) {
+ virReportError(errType,
+ _("Invalid PCI address %s. "
+ "Only PCI domain 0 is available"),
+ addrStr);
+ return false;
+ }
+ if (addr->bus >= addrs->nbuses) {
+ virReportError(errType,
+ _("Invalid PCI address %s. "
+ "Only PCI buses up to %zu are available"),
+ addrStr, addrs->nbuses - 1);
+ return false;
+ }
+
+ bus = &addrs->buses[addr->bus];
+
+ /* assure that at least one of the requested connection types is
+ * provided by this bus
+ */
+ if (!virDomainPCIAddressFlagsCompatible(addr, addrStr, bus->flags,
+ flags, true, fromConfig))
+ return false;
+
+ /* some "buses" are really just a single port */
+ if (bus->minSlot && addr->slot < bus->minSlot) {
+ virReportError(errType,
+ _("Invalid PCI address %s. slot must be >= %zu"),
+ addrStr, bus->minSlot);
+ return false;
+ }
+ if (addr->slot > bus->maxSlot) {
+ virReportError(errType,
+ _("Invalid PCI address %s. slot must be <= %zu"),
+ addrStr, bus->maxSlot);
+ return false;
+ }
+ if (addr->function > VIR_PCI_ADDRESS_FUNCTION_LAST) {
+ virReportError(errType,
+ _("Invalid PCI address %s. function must be <= %u"),
+ addrStr, VIR_PCI_ADDRESS_FUNCTION_LAST);
+ return false;
+ }
+ return true;
+}
+
+
+int
+virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus,
+ virDomainControllerModelPCI model)
+{
+ switch (model) {
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
+ bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
+ VIR_PCI_CONNECT_TYPE_PCI);
+ bus->minSlot = 1;
+ bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
+ /* slots 1 - 31, no hotplug, PCIe only unless the address was
+ * specified in user config *and* the particular device being
+ * attached also allows it
+ */
+ bus->flags = (VIR_PCI_CONNECT_TYPE_PCIE |
+ VIR_PCI_CONNECT_TYPE_EITHER_IF_CONFIG);
+ bus->minSlot = 1;
+ bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+ /* slots 1 - 31, standard PCI slots,
+ * but *not* hot-pluggable */
+ bus->flags = VIR_PCI_CONNECT_TYPE_PCI;
+ bus->minSlot = 1;
+ bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
+ break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invalid PCI controller model %d"), model);
+ return -1;
+ }
+
+ bus->model = model;
+ return 0;
+}
+
+
+/* Ensure addr fits in the address set, by expanding it if needed.
+ * This will only grow if the flags say that we need a normal
+ * hot-pluggable PCI slot. If we need a different type of slot, it
+ * will fail.
+ *
+ * Return value:
+ * -1 = OOM
+ * 0 = no action performed
+ * >0 = number of buses added
+ */
+int
+virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+ virDomainPCIConnectFlags flags)
+{
+ int add;
+ size_t i;
+
+ add = addr->bus - addrs->nbuses + 1;
+ i = addrs->nbuses;
+ if (add <= 0)
+ return 0;
+
+ /* auto-grow only works when we're adding plain PCI devices */
+ if (!(flags & VIR_PCI_CONNECT_TYPE_PCI)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot automatically add a new PCI bus for a "
+ "device requiring a slot other than standard PCI."));
+ return -1;
+ }
+
+ if (VIR_EXPAND_N(addrs->buses, addrs->nbuses, add) < 0)
+ return -1;
+
+ for (; i < addrs->nbuses; i++) {
+ /* Any time we auto-add a bus, we will want a multi-slot
+ * bus. Currently the only type of bus we will auto-add is a
+ * pci-bridge, which is hot-pluggable and provides standard
+ * PCI slots.
+ */
+ virDomainPCIAddressBusSetModel(&addrs->buses[i],
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE);
+ }
+ return add;
+}
+
+
+char *
+virDomainPCIAddressAsString(virDevicePCIAddressPtr addr)
+{
+ char *str;
+
+ ignore_value(virAsprintf(&str, "%.4x:%.2x:%.2x.%.1x",
+ addr->domain,
+ addr->bus,
+ addr->slot,
+ addr->function));
+ return str;
+}
+
+
+/*
+ * Check if the PCI slot is used by another device.
+ */
+bool
+virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr)
+{
+ return !!addrs->buses[addr->bus].slots[addr->slot];
+}
+
+
+/*
+ * Reserve a slot (or just one function) for a device. If
+ * reserveEntireSlot is true, all functions for the slot are reserved,
+ * otherwise only one. If fromConfig is true, the address being
+ * requested came directly from the config and errors should be worded
+ * appropriately. If fromConfig is false, the address was
+ * automatically created by libvirt, so it is an internal error (not
+ * XML).
+ */
+int
+virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+ virDomainPCIConnectFlags flags,
+ bool reserveEntireSlot,
+ bool fromConfig)
+{
+ int ret = -1;
+ char *addrStr = NULL;
+ virDomainPCIAddressBusPtr bus;
+ virErrorNumber errType = (fromConfig
+ ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
+
+ if (!(addrStr = virDomainPCIAddressAsString(addr)))
+ goto cleanup;
+
+ /* Add an extra bus if necessary */
+ if (addrs->dryRun && virDomainPCIAddressSetGrow(addrs, addr, flags) <
0)
+ goto cleanup;
+ /* Check that the requested bus exists, is the correct type, and we
+ * are asking for a valid slot
+ */
+ if (!virDomainPCIAddressValidate(addrs, addr, addrStr, flags, fromConfig))
+ goto cleanup;
+
+ bus = &addrs->buses[addr->bus];
+
+ if (reserveEntireSlot) {
+ if (bus->slots[addr->slot]) {
+ virReportError(errType,
+ _("Attempted double use of PCI slot %s "
+ "(may need \"multifunction='on'\" for
"
+ "device on function 0)"), addrStr);
+ goto cleanup;
+ }
+ bus->slots[addr->slot] = 0xFF; /* reserve all functions of slot */
+ VIR_DEBUG("Reserving PCI slot %s (multifunction='off')",
addrStr);
+ } else {
+ if (bus->slots[addr->slot] & (1 << addr->function)) {
+ if (addr->function == 0) {
+ virReportError(errType,
+ _("Attempted double use of PCI Address %s"),
+ addrStr);
+ } else {
+ virReportError(errType,
+ _("Attempted double use of PCI Address %s "
+ "(may need \"multifunction='on'\"
"
+ "for device on function 0)"), addrStr);
+ }
+ goto cleanup;
+ }
+ bus->slots[addr->slot] |= (1 << addr->function);
+ VIR_DEBUG("Reserving PCI address %s", addrStr);
+ }
+
+ ret = 0;
+ cleanup:
+ VIR_FREE(addrStr);
+ return ret;
+}
+
+
+int
+virDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+ virDomainPCIConnectFlags flags)
+{
+ return virDomainPCIAddressReserveAddr(addrs, addr, flags, true, false);
+}
+
+int
+virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev)
+{
+ int ret = -1;
+ char *addrStr = NULL;
+ /* Flags should be set according to the particular device,
+ * but only the caller knows the type of device. Currently this
+ * function is only used for hot-plug, though, and hot-plug is
+ * only supported for standard PCI devices, so we can safely use
+ * the setting below */
+ virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
+ VIR_PCI_CONNECT_TYPE_PCI);
+
+ if (!(addrStr = virDomainPCIAddressAsString(&dev->addr.pci)))
+ goto cleanup;
+
+ if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+ /* We do not support hotplug multi-function PCI device now, so we should
+ * reserve the whole slot. The function of the PCI device must be 0.
+ */
+ if (dev->addr.pci.function != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Only PCI device addresses with function=0"
+ " are supported"));
+ goto cleanup;
+ }
+
+ if (!virDomainPCIAddressValidate(addrs, &dev->addr.pci,
+ addrStr, flags, true))
+ goto cleanup;
+
+ ret = virDomainPCIAddressReserveSlot(addrs, &dev->addr.pci, flags);
+ } else {
+ ret = virDomainPCIAddressReserveNextSlot(addrs, dev, flags);
+ }
+
+ cleanup:
+ VIR_FREE(addrStr);
+ return ret;
+}
+
+
+int
+virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr)
+{
+ addrs->buses[addr->bus].slots[addr->slot] &= ~(1 <<
addr->function);
+ return 0;
+}
+
+int
+virDomainPCIAddressReleaseSlot(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr)
+{
+ /* permit any kind of connection type in validation, since we
+ * already had it, and are giving it back.
+ */
+ virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPES_MASK;
+ int ret = -1;
+ char *addrStr = NULL;
+
+ if (!(addrStr = virDomainPCIAddressAsString(addr)))
+ goto cleanup;
+
+ if (!virDomainPCIAddressValidate(addrs, addr, addrStr, flags, false))
+ goto cleanup;
+
+ addrs->buses[addr->bus].slots[addr->slot] = 0;
+ ret = 0;
+ cleanup:
+ VIR_FREE(addrStr);
+ return ret;
+}
+
+
+virDomainPCIAddressSetPtr
+virDomainPCIAddressSetAlloc(unsigned int nbuses)
+{
+ virDomainPCIAddressSetPtr addrs;
+
+ if (VIR_ALLOC(addrs) < 0)
+ goto error;
+
+ if (VIR_ALLOC_N(addrs->buses, nbuses) < 0)
+ goto error;
+
+ addrs->nbuses = nbuses;
+ return addrs;
+
+ error:
+ virDomainPCIAddressSetFree(addrs);
+ return NULL;
+}
+
+
+void
+virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs)
+{
+ if (!addrs)
+ return;
+
+ VIR_FREE(addrs->buses);
+ VIR_FREE(addrs);
+}
+
+
+int
+virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr next_addr,
+ virDomainPCIConnectFlags flags)
+{
+ /* default to starting the search for a free slot from
+ * 0000:00:00.0
+ */
+ virDevicePCIAddress a = { 0, 0, 0, 0, false };
+ char *addrStr = NULL;
+
+ /* except if this search is for the exact same type of device as
+ * last time, continue the search from the previous match
+ */
+ if (flags == addrs->lastFlags)
+ a = addrs->lastaddr;
+
+ if (addrs->nbuses == 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses
available"));
+ goto error;
+ }
+
+ /* Start the search at the last used bus and slot */
+ for (a.slot++; a.bus < addrs->nbuses; a.bus++) {
+ if (!(addrStr = virDomainPCIAddressAsString(&a)))
+ goto error;
+ if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
+ addrs->buses[a.bus].flags,
+ flags, false, false)) {
+ VIR_FREE(addrStr);
+ VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
+ a.domain, a.bus);
+ continue;
+ }
+ for (; a.slot <= VIR_PCI_ADDRESS_SLOT_LAST; a.slot++) {
+ if (!virDomainPCIAddressSlotInUse(addrs, &a))
+ goto success;
+
+ VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
+ a.domain, a.bus, a.slot);
+ }
+ a.slot = 1;
+ VIR_FREE(addrStr);
+ }
+
+ /* There were no free slots after the last used one */
+ if (addrs->dryRun) {
+ /* a is already set to the first new bus and slot 1 */
+ if (virDomainPCIAddressSetGrow(addrs, &a, flags) < 0)
+ goto error;
+ goto success;
+ } else if (flags == addrs->lastFlags) {
+ /* Check the buses from 0 up to the last used one */
+ for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) {
+ addrStr = NULL;
+ if (!(addrStr = virDomainPCIAddressAsString(&a)))
+ goto error;
+ if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
+ addrs->buses[a.bus].flags,
+ flags, false, false)) {
+ VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the
device",
+ a.domain, a.bus);
+ continue;
+ }
+ for (a.slot = 1; a.slot <= VIR_PCI_ADDRESS_SLOT_LAST; a.slot++) {
+ if (!virDomainPCIAddressSlotInUse(addrs, &a))
+ goto success;
+
+ VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
+ a.domain, a.bus, a.slot);
+ }
+ }
+ }
+
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("No more available PCI slots"));
+ error:
+ VIR_FREE(addrStr);
+ return -1;
+
+ success:
+ VIR_DEBUG("Found free PCI slot %.4x:%.2x:%.2x",
+ a.domain, a.bus, a.slot);
+ *next_addr = a;
+ VIR_FREE(addrStr);
+ return 0;
+}
+
+int
+virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev,
+ virDomainPCIConnectFlags flags)
+{
+ virDevicePCIAddress addr;
+ if (virDomainPCIAddressGetNextSlot(addrs, &addr, flags) < 0)
+ return -1;
+
+ if (virDomainPCIAddressReserveSlot(addrs, &addr, flags) < 0)
+ return -1;
+
+ if (!addrs->dryRun) {
+ dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+ dev->addr.pci = addr;
+ }
+
+ addrs->lastaddr = addr;
+ addrs->lastFlags = flags;
+ return 0;
+}
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index f5a5199..c59ef85 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -76,4 +76,74 @@ typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr;
# define VIR_PCI_CONNECT_TYPES_MASK \
(VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE)
+char *virDomainPCIAddressAsString(virDevicePCIAddressPtr addr)
+ ATTRIBUTE_NONNULL(1);
+
+virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses);
+
+void virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs);
+
+bool virDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
+ const char *addrStr,
+ virDomainPCIConnectFlags busFlags,
+ virDomainPCIConnectFlags devFlags,
+ bool reportError,
+ bool fromConfig)
+ ATTRIBUTE_NONNULL(1);
+
+bool virDomainPCIAddressValidate(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+ const char *addrStr,
+ virDomainPCIConnectFlags flags,
+ bool fromConfig)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+
+int virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus,
+ virDomainControllerModelPCI model)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+int virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+ virDomainPCIConnectFlags flags)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+ virDomainPCIConnectFlags flags,
+ bool reserveEntireSlot,
+ bool fromConfig)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+int virDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr,
+ virDomainPCIConnectFlags flags)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+int virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+int virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+int virDomainPCIAddressReleaseSlot(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr addr)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+int virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
+ virDevicePCIAddressPtr next_addr,
+ virDomainPCIConnectFlags flags)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+int virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev,
+ virDomainPCIConnectFlags flags)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
#endif /* __DOMAIN_ADDR_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b4dd338..0a5fb14 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -85,6 +85,23 @@ virDevicePCIAddressIsValid;
virDevicePCIAddressParseXML;
+# conf/domain_addr.h
+virDomainPCIAddressAsString;
+virDomainPCIAddressBusSetModel;
+virDomainPCIAddressEnsureAddr;
+virDomainPCIAddressFlagsCompatible;
+virDomainPCIAddressGetNextSlot;
+virDomainPCIAddressReleaseSlot;
+virDomainPCIAddressReserveAddr;
+virDomainPCIAddressReserveNextSlot;
+virDomainPCIAddressReserveSlot;
+virDomainPCIAddressSetAlloc;
+virDomainPCIAddressSetFree;
+virDomainPCIAddressSetGrow;
+virDomainPCIAddressSlotInUse;
+virDomainPCIAddressValidate;
+
+
# conf/domain_audit.h
virDomainAuditCgroup;
virDomainAuditCgroupMajor;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index ebf17a8..aeaadbd 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1240,7 +1240,7 @@ void qemuDomainCCWAddressSetFree(qemuDomainCCWAddressSetPtr addrs)
static qemuDomainCCWAddressSetPtr
qemuDomainCCWAddressSetCreate(void)
{
- qemuDomainCCWAddressSetPtr addrs = NULL;
+ qemuDomainCCWAddressSetPtr addrs = NULL;
if (VIR_ALLOC(addrs) < 0)
goto error;
@@ -1445,232 +1445,6 @@ int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def,
}
-static bool
-qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
- const char *addrStr,
- virDomainPCIConnectFlags busFlags,
- virDomainPCIConnectFlags devFlags,
- bool reportError,
- bool fromConfig)
-{
- virErrorNumber errType = (fromConfig
- ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
- virDomainPCIConnectFlags flagsMatchMask = VIR_PCI_CONNECT_TYPES_MASK;
-
- if (fromConfig)
- flagsMatchMask |= VIR_PCI_CONNECT_TYPE_EITHER_IF_CONFIG;
-
- /* If this bus doesn't allow the type of connection (PCI
- * vs. PCIe) required by the device, or if the device requires
- * hot-plug and this bus doesn't have it, return false.
- */
- if (!(devFlags & busFlags & flagsMatchMask)) {
- if (reportError) {
- if (devFlags & VIR_PCI_CONNECT_TYPE_PCI) {
- virReportError(errType,
- _("PCI bus is not compatible with the device "
- "at %s. Device requires a standard PCI slot,
"
- "which is not provided by bus %.4x:%.2x"),
- addrStr, addr->domain, addr->bus);
- } else if (devFlags & VIR_PCI_CONNECT_TYPE_PCIE) {
- virReportError(errType,
- _("PCI bus is not compatible with the device "
- "at %s. Device requires a PCI Express slot, "
- "which is not provided by bus %.4x:%.2x"),
- addrStr, addr->domain, addr->bus);
- } else {
- /* this should never happen. If it does, there is a
- * bug in the code that sets the flag bits for devices.
- */
- virReportError(errType,
- _("The device information for %s has no PCI "
- "connection types listed"), addrStr);
- }
- }
- return false;
- }
- if ((devFlags & VIR_PCI_CONNECT_HOTPLUGGABLE) &&
- !(busFlags & VIR_PCI_CONNECT_HOTPLUGGABLE)) {
- if (reportError) {
- virReportError(errType,
- _("PCI bus is not compatible with the device "
- "at %s. Device requires hot-plug capability, "
- "which is not provided by bus %.4x:%.2x"),
- addrStr, addr->domain, addr->bus);
- }
- return false;
- }
- return true;
-}
-
-
-/* Verify that the address is in bounds for the chosen bus, and
- * that the bus is of the correct type for the device (via
- * comparing the flags).
- */
-static bool
-qemuDomainPCIAddressValidate(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr addr,
- const char *addrStr,
- virDomainPCIConnectFlags flags,
- bool fromConfig)
-{
- virDomainPCIAddressBusPtr bus;
- virErrorNumber errType = (fromConfig
- ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
-
- if (addrs->nbuses == 0) {
- virReportError(errType, "%s", _("No PCI buses available"));
- return false;
- }
- if (addr->domain != 0) {
- virReportError(errType,
- _("Invalid PCI address %s. "
- "Only PCI domain 0 is available"),
- addrStr);
- return false;
- }
- if (addr->bus >= addrs->nbuses) {
- virReportError(errType,
- _("Invalid PCI address %s. "
- "Only PCI buses up to %zu are available"),
- addrStr, addrs->nbuses - 1);
- return false;
- }
-
- bus = &addrs->buses[addr->bus];
-
- /* assure that at least one of the requested connection types is
- * provided by this bus
- */
- if (!qemuDomainPCIAddressFlagsCompatible(addr, addrStr, bus->flags,
- flags, true, fromConfig))
- return false;
-
- /* some "buses" are really just a single port */
- if (bus->minSlot && addr->slot < bus->minSlot) {
- virReportError(errType,
- _("Invalid PCI address %s. slot must be >= %zu"),
- addrStr, bus->minSlot);
- return false;
- }
- if (addr->slot > bus->maxSlot) {
- virReportError(errType,
- _("Invalid PCI address %s. slot must be <= %zu"),
- addrStr, bus->maxSlot);
- return false;
- }
- if (addr->function > VIR_PCI_ADDRESS_FUNCTION_LAST) {
- virReportError(errType,
- _("Invalid PCI address %s. function must be <= %u"),
- addrStr, VIR_PCI_ADDRESS_FUNCTION_LAST);
- return false;
- }
- return true;
-}
-
-
-static int
-qemuDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus,
- virDomainControllerModelPCI model)
-{
- switch (model) {
- case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
- case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
- bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
- VIR_PCI_CONNECT_TYPE_PCI);
- bus->minSlot = 1;
- bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
- break;
- case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
- /* slots 1 - 31, no hotplug, PCIe only unless the address was
- * specified in user config *and* the particular device being
- * attached also allows it
- */
- bus->flags = (VIR_PCI_CONNECT_TYPE_PCIE |
- VIR_PCI_CONNECT_TYPE_EITHER_IF_CONFIG);
- bus->minSlot = 1;
- bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
- break;
- case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
- /* slots 1 - 31, standard PCI slots,
- * but *not* hot-pluggable */
- bus->flags = VIR_PCI_CONNECT_TYPE_PCI;
- bus->minSlot = 1;
- bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
- break;
- default:
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Invalid PCI controller model %d"), model);
- return -1;
- }
-
- bus->model = model;
- return 0;
-}
-
-
-/* Ensure addr fits in the address set, by expanding it if needed.
- * This will only grow if the flags say that we need a normal
- * hot-pluggable PCI slot. If we need a different type of slot, it
- * will fail.
- *
- * Return value:
- * -1 = OOM
- * 0 = no action performed
- * >0 = number of buses added
- */
-static int
-qemuDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr addr,
- virDomainPCIConnectFlags flags)
-{
- int add;
- size_t i;
-
- add = addr->bus - addrs->nbuses + 1;
- i = addrs->nbuses;
- if (add <= 0)
- return 0;
-
- /* auto-grow only works when we're adding plain PCI devices */
- if (!(flags & VIR_PCI_CONNECT_TYPE_PCI)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Cannot automatically add a new PCI bus for a "
- "device requiring a slot other than standard PCI."));
- return -1;
- }
-
- if (VIR_EXPAND_N(addrs->buses, addrs->nbuses, add) < 0)
- return -1;
-
- for (; i < addrs->nbuses; i++) {
- /* Any time we auto-add a bus, we will want a multi-slot
- * bus. Currently the only type of bus we will auto-add is a
- * pci-bridge, which is hot-pluggable and provides standard
- * PCI slots.
- */
- qemuDomainPCIAddressBusSetModel(&addrs->buses[i],
- VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE);
- }
- return add;
-}
-
-
-static char *
-qemuDomainPCIAddressAsString(virDevicePCIAddressPtr addr)
-{
- char *str;
-
- ignore_value(virAsprintf(&str, "%.4x:%.2x:%.2x.%.1x",
- addr->domain,
- addr->bus,
- addr->slot,
- addr->function));
- return str;
-}
-
-
static int
qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
virDomainDeviceDefPtr device,
@@ -1816,8 +1590,8 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
entireSlot = (addr->function == 0 &&
addr->multi != VIR_DEVICE_ADDRESS_PCI_MULTI_ON);
- if (qemuDomainPCIAddressReserveAddr(addrs, addr, flags,
- entireSlot, true) < 0)
+ if (virDomainPCIAddressReserveAddr(addrs, addr, flags,
+ entireSlot, true) < 0)
goto cleanup;
ret = 0;
@@ -1872,7 +1646,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
if (qemuAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
goto cleanup;
/* Reserve 1 extra slot for a (potential) bridge */
- if (qemuDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs, &info, flags) < 0)
goto cleanup;
for (i = 1; i < addrs->nbuses; i++) {
@@ -1883,12 +1657,12 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
i, bus->model)) < 0)
goto cleanup;
/* If we added a new bridge, we will need one more address */
- if (rv > 0 && qemuDomainPCIAddressReserveNextSlot(addrs,
&info,
- flags) < 0)
+ if (rv > 0 && virDomainPCIAddressReserveNextSlot(addrs,
&info,
+ flags) < 0)
goto cleanup;
}
nbuses = addrs->nbuses;
- qemuDomainPCIAddressSetFree(addrs);
+ virDomainPCIAddressSetFree(addrs);
addrs = NULL;
} else if (max_idx > 0) {
@@ -1911,7 +1685,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
priv = obj->privateData;
if (addrs) {
/* if this is the live domain object, we persist the PCI addresses*/
- qemuDomainPCIAddressSetFree(priv->pciaddrs);
+ virDomainPCIAddressSetFree(priv->pciaddrs);
priv->persistentAddrs = 1;
priv->pciaddrs = addrs;
addrs = NULL;
@@ -1923,7 +1697,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
ret = 0;
cleanup:
- qemuDomainPCIAddressSetFree(addrs);
+ virDomainPCIAddressSetFree(addrs);
return ret;
}
@@ -1958,11 +1732,8 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
virDomainPCIAddressSetPtr addrs;
size_t i;
- if (VIR_ALLOC(addrs) < 0)
- goto error;
-
- if (VIR_ALLOC_N(addrs->buses, nbuses) < 0)
- goto error;
+ if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
+ return NULL;
addrs->nbuses = nbuses;
addrs->dryRun = dryRun;
@@ -1975,11 +1746,11 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
*
*/
if (nbuses > 0)
- qemuDomainPCIAddressBusSetModel(&addrs->buses[0],
- VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT);
+ virDomainPCIAddressBusSetModel(&addrs->buses[0],
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT);
for (i = 1; i < nbuses; i++) {
- qemuDomainPCIAddressBusSetModel(&addrs->buses[i],
- VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE);
+ virDomainPCIAddressBusSetModel(&addrs->buses[i],
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE);
}
for (i = 0; i < def->ncontrollers; i++) {
@@ -1995,8 +1766,8 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
goto error;
}
- if (qemuDomainPCIAddressBusSetModel(&addrs->buses[idx],
- def->controllers[i]->model) < 0)
+ if (virDomainPCIAddressBusSetModel(&addrs->buses[idx],
+ def->controllers[i]->model) < 0)
goto error;
}
@@ -2006,292 +1777,10 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
return addrs;
error:
- qemuDomainPCIAddressSetFree(addrs);
+ virDomainPCIAddressSetFree(addrs);
return NULL;
}
-/*
- * Check if the PCI slot is used by another device.
- */
-static bool qemuDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr addr)
-{
- return !!addrs->buses[addr->bus].slots[addr->slot];
-}
-
-
-/*
- * Reserve a slot (or just one function) for a device. If
- * reserveEntireSlot is true, all functions for the slot are reserved,
- * otherwise only one. If fromConfig is true, the address being
- * requested came directly from the config and errors should be worded
- * appropriately. If fromConfig is false, the address was
- * automatically created by libvirt, so it is an internal error (not
- * XML).
- */
-int
-qemuDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr addr,
- virDomainPCIConnectFlags flags,
- bool reserveEntireSlot,
- bool fromConfig)
-{
- int ret = -1;
- char *addrStr = NULL;
- virDomainPCIAddressBusPtr bus;
- virErrorNumber errType = (fromConfig
- ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
-
- if (!(addrStr = qemuDomainPCIAddressAsString(addr)))
- goto cleanup;
-
- /* Add an extra bus if necessary */
- if (addrs->dryRun && qemuDomainPCIAddressSetGrow(addrs, addr, flags) <
0)
- goto cleanup;
- /* Check that the requested bus exists, is the correct type, and we
- * are asking for a valid slot
- */
- if (!qemuDomainPCIAddressValidate(addrs, addr, addrStr, flags, fromConfig))
- goto cleanup;
-
- bus = &addrs->buses[addr->bus];
-
- if (reserveEntireSlot) {
- if (bus->slots[addr->slot]) {
- virReportError(errType,
- _("Attempted double use of PCI slot %s "
- "(may need \"multifunction='on'\" for
"
- "device on function 0)"), addrStr);
- goto cleanup;
- }
- bus->slots[addr->slot] = 0xFF; /* reserve all functions of slot */
- VIR_DEBUG("Reserving PCI slot %s (multifunction='off')",
addrStr);
- } else {
- if (bus->slots[addr->slot] & (1 << addr->function)) {
- if (addr->function == 0) {
- virReportError(errType,
- _("Attempted double use of PCI Address %s"),
- addrStr);
- } else {
- virReportError(errType,
- _("Attempted double use of PCI Address %s "
- "(may need \"multifunction='on'\"
"
- "for device on function 0)"), addrStr);
- }
- goto cleanup;
- }
- bus->slots[addr->slot] |= (1 << addr->function);
- VIR_DEBUG("Reserving PCI address %s", addrStr);
- }
-
- ret = 0;
- cleanup:
- VIR_FREE(addrStr);
- return ret;
-}
-
-
-int
-qemuDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr addr,
- virDomainPCIConnectFlags flags)
-{
- return qemuDomainPCIAddressReserveAddr(addrs, addr, flags, true, false);
-}
-
-int qemuDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
- virDomainDeviceInfoPtr dev)
-{
- int ret = -1;
- char *addrStr = NULL;
- /* Flags should be set according to the particular device,
- * but only the caller knows the type of device. Currently this
- * function is only used for hot-plug, though, and hot-plug is
- * only supported for standard PCI devices, so we can safely use
- * the setting below */
- virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
- VIR_PCI_CONNECT_TYPE_PCI);
-
- if (!(addrStr = qemuDomainPCIAddressAsString(&dev->addr.pci)))
- goto cleanup;
-
- if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
- /* We do not support hotplug multi-function PCI device now, so we should
- * reserve the whole slot. The function of the PCI device must be 0.
- */
- if (dev->addr.pci.function != 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Only PCI device addresses with function=0"
- " are supported"));
- goto cleanup;
- }
-
- if (!qemuDomainPCIAddressValidate(addrs, &dev->addr.pci,
- addrStr, flags, true))
- goto cleanup;
-
- ret = qemuDomainPCIAddressReserveSlot(addrs, &dev->addr.pci, flags);
- } else {
- ret = qemuDomainPCIAddressReserveNextSlot(addrs, dev, flags);
- }
-
- cleanup:
- VIR_FREE(addrStr);
- return ret;
-}
-
-
-int qemuDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr addr)
-{
- addrs->buses[addr->bus].slots[addr->slot] &= ~(1 <<
addr->function);
- return 0;
-}
-
-static int
-qemuDomainPCIAddressReleaseSlot(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr addr)
-{
- /* permit any kind of connection type in validation, since we
- * already had it, and are giving it back.
- */
- virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPES_MASK;
- int ret = -1;
- char *addrStr = NULL;
-
- if (!(addrStr = qemuDomainPCIAddressAsString(addr)))
- goto cleanup;
-
- if (!qemuDomainPCIAddressValidate(addrs, addr, addrStr, flags, false))
- goto cleanup;
-
- addrs->buses[addr->bus].slots[addr->slot] = 0;
- ret = 0;
- cleanup:
- VIR_FREE(addrStr);
- return ret;
-}
-
-void qemuDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs)
-{
- if (!addrs)
- return;
-
- VIR_FREE(addrs->buses);
- VIR_FREE(addrs);
-}
-
-
-static int
-qemuDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr next_addr,
- virDomainPCIConnectFlags flags)
-{
- /* default to starting the search for a free slot from
- * 0000:00:00.0
- */
- virDevicePCIAddress a = { 0, 0, 0, 0, false };
- char *addrStr = NULL;
-
- /* except if this search is for the exact same type of device as
- * last time, continue the search from the previous match
- */
- if (flags == addrs->lastFlags)
- a = addrs->lastaddr;
-
- if (addrs->nbuses == 0) {
- virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses
available"));
- goto error;
- }
-
- /* Start the search at the last used bus and slot */
- for (a.slot++; a.bus < addrs->nbuses; a.bus++) {
- if (!(addrStr = qemuDomainPCIAddressAsString(&a)))
- goto error;
- if (!qemuDomainPCIAddressFlagsCompatible(&a, addrStr,
- addrs->buses[a.bus].flags,
- flags, false, false)) {
- VIR_FREE(addrStr);
- VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
- a.domain, a.bus);
- continue;
- }
- for (; a.slot <= VIR_PCI_ADDRESS_SLOT_LAST; a.slot++) {
- if (!qemuDomainPCIAddressSlotInUse(addrs, &a))
- goto success;
-
- VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
- a.domain, a.bus, a.slot);
- }
- a.slot = 1;
- VIR_FREE(addrStr);
- }
-
- /* There were no free slots after the last used one */
- if (addrs->dryRun) {
- /* a is already set to the first new bus and slot 1 */
- if (qemuDomainPCIAddressSetGrow(addrs, &a, flags) < 0)
- goto error;
- goto success;
- } else if (flags == addrs->lastFlags) {
- /* Check the buses from 0 up to the last used one */
- for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) {
- addrStr = NULL;
- if (!(addrStr = qemuDomainPCIAddressAsString(&a)))
- goto error;
- if (!qemuDomainPCIAddressFlagsCompatible(&a, addrStr,
- addrs->buses[a.bus].flags,
- flags, false, false)) {
- VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the
device",
- a.domain, a.bus);
- continue;
- }
- for (a.slot = 1; a.slot <= VIR_PCI_ADDRESS_SLOT_LAST; a.slot++) {
- if (!qemuDomainPCIAddressSlotInUse(addrs, &a))
- goto success;
-
- VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
- a.domain, a.bus, a.slot);
- }
- }
- }
-
- virReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("No more available PCI slots"));
- error:
- VIR_FREE(addrStr);
- return -1;
-
- success:
- VIR_DEBUG("Found free PCI slot %.4x:%.2x:%.2x",
- a.domain, a.bus, a.slot);
- *next_addr = a;
- VIR_FREE(addrStr);
- return 0;
-}
-
-int
-qemuDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs,
- virDomainDeviceInfoPtr dev,
- virDomainPCIConnectFlags flags)
-{
- virDevicePCIAddress addr;
- if (qemuDomainPCIAddressGetNextSlot(addrs, &addr, flags) < 0)
- return -1;
-
- if (qemuDomainPCIAddressReserveSlot(addrs, &addr, flags) < 0)
- return -1;
-
- if (!addrs->dryRun) {
- dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
- dev->addr.pci = addr;
- }
-
- addrs->lastaddr = addr;
- addrs->lastFlags = flags;
- return 0;
-}
-
void
qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
@@ -2311,8 +1800,8 @@ qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
NULLSTR(devstr));
else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
- qemuDomainPCIAddressReleaseSlot(priv->pciaddrs,
- &info->addr.pci) < 0)
+ virDomainPCIAddressReleaseSlot(priv->pciaddrs,
+ &info->addr.pci) < 0)
VIR_WARN("Unable to release PCI address on %s",
NULLSTR(devstr));
}
@@ -2388,7 +1877,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
if (addrs->nbuses) {
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 1;
- if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
+ if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
goto cleanup;
}
@@ -2404,17 +1893,17 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 2;
- if (!(addrStr = qemuDomainPCIAddressAsString(&tmp_addr)))
+ if (!(addrStr = virDomainPCIAddressAsString(&tmp_addr)))
goto cleanup;
- if (!qemuDomainPCIAddressValidate(addrs, &tmp_addr,
- addrStr, flags, false))
+ if (!virDomainPCIAddressValidate(addrs, &tmp_addr,
+ addrStr, flags, false))
goto cleanup;
- if (qemuDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
+ if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
if (qemuDeviceVideoUsable) {
- if (qemuDomainPCIAddressReserveNextSlot(addrs,
- &primaryVideo->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs,
+ &primaryVideo->info,
+ flags) < 0)
goto cleanup;
} else {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -2423,7 +1912,7 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
goto cleanup;
}
} else {
- if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
+ if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
goto cleanup;
primaryVideo->info.addr.pci = tmp_addr;
primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
@@ -2444,12 +1933,12 @@ qemuValidateDevicePCISlotsPIIX3(virDomainDefPtr def,
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 2;
- if (qemuDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
+ 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");
virResetLastError();
- } else if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
{
+ } else if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
goto cleanup;
}
}
@@ -2527,9 +2016,9 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
*/
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 0x1E;
- if (!qemuDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
- if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr,
- flags, true, false) < 0)
+ 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;
@@ -2552,13 +2041,13 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
tmp_addr.slot = 0x1F;
tmp_addr.function = 0;
tmp_addr.multi = 1;
- if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
- false, false) < 0)
+ if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
+ false, false) < 0)
goto cleanup;
tmp_addr.function = 3;
tmp_addr.multi = 0;
- if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
- false, false) < 0)
+ if (virDomainPCIAddressReserveAddr(addrs, &tmp_addr, flags,
+ false, false) < 0)
goto cleanup;
}
@@ -2574,17 +2063,17 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 1;
- if (!(addrStr = qemuDomainPCIAddressAsString(&tmp_addr)))
+ if (!(addrStr = virDomainPCIAddressAsString(&tmp_addr)))
goto cleanup;
- if (!qemuDomainPCIAddressValidate(addrs, &tmp_addr,
- addrStr, flags, false))
+ if (!virDomainPCIAddressValidate(addrs, &tmp_addr,
+ addrStr, flags, false))
goto cleanup;
- if (qemuDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
+ if (virDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
if (qemuDeviceVideoUsable) {
- if (qemuDomainPCIAddressReserveNextSlot(addrs,
- &primaryVideo->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs,
+ &primaryVideo->info,
+ flags) < 0)
goto cleanup;
} else {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -2593,7 +2082,7 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
goto cleanup;
}
} else {
- if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
+ if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
goto cleanup;
primaryVideo->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
primaryVideo->info.addr.pci = tmp_addr;
@@ -2614,12 +2103,12 @@ qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 1;
- if (qemuDomainPCIAddressSlotInUse(addrs, &tmp_addr)) {
+ 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 (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0)
{
+ } else if (virDomainPCIAddressReserveSlot(addrs, &tmp_addr, flags) < 0) {
goto cleanup;
}
}
@@ -2712,9 +2201,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
flags = VIR_PCI_CONNECT_HOTPLUGGABLE | VIR_PCI_CONNECT_TYPE_PCI;
break;
}
- if (qemuDomainPCIAddressReserveNextSlot(addrs,
-
&def->controllers[i]->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs,
+ &def->controllers[i]->info,
+ flags) < 0)
goto error;
}
}
@@ -2727,8 +2216,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
/* Only support VirtIO-9p-pci so far. If that changes,
* we might need to skip devices here */
- if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->fss[i]->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs, &def->fss[i]->info,
+ flags) < 0)
goto error;
}
@@ -2742,8 +2231,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
(def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)) {
continue;
}
- if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->nets[i]->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs, &def->nets[i]->info,
+ flags) < 0)
goto error;
}
@@ -2756,8 +2245,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_PCSPK)
continue;
- if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->sounds[i]->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs, &def->sounds[i]->info,
+ flags) < 0)
goto error;
}
@@ -2819,7 +2308,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
if (addr.slot == 0) {
/* This is the first part of the controller, so need
* to find a free slot & then reserve a function */
- if (qemuDomainPCIAddressGetNextSlot(addrs, &tmp_addr, flags) < 0)
+ if (virDomainPCIAddressGetNextSlot(addrs, &tmp_addr, flags) < 0)
goto error;
addr.bus = tmp_addr.bus;
@@ -2830,16 +2319,16 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
addrs->lastaddr.multi = 0;
}
/* Finally we can reserve the slot+function */
- if (qemuDomainPCIAddressReserveAddr(addrs, &addr, flags,
- false, false) < 0)
+ if (virDomainPCIAddressReserveAddr(addrs, &addr, flags,
+ false, false) < 0)
goto error;
def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
def->controllers[i]->info.addr.pci = addr;
} else {
- if (qemuDomainPCIAddressReserveNextSlot(addrs,
-
&def->controllers[i]->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs,
+ &def->controllers[i]->info,
+ flags) < 0)
goto error;
}
}
@@ -2864,8 +2353,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
goto error;
}
- if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->disks[i]->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs, &def->disks[i]->info,
+ flags) < 0)
goto error;
}
@@ -2877,9 +2366,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
def->hostdevs[i]->source.subsys.type !=
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
continue;
- if (qemuDomainPCIAddressReserveNextSlot(addrs,
- def->hostdevs[i]->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs,
+ def->hostdevs[i]->info,
+ flags) < 0)
goto error;
}
@@ -2887,9 +2376,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
if (def->memballoon &&
def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
- if (qemuDomainPCIAddressReserveNextSlot(addrs,
- &def->memballoon->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs,
+ &def->memballoon->info,
+ flags) < 0)
goto error;
}
@@ -2897,8 +2386,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
if (def->rng &&
def->rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO &&
def->rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
- if (qemuDomainPCIAddressReserveNextSlot(addrs,
- &def->rng->info, flags) <
0)
+ if (virDomainPCIAddressReserveNextSlot(addrs,
+ &def->rng->info, flags) < 0)
goto error;
}
@@ -2906,8 +2395,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
if (def->watchdog &&
def->watchdog->model != VIR_DOMAIN_WATCHDOG_MODEL_IB700 &&
def->watchdog->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
- if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->watchdog->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs, &def->watchdog->info,
+ flags) < 0)
goto error;
}
@@ -2915,8 +2404,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
* assigned address. */
if (def->nvideos > 0 &&
def->videos[0]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
- if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->videos[0]->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs, &def->videos[0]->info,
+ flags) < 0)
goto error;
}
/* Further non-primary video cards which have to be qxl type */
@@ -2928,8 +2417,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
}
if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
continue;
- if (qemuDomainPCIAddressReserveNextSlot(addrs, &def->videos[i]->info,
- flags) < 0)
+ if (virDomainPCIAddressReserveNextSlot(addrs, &def->videos[i]->info,
+ flags) < 0)
goto error;
}
for (i = 0; i < def->ninputs; i++) {
@@ -2976,7 +2465,7 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
const char *contAlias = NULL;
size_t i;
- if (!(devStr = qemuDomainPCIAddressAsString(&info->addr.pci)))
+ if (!(devStr = virDomainPCIAddressAsString(&info->addr.pci)))
goto cleanup;
for (i = 0; i < domainDef->ncontrollers; i++) {
virDomainControllerDefPtr cont = domainDef->controllers[i];
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 29da1ca..afbd6ff 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -242,23 +242,7 @@ int qemuDomainAssignPCIAddresses(virDomainDefPtr def,
virDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
unsigned int nbuses,
bool dryRun);
-int qemuDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr addr,
- virDomainPCIConnectFlags flags);
-int qemuDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr addr,
- virDomainPCIConnectFlags flags,
- bool reserveEntireSlot,
- bool fromConfig);
-int qemuDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs,
- virDomainDeviceInfoPtr dev,
- virDomainPCIConnectFlags flags);
-int qemuDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
- virDomainDeviceInfoPtr dev);
-int qemuDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
- virDevicePCIAddressPtr addr);
-
-void qemuDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs);
+
int qemuAssignDevicePCISlots(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
virDomainPCIAddressSetPtr addrs);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 34cc736..8415f1a 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -34,6 +34,7 @@
#include "cpu/cpu.h"
#include "viruuid.h"
#include "virfile.h"
+#include "domain_addr.h"
#include "domain_event.h"
#include "virtime.h"
#include "virstoragefile.h"
@@ -245,7 +246,7 @@ qemuDomainObjPrivateFree(void *data)
virObjectUnref(priv->qemuCaps);
virCgroupFree(&priv->cgroup);
- qemuDomainPCIAddressSetFree(priv->pciaddrs);
+ virDomainPCIAddressSetFree(priv->pciaddrs);
qemuDomainCCWAddressSetFree(priv->ccwaddrs);
virDomainChrSourceDefFree(priv->monConfig);
qemuDomainObjFreeJob(priv);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 7c8830e..125a2db 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -284,7 +284,7 @@ qemuDomainAttachVirtioDiskDevice(virConnectPtr conn,
goto error;
} else if (!disk->info.type ||
disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
- if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info)
< 0)
+ if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &disk->info) <
0)
goto error;
}
releaseaddr = true;
@@ -386,7 +386,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 (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs,
&controller->info) < 0)
+ if (virDomainPCIAddressEnsureAddr(priv->pciaddrs,
&controller->info) < 0)
goto cleanup;
} else if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
if (qemuDomainCCWAddressAssign(&controller->info, priv->ccwaddrs,
@@ -940,7 +940,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("virtio-s390 net device cannot be hotplugged."));
else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) &&
- qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) <
0)
+ virDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0)
goto cleanup;
releaseaddr = true;
@@ -1230,7 +1230,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
goto error;
- if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, hostdev->info) < 0)
+ if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, hostdev->info) < 0)
goto error;
releaseaddr = true;
if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO &&
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 592e3b7..606478e 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4390,7 +4390,7 @@ void qemuProcessStop(virQEMUDriverPtr driver,
virDomainDefClearDeviceAliases(vm->def);
if (!priv->persistentAddrs) {
virDomainDefClearPCIAddresses(vm->def);
- qemuDomainPCIAddressSetFree(priv->pciaddrs);
+ virDomainPCIAddressSetFree(priv->pciaddrs);
priv->pciaddrs = NULL;
virDomainDefClearCCWAddresses(vm->def);
qemuDomainCCWAddressSetFree(priv->ccwaddrs);
--
1.9.0