Add a final reconciliation pass to update bridge prefetch windows after all BARs have been assigned across all phases.
This ensures bridge windows accurately reflect final BAR placement across all buses. SR-IOV virtual functions are not included when sizing bridge prefetch apertures and may require additional work. Signed-off-by: Tushar Dave <[email protected]> --- hw/pci/pci-resource.c | 89 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/hw/pci/pci-resource.c b/hw/pci/pci-resource.c index e2d2adc7de..01db59c4af 100644 --- a/hw/pci/pci-resource.c +++ b/hw/pci/pci-resource.c @@ -190,6 +190,76 @@ static void pci_update_prefetch_window(PCIBus *bus, uint64_t base, uint64_t limi 4); } +static void pci_get_bridge_window(PCIBus *bus, void *opaque) +{ + PCIDevice *bridge = pci_bridge_get_device(bus); + PciAllocCfg *pci_res = (PciAllocCfg *)opaque; + + if (!bridge) { + pci_res->wbase = pci_res->mmio32_base; + pci_res->wlimit = pci_res->mmio32_base + pci_res->mmio32_size - 1; + pci_res->wbase64 = pci_res->mmio64_base; + pci_res->wlimit64 = pci_res->mmio64_base + pci_res->mmio64_size - 1; + } else { + pci_res->wbase = pci_bridge_get_base(bridge, PCI_BASE_ADDRESS_MEM_TYPE_32); + pci_res->wlimit = pci_bridge_get_limit(bridge, PCI_BASE_ADDRESS_MEM_TYPE_32); + pci_res->wbase64 = pci_bridge_get_base(bridge, PCI_BASE_ADDRESS_MEM_PREFETCH); + pci_res->wlimit64 = pci_bridge_get_limit(bridge, PCI_BASE_ADDRESS_MEM_PREFETCH); + } +} + +static void pci_collect_mmio64_window(PCIBus *bus, PCIDevice *dev, void *opaque) +{ + PciAllocCfg *pci_res = (PciAllocCfg *)opaque; + uint64_t rbase, rlimit; + uint32_t idx; + + for (idx = 0; idx < PCI_ROM_SLOT; idx++) { + PCIIORegion *res = &dev->io_regions[idx]; + + if (!res->size) { + continue; + } + rbase = res->addr; + rlimit = res->addr + res->size - 1; + /* Entire BAR must lie in the window; do not count partial overlap. */ + if (rbase < pci_res->wbase64 || rlimit > pci_res->wlimit64) { + continue; + } + pci_res->rbase = MIN(pci_res->rbase, rbase); + pci_res->rlimit = MAX(pci_res->rlimit, rlimit); + } + + if (IS_PCI_BRIDGE(dev)) { + rbase = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); + rlimit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); + + if ((rbase < pci_res->wbase64) || + (rbase > pci_res->wlimit64) || + (rlimit < pci_res->wbase64) || + (rlimit > pci_res->wlimit64)) { + return; + } + + pci_res->rbase = MIN(pci_res->rbase, rbase); + pci_res->rlimit = MAX(pci_res->rlimit, rlimit); + } +} + +static void pci_bus_update_prefetch_window(PCIBus *bus, void *opaque) +{ + PciAllocCfg *pci_res = (PciAllocCfg *)opaque; + pci_res->rbase = ~0; + pci_res->rlimit = 0; + + assert(pci_bridge_get_device(bus)); + pci_for_each_device_under_bus(bus, pci_collect_mmio64_window, pci_res); + + if (pci_res->rlimit > pci_res->rbase) { + pci_update_prefetch_window(bus, pci_res->rbase, pci_res->rlimit); + } +} + static inline bool is_64bit_pref_bar(PCIIORegion *r) { if (!r->size) { @@ -1004,6 +1074,25 @@ void pci_fixed_bar_allocator(PCIBus *root, const PciFixedBarMmioParams *mmio) /* Phase 3: allocate BARs for buses that have no fixed-BAR devices */ pci_for_each_bus(bus, pci_bus_phase3_allocate_no_fixed_bars, &pctx); + memset(pci_res, 0, sizeof(PciAllocCfg)); + pci_resource_init_from_mmio(pci_res, mmio); + + /* TODO: 32-bit MMIO/ROM adjustment */ + /* TODO: PIO assignment */ + /* TODO: 64-bit non-prefetchable */ + + /* Align bridge prefetch window with assigned BAR ranges */ + pci_get_bridge_window(bus, pci_res); + + QLIST_FOREACH(bus, &bus->child, sibling) { + pci_res->bus = bus; + /* Use the full mmio64 window */ + pci_res->wbase64 = pci_res->mmio64_base; + pci_res->wlimit64 = pci_res->mmio64_base + pci_res->mmio64_size - 1; + + pci_for_each_bus(bus, pci_bus_update_prefetch_window, pci_res); + } + /* Cleanup */ g_hash_table_destroy(pctx.had_fixed); fixed_claim_regions_reset(); -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#121923): https://edk2.groups.io/g/devel/message/121923 Mute This Topic: https://groups.io/mt/119221710/21656 Group Owner: [email protected] Unsubscribe: https://edk2.groups.io/g/devel/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
