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 <mariano-paulx.pastorcici@intel.com>
This commit is contained in:
Pastorcici, Mariano-paulX 2024-08-26 01:08:04 +03:00 committed by Guo Dong
parent 32704b0653
commit c50658ae6b
7 changed files with 156 additions and 2 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -5,6 +5,7 @@
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/BaseLib.h>
#include <Uefi/UefiBaseType.h>
#include <Library/DebugLib.h>

View File

@ -17,6 +17,7 @@
#include <Library/BootloaderCommonLib.h>
#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;
}

View File

@ -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

View File

@ -0,0 +1,120 @@
/** @file
Copyright (c) 2020 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi/UefiBaseType.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/PciExpressLib.h>
#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);
}
}