summaryrefslogtreecommitdiff
path: root/BaseTools/Source/Python
diff options
context:
space:
mode:
authorShubham Aggarwal <shubagga@google.com>2026-10-09 09:51:20 +0300
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2026-10-12 12:31:30 +0300
commit05b96e3ccf3fe6b899651d2e245b29a4f7a0e472 (patch)
treefda6d325620ea27cdc07911800848e6b897be877 /BaseTools/Source/Python
parent1a44fc33295d32653fb114e1f1b9b91a81d47239 (diff)
downloadedk2-05b96e3ccf3fe6b899651d2e245b29a4f7a0e472.tar.xz
MdeModulePkg/PciBusDxe: Keep discovery order of equally aligned BARs
InsertResourceNode() keeps the resource list of a bridge sorted by descending alignment. The new node is inserted at the head of the list and then moved towards the tail, but it stops in front of the first node that it does not need to follow. Resources that rank equal, such as BARs of the same size, therefore end up in the reverse order of their discovery (LIFO), and the last discovered one is assigned the lowest address. Linux also sorts the resources by descending alignment in pdev_sort_resources() (drivers/pci/setup-bus.c), but it inserts a new resource after all the resources with the same alignment, so these keep their discovery order (FIFO). When the OS reassigns the PCI resources instead of keeping the firmware assignment (for example Linux on ARM64 ACPI systems, unless the firmware requests to preserve the PCI boot configuration through _DSM function 5), this difference makes it swap the addresses of equally sized BARs. While doing so, a BAR is temporarily programmed with a range that is still decoded by another device, which is not handled by some platforms, such as VMMs that do not allow overlapping BARs. Insert the new node at the tail of the list and move it towards the head instead, swapping the roles of the two compared nodes, so that resources that rank equal keep their discovery order, consistent with Linux. Resources with the same alignment are also sorted by the remainder of their length modulo the alignment. In practice, the remainder is only non-zero for the window of a child bridge, whose length is a multiple of the window granularity but whose alignment is the largest alignment of the resources behind it. Such a window leaves a gap in front of the next resource with the same alignment, so resources without a remainder should come first. However, the check only ranks a zero remainder first for the node that is being inserted, not for the existing node that it is compared with, so the relative order of windows with and without a remainder also depends on the insertion order. Reversing it can waste address space. For example, on QEMU q35 with three PCIe root ports, where the first one has a 3 MB MMIO window aligned to 2 MB and the other two have a 2 MB window, the 3 MB window would be placed first, leaving a 1 MB gap and growing the MMIO32 aperture of the root bridge from 8 MB to 9 MB. Therefore, rank a zero remainder first for both compared nodes. Resources without a remainder now always come first, regardless of the discovery order, which never increases the size of the aperture, and only resources that rank equal are ordered by their discovery. Update the description of InsertResourceNode() to document the full ordering. Signed-off-by: Shubham Aggarwal <shubagga@google.com>
Diffstat (limited to 'BaseTools/Source/Python')
0 files changed, 0 insertions, 0 deletions