From c92403a77ea960fcbe97d107b1b8119728523047 Mon Sep 17 00:00:00 2001 From: Jacek Kolakowski Date: Fri, 10 Oct 2025 21:37:26 +0200 Subject: [PATCH] [CHERRY-PICK] MdeModulePkg: Add platform limit for size in Resizable BAR Resizable BAR driver selects max available BAR size to configure for use. It may happen that some PCIe device declare support for size that exceeds processor address width. Platform needs a way to define the max size it can accept. This change introduce PCD called PcdPcieResizableBarMaxSize. It is dynamic PCD where platform can provide its limit for BAR size. Such PCD can be also controlled with a configuration knob. Signed-off-by: Jacek Kolakowski (cherry picked from commit 24eddc65b34538b397bcacec057a4a1fff7550df) --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c | 91 ++++++++++++++++---- MdeModulePkg/MdeModulePkg.dec | 9 ++ MdeModulePkg/MdeModulePkg.uni | 5 ++ 4 files changed, 88 insertions(+), 18 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf index cb44743f510..7bd8e8ba05a 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf @@ -105,6 +105,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdDisableBMEonEBS ## MU_CHANGE gEfiMdeModulePkgTokenSpaceGuid.PcdPcieInitializeMps ## MU_CHANGE: Add support for initializing PCIe MPS gEfiMdeModulePkgTokenSpaceGuid.PcdPciDegradeMem64toPMem64 ## CONSUMES # MU_CHANGE - MEM64 to PMEM64 conversion + gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarMaxSize ## CONSUMES [UserExtensions.TianoCore."ExtraFiles"] PciBusDxeExtra.uni diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c index 1601ee51f73..58e99211d5f 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c @@ -1827,22 +1827,59 @@ PciProgramResizableBar ( DEBUG (( DEBUG_INFO, - " Programs Resizable BAR register, offset: 0x%08x, number: %d\n", + " Program Resizable BAR registers at offset 0x%03X to %a (platform constraint 0x%lX)\n", PciIoDevice->ResizableBarOffset, - PciIoDevice->ResizableBarNumber + (ResizableBarOp == PciResizableBarMax) ? "max" : + (ResizableBarOp == PciResizableBarMin) ? "min" : "???", + LShiftU64 (SIZE_1MB, PcdGet8 (PcdPcieResizableBarMaxSize)) )); - ResizableBarNumber = MIN (PciIoDevice->ResizableBarNumber, PCI_MAX_BAR); - PciIo = &PciIoDevice->PciIo; - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint8, - PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER), - sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber, - (VOID *)(&Entries) - ); + ResizableBarNumber = PciIoDevice->ResizableBarNumber; + if ((ResizableBarNumber == 0) || (ResizableBarNumber > PCI_MAX_BAR)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Device %04X:%04x expose illegal Resizable BAR register (NumberOfResizableBar=%d) - ignore capability\n", + PciIoDevice->Pci.Hdr.VendorId, + PciIoDevice->Pci.Hdr.DeviceId, + ResizableBarNumber + )); + return EFI_DEVICE_ERROR; + } + + PciIo = &PciIoDevice->PciIo; + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER), + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber, + (VOID *)(&Entries) + ); ASSERT_EFI_ERROR (Status); + for (Index = 0; Index < PciIoDevice->ResizableBarNumber; Index++) { + // + // BAR index can be 0..5 for: + // 0 BAR located at offset 10h + // 1 BAR located at offset 14h + // 2 BAR located at offset 18h + // 3 BAR located at offset 1ch + // 4 BAR located at offset 20h + // 5 BAR located at offset 24h + // other illegal, do not configure anything if such entry was found. + // + if (Entries[Index].ResizableBarControl.Bits.BarIndex >= PCI_MAX_BAR ) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Device %04X:%04x expose illegal Resizable BAR register (Entry[%d].BarIndex=%d) - ignore capability\n", + PciIoDevice->Pci.Hdr.VendorId, + PciIoDevice->Pci.Hdr.DeviceId, + Index, + Entries[Index].ResizableBarControl.Bits.BarIndex + )); + return EFI_DEVICE_ERROR; + } + } + for (Index = 0; Index < ResizableBarNumber; Index++) { // // When the bit of Capabilities Set, indicates that the Function supports @@ -1851,18 +1888,36 @@ PciProgramResizableBar ( // Bit 0 is set: supports operating with the BAR sized to 1 MB // Bit 1 is set: supports operating with the BAR sized to 2 MB // Bit n is set: supports operating with the BAR sized to (2^n) MB + // With PcdPcieResizableBarMaxSize platform may impose limitation on the BAR size it supports. // Capabilities = LShiftU64 (Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28) | Entries[Index].ResizableBarCapability.Bits.BarSizeCapability; - - if (ResizableBarOp == PciResizableBarMax) { - Bit = HighBitSet64 (Capabilities); + Capabilities &= LShiftU64 (1, PcdGet8 (PcdPcieResizableBarMaxSize) + 1) - 1; + if (Capabilities == 0) { + // + // No size within the constraint, just set lowest size supported, per spec there must be something in legacy bits. + // + Bit = LowBitSet64 (Entries[Index].ResizableBarCapability.Bits.BarSizeCapability); } else { - ASSERT (ResizableBarOp == PciResizableBarMin); - Bit = LowBitSet64 (Capabilities); + if (ResizableBarOp == PciResizableBarMax) { + Bit = HighBitSet64 (Capabilities); + } else { + ASSERT (ResizableBarOp == PciResizableBarMin); + Bit = LowBitSet64 (Capabilities); + } } - ASSERT (Bit >= 0); + if (Bit < 0) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Device %04X:%04x expose illegal Resizable BAR register (Entry[%d].BarSizeCapability=%04X) - ignore entry\n", + PciIoDevice->Pci.Hdr.VendorId, + PciIoDevice->Pci.Hdr.DeviceId, + Index, + Entries[Index].ResizableBarCapability.Bits.BarSizeCapability + )); + continue; + } Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER) + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) @@ -1871,7 +1926,7 @@ PciProgramResizableBar ( Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32)Bit; DEBUG (( DEBUG_INFO, - " Resizable Bar: Offset = 0x%x, Bar Size Capability = 0x%016lx, New Bar Size = 0x%lx\n", + " Resizable BAR: offset = 0x%X, size capability mask = 0x%012lX, new BAR size = 0x%lX\n", OFFSET_OF (PCI_TYPE00, Device.Bar[Entries[Index].ResizableBarControl.Bits.BarIndex]), Capabilities, LShiftU64 (SIZE_1MB, Bit) diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index aefb8e52eb3..d8e656ce2f0 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -2564,6 +2564,15 @@ # @Prompt Support degrading Mem64 to PMem64 during PCI enumeration gEfiMdeModulePkgTokenSpaceGuid.PcdPciDegradeMem64toPMem64|FALSE|BOOLEAN|0x1000002C # MU_CHANGE End - MEM64 to PMEM64 conversion + ## Defines platform limit for BAR size that can be accepted in Resizable BAR Capability. + # BAR Capability bits specify size in MB, thus this PCD value shall be extended with +20 bits. + # 0 2^(0+20) = 1 MB + # 1 2^(1+20) = 2 MB + # ... + # 42 2^(42+20) = 4 EB + # 43 2^(43+20) = 8 EB + # @Prompt Max size to accept in PCIe Resizable BAR Capability register. + gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarMaxSize|43|UINT8|0x10000030 [PcdsPatchableInModule] ## Specify memory size with page number for PEI code when diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni index cce8426bb9d..b4d33ac3c7f 100644 --- a/MdeModulePkg/MdeModulePkg.uni +++ b/MdeModulePkg/MdeModulePkg.uni @@ -1352,3 +1352,8 @@ #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPcieResizableBarSupport_HELP #language en-US "Indicates if the PCIe Resizable BAR Capability Supported.

\n" "TRUE - PCIe Resizable BAR Capability is supported.
\n" "FALSE - PCIe Resizable BAR Capability is not supported.
" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPcieResizableBarMaxSize_PROMPT #language en-US "Define Resizable BAR Max Size Constraint" +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPcieResizableBarMaxSize_HELP #language en-US "Set platform limit for max size to pick from Resizable BAR Capability register.

\n" + "Decimal value 'n' is interpreted as 2^(n+20), which means 0=>1MB, 1=>2MB, 2=>4MB, 3=>8MB, etc.
\n" + "Maximum reasonable size to set is half of processor address with, i.e. address width - 1.
\n"