2 * domain_addr.c: helper APIs for managing domain device addresses
4 * Copyright (C) 2006-2014 Red Hat, Inc.
5 * Copyright (C) 2006 Daniel P. Berrange
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <http://www.gnu.org/licenses/>.
21 * Author: Daniel P. Berrange <berrange@redhat.com>
28 #include "virstring.h"
29 #include "domain_addr.h"
31 #define VIR_FROM_THIS VIR_FROM_DOMAIN
33 VIR_LOG_INIT("conf.domain_addr");
36 virDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr,
38 virDomainPCIConnectFlags busFlags,
39 virDomainPCIConnectFlags devFlags,
43 virErrorNumber errType = (fromConfig
44 ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
45 virDomainPCIConnectFlags flagsMatchMask = VIR_PCI_CONNECT_TYPES_MASK;
48 flagsMatchMask |= VIR_PCI_CONNECT_TYPE_EITHER_IF_CONFIG;
50 /* If this bus doesn't allow the type of connection (PCI
51 * vs. PCIe) required by the device, or if the device requires
52 * hot-plug and this bus doesn't have it, return false.
54 if (!(devFlags & busFlags & flagsMatchMask)) {
56 if (devFlags & VIR_PCI_CONNECT_TYPE_PCI) {
57 virReportError(errType,
58 _("PCI bus is not compatible with the device "
59 "at %s. Device requires a standard PCI slot, "
60 "which is not provided by bus %.4x:%.2x"),
61 addrStr, addr->domain, addr->bus);
62 } else if (devFlags & VIR_PCI_CONNECT_TYPE_PCIE) {
63 virReportError(errType,
64 _("PCI bus is not compatible with the device "
65 "at %s. Device requires a PCI Express slot, "
66 "which is not provided by bus %.4x:%.2x"),
67 addrStr, addr->domain, addr->bus);
69 /* this should never happen. If it does, there is a
70 * bug in the code that sets the flag bits for devices.
72 virReportError(errType,
73 _("The device information for %s has no PCI "
74 "connection types listed"), addrStr);
79 if ((devFlags & VIR_PCI_CONNECT_HOTPLUGGABLE) &&
80 !(busFlags & VIR_PCI_CONNECT_HOTPLUGGABLE)) {
82 virReportError(errType,
83 _("PCI bus is not compatible with the device "
84 "at %s. Device requires hot-plug capability, "
85 "which is not provided by bus %.4x:%.2x"),
86 addrStr, addr->domain, addr->bus);
94 /* Verify that the address is in bounds for the chosen bus, and
95 * that the bus is of the correct type for the device (via
96 * comparing the flags).
99 virDomainPCIAddressValidate(virDomainPCIAddressSetPtr addrs,
100 virDevicePCIAddressPtr addr,
102 virDomainPCIConnectFlags flags,
105 virDomainPCIAddressBusPtr bus;
106 virErrorNumber errType = (fromConfig
107 ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
109 if (addrs->nbuses == 0) {
110 virReportError(errType, "%s", _("No PCI buses available"));
113 if (addr->domain != 0) {
114 virReportError(errType,
115 _("Invalid PCI address %s. "
116 "Only PCI domain 0 is available"),
120 if (addr->bus >= addrs->nbuses) {
121 virReportError(errType,
122 _("Invalid PCI address %s. "
123 "Only PCI buses up to %zu are available"),
124 addrStr, addrs->nbuses - 1);
128 bus = &addrs->buses[addr->bus];
130 /* assure that at least one of the requested connection types is
131 * provided by this bus
133 if (!virDomainPCIAddressFlagsCompatible(addr, addrStr, bus->flags,
134 flags, true, fromConfig))
137 /* some "buses" are really just a single port */
138 if (bus->minSlot && addr->slot < bus->minSlot) {
139 virReportError(errType,
140 _("Invalid PCI address %s. slot must be >= %zu"),
141 addrStr, bus->minSlot);
144 if (addr->slot > bus->maxSlot) {
145 virReportError(errType,
146 _("Invalid PCI address %s. slot must be <= %zu"),
147 addrStr, bus->maxSlot);
150 if (addr->function > VIR_PCI_ADDRESS_FUNCTION_LAST) {
151 virReportError(errType,
152 _("Invalid PCI address %s. function must be <= %u"),
153 addrStr, VIR_PCI_ADDRESS_FUNCTION_LAST);
161 virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus,
162 virDomainControllerModelPCI model)
165 case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
166 case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
167 bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
168 VIR_PCI_CONNECT_TYPE_PCI);
170 bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
172 case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
173 /* slots 1 - 31, no hotplug, PCIe only unless the address was
174 * specified in user config *and* the particular device being
175 * attached also allows it
177 bus->flags = (VIR_PCI_CONNECT_TYPE_PCIE |
178 VIR_PCI_CONNECT_TYPE_EITHER_IF_CONFIG);
180 bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
182 case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
183 /* slots 1 - 31, standard PCI slots,
184 * but *not* hot-pluggable */
185 bus->flags = VIR_PCI_CONNECT_TYPE_PCI;
187 bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
190 virReportError(VIR_ERR_INTERNAL_ERROR,
191 _("Invalid PCI controller model %d"), model);
200 /* Ensure addr fits in the address set, by expanding it if needed.
201 * This will only grow if the flags say that we need a normal
202 * hot-pluggable PCI slot. If we need a different type of slot, it
207 * 0 = no action performed
208 * >0 = number of buses added
211 virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs,
212 virDevicePCIAddressPtr addr,
213 virDomainPCIConnectFlags flags)
218 add = addr->bus - addrs->nbuses + 1;
223 /* auto-grow only works when we're adding plain PCI devices */
224 if (!(flags & VIR_PCI_CONNECT_TYPE_PCI)) {
225 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
226 _("Cannot automatically add a new PCI bus for a "
227 "device requiring a slot other than standard PCI."));
231 if (VIR_EXPAND_N(addrs->buses, addrs->nbuses, add) < 0)
234 for (; i < addrs->nbuses; i++) {
235 /* Any time we auto-add a bus, we will want a multi-slot
236 * bus. Currently the only type of bus we will auto-add is a
237 * pci-bridge, which is hot-pluggable and provides standard
240 virDomainPCIAddressBusSetModel(&addrs->buses[i],
241 VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE);
248 virDomainPCIAddressAsString(virDevicePCIAddressPtr addr)
252 ignore_value(virAsprintf(&str, "%.4x:%.2x:%.2x.%.1x",
262 * Check if the PCI slot is used by another device.
265 virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
266 virDevicePCIAddressPtr addr)
268 return !!addrs->buses[addr->bus].slots[addr->slot];
273 * Reserve a slot (or just one function) for a device. If
274 * reserveEntireSlot is true, all functions for the slot are reserved,
275 * otherwise only one. If fromConfig is true, the address being
276 * requested came directly from the config and errors should be worded
277 * appropriately. If fromConfig is false, the address was
278 * automatically created by libvirt, so it is an internal error (not
282 virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
283 virDevicePCIAddressPtr addr,
284 virDomainPCIConnectFlags flags,
285 bool reserveEntireSlot,
289 char *addrStr = NULL;
290 virDomainPCIAddressBusPtr bus;
291 virErrorNumber errType = (fromConfig
292 ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR);
294 if (!(addrStr = virDomainPCIAddressAsString(addr)))
297 /* Add an extra bus if necessary */
298 if (addrs->dryRun && virDomainPCIAddressSetGrow(addrs, addr, flags) < 0)
300 /* Check that the requested bus exists, is the correct type, and we
301 * are asking for a valid slot
303 if (!virDomainPCIAddressValidate(addrs, addr, addrStr, flags, fromConfig))
306 bus = &addrs->buses[addr->bus];
308 if (reserveEntireSlot) {
309 if (bus->slots[addr->slot]) {
310 virReportError(errType,
311 _("Attempted double use of PCI slot %s "
312 "(may need \"multifunction='on'\" for "
313 "device on function 0)"), addrStr);
316 bus->slots[addr->slot] = 0xFF; /* reserve all functions of slot */
317 VIR_DEBUG("Reserving PCI slot %s (multifunction='off')", addrStr);
319 if (bus->slots[addr->slot] & (1 << addr->function)) {
320 if (addr->function == 0) {
321 virReportError(errType,
322 _("Attempted double use of PCI Address %s"),
325 virReportError(errType,
326 _("Attempted double use of PCI Address %s "
327 "(may need \"multifunction='on'\" "
328 "for device on function 0)"), addrStr);
332 bus->slots[addr->slot] |= (1 << addr->function);
333 VIR_DEBUG("Reserving PCI address %s", addrStr);
344 virDomainPCIAddressReserveSlot(virDomainPCIAddressSetPtr addrs,
345 virDevicePCIAddressPtr addr,
346 virDomainPCIConnectFlags flags)
348 return virDomainPCIAddressReserveAddr(addrs, addr, flags, true, false);
352 virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
353 virDomainDeviceInfoPtr dev)
356 char *addrStr = NULL;
357 /* Flags should be set according to the particular device,
358 * but only the caller knows the type of device. Currently this
359 * function is only used for hot-plug, though, and hot-plug is
360 * only supported for standard PCI devices, so we can safely use
361 * the setting below */
362 virDomainPCIConnectFlags flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
363 VIR_PCI_CONNECT_TYPE_PCI);
365 if (!(addrStr = virDomainPCIAddressAsString(&dev->addr.pci)))
368 if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
369 /* We do not support hotplug multi-function PCI device now, so we should
370 * reserve the whole slot. The function of the PCI device must be 0.
372 if (dev->addr.pci.function != 0) {
373 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
374 _("Only PCI device addresses with function=0"
379 if (!virDomainPCIAddressValidate(addrs, &dev->addr.pci,
380 addrStr, flags, true))
383 ret = virDomainPCIAddressReserveSlot(addrs, &dev->addr.pci, flags);
385 ret = virDomainPCIAddressReserveNextSlot(addrs, dev, flags);
395 virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
396 virDevicePCIAddressPtr addr)
398 addrs->buses[addr->bus].slots[addr->slot] &= ~(1 << addr->function);
403 virDomainPCIAddressReleaseSlot(virDomainPCIAddressSetPtr addrs,
404 virDevicePCIAddressPtr addr)
406 /* permit any kind of connection type in validation, since we
407 * already had it, and are giving it back.
409 virDomainPCIConnectFlags flags = VIR_PCI_CONNECT_TYPES_MASK;
411 char *addrStr = NULL;
413 if (!(addrStr = virDomainPCIAddressAsString(addr)))
416 if (!virDomainPCIAddressValidate(addrs, addr, addrStr, flags, false))
419 addrs->buses[addr->bus].slots[addr->slot] = 0;
427 virDomainPCIAddressSetPtr
428 virDomainPCIAddressSetAlloc(unsigned int nbuses)
430 virDomainPCIAddressSetPtr addrs;
432 if (VIR_ALLOC(addrs) < 0)
435 if (VIR_ALLOC_N(addrs->buses, nbuses) < 0)
438 addrs->nbuses = nbuses;
442 virDomainPCIAddressSetFree(addrs);
448 virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs)
453 VIR_FREE(addrs->buses);
459 virDomainPCIAddressGetNextSlot(virDomainPCIAddressSetPtr addrs,
460 virDevicePCIAddressPtr next_addr,
461 virDomainPCIConnectFlags flags)
463 /* default to starting the search for a free slot from
466 virDevicePCIAddress a = { 0, 0, 0, 0, false };
467 char *addrStr = NULL;
469 /* except if this search is for the exact same type of device as
470 * last time, continue the search from the previous match
472 if (flags == addrs->lastFlags)
475 if (addrs->nbuses == 0) {
476 virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
480 /* Start the search at the last used bus and slot */
481 for (a.slot++; a.bus < addrs->nbuses; a.bus++) {
482 if (!(addrStr = virDomainPCIAddressAsString(&a)))
484 if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
485 addrs->buses[a.bus].flags,
486 flags, false, false)) {
488 VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
492 for (; a.slot <= VIR_PCI_ADDRESS_SLOT_LAST; a.slot++) {
493 if (!virDomainPCIAddressSlotInUse(addrs, &a))
496 VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
497 a.domain, a.bus, a.slot);
503 /* There were no free slots after the last used one */
505 /* a is already set to the first new bus and slot 1 */
506 if (virDomainPCIAddressSetGrow(addrs, &a, flags) < 0)
509 } else if (flags == addrs->lastFlags) {
510 /* Check the buses from 0 up to the last used one */
511 for (a.bus = 0; a.bus <= addrs->lastaddr.bus; a.bus++) {
513 if (!(addrStr = virDomainPCIAddressAsString(&a)))
515 if (!virDomainPCIAddressFlagsCompatible(&a, addrStr,
516 addrs->buses[a.bus].flags,
517 flags, false, false)) {
518 VIR_DEBUG("PCI bus %.4x:%.2x is not compatible with the device",
522 for (a.slot = 1; a.slot <= VIR_PCI_ADDRESS_SLOT_LAST; a.slot++) {
523 if (!virDomainPCIAddressSlotInUse(addrs, &a))
526 VIR_DEBUG("PCI slot %.4x:%.2x:%.2x already in use",
527 a.domain, a.bus, a.slot);
532 virReportError(VIR_ERR_INTERNAL_ERROR,
533 "%s", _("No more available PCI slots"));
539 VIR_DEBUG("Found free PCI slot %.4x:%.2x:%.2x",
540 a.domain, a.bus, a.slot);
547 virDomainPCIAddressReserveNextSlot(virDomainPCIAddressSetPtr addrs,
548 virDomainDeviceInfoPtr dev,
549 virDomainPCIConnectFlags flags)
551 virDevicePCIAddress addr;
552 if (virDomainPCIAddressGetNextSlot(addrs, &addr, flags) < 0)
555 if (virDomainPCIAddressReserveSlot(addrs, &addr, flags) < 0)
558 if (!addrs->dryRun) {
559 dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
560 dev->addr.pci = addr;
563 addrs->lastaddr = addr;
564 addrs->lastFlags = flags;