alder_lake_bios/Intel/AlderLake/ClientOneSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.c

659 lines
26 KiB
C

/** @file
This SMM driver will handle SA relevant late initialization
@copyright
INTEL CONFIDENTIAL
Copyright 2012 - 2021 Intel Corporation.
The source code contained or described herein and all documents related to the
source code ("Material") are owned by Intel Corporation or its suppliers or
licensors. Title to the Material remains with Intel Corporation or its suppliers
and licensors. The Material may contain trade secrets and proprietary and
confidential information of Intel Corporation and its suppliers and licensors,
and is protected by worldwide copyright and trade secret laws and treaty
provisions. No part of the Material may be used, copied, reproduced, modified,
published, uploaded, posted, transmitted, distributed, or disclosed in any way
without Intel's prior express written permission.
No license under any patent, copyright, trade secret or other intellectual
property right is granted to or conferred upon you by disclosure or delivery
of the Materials, either expressly, by implication, inducement, estoppel or
otherwise. Any license under such intellectual property rights must be
express and approved by Intel in writing.
Unless otherwise agreed by Intel in writing, you may not remove or alter
this notice or any other notice embedded in Materials by Intel or
Intel's suppliers or licensors in any way.
This file contains an 'Intel Peripheral Driver' and is uniquely identified as
"Intel Reference Module" and is licensed for Intel CPUs and chipsets under
the terms of your license agreement with Intel or your vendor. This file may
be modified by the user, subject to additional terms of the license agreement.
@par Specification Reference:
**/
#include <Library/BaseLib.h>
#include <Base.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/SmmServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/HobLib.h>
#include <Library/SaPlatformLib.h>
#include <Protocol/SmmIoTrapDispatch2.h>
#include "SaLateInitSmm.h"
#include <CpuRegs.h>
#include <Library/PciSegmentLib.h>
#include <CpuDataStruct.h>
#include <CpuPcieHob.h>
#include <CpuPcieHobGen3.h>
#include <Protocol/SaIotrapSmi.h>
#include <PchPcieRpConfig.h>
#include <Library/GraphicsInfoFruLib.h>
#include <SaConfigHob.h>
#include "CpuPcieInfo.h"
#include <Register/CpuPcieRegs.h>
#include <Library/CpuPlatformLib.h>
#include <IndustryStandard/Pci30.h>
#include <Register/IgdRegs.h>
#include <Register/SaPcieDmiRegs.h>
#include <Register/CommonMsr.h>
#include <Library/CpuPcieRpLib.h>
typedef enum {
EnumSaSmiCallbackForMaxPayLoad,
EnumSaSmiCallbackForSaSaveRestore,
EnumSaSmiCallbackForLateInit,
EnumSaSmiCallbackForS3resume,
EnumSaSmiCallbackMax
} SMI_OPERATION;
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSaSmiCallbackPhase = EnumSaSmiCallbackForMaxPayLoad;
GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *mPchIoTrap;
GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
typedef struct {
UINT64 BaseAddr;
UINT32 Offset;
UINT32 AndMask;
UINT32 OrMask;
} BOOT_SCRIPT_REGISTER_SETTING;
typedef union {
struct {
UINT32 Low;
UINT32 High;
} Data32;
UINT64 Data;
} UINT64_STRUCT;
///
/// SA PCI Registers to save for S3 resume
///
GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSaChipsetPciRegistersTable[] = {
R_SA_DEVEN,
};
//
// Address values for mSaChipsetPciRegistersSaveTable will be initialized at Runtime inside function
// CpuPcieInitPolicy(). The Address uses the Register Offset from table mSaChipsetPciRegistersTable
//
GLOBAL_REMOVE_IF_UNREFERENCED BOOT_SCRIPT_PCI_REGISTER_SAVE mSaChipsetPciRegistersSaveTable[] = {
{0, S3BootScriptWidthUint32, 0}, // R_SA_DEVEN
};
GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mDeviceCapMmBaseSave [CPU_PCIE_MAX_ROOT_PORTS][MAX_SUPPORTED_DEVICE_NUMBER];
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mDeviceExtCapLtrOffsetSave [CPU_PCIE_MAX_ROOT_PORTS][MAX_SUPPORTED_DEVICE_NUMBER];
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mDeviceExtCapVcOffsetSave [CPU_PCIE_MAX_ROOT_PORTS][MAX_SUPPORTED_DEVICE_NUMBER];
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mDeviceBusNumberSave [CPU_PCIE_MAX_ROOT_PORTS][MAX_SUPPORTED_DEVICE_NUMBER];
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mDeviceAspmSave [CPU_PCIE_MAX_ROOT_PORTS][MAX_SUPPORTED_DEVICE_NUMBER];
GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mDeviceLtrObffSave [CPU_PCIE_MAX_ROOT_PORTS][MAX_SUPPORTED_DEVICE_NUMBER];
GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mDeviceMaxSnoopLatencySave [CPU_PCIE_MAX_ROOT_PORTS][MAX_SUPPORTED_DEVICE_NUMBER];
GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mDeviceMaxNoSnoopLatencySave [CPU_PCIE_MAX_ROOT_PORTS][MAX_SUPPORTED_DEVICE_NUMBER];
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mDeviceTcxVc0MappingSave [CPU_PCIE_MAX_ROOT_PORTS][MAX_SUPPORTED_DEVICE_NUMBER];
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mCommonClock [CPU_PCIE_MAX_ROOT_PORTS] = {0, 0, 0};
GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mDeviceControlRegisterSave [CPU_PCIE_MAX_ROOT_PORTS][MAX_SUPPORTED_DEVICE_NUMBER];
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mNumberOfDeviceFound [CPU_PCIE_MAX_ROOT_PORTS] = {0, 0, 0};
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPAMSave [MAX_PAM_REG_COUNT];
GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSaChipsetPciRegistersSave [sizeof (mSaChipsetPciRegistersSaveTable) / sizeof (BOOT_SCRIPT_PCI_REGISTER_SAVE)];
///
/// Store required policy setting in global variables.
///
GLOBAL_REMOVE_IF_UNREFERENCED CPU_PCIE_ASPM_CONFIG mPegAspmPerPort[CPU_PCIE_MAX_ROOT_PORTS];
GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mCridEnable;
GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mSnoopLatencyOvrValue;
GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mNonSnoopLatencyOvrValue;
GLOBAL_REMOVE_IF_UNREFERENCED CPU_PCIE_PWR_OPT mPegPwrOpt[SA_PEG_MAX_FUN];
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMaxBusNumberSupported;
GLOBAL_REMOVE_IF_UNREFERENCED EFI_STATUS mEnumStatus;
/**
This function programs the LTR Override values
**/
VOID
PcieILtrOverride (
VOID
)
{
UINT64_STRUCT MchBar;
UINT32 Data32And;
UINT32 Data32Or;
MchBar.Data32.High = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, R_SA_MCHBAR + 4));
MchBar.Data32.Low = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, R_SA_MCHBAR));
MchBar.Data &= (UINT64) ~BIT0;
Data32And = 0x0;
///
/// Configure Snoop Latency value
///
if (mSnoopLatencyOvrValue != 0) {
mSnoopLatencyOvrValue |= BIT14;
}
Data32Or = ((UINT32) (mSnoopLatencyOvrValue << 16));
///
/// Configure Non-Snoop Latency value
///
if (mNonSnoopLatencyOvrValue != 0) {
mNonSnoopLatencyOvrValue |= BIT14;
}
Data32Or |= (UINT32) mNonSnoopLatencyOvrValue;
///
/// Program ILTR_OVRD with latency values
///
MmioAndThenOr32 (MchBar.Data + R_SA_MCHBAR_ILTR_OVRD_OFFSET, Data32And, Data32Or);
S3BootScriptSaveMemReadWrite (
S3BootScriptWidthUint32,
(UINTN) (MchBar.Data + R_SA_MCHBAR_ILTR_OVRD_OFFSET),
&Data32Or, /// Data to be ORed
&Data32And /// Data to be ANDed
);
}
/**
This function apply additional settings before ASPM enabling
@param[in] RootBridgeIndex - Root Bridge Index to select mDeviceCapMmBaseSave array elements for ASPM capability calculation.
**/
VOID
PcieAdditionalSettingBeforeASPM (
IN UINT8 RootBridgeIndex
)
{
UINT32 Data32Or;
UINT32 Data32And;
if ((mPegAspmPerPort[RootBridgeIndex] != PcieAspmDisabled) && (mCommonClock [RootBridgeIndex] == 1)) {
///
/// Enable support for L0s and L1 by programming the `Active State Link
/// PM Support' field of the LCAP register at D.F.R 0ACh [11:10] = `11b'.
///
PciSegmentOr32 ((mDeviceCapMmBaseSave[RootBridgeIndex][0] & (UINTN) ~0xFF) + 0x0AC, BIT11 | BIT10);
Data32Or = (BIT11 | BIT10);
Data32And = (UINT32) ~(BIT11 | BIT10);
S3BootScriptSaveMemReadWrite (
S3BootScriptWidthUint32,
PcdGet64 (PcdSiPciExpressBaseAddress) + (mDeviceCapMmBaseSave [RootBridgeIndex][0] & (UINT64) ~0xFF) + 0x0AC,
&Data32Or, ///< Data to be ORed
&Data32And ///< Data to be ANDed
);
///
/// Set D.F.R 0200h [27:26] to `00b'.
///
PciSegmentAnd32 ((mDeviceCapMmBaseSave[RootBridgeIndex][0] & (UINTN) ~0xFF) + 0x200, (UINT32) ~(BIT27 | BIT26));
Data32Or = 0;
Data32And = (UINT32) ~(BIT27 | BIT26);
S3BootScriptSaveMemReadWrite (
S3BootScriptWidthUint32,
PcdGet64 (PcdSiPciExpressBaseAddress) + (mDeviceCapMmBaseSave [RootBridgeIndex][0] & (UINT64) ~0xFFu) + 0x200,
&Data32Or, ///< Data to be ORed
&Data32And ///< Data to be ANDed
);
///
/// Set D.F.R 0258 [2] to '1b' for PCI Express 2.0 compliance
/// Note: Other fields within this register must not be changed
/// while writing to D1.F0.R 0258h [2]
///
PciSegmentOr16 ((mDeviceCapMmBaseSave [RootBridgeIndex][0] & (UINT64) ~0xFF) + R_SA_PEG_CFG4_OFFSET, BIT2);
Data32Or = BIT2;
Data32And = (UINT32) ~(BIT2);
S3BootScriptSaveMemReadWrite (
S3BootScriptWidthUint32,
PcdGet64 (PcdSiPciExpressBaseAddress) + (mDeviceCapMmBaseSave [RootBridgeIndex][0] & (UINT64) ~0xFF) + R_SA_PEG_CFG4_OFFSET,
&Data32Or, ///< Data to be ORed
&Data32And ///< Data to be ANDed
);
}
}
/**
This function saves/restores Chipset registers
@param[in] IsSaving - TRUE for saving and FALSE for restoring
@param[in] PciRegistersSaveTable[] - The register table that has to be saved/restored
@param[in] PciRegistersSaveTableSize - Size of above table
@param[in] PciRegistersSaveBuffer - A saving/restoring buffer for those register settings.
**/
VOID
SaSaveRestoreChipset (
IN BOOLEAN IsSaving,
IN BOOT_SCRIPT_PCI_REGISTER_SAVE PciRegistersSaveTable[],
IN UINTN PciRegistersSaveTableSize,
IN OUT UINTN *PciRegistersSaveBuffer
)
{
UINT8 Index;
if (IsSaving == TRUE) {
DEBUG ((DEBUG_INFO, "SA Save PCI register settings\n"));
///
/// Save SA PCI Registers for S3 resume
///
for (Index = 0; Index < PciRegistersSaveTableSize; Index++) {
PciRegistersSaveBuffer[Index] = PciSegmentRead32 (PciRegistersSaveTable[Index].Address);
S3BootScriptSaveMemWrite (
S3BootScriptWidthUint32,
PcdGet64 (PcdSiPciExpressBaseAddress) + PciRegistersSaveTable[Index].Address,
1,
&PciRegistersSaveBuffer[Index]
);
DEBUG ((DEBUG_INFO, "SA Register = %X, SaPciRegSave = %08X\n", PciRegistersSaveTable[Index].Address, PciRegistersSaveBuffer[Index]));
}
} else {
DEBUG ((DEBUG_INFO, "SA Restore PCI register settings\n"));
///
/// Restore SA PCI Registers for S3 resume
///
for (Index = 0; Index < PciRegistersSaveTableSize; Index++) {
PciSegmentWrite32 (PciRegistersSaveTable[Index].Address, (UINT32) PciRegistersSaveBuffer[Index]);
DEBUG ((DEBUG_INFO, "SA Register = %X, SaPciRegSave = %08X\n", PciRegistersSaveTable[Index].Address, PciRegistersSaveBuffer[Index]));
}
}
}
/**
This function saves/restores platform relative registers
@param[in] IsSaving - TRUE for saving and FALSE for restoring
**/
VOID
SaSaveRestorePlatform (
IN BOOLEAN IsSaving
)
{
UINTN McBaseAddress;
UINT8 Index;
McBaseAddress = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, 0);
if (IsSaving == TRUE) {
DEBUG ((DEBUG_INFO, "SA Save platform register settings\n"));
///
/// Save PAM register
///
for (Index = 0; Index < MAX_PAM_REG_COUNT; Index++) {
mPAMSave[Index] = PciSegmentRead8 (McBaseAddress + (PAM_REG_BASE + Index));
S3BootScriptSaveMemWrite (
S3BootScriptWidthUint8,
PcdGet64 (PcdSiPciExpressBaseAddress) + McBaseAddress + (PAM_REG_BASE + Index),
1,
&mPAMSave[Index]
);
}
} else {
DEBUG ((DEBUG_INFO, "SA Restore platform register settings\n"));
///
/// Restore PAM register
///
for (Index = 0; Index < MAX_PAM_REG_COUNT; Index++) {
PciSegmentWrite8 (McBaseAddress + (PAM_REG_BASE + Index), mPAMSave [Index]);
}
}
}
/**
This function handles SA S3 resume
**/
VOID
SaS3Resume (
VOID
)
{
UINT8 PegComplete;
UINT8 EndpointCompleted;
UINT32 PegBaseAddress;
DEBUG ((DEBUG_INFO, "SA S3 resume\n"));
if (mEnumStatus == EFI_SUCCESS) {
///
/// Restore Bus number assignment first
///
for (PegComplete = 0; PegComplete < CPU_PCIE_MAX_ROOT_PORTS; PegComplete++) {
if (mDeviceCapMmBaseSave [PegComplete][0] == 0) {
continue;
}
EndpointCompleted = 0;
while (EndpointCompleted < mNumberOfDeviceFound [PegComplete]) {
PegBaseAddress = (mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] & (UINTN) ~0xFF);
PciSegmentWrite32 (PegBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, mDeviceBusNumberSave [PegComplete][EndpointCompleted]);
DEBUG ((DEBUG_INFO, " Restore Bus number [%X] = %08X\n", PegBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, PciSegmentRead32 (PegBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET)));
EndpointCompleted ++;
}
}
for (PegComplete = 0; PegComplete < CPU_PCIE_MAX_ROOT_PORTS; PegComplete++) {
if (mDeviceCapMmBaseSave [PegComplete][0] == 0) {
continue;
}
PcieAdditionalSettingBeforeASPM (PegComplete);
EndpointCompleted = 0;
while (EndpointCompleted < mNumberOfDeviceFound [PegComplete]) {
PegBaseAddress = (mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] & (UINTN) ~0xFF);
///
/// Restore Max Pay Load and Extended Tag
///
PciSegmentWrite16 (mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] + 0x8, mDeviceControlRegisterSave [PegComplete][EndpointCompleted]);
DEBUG ((DEBUG_INFO, "[B%X|D%X|F%X|R%X] DCTL=%X\n",
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] >> 20) & mMaxBusNumberSupported,
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] >> 15) & 0x1F,
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] >> 12) & 0x07,
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] + 0x08) & 0xFFF,
mDeviceControlRegisterSave [PegComplete][EndpointCompleted]));
///
/// Restore ASPM and Common Clock
///
PciSegmentWrite8 ((mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] + 0x010), mDeviceAspmSave [PegComplete][EndpointCompleted]);
DEBUG ((DEBUG_INFO, "[B%X|D%X|F%X|R%X] ASPM/CommonClock=%X\n",
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] >> 20) & mMaxBusNumberSupported,
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] >> 15) & 0x1F,
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] >> 12) & 0x07,
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] + 0x10) & 0xFFF,
mDeviceAspmSave [PegComplete][EndpointCompleted]));
///
/// Restore PEG power optimization.
///
PciSegmentAndThenOr16 (mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] + 0x28, (UINT16) ~(BIT10 + BIT13 + BIT14), mDeviceLtrObffSave [PegComplete][EndpointCompleted]);
DEBUG ((DEBUG_INFO, "[B%X|D%X|F%X|R%X] LTR/OBFF=%X\n",
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] >> 20) & mMaxBusNumberSupported,
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] >> 15) & 0x1F,
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] >> 12) & 0x07,
(mDeviceCapMmBaseSave [PegComplete][EndpointCompleted] + 0x28) & 0xFFF,
mDeviceLtrObffSave [PegComplete][EndpointCompleted]));
if (mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted] != 0) {
PciSegmentAndThenOr16 (PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted] + 0x4, (UINT16) (~0x1FFF), mDeviceMaxSnoopLatencySave [PegComplete][EndpointCompleted]);
DEBUG ((DEBUG_INFO, "[B%X|D%X|F%X|R%X] Max snoop latency=%X\n",
((PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted]) >> 20) & mMaxBusNumberSupported,
((PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted]) >> 15) & 0x1F,
((PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted]) >> 12) & 0x07,
(PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted] + 0x4) & 0xFFF,
mDeviceMaxSnoopLatencySave [PegComplete][EndpointCompleted]));
PciSegmentAndThenOr16 ((PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted] + 0x6), (UINT16) (~0x1FFF), mDeviceMaxNoSnoopLatencySave [PegComplete][EndpointCompleted]);
DEBUG ((DEBUG_INFO, "[B%X|D%X|F%X|R%X] Max No-snoop latency=%X\n",
((PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted]) >> 20) & mMaxBusNumberSupported,
((PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted]) >> 15) & 0x1F,
((PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted]) >> 12) & 0x07,
(PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted] + 0x6) & 0xFFF,
mDeviceMaxNoSnoopLatencySave [PegComplete][EndpointCompleted]));
}
if (mDeviceExtCapVcOffsetSave [PegComplete][EndpointCompleted]) {
PciSegmentAndThenOr8 ((mDeviceExtCapVcOffsetSave [PegComplete][EndpointCompleted] + 0x14), 0, mDeviceTcxVc0MappingSave [PegComplete][EndpointCompleted]);
DEBUG ((DEBUG_INFO, "[B%X|D%X|F%X|R%X] TCx/VC0 mapping=%X\n",
((PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted]) >> 20) & mMaxBusNumberSupported,
((PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted]) >> 15) & 0x1F,
((PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted]) >> 12) & 0x07,
(PegBaseAddress + mDeviceExtCapLtrOffsetSave [PegComplete][EndpointCompleted] + 0x14) & 0xFFF,
mDeviceTcxVc0MappingSave [PegComplete][EndpointCompleted]));
}
EndpointCompleted ++;
}
///
/// If common clock supported on root port and endpoint, retrain link
///
if (mCommonClock [PegComplete] == 1) {
DEBUG ((DEBUG_INFO, "Retrain Link for Common Clock\n"));
///
/// Retrain the Link per PCI Express Specification.
///
PciSegmentOr8 (mDeviceCapMmBaseSave [PegComplete][0] + 0x010, BIT5);
///
/// Wait until Re-Training has completed.
///
while ((PciSegmentRead16 (mDeviceCapMmBaseSave [PegComplete][0] + 0x012) & BIT11) != 0) {
}
}
}
}
///
/// Re-do this during S3 resume
///
PcieILtrOverride ();
}
/**
Wrapper function for all SA S3 resume tasks which can be a callback function.
**/
VOID
SaS3ResumeCallback (
VOID
)
{
SaS3Resume ();
SaSaveRestoreChipset (FALSE, mSaChipsetPciRegistersSaveTable, sizeof (mSaChipsetPciRegistersSaveTable) / sizeof (BOOT_SCRIPT_PCI_REGISTER_SAVE), mSaChipsetPciRegistersSave);
SaSaveRestorePlatform (FALSE);
}
/**
A SMI callback to do SA relevant late initialization
@param[in] DispatchHandle - The handle of this callback, obtained when registering
@param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
**/
VOID
EFIAPI
SaIoTrapSmiCallback (
IN EFI_HANDLE DispatchHandle,
IN CONST VOID *CallbackContext,
IN OUT VOID *CommBuffer,
IN OUT UINTN *CommBufferSize
)
{
if (mSaSmiCallbackPhase == EnumSaSmiCallbackMax) {
return;
}
if (mSaSmiCallbackPhase == EnumSaSmiCallbackForMaxPayLoad) {
///
/// Switch to next phase
///
mSaSmiCallbackPhase = EnumSaSmiCallbackForSaSaveRestore;
} else if (mSaSmiCallbackPhase == EnumSaSmiCallbackForSaSaveRestore) {
///
/// Save platform registers including IGFX BAR & COMMAND registers and PAM
///
SaSaveRestorePlatform (TRUE);
///
/// Switch to next phase
///
mSaSmiCallbackPhase = EnumSaSmiCallbackForLateInit;
} else if (mSaSmiCallbackPhase == EnumSaSmiCallbackForLateInit) {
///
/// Switch to next phase
///
mSaSmiCallbackPhase = EnumSaSmiCallbackForS3resume;
} else if (mSaSmiCallbackPhase == EnumSaSmiCallbackForS3resume) {
///
/// Expected to execute in end of S3 resume flow
///
SaS3ResumeCallback ();
}
}
/**
This function will initialize all required policy into global veriables so no need to locate policy protocol during runtime.
**/
VOID
CpuPcieInitPolicy (
IN SA_POLICY_PROTOCOL *SaPolicy
)
{
UINT8 RootPortCount;
UINT8 Index;
SA_CONFIG_HOB *SaConfigHob;
EFI_STATUS Status;
PCIE_DXE_CONFIG *PcieDxeConfig;
Status = GetConfigBlock ((VOID *) SaPolicy, &gPcieDxeConfigGuid, (VOID *)&PcieDxeConfig);
ASSERT_EFI_ERROR (Status);
SaConfigHob = NULL;
SaConfigHob = GetFirstGuidHob (&gSaConfigHobGuid);
///
/// Initialize module global variables - Stepping ID and Policy
///
for (Index = 0; (Index < (sizeof (mSaChipsetPciRegistersSaveTable) / sizeof (BOOT_SCRIPT_PCI_REGISTER_SAVE))) && (Index < (sizeof (mSaChipsetPciRegistersTable) / sizeof (UINTN))); Index++) {
mSaChipsetPciRegistersSaveTable[Index].Address = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, mSaChipsetPciRegistersTable[Index]);
}
for (RootPortCount = 0; RootPortCount < CPU_PCIE_MAX_ROOT_PORTS; RootPortCount++) {
mPegAspmPerPort[RootPortCount] = PcieDxeConfig->PegAspm[RootPortCount];
mPegPwrOpt[RootPortCount] = PcieDxeConfig->PegPwrOpt[RootPortCount];
}
if (SaConfigHob != NULL) {
mCridEnable = SaConfigHob->CridEnable;
}
///
/// Initialize Snoop and Non-Snoop Latencies
///
mSnoopLatencyOvrValue = 0;
mNonSnoopLatencyOvrValue = 0;
}
/**
Initializes the SA SMM handler
@param[in] ImageHandle - The image handle of Wake On Lan driver
@param[in] SystemTable - The standard EFI system table
@retval EFI_SUCCESS - SA SMM handler was installed or not necessary
@retval EFI_NOT_FOUND - Fail to register SMI callback or required protocol/hob missing.
**/
EFI_STATUS
EFIAPI
SaLateInitSmmEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
#if FixedPcdGetBool(PcdCpuPcieEnable) == 1
EFI_SMM_IO_TRAP_REGISTER_CONTEXT PchIoTrapContext;
EFI_HANDLE PchIoTrapHandle;
CPU_PCIE_HOB *CpuPcieHob = NULL;
SA_POLICY_PROTOCOL *SaPolicy;
SA_IOTRAP_SMI_PROTOCOL *SaIotrapSmiProtocol;
EFI_STATUS Status;
BOOLEAN InitPcieAspmAfterOprom = FALSE;
#endif
DEBUG ((DEBUG_INFO, "SaLateInitSmmEntryPoint()\n"));
//
// Force RC6 for DisplayOnly SKU
//
if (IsDisplayOnlySku()) {
ForceGtRc6 ();
}
#if FixedPcdGetBool(PcdCpuPcieEnable) == 1
CpuPcieHob = (CPU_PCIE_HOB *) GetFirstGuidHob (&gCpuPcieHobGuid);
Status = EFI_NOT_FOUND;
if (CpuPcieHob == NULL) {
DEBUG ((DEBUG_INFO, "CPU PCIE HOB Not found\n"));
ASSERT (CpuPcieHob != NULL);
return Status;
}
InitPcieAspmAfterOprom = CpuPcieHob->InitPcieAspmAfterOprom;
///
/// Locate the PCH Trap dispatch protocol
///
Status = gSmst->SmmLocateProtocol (&gEfiSmmIoTrapDispatch2ProtocolGuid, NULL, (VOID **) &mPchIoTrap);
ASSERT_EFI_ERROR (Status);
Status = gSmst->SmmLocateProtocol (&gEfiSmmSxDispatch2ProtocolGuid, NULL, (VOID**) &mSxDispatch);
ASSERT_EFI_ERROR (Status);
if (Status == EFI_SUCCESS) {
if (InitPcieAspmAfterOprom == TRUE) {
///
/// Register SMI callback to initialize PCIe ASPM after OPROM
///
PchIoTrapContext.Type = ReadWriteTrap;
PchIoTrapContext.Length = 4;
PchIoTrapContext.Address = 0;
Status = mPchIoTrap->Register (
mPchIoTrap,
(EFI_SMM_HANDLER_ENTRY_POINT2) SaIoTrapSmiCallback,
&PchIoTrapContext,
&PchIoTrapHandle
);
ASSERT_EFI_ERROR (Status);
if (Status == EFI_SUCCESS) {
///
/// Initialize module global variables - Stepping ID and Policy for runtime SMI handler
/// Get the platform setup policy.
///
Status = gBS->LocateProtocol (&gSaPolicyProtocolGuid, NULL, (VOID **) &SaPolicy);
ASSERT_EFI_ERROR (Status);
if (SaPolicy != NULL) {
CpuPcieInitPolicy (SaPolicy);
}
///
/// Install the SA IOTRAP SMI protocol
///
(gBS->AllocatePool) (EfiBootServicesData, sizeof (SA_IOTRAP_SMI_PROTOCOL), (VOID **)&SaIotrapSmiProtocol);
SaIotrapSmiProtocol->SaIotrapSmiAddress = PchIoTrapContext.Address;
Status = gBS->InstallMultipleProtocolInterfaces (
&ImageHandle,
&gSaIotrapSmiProtocolGuid,
SaIotrapSmiProtocol,
NULL
);
DEBUG ((DEBUG_INFO, "SA Iotrap address=%X\n", SaIotrapSmiProtocol->SaIotrapSmiAddress));
}
} else {
///
/// If ASPM policy is set to "Before OPROM", this SMI callback is not necessary
/// Ensure the SMI callback handler will directly return and continue the POST.
///
mSaSmiCallbackPhase = EnumSaSmiCallbackMax;
Status = EFI_SUCCESS;
}
}
Status = InitializeCpuPcieSmm (ImageHandle, SystemTable);
ASSERT_EFI_ERROR (Status);
if (Status != EFI_SUCCESS) {
DEBUG ((DEBUG_ERROR, "Failed to register SaIotrapSmiCallback!\n"));
///
/// System will halt when failing to register required SMI handler
///
CpuDeadLoop ();
}
#endif
return EFI_SUCCESS;
}