diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 002e66920c..21e203b056 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -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", diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index 5484a9b5c5..bc34fd0017 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -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;