402 lines
15 KiB
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);
|
|
}
|
|
|