From c50658ae6ba27f63cf690b9036dd7f8c10bcda9a Mon Sep 17 00:00:00 2001 From: "Pastorcici, Mariano-paulX" Date: Mon, 26 Aug 2024 01:08:04 +0300 Subject: [PATCH] feat: [common] Enable PCIe resizable BAR support This commit adds support for PCIe resizable BARsupport. The feature can be enabled by setting PcdResizableBarSupport for the board build script and its disabled by default. Signed-off-by: pastorcx --- BootloaderCorePkg/BootloaderCorePkg.dec | 1 + BootloaderCorePkg/BootloaderCorePkg.dsc | 1 + .../InternalPciEnumerationLib.h | 26 ++++ .../Library/PciEnumerationLib/PciCommand.c | 1 + .../PciEnumerationLib/PciEnumerationLib.c | 7 +- .../PciEnumerationLib/PciEnumerationLib.inf | 2 + .../PciEnumerationLib/PciResizableBar.c | 120 ++++++++++++++++++ 7 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 BootloaderCorePkg/Library/PciEnumerationLib/PciResizableBar.c diff --git a/BootloaderCorePkg/BootloaderCorePkg.dec b/BootloaderCorePkg/BootloaderCorePkg.dec index 0c9d8cca..4d2fd841 100644 --- a/BootloaderCorePkg/BootloaderCorePkg.dec +++ b/BootloaderCorePkg/BootloaderCorePkg.dec @@ -248,6 +248,7 @@ gPlatformModuleTokenSpaceGuid.PcdEnableSetup | FALSE | BOOLEAN | 0x20000213 gPlatformModuleTokenSpaceGuid.PcdLegacyEfSegmentEnabled | TRUE | BOOLEAN | 0x20000214 gPlatformModuleTokenSpaceGuid.PcdEnableDts | FALSE | BOOLEAN | 0x20000215 + gPlatformModuleTokenSpaceGuid.PcdResizableBarSupport | FALSE | BOOLEAN | 0x20000216 gPlatformModuleTokenSpaceGuid.PcdEnablePciePm | FALSE | BOOLEAN | 0x20000222 gPlatformModuleTokenSpaceGuid.PcdEnableFwuNotify | FALSE | BOOLEAN | 0x20000225 diff --git a/BootloaderCorePkg/BootloaderCorePkg.dsc b/BootloaderCorePkg/BootloaderCorePkg.dsc index 2a235974..aa815788 100644 --- a/BootloaderCorePkg/BootloaderCorePkg.dsc +++ b/BootloaderCorePkg/BootloaderCorePkg.dsc @@ -347,6 +347,7 @@ gPlatformCommonLibTokenSpaceGuid.PcdCpuX2ApicEnabled | $(SUPPORT_X2APIC) gPlatformModuleTokenSpaceGuid.PcdAriSupport | $(SUPPORT_ARI) gPlatformModuleTokenSpaceGuid.PcdSrIovSupport | $(SUPPORT_SR_IOV) + gPlatformModuleTokenSpaceGuid.PcdResizableBarSupport | $(SUPPORT_RESIZABLE_BAR) gPlatformModuleTokenSpaceGuid.PcdEnableSetup | $(ENABLE_SBL_SETUP) gPayloadTokenSpaceGuid.PcdPayloadModuleEnabled | $(ENABLE_PAYLOD_MODULE) gPlatformModuleTokenSpaceGuid.PcdEnableDts | $(ENABLE_DTS) diff --git a/BootloaderCorePkg/Library/PciEnumerationLib/InternalPciEnumerationLib.h b/BootloaderCorePkg/Library/PciEnumerationLib/InternalPciEnumerationLib.h index a1716ec9..46876c1b 100644 --- a/BootloaderCorePkg/Library/PciEnumerationLib/InternalPciEnumerationLib.h +++ b/BootloaderCorePkg/Library/PciEnumerationLib/InternalPciEnumerationLib.h @@ -61,6 +61,11 @@ typedef enum { BusScanTypeInvalid = 0xFF } BUS_SCAN_TYPE; +typedef enum { + PciResizableBarMin = 0x00, + PciResizableBarMax = 0xFF +} PCI_RESIZABLE_BAR_OPERATION; + typedef struct { UINT16 Io32 : 1; UINT16 Mem64 : 1; @@ -152,6 +157,7 @@ struct _PCI_IO_DEVICE { BOOLEAN IsPciExp; UINT8 PciExpressCapabilityOffset; UINT32 AriCapabilityOffset; + // // SR-IOV // @@ -161,6 +167,15 @@ struct _PCI_IO_DEVICE { UINT16 InitialVFs; UINT16 ReservedBusNum; + // + // Per PCI to PCI Bridge spec, I/O window is 4K aligned, + // but some chipsets support non-standard I/O window alignments less than 4K. + // This field is used to support this case. + // + UINT16 BridgeIoAlignment; + UINT32 ResizableBarOffset; + UINT32 ResizableBarNumber; + // // The bridge device this pci device is subject to // @@ -194,4 +209,15 @@ BarExisted ( OUT UINT32 *OriginalBarValue ); +/** + Initialize Resizable BAR + + @param[in,out] PciIoDevice Pointer to instance of PCI_IO_DEVICE. + +**/ +VOID +InitializeResizeBar ( + IN OUT PCI_IO_DEVICE *PciIoDevice + ); + #endif diff --git a/BootloaderCorePkg/Library/PciEnumerationLib/PciCommand.c b/BootloaderCorePkg/Library/PciEnumerationLib/PciCommand.c index 76e05eea..662d01e5 100644 --- a/BootloaderCorePkg/Library/PciEnumerationLib/PciCommand.c +++ b/BootloaderCorePkg/Library/PciEnumerationLib/PciCommand.c @@ -5,6 +5,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ +#include #include #include diff --git a/BootloaderCorePkg/Library/PciEnumerationLib/PciEnumerationLib.c b/BootloaderCorePkg/Library/PciEnumerationLib/PciEnumerationLib.c index 76a46740..5c7965af 100644 --- a/BootloaderCorePkg/Library/PciEnumerationLib/PciEnumerationLib.c +++ b/BootloaderCorePkg/Library/PciEnumerationLib/PciEnumerationLib.c @@ -17,6 +17,7 @@ #include #include "PciAri.h" #include "PciIov.h" +#include "InternalPciEnumerationLib.h" #define DEBUG_PCI_ENUM 0 @@ -432,7 +433,7 @@ CreatePciIoDevice ( PciIoDevice->Decodes = 0; PciIoDevice->IsPciExp = FALSE; PciIoDevice->PciExpressCapabilityOffset = 0; - if (FeaturePcdGet (PcdAriSupport) || FeaturePcdGet (PcdSrIovSupport)) { + if (FeaturePcdGet (PcdAriSupport) || FeaturePcdGet (PcdSrIovSupport) || FeaturePcdGet (PcdResizableBarSupport)) { InitializePciExpCapability (PciIoDevice); } if (FeaturePcdGet (PcdAriSupport)) { @@ -441,7 +442,9 @@ CreatePciIoDevice ( if (FeaturePcdGet (PcdSrIovSupport)) { InitializeSrIov (PciIoDevice, Bus, Device, Func); } - + if (FeaturePcdGet (PcdResizableBarSupport)) { + InitializeResizeBar (PciIoDevice); + } return PciIoDevice; } diff --git a/BootloaderCorePkg/Library/PciEnumerationLib/PciEnumerationLib.inf b/BootloaderCorePkg/Library/PciEnumerationLib/PciEnumerationLib.inf index bfeb3894..6a699cac 100644 --- a/BootloaderCorePkg/Library/PciEnumerationLib/PciEnumerationLib.inf +++ b/BootloaderCorePkg/Library/PciEnumerationLib/PciEnumerationLib.inf @@ -28,6 +28,7 @@ PciCommand.c PciAri.c PciIov.c + PciResizableBar.c PciEnumerationLib.c [Packages] @@ -55,5 +56,6 @@ gPlatformModuleTokenSpaceGuid.PcdPciResourceMem64Base gPlatformModuleTokenSpaceGuid.PcdAriSupport gPlatformModuleTokenSpaceGuid.PcdSrIovSupport + gPlatformModuleTokenSpaceGuid.PcdResizableBarSupport gPlatformModuleTokenSpaceGuid.PcdPciResAllocTableBase gPlatformModuleTokenSpaceGuid.PcdPciEnumHookProc diff --git a/BootloaderCorePkg/Library/PciEnumerationLib/PciResizableBar.c b/BootloaderCorePkg/Library/PciEnumerationLib/PciResizableBar.c new file mode 100644 index 00000000..7e6f39a1 --- /dev/null +++ b/BootloaderCorePkg/Library/PciEnumerationLib/PciResizableBar.c @@ -0,0 +1,120 @@ +/** @file + + Copyright (c) 2020 - 2024, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include "InternalPciEnumerationLib.h" +#include "PciCommand.h" + +/** + This function is used to program the Resizable BAR Register. + + @param PciIoDevice A pointer to the PCI_IO_DEVICE. + @param ResizableBarOp PciResizableBarMax: Set BAR to max size + PciResizableBarMin: set BAR to min size. + + @retval EFI_SUCCESS Successfully enumerated the host bridge. + @retval other Some error occurred when enumerating the host bridge. + +**/ +STATIC +EFI_STATUS +PciProgramResizableBar ( + IN PCI_IO_DEVICE *PciIoDevice, + IN PCI_RESIZABLE_BAR_OPERATION ResizableBarOp + ) +{ + UINT64 Capabilities; + UINT32 Index; + UINT32 Offset; + INTN Bit; + UINTN ResizableBarNumber; + PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY Entries[PCI_MAX_BAR]; + + ASSERT (PciIoDevice->ResizableBarOffset != 0); + + DEBUG ((DEBUG_VERBOSE, "Programs Resizable BAR register, address %x offset: 0x%08x, number: %d\n", + PciIoDevice->Address, + PciIoDevice->ResizableBarOffset, + PciIoDevice->ResizableBarNumber)); + ResizableBarNumber = MIN (PciIoDevice->ResizableBarNumber, PCI_MAX_BAR); + for (Index = 0; Index < ResizableBarNumber; Index++) { + Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER) + + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * Index; + Entries[Index].ResizableBarCapability.Uint32 = PciExpressRead32 (PciIoDevice->Address + Offset); + Offset += sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY); + Entries[Index].ResizableBarControl.Uint32 = PciExpressRead32 (PciIoDevice->Address + Offset); + } + + for (Index = 0; Index < ResizableBarNumber; Index++) { + // + // When the bit of Capabilities Set, indicates that the Function supports + // operating with the BAR sized to (2^Bit) MB. + // Example: + // 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 + // + Capabilities = LShiftU64 (Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28) + | Entries[Index].ResizableBarCapability.Bits.BarSizeCapability; + + if (ResizableBarOp == PciResizableBarMax) { + Bit = HighBitSet64 (Capabilities); + } else { + ASSERT (ResizableBarOp == PciResizableBarMin); + Bit = LowBitSet64 (Capabilities); + } + + ASSERT (Bit >= 0); + + Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER) + + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) + + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY, ResizableBarControl); + + Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32)Bit; + DEBUG ((DEBUG_VERBOSE, "Resizable Bar: Offset = 0x%x, Bar Size Capability = 0x%016lx, New Bar Size = 0x%lx\n", + OFFSET_OF (PCI_TYPE00, Device.Bar[Entries[Index].ResizableBarControl.Bits.BarIndex]), + Capabilities, + LShiftU64 (SIZE_1MB, Bit))); + PciExpressWrite32 (PciIoDevice->Address + Offset, Entries[Index].ResizableBarControl.Uint32); + } + return EFI_SUCCESS; +} + +/** + Initialize Resizable BAR + + @param[in,out] PciIoDevice Pointer to instance of PCI_IO_DEVICE. + +**/ +VOID +InitializeResizeBar ( + IN OUT PCI_IO_DEVICE *PciIoDevice + ) +{ + EFI_STATUS Status; + + PciIoDevice->ResizableBarOffset = 0; + Status = LocatePciExpressCapabilityRegBlock ( + PciIoDevice, + PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID, + &PciIoDevice->ResizableBarOffset + ); + if (!EFI_ERROR (Status)) { + PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL ResizableBarControl; + UINT32 Offset; + + Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER) + + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY); + ResizableBarControl.Uint32 = PciExpressRead32(PciIoDevice->Address + Offset); + PciIoDevice->ResizableBarNumber = ResizableBarControl.Bits.ResizableBarNumber; + DEBUG ((DEBUG_VERBOSE, "PciResizableBarNumber %d ResizableBarControl %x \n", PciIoDevice->ResizableBarNumber, ResizableBarControl.Uint32)); + PciProgramResizableBar (PciIoDevice, PciResizableBarMax); + } +}