alder_lake_bios/Intel/AlderLake/ClientOneSiliconPkg/Cpu/LibraryPrivate/PeiCpuPowerOnConfigLib/PeiCpuPowerOnConfigLib.c

402 lines
15 KiB
C

/** @file
CpuPowerOnConfig PEI Library
@copyright
INTEL CONFIDENTIAL
Copyright 2014 - 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
**/
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/CpuPowerOnConfigLib.h>
#include <Library/DebugLib.h>
#include <Library/CpuPlatformLib.h>
#include <Library/CpuInfoFruLib.h>
#include <Library/PeiCpuInitFruLib.h>
#include <Ppi/MasterBootMode.h>
#include <Register/Cpuid.h>
#include <Register/Msr.h>
#include <Library/ConfigBlockLib.h>
#include <Library/PostCodeLib.h>
#include <Library/PmcPrivateLib.h>
#include <Library/PmcSocLib.h>
#include <Library/CpuMailboxLib.h>
#include <Ppi/Spi.h>
#include <Register/CommonMsr.h>
#include <VoltageRegulatorCommands.h>
#include <Library/PeiVrLib.h>
#include <Library/MsrFruLib.h>
/**
Check if VT is fused and disabled by Setup Option so reset is needed.
@param[in] VmxEnable - VmxEnable CPU policy.
@retval NO_RESET - No reset is needed.
@retval COLD_RESET - Update requires a cold reset.
**/
CPU_RESET_TYPE
CheckVmxIfNeedReset (
IN UINT8 VmxEnable
)
{
MSR_IA32_FEATURE_CONTROL_REGISTER Msr;
CPUID_VERSION_INFO_ECX Ecx;
AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &Ecx.Uint32, NULL);
///
/// Check if VMX is supported
///
if (Ecx.Bits.VMX == 0) {
return NO_RESET;
}
Msr.Uint64 = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);
///
/// Need to reset only if locked and VMX state has to be changed.
///
if ((Msr.Bits.Lock == 1) && (Msr.Bits.EnableVmxOutsideSmx != VmxEnable)) {
return COLD_RESET;
}
return NO_RESET;
}
/**
Get 32-bit CPU strap data.
@param[out] CpuStrapData1 CPU strap value
@param[out] CpuStrapData2 CPU strap value
@param[out] CpuStrapData3 CPU strap value
@retval TRUE Fetched data is valid
@retval FALSE Fetched data is not valid
**/
STATIC
BOOLEAN
GetCpuStrapData (
OUT UINT32 *CpuStrapData1,
OUT UINT32 *CpuStrapData2,
OUT UINT32 *CpuStrapData3
)
{
EFI_STATUS Status;
PCH_SPI_PPI *SpiPpi;
UINT8 TempBuffer[4];
PCODE_MAILBOX_INTERFACE MailboxCommand;
UINT32 MailboxData;
UINT32 MailboxStatus;
if (PmcIsSetStrapMsgInterfaceEnabled ()) {
PmcGetStrapMsgData32 (CpuStrapData1, CpuStrapData2, CpuStrapData3);
} else if (PmcIsCpuStrapsIpcCommandSupported ()) {
//
// Get the Cpu Strap 1 High
//
MailboxCommand.InterfaceData = 0;
MailboxCommand.Fields.Command = MAILBOX_PCODE_CMD_READ_SOFT_STRAPS;
MailboxCommand.Fields.Param1 = CPU_SOFTSTRAP_SET1_HIGH;
MailboxCommand.Fields.Param2 = STRAP_RESOLVED_VALUE;
MailboxData = 0;
Status = MailboxRead (MAILBOX_TYPE_PCODE, MailboxCommand.InterfaceData, (UINT32*) &MailboxData, &MailboxStatus);
if (MailboxStatus != PCODE_MAILBOX_CC_SUCCESS) {
DEBUG ((DEBUG_ERROR, "VR: Error Reading CPU Softstraps. EFI_STATUS = %r, Mailbox Status = %X\n", Status, MailboxStatus));
return FALSE;
}
*CpuStrapData1 = MailboxData;
//
// Get the Cpu Strap 2 Low
//
MailboxCommand.InterfaceData = 0;
MailboxCommand.Fields.Command = MAILBOX_PCODE_CMD_READ_SOFT_STRAPS;
MailboxCommand.Fields.Param1 = CPU_SOFTSTRAP_SET2_LOW;
MailboxCommand.Fields.Param2 = STRAP_RESOLVED_VALUE;
MailboxData = 0;
Status = MailboxRead (MAILBOX_TYPE_PCODE, MailboxCommand.InterfaceData, (UINT32*) &MailboxData, &MailboxStatus);
if (MailboxStatus != PCODE_MAILBOX_CC_SUCCESS) {
DEBUG ((DEBUG_ERROR, "VR: Error Reading CPU Softstraps. EFI_STATUS = %r, Mailbox Status = %X\n", Status, MailboxStatus));
return FALSE;
}
*CpuStrapData2 = MailboxData;
//
// Get the Cpu Strap 2 High
//
MailboxCommand.InterfaceData = 0;
MailboxCommand.Fields.Command = MAILBOX_PCODE_CMD_READ_SOFT_STRAPS;
MailboxCommand.Fields.Param1 = CPU_SOFTSTRAP_SET2_HIGH;
MailboxCommand.Fields.Param2 = STRAP_RESOLVED_VALUE;
MailboxData = 0;
Status = MailboxRead (MAILBOX_TYPE_PCODE, MailboxCommand.InterfaceData, (UINT32*) &MailboxData, &MailboxStatus);
if (MailboxStatus != PCODE_MAILBOX_CC_SUCCESS) {
DEBUG ((DEBUG_ERROR, "VR: Error Reading CPU Softstraps. EFI_STATUS = %r, Mailbox Status = %X\n", Status, MailboxStatus));
return FALSE;
}
*CpuStrapData3 = MailboxData;
} else {
Status = PeiServicesLocatePpi (
&gPchSpiPpiGuid,
0,
NULL,
(VOID**) &SpiPpi
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failed to locate SPI PPI\n"));
return FALSE;
}
Status = SpiPpi->ReadCpuSoftStrap (SpiPpi, 0, sizeof (UINT32), TempBuffer);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failed to read image descriptor\n"));
return FALSE;
}
*CpuStrapData1 = TempBuffer[0] + (TempBuffer[1] << 8) + (TempBuffer[2] << 16) + (TempBuffer[3] << 24);
if (PmcIsExtendedStrapsSupported ()) {
Status = SpiPpi->ReadCpuSoftStrap (SpiPpi, 4, sizeof (UINT32), TempBuffer);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failed to read image descriptor\n"));
return FALSE;
}
*CpuStrapData2 = TempBuffer[0] + (TempBuffer[1] << 8) + (TempBuffer[2] << 16) + (TempBuffer[3] << 24);
Status = SpiPpi->ReadCpuSoftStrap (SpiPpi, 8, sizeof (UINT32), TempBuffer);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failed to read image descriptor\n"));
return FALSE;
}
*CpuStrapData3 = TempBuffer[0] + (TempBuffer[1] << 8) + (TempBuffer[2] << 16) + (TempBuffer[3] << 24);
}
}
return TRUE;
}
/**
This function return Package TDP
@param[in] MsrTdp - TDP value from MSR
@retval PackageTdp - Package TDP
**/
STATIC
UINT16
GetTdpWatt (
IN UINT32 MsrTdp
)
{
UINT16 PackageTdp;
UINT16 PackageTdpWatt;
UINT16 TempPackageTdp;
UINT8 ProcessorPowerUnit;
MSR_PACKAGE_POWER_SKU_UNIT_REGISTER PackagePowerSkuUnitMsr;
///
/// Find Package TDP value in 1/100 Watt units
///
PackagePowerSkuUnitMsr.Uint64 = AsmReadMsr64 (MSR_PACKAGE_POWER_SKU_UNIT);
ProcessorPowerUnit = (UINT8) (PackagePowerSkuUnitMsr.Bits.PwrUnit);
if (ProcessorPowerUnit == 0) {
ProcessorPowerUnit = 1;
} else {
ProcessorPowerUnit = (UINT8) LShiftU64 (2, (ProcessorPowerUnit - 1));
if (IsSimicsEnvironment () && ProcessorPowerUnit == 0) {
ProcessorPowerUnit = 1;
}
}
TempPackageTdp = (UINT16) MsrTdp;
PackageTdpWatt = (UINT16) DivU64x32 (TempPackageTdp, ProcessorPowerUnit);
PackageTdp = (PackageTdpWatt * 100);
if ((TempPackageTdp % ProcessorPowerUnit) !=0) {
PackageTdp += ((TempPackageTdp % ProcessorPowerUnit) * 100) / ProcessorPowerUnit;
}
return (PackageTdp / 100);
}
/**
This function return Flex Ratio Override
@param[in,out] FlexRatioPolicyValue - Flex Ratio Policy Value
@param[in] BootFrequency - Boot Frequency
@param[in] ConfigTdpLevel - ConfigTdp Level
@param[in] CustomPowerLimit1 - Custom PowerLimit1
**/
VOID
FlexRatioPolicyValueOverride (
IN OUT UINT32 *FlexRatioPolicyValue,
IN UINT32 BootFrequency,
IN UINT32 ConfigTdpLevel,
IN UINT32 CustomPowerLimit1
)
{
UINT8 SupportedTdpLevels;
MSR_CONFIG_TDP_NOMINAL_REGISTER ConfigTdpNominalMsr;
MSR_CONFIG_TDP_LEVEL1_REGISTER ConfigTdpLevel1Msr;
MSR_PACKAGE_POWER_SKU_REGISTER PackagePowerMsr;
UINT32 PackageTdp;
UINT32 ConfigLevel1Tdp;
UINT32 Pl1Override;
if ((*FlexRatioPolicyValue == 0) && (BootFrequency != BOOT_FREQUENCY_MAX_BATTERY_PERF)) {
SupportedTdpLevels = MsrGetConfigTdpLevels ();
DEBUG ((DEBUG_INFO, "Supported ConfigTdpLevels = 0x%X\n", SupportedTdpLevels));
if (SupportedTdpLevels > 0) {
//
// Update FlexRatio according to cTDP ratio.
//
ConfigTdpLevel1Msr.Uint64 = AsmReadMsr64 (MSR_CONFIG_TDP_LEVEL1);
if (ConfigTdpLevel == 1) {
*FlexRatioPolicyValue = (UINT8) ConfigTdpLevel1Msr.Bits.TdpRatio;
} else if ((ConfigTdpLevel == 0) &&
(CustomPowerLimit1 != 0) &&
(GetCpuSku () != EnumCpuTrad)) {
PackagePowerMsr.Uint64 = AsmReadMsr64 (MSR_PACKAGE_POWER_SKU);
PackageTdp = GetTdpWatt (PackagePowerMsr.Bits.PkgTdp);
ConfigLevel1Tdp = GetTdpWatt (ConfigTdpLevel1Msr.Bits.PkgTdp);
Pl1Override = GetTdpWatt (CustomPowerLimit1);
if ((Pl1Override >= ConfigLevel1Tdp) && (Pl1Override < PackageTdp)) {
*FlexRatioPolicyValue = (UINT8) ConfigTdpLevel1Msr.Bits.TdpRatio;
}
}
//
// Don't override FlexRatio if cTDP ratio is over nominal TDP ratio.
//
ConfigTdpNominalMsr.Uint64 = AsmReadMsr64 (MSR_CONFIG_TDP_NOMINAL);
DEBUG ((DEBUG_INFO, "cTDP FlexRatio = 0x%X, Nominal FlexRatio = 0x%x\n", *FlexRatioPolicyValue, ConfigTdpNominalMsr.Bits.TdpRatio));
if (*FlexRatioPolicyValue > ConfigTdpNominalMsr.Bits.TdpRatio) {
*FlexRatioPolicyValue = 0;
}
}
}
}
/**
Set Cpu Strap and Set Early Power On Configuration setting for feature change.
@param[in] SiPreMemPolicyPpi - Address of the SI_PREMEM_POLICY_PPI.
**/
VOID
SetCpuStrapAndEarlyPowerOnConfig (
IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
)
{
EFI_STATUS Status;
CPU_RESET_TYPE ResetType;
UINT32 CpuStrapSetData1;
UINT32 CpuStrapSetData2;
UINT32 CpuStrapSetData3;
EFI_BOOT_MODE BootMode;
CPU_CONFIG_LIB_PREMEM_CONFIG *CpuConfigLibPreMemConfig;
OVERCLOCKING_PREMEM_CONFIG *OverClockingConfig;
MSR_FLEX_RATIO_REGISTER MsrFlexRatio;
UINT32 VendorId;
UINT32 ProdId;
UINT32 FlexRatioPolicyValue;
ResetType = NO_RESET;
CpuStrapSetData1 = 0;
CpuStrapSetData2 = 0;
CpuStrapSetData3 = 0;
DEBUG((DEBUG_INFO, "SetCpuStrapAndEarlyPowerOnConfig Start \n"));
PostCode (0xC0A);
Status = PeiServicesGetBootMode (&BootMode);
DEBUG ((DEBUG_INFO, "SetCpuStrapAndEarlyPowerOnConfig: BootMode = %X\n", BootMode));
if ((Status == EFI_SUCCESS) && (BootMode == BOOT_ON_S3_RESUME)) {
PmcLockSetStrapMsgInterface ();
return;
}
DEBUG ((DEBUG_INFO, "Set CPU Soft Straps Entry Point\n"));
Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gCpuConfigLibPreMemConfigGuid, (VOID *) &CpuConfigLibPreMemConfig);
ASSERT_EFI_ERROR (Status);
Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gOverclockingPreMemConfigGuid, (VOID *) &OverClockingConfig);
ASSERT_EFI_ERROR (Status);
GetVrVendorIdProdId (&VendorId, &ProdId);
///
/// Get Cpu Strap Set Data
///
if (GetCpuStrapData (&CpuStrapSetData1, &CpuStrapSetData2, &CpuStrapSetData3)) {
DEBUG ((DEBUG_INFO, "Current CPU Strap Data 1 = 0x%04X\n", CpuStrapSetData1));
DEBUG ((DEBUG_INFO, "Current CPU Strap Data 2 = 0x%04X\n", CpuStrapSetData2));
DEBUG ((DEBUG_INFO, "Current CPU Strap Data 3 = 0x%04X\n", CpuStrapSetData3));
ResetType |= PeiCpuStrapHtEnableDisable (&CpuStrapSetData1, (UINT8) CpuConfigLibPreMemConfig->HyperThreading);
ResetType |= PeiCpuStrapSetActiveCores (&CpuStrapSetData1, (UINT8) CpuConfigLibPreMemConfig->ActiveCoreCount1, (UINT8) CpuConfigLibPreMemConfig->ActiveSmallCoreCount, CpuConfigLibPreMemConfig->ActiveSocNorthAtomCoreCount);
ResetType |= PeiCpuStrapBistEnableDisable (&CpuStrapSetData1, (UINT8) CpuConfigLibPreMemConfig->BistOnReset);
///
/// Perform Flex Ratio if processor is fused to perform Flex Ratio
///
MsrFlexRatio.Uint64 = AsmReadMsr64 (MSR_FLEX_RATIO);
if (MsrFlexRatio.Bits.Enable == 1) {
FlexRatioPolicyValue = (UINT8) CpuConfigLibPreMemConfig->CpuRatio;
FlexRatioPolicyValueOverride (&FlexRatioPolicyValue, CpuConfigLibPreMemConfig->BootFrequency, CpuConfigLibPreMemConfig->ConfigTdpLevel, CpuConfigLibPreMemConfig->CustomPowerLimit1);
ResetType |= PeiCpuStrapProgramFlexMultiplier (&CpuStrapSetData1, (UINT8) FlexRatioPolicyValue);
}
ResetType |= PeiCpuStrapBootRatioEnableDisable (&CpuStrapSetData1, (UINT8) CpuConfigLibPreMemConfig->BootFrequency);
ResetType |= PeiCpuStrapJtagPowerGateEnableDisable (&CpuStrapSetData1, (UINT8) CpuConfigLibPreMemConfig->JtagC10PowerGateDisable);
if (OverClockingConfig->OcSupport == 1) {
ResetType |= PeiCpuStrapDlvrSetting (&CpuStrapSetData1, (UINT8) OverClockingConfig->DlvrBypassModeEnable);
}
ResetType |= PeiCpuStrapPlatformType (&CpuStrapSetData2, VendorId, ProdId);
if (ResetType != NO_RESET) {
DEBUG ((DEBUG_INFO, "New CPU Strap Data1 = 0x%04X\n", CpuStrapSetData1));
DEBUG ((DEBUG_INFO, "New CPU Strap Data2 = 0x%04X\n", CpuStrapSetData2));
DEBUG ((DEBUG_INFO, "New CPU Strap Data3 = 0x%04X\n", CpuStrapSetData3));
PmcSetStrapMsgData32 (CpuStrapSetData1, CpuStrapSetData2, CpuStrapSetData3);
}
}
PmcLockSetStrapMsgInterface ();
ResetType |= CheckVmxIfNeedReset ((UINT8) CpuConfigLibPreMemConfig->VmxEnable);
if (ResetType != NO_RESET) {
DEBUG ((DEBUG_INFO, "Cpu straps changed, performing reset - ResetType = %x\n", ResetType));
PostCode (0xC13);
PerformWarmOrColdReset (ResetType);
}
DEBUG((DEBUG_INFO, "SetCpuStrapAndEarlyPowerOnConfig Done \n"));
PostCode (0xC14);
}