472 lines
16 KiB
C
472 lines
16 KiB
C
/** @file
|
|
Power Management EarlyPost initializations.
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 2014 - 2020 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
|
|
**/
|
|
|
|
#include <Ppi/SiPolicy.h>
|
|
#include <Library/CpuPlatformLib.h>
|
|
#include <Library/CpuMailboxLib.h>
|
|
#include <Library/CpuCommonLib.h>
|
|
#include <Library/PeiOcLib.h>
|
|
#include <Library/BiosGuardInit.h>
|
|
#include <Library/ConfigBlockLib.h>
|
|
#include "Features.h"
|
|
#include <Library/PostCodeLib.h>
|
|
#include <Library/PciSegmentLib.h>
|
|
|
|
/**
|
|
Based on ResetType, perform warm or cold reset using PCH reset PPI.
|
|
|
|
@param[in] ResetType - CPU_RESET_TYPE to indicate which reset should be performed.
|
|
|
|
@retval EFI_SUCCESS - Function successful (system should already reset).
|
|
@retval EFI_UNSUPPORTED - Reset type unsupported.
|
|
**/
|
|
EFI_STATUS
|
|
PerformWarmOrColdReset (
|
|
IN CPU_RESET_TYPE ResetType
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
///
|
|
/// Perform the requested reset using EFI RESET2 PeiService.
|
|
///
|
|
switch (ResetType) {
|
|
case COLD_RESET:
|
|
(*GetPeiServicesTablePointer ())->ResetSystem2 (EfiResetCold, EFI_SUCCESS, 0, NULL);
|
|
break;
|
|
|
|
case WARM_RESET:
|
|
(*GetPeiServicesTablePointer ())->ResetSystem2 (EfiResetWarm, EFI_SUCCESS, 0, NULL);
|
|
break;
|
|
|
|
default:
|
|
DEBUG ((DEBUG_ERROR, "CpuInitPreResetCpl: PerformWarmOrColdReset - ResetType %d not supported: \n", ResetType));
|
|
Status = EFI_UNSUPPORTED;
|
|
ASSERT_EFI_ERROR (Status);
|
|
break;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Program Tcc Activation Offset and Running Average Temperature Limit (RATL).
|
|
|
|
@param[in] SiPolicyPpi - The SI Policy PPI instance
|
|
**/
|
|
VOID
|
|
InitRatl (
|
|
IN SI_POLICY_PPI *SiPolicyPpi
|
|
)
|
|
{
|
|
MSR_TEMPERATURE_TARGET_REGISTER TempMsr;
|
|
BOOLEAN IsTccActivationOffsetProgrammable;
|
|
CPU_POWER_MGMT_BASIC_CONFIG *CpuPowerMgmtBasicConfig;
|
|
BOOLEAN IsTimeWindowInSeconds;
|
|
UINT8 ConvertedTccOffsetTime;
|
|
EFI_STATUS Status;
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtBasicConfigGuid, (VOID *) &CpuPowerMgmtBasicConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
///
|
|
/// Check Tcc Activation Offset Programmable Setting from Platform Info MSR Bits[30]
|
|
///
|
|
IsTccActivationOffsetProgrammable = MsrIsPrgTjOffsetEn ();
|
|
DEBUG ((DEBUG_INFO,"TCC activation programmable = %x\n", IsTccActivationOffsetProgrammable));
|
|
|
|
///
|
|
/// First check if TCC Activation Offset is programmable based on PLATFORM INFO MSR [30]
|
|
/// If TCC activation offset is not programmable, skip programming TEMPERATURE_TARGET MSR.
|
|
/// If TCC Activation Offset is programable, program the TCC Activation offset value
|
|
/// from Policy, and the Tcc activation offset programming should be dependent on RESET_CPL done.
|
|
///
|
|
if (IsTccActivationOffsetProgrammable) {
|
|
///
|
|
/// Read Temperature Target MSR
|
|
///
|
|
TempMsr.Uint64 = AsmReadMsr64 (MSR_TEMPERATURE_TARGET);
|
|
|
|
///
|
|
/// If TccActivationOffset is greater than max supported value, set it to max value.
|
|
///
|
|
if (CpuPowerMgmtBasicConfig->TccActivationOffset > TempMsr.Bits.RefTemp) {
|
|
TempMsr.Bits.TjMaxTccOffset = (UINT8) TempMsr.Bits.RefTemp;
|
|
} else {
|
|
TempMsr.Bits.TjMaxTccOffset = CpuPowerMgmtBasicConfig->TccActivationOffset;
|
|
}
|
|
|
|
///
|
|
/// Running Average Temperature Limit (RATL) permits advanced thermal management with bursts of excursion above Tjmax
|
|
/// while maintaining the overall average temperature.
|
|
///
|
|
IsTimeWindowInSeconds = (CpuPowerMgmtBasicConfig->TccOffsetTimeWindowForRatl / 1000) >= 1;
|
|
if (IsTimeWindowInSeconds) {
|
|
ConvertedTccOffsetTime = GetConvertedTime ((CpuPowerMgmtBasicConfig->TccOffsetTimeWindowForRatl / 1000), SecondsTimeWindowConvert);
|
|
} else {
|
|
ConvertedTccOffsetTime = GetConvertedTime (CpuPowerMgmtBasicConfig->TccOffsetTimeWindowForRatl, MilliSecondsTimeWindowConvert);
|
|
}
|
|
TempMsr.Bits.TccOffsetTimeWindow = 0;
|
|
if (CpuPowerMgmtBasicConfig->TccOffsetTimeWindowForRatl != 0) {
|
|
///
|
|
/// Get converted time window based on setting of policy
|
|
///
|
|
TempMsr.Bits.TccOffsetTimeWindow = ConvertedTccOffsetTime;
|
|
}
|
|
|
|
///
|
|
/// When Clamp enable bit set, allow throttling below P1.
|
|
///
|
|
TempMsr.Bits.TccOffsetClampingBit = 0;
|
|
if (CpuPowerMgmtBasicConfig->TccOffsetClamp) {
|
|
TempMsr.Bits.TccOffsetClampingBit = 1;
|
|
}
|
|
|
|
///
|
|
/// Lock the MSR by setting BIT31 of MSR 1A2h.
|
|
///
|
|
TempMsr.Bits.Locked = 0;
|
|
if (CpuPowerMgmtBasicConfig->TccOffsetLock) {
|
|
TempMsr.Bits.Locked = 1;
|
|
}
|
|
|
|
///
|
|
/// Write Temperature Target MSR
|
|
///
|
|
AsmWriteMsr64 (MSR_TEMPERATURE_TARGET, TempMsr.Uint64);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Set processor P state based on input parameter.
|
|
|
|
@param[in out] Buffer - Pointer to UINT8 BootRatio parameter.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
ApSafeSetBootPState (
|
|
IN OUT VOID *Buffer
|
|
)
|
|
{
|
|
UINT8 BootRatio;
|
|
MSR_PERF_CTL_REGISTER Ia32PerfCtl;
|
|
|
|
///
|
|
/// Extract the boot ratio from the buffer.
|
|
///
|
|
BootRatio = *((UINT8 *) Buffer);
|
|
//
|
|
// Same MSR offset definition MSR_IA32_PERF_CTL 0x00000199 in ArchitecturalMsr.h
|
|
//
|
|
Ia32PerfCtl.Uint64 = AsmReadMsr64 (MSR_PERF_CTL);
|
|
Ia32PerfCtl.Bits.PReq = BootRatio;
|
|
AsmWriteMsr64 (MSR_PERF_CTL, Ia32PerfCtl.Uint64);
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Set the Boot Frequency across all logical processors.
|
|
|
|
@param[in] SiPolicyPpi - The SI Policy PPI instance.
|
|
**/
|
|
VOID
|
|
SetBootFrequency (
|
|
IN SI_POLICY_PPI *SiPolicyPpi
|
|
)
|
|
{
|
|
UINT8 BootRatio;
|
|
MSR_MISC_ENABLES_REGISTER MiscEnable;
|
|
MSR_TURBO_RATIO_LIMIT_REGISTER TurboRatioLimit;
|
|
MSR_CONFIG_TDP_NOMINAL_REGISTER TdpNominal;
|
|
MSR_CONFIG_TDP_LEVEL2_REGISTER TdpLevelx;
|
|
UINT8 MaxBusRatio;
|
|
UINT8 MinBusRatio;
|
|
UINT8 BootFrequencyMode;
|
|
CPUID_THERMAL_POWER_MANAGEMENT_EAX Eax;
|
|
UINT8 NumberOfConfigTdpLevels;
|
|
UINT8 SupportedCtdpLevels;
|
|
UINT8 SelectedCtdpLevel;
|
|
UINT8 CtdpTarRatioPlusOne;
|
|
CPU_POWER_MGMT_BASIC_CONFIG *CpuPowerMgmtBasicConfig;
|
|
CPU_POWER_MGMT_TEST_CONFIG *CpuPowerMgmtTestConfig;
|
|
CPU_POWER_MGMT_CUSTOM_CONFIG *CpuPowerMgmtCustomConfig;
|
|
CPU_CONFIG_LIB_PREMEM_CONFIG *CpuConfigLibPreMemConfig;
|
|
EFI_STATUS Status;
|
|
SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi;
|
|
|
|
Status = PeiServicesLocatePpi (
|
|
&gSiPreMemPolicyPpiGuid,
|
|
0,
|
|
NULL,
|
|
(VOID **)&SiPreMemPolicyPpi
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtBasicConfigGuid, (VOID *) &CpuPowerMgmtBasicConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtCustomConfigGuid, (VOID *) &CpuPowerMgmtCustomConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtTestConfigGuid, (VOID *) &CpuPowerMgmtTestConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gCpuConfigLibPreMemConfigGuid, (VOID *) &CpuConfigLibPreMemConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
///
|
|
/// Get Maximum Non-Turbo bus ratio (HFM) from Platform Info MSR Bits[15:8]
|
|
/// Get Maximum Efficiency bus ratio (LFM) from Platform Info MSR Bits[47:40]
|
|
///
|
|
MsrGetBusRatio (&MaxBusRatio, &MinBusRatio);
|
|
|
|
BootRatio = MinBusRatio;
|
|
BootFrequencyMode = (UINT8) CpuConfigLibPreMemConfig->BootFrequency;
|
|
|
|
///
|
|
/// Temporarily enable EIST on BSP.
|
|
///
|
|
//
|
|
// Same MSR offset defintion MSR_IA32_MISC_ENABLE 0x000001A0 in ArchitecturalMsr.h
|
|
//
|
|
MiscEnable.Uint64 = AsmReadMsr64 (MSR_MISC_ENABLES);
|
|
MiscEnable.Bits.EnableGv3 = 1;
|
|
AsmWriteMsr64 (MSR_MISC_ENABLES, MiscEnable.Uint64);
|
|
|
|
if (CpuConfigLibPreMemConfig->BootFrequency == 2) {
|
|
if (CpuPowerMgmtBasicConfig->TurboMode && (CpuPowerMgmtTestConfig->Eist || CpuPowerMgmtBasicConfig->Hwp)) {
|
|
//
|
|
// Set processor P state as TURBO_RATIO_LIMIT_1C if available
|
|
//
|
|
AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &Eax.Uint32, NULL, NULL, NULL);
|
|
if ((Eax.Bits.TurboBoostTechnology == 1) ||
|
|
(MiscEnable.Bits.TurboModeDisable)) {
|
|
//
|
|
// Enable Turbo
|
|
//
|
|
MiscEnable.Bits.TurboModeDisable = 0;
|
|
AsmWriteMsr64 (MSR_MISC_ENABLES, MiscEnable.Uint64);
|
|
//
|
|
// Set Boot Ratio to TURBO_RATIO_LIMIT_1C
|
|
//
|
|
TurboRatioLimit.Uint64 = AsmReadMsr64 (MSR_TURBO_RATIO_LIMIT);
|
|
BootRatio = (UINT8) TurboRatioLimit.Bits.MaxTurbo1Core;
|
|
} else {
|
|
//
|
|
// Turbo is not available, down to HFM
|
|
//
|
|
DEBUG ((DEBUG_INFO, "CPU: Turbo mode is not available, down to HFM mode.\n"));
|
|
BootFrequencyMode = 1;
|
|
BootRatio = MaxBusRatio;
|
|
}
|
|
} else {
|
|
//
|
|
// Turbo is disabled, down to HFM
|
|
//
|
|
BootFrequencyMode = 1;
|
|
BootRatio = MaxBusRatio;
|
|
}
|
|
} else if (CpuConfigLibPreMemConfig->BootFrequency == 1) {
|
|
BootRatio = MaxBusRatio;
|
|
} else {
|
|
BootRatio = MinBusRatio;
|
|
}
|
|
|
|
///
|
|
/// If there are any configurable TDP Levels supported, set the boot ratio
|
|
/// based on BootFrequencyMode and cTDP TAR ratio.
|
|
///
|
|
NumberOfConfigTdpLevels = MsrGetConfigTdpLevels ();
|
|
if (NumberOfConfigTdpLevels != 0) {
|
|
//
|
|
// Find the selected level and the TAR ratio.
|
|
//
|
|
SupportedCtdpLevels = NumberOfConfigTdpLevels + 1;
|
|
SelectedCtdpLevel = (UINT8) CpuConfigLibPreMemConfig->ConfigTdpLevel;
|
|
|
|
//
|
|
// Select cTDP Nominal if cTDP is disabled or the level is not supported.
|
|
//
|
|
if (SelectedCtdpLevel == CONFIG_TDP_DEACTIVATE || SelectedCtdpLevel >= SupportedCtdpLevels) {
|
|
SelectedCtdpLevel = 0;
|
|
}
|
|
|
|
if (SelectedCtdpLevel >= 3) {
|
|
DEBUG ((DEBUG_ERROR, "ERROR: Invalid SelectedCtdpLevel=%x, and SelectedCtdpLevel should be range in 0-2 \n", SelectedCtdpLevel));
|
|
ASSERT (FALSE);
|
|
return;
|
|
}
|
|
|
|
if (CpuPowerMgmtCustomConfig->CustomConfigTdpTable[SelectedCtdpLevel].CustomTurboActivationRatio != 0) {
|
|
CtdpTarRatioPlusOne = (UINT8) CpuPowerMgmtCustomConfig->CustomConfigTdpTable[SelectedCtdpLevel].CustomTurboActivationRatio + 1;
|
|
} else {
|
|
if (SelectedCtdpLevel == 0) {
|
|
TdpNominal.Uint64 = AsmReadMsr64 (MSR_CONFIG_TDP_NOMINAL);
|
|
CtdpTarRatioPlusOne = (UINT8) TdpNominal.Bits.TdpRatio;
|
|
} else if (SelectedCtdpLevel == 1) {
|
|
TdpLevelx.Uint64 = AsmReadMsr64 (MSR_CONFIG_TDP_LEVEL1);
|
|
if (TdpLevelx.Bits.TdpRatio == 0) {
|
|
//
|
|
// If Level1 was not valid, then read Level2 register
|
|
//
|
|
TdpLevelx.Uint64 = AsmReadMsr64 (MSR_CONFIG_TDP_LEVEL2);
|
|
CtdpTarRatioPlusOne = (UINT8) TdpLevelx.Bits.TdpRatio;
|
|
}
|
|
CtdpTarRatioPlusOne = (UINT8) TdpLevelx.Bits.TdpRatio;
|
|
} else {
|
|
TdpLevelx.Uint64 = AsmReadMsr64 (MSR_CONFIG_TDP_LEVEL2);
|
|
CtdpTarRatioPlusOne = (UINT8) TdpLevelx.Bits.TdpRatio;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make sure the TAR+1 ratio is between the fused min and (max+1) ratios.
|
|
//
|
|
if (CtdpTarRatioPlusOne < MinBusRatio) {
|
|
CtdpTarRatioPlusOne = MinBusRatio;
|
|
} else if (CtdpTarRatioPlusOne > MaxBusRatio + 1) {
|
|
CtdpTarRatioPlusOne = MaxBusRatio + 1;
|
|
}
|
|
|
|
if (BootFrequencyMode == 2) {
|
|
//
|
|
// Use TAR Ratio + 1 to go to Turbo mode once ConfigTDP is fully configured and the TAR ratio MSR is configured.
|
|
//
|
|
BootRatio = CtdpTarRatioPlusOne;
|
|
} else if (BootFrequencyMode == 1) {
|
|
//
|
|
// Use TAR Ratio as max non-turbo ratio, which is equal to ConfigTDP boot ratio - 1.
|
|
//
|
|
BootRatio = CtdpTarRatioPlusOne - 1;
|
|
|
|
//
|
|
// If EIST is disabled use ConfigTDP boot ratio, which is equal to TAR+1.
|
|
//
|
|
if (!CpuPowerMgmtTestConfig->Eist) {
|
|
BootRatio = BootRatio + 1;
|
|
}
|
|
} else {
|
|
//
|
|
// Use MinBusRatio (LFM) unless ConfigTDP boot ratio is equal to LFM.
|
|
// In that case, use 'fake' P-State of ConfigTDP boot ratio - 1, which is equal to TAR ratio.
|
|
//
|
|
BootRatio = MinBusRatio;
|
|
if ((CtdpTarRatioPlusOne == MinBusRatio) && CpuPowerMgmtTestConfig->Eist) {
|
|
BootRatio = CtdpTarRatioPlusOne - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Set MSR_IA32_PERF_CTL on BSP.
|
|
///
|
|
ApSafeSetBootPState (&BootRatio);
|
|
|
|
///
|
|
/// Set MSR_IA32_PERF_CTL on all APs unless disabled by policy setting.
|
|
///
|
|
if (CpuPowerMgmtBasicConfig->SkipSetBootPState != CPU_FEATURE_ENABLE) {
|
|
mMpServices2Ppi->StartupAllAPs (
|
|
mMpServices2Ppi,
|
|
(EFI_AP_PROCEDURE) ApSafeSetBootPState,
|
|
FALSE,
|
|
0,
|
|
&BootRatio
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Initialize performance and power management features before RESET_CPL at Post-memory phase.
|
|
|
|
@param[in] SiPolicyPpi The SI Policy PPI instance.
|
|
**/
|
|
VOID
|
|
CpuInitPreResetCpl (
|
|
IN SI_POLICY_PPI *SiPolicyPpi
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
CPUID_VERSION_INFO_ECX Ecx;
|
|
CPU_TEST_CONFIG *CpuTestConfig;
|
|
CPU_CONFIG *CpuConfig;
|
|
|
|
DEBUG ((DEBUG_INFO, "CpuInitPreResetCpl Start \n"));
|
|
PostCode (0xC20);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuTestConfigGuid, (VOID *) &CpuTestConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuConfigGuid, (VOID *) &CpuConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
DEBUG ((DEBUG_INFO, "InitRatl Start \n"));
|
|
PostCode (0xC22);
|
|
|
|
///
|
|
/// Program Tcc Activation Offset and Running Average Temperature Limit (RATL)
|
|
///
|
|
InitRatl (SiPolicyPpi);
|
|
|
|
///
|
|
/// Check to see if CPU supports EIST capability.
|
|
///
|
|
if (CpuConfig->SkipMpInit == 0) {
|
|
AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &Ecx.Uint32, NULL);
|
|
if (Ecx.Bits.EIST == 1) {
|
|
DEBUG ((DEBUG_INFO, "SetBootFrequency Start \n"));
|
|
PostCode (0xC25);
|
|
///
|
|
/// Program Boot Frequency on all threads.
|
|
///
|
|
SetBootFrequency (SiPolicyPpi);
|
|
}
|
|
}
|
|
|
|
///
|
|
/// BIOS Guard Initialization
|
|
///
|
|
BiosGuardInit (SiPolicyPpi);
|
|
|
|
DEBUG((DEBUG_INFO, "CpuInitPreResetCpl Done \n"));
|
|
PostCode (0xC3F);
|
|
|
|
return;
|
|
}
|