/** @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 #include #include #include #include #include #include #include "Features.h" #include #include /** 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; }