@@ -23,6 +23,7 @@ struct PCIBus {
PCIIOMMUFunc iommu_fn;
void *iommu_opaque;
uint8_t devfn_min;
+ uint32_t slot_reserved_mask;
pci_set_irq_fn set_irq;
pci_map_irq_fn map_irq;
pci_route_irq_fn route_intx_to_irq;
@@ -373,6 +373,7 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent,
{
assert(PCI_FUNC(devfn_min) == 0);
bus->devfn_min = devfn_min;
+ bus->slot_reserved_mask = 0x0;
bus->address_space_mem = address_space_mem;
bus->address_space_io = address_space_io;
@@ -958,6 +959,11 @@ static bool pci_bus_devfn_available(PCIBus *bus, int devfn)
return !(bus->devices[devfn]);
}
+static bool pci_bus_devfn_reserved(PCIBus *bus, int devfn)
+{
+ return bus->slot_reserved_mask & (1UL << PCI_SLOT(devfn));
+}
+
/* -1 for devfn means auto assign */
static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
const char *name, int devfn,
@@ -981,14 +987,20 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
if (devfn < 0) {
for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);
devfn += PCI_FUNC_MAX) {
- if (pci_bus_devfn_available(bus, devfn)) {
+ if (pci_bus_devfn_available(bus, devfn) &&
+ !pci_bus_devfn_reserved(bus, devfn)) {
goto found;
}
}
- error_setg(errp, "PCI: no slot/function available for %s, all in use",
- name);
+ error_setg(errp, "PCI: no slot/function available for %s, all in use "
+ "or reserved", name);
return NULL;
found: ;
+ } else if (pci_bus_devfn_reserved(bus, devfn)) {
+ error_setg(errp, "PCI: slot %d function %d not available for %s,"
+ " reserved",
+ PCI_SLOT(devfn), PCI_FUNC(devfn), name);
+ return NULL;
} else if (!pci_bus_devfn_available(bus, devfn)) {
error_setg(errp, "PCI: slot %d function %d not available for %s,"
" in use by %s",