alder_lake_bios/Intel/AlderLake/ClientOneSiliconPkg/Cpu/LibraryPrivate/PeiCpuPowerMgmtLib/IdleStates.c

427 lines
16 KiB
C

/** @file
This file contains power management C State configuration functions for
processors.
Acronyms:
- PPM: Processor Power Management
- TM: Thermal Monitor
- IST: Intel(R) Speedstep technology
- HT: Hyper-Threading Technology
@copyright
INTEL CONFIDENTIAL
Copyright 2012 - 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 "PowerMgmtCommon.h"
/**
Initializes C States Power management features
**/
VOID
InitCState (
VOID
)
{
///
/// Initialize C states, some are general, some are processor specific.
///
/// AcpiIoBase + 0x14 (PM_CST_LVL2) register no longer exists in PCH.
/// When the IO in this range is read, the CPU puts itself into a mwait
/// and does not forward this IO to the PCH. MSR_PMG_IO_CAPTURE_BASE was created because
/// the functionality was moved from the PCH to the CPU.
///
EnableCStates (PmcGetAcpiBase () + PM_CST_LVL2);
InitCstatePreWake ();
}
/**
Disable/Enable the CState Pre-Wake Feature
**/
VOID
InitCstatePreWake (
VOID
)
{
MSR_POWER_CTL_REGISTER PowerCtl;
PowerCtl.Uint64 = AsmReadMsr64 (MSR_POWER_CTL);
PowerCtl.Bits.CstatePrewakeDisable = 0;
if (gCpuPowerMgmtTestConfig->CStatePreWake == FALSE) {
PowerCtl.Bits.CstatePrewakeDisable = 1;
}
AsmWriteMsr64 (MSR_POWER_CTL, PowerCtl.Uint64);
return;
}
/**
Enables C-State support as specified by the input flags on all logical
processors and sets associated timing requirements in the chipset.
@param[in] C3IoAddress IO address to generate C3 states (PM base + 014 usually)
**/
VOID
EnableCStates (
IN UINT16 C3IoAddress
)
{
MSR_POWER_CTL_REGISTER PowerCtl;
MSR_C_STATE_LATENCY_CONTROL_0_REGISTER CStateLatencyControl0;
MSR_C_STATE_LATENCY_CONTROL_1_REGISTER CStateLatencyControl1;
MSR_C_STATE_LATENCY_CONTROL_2_REGISTER CStateLatencyControl2;
MSR_C_STATE_LATENCY_CONTROL_3_REGISTER CStateLatencyControl3;
MSR_C_STATE_LATENCY_CONTROL_4_REGISTER CStateLatencyControl4;
MSR_C_STATE_LATENCY_CONTROL_5_REGISTER CStateLatencyControl5;
UINT16 EnableCStateParameters;
///
/// Load the C-State parameters to pass to the core function.
///
EnableCStateParameters = C3IoAddress;
///
/// Enable C-States on all logical processors.
///
ApSafeEnableCStates(&EnableCStateParameters);
mMpServices2Ppi->StartupAllAPs (
mMpServices2Ppi,
(EFI_AP_PROCEDURE) ApSafeEnableCStates,
FALSE,
0,
(VOID *) &EnableCStateParameters
);
///
/// If C-states are disabled or not supported, Disable C1e and retrun
///
if ((mPpmFlags & PPM_C_STATES) == 0) {
PowerCtl.Uint64 = AsmReadMsr64 (MSR_POWER_CTL);
PowerCtl.Bits.C1eEnable = 0;
AsmWriteMsr64 (MSR_POWER_CTL, PowerCtl.Uint64);
DEBUG ((DEBUG_INFO, "Setup C state disabled.Disable C1e. MSR(1FC) : 0x%08x\n", PowerCtl.Uint64));
return;
}
///
/// Configure supported enhanced C-states
///
/// Read Power Ctl MSR
///
PowerCtl.Uint64 = AsmReadMsr64 (MSR_POWER_CTL);
DEBUG ((DEBUG_INFO, "MSR(1FC) before configuring C1E: 0x%08x\n", PowerCtl.Uint64));
///
/// Enable supported states
///
if (mPpmFlags & PPM_C1E) {
PowerCtl.Bits.C1eEnable = 1;
} else {
PowerCtl.Bits.C1eEnable = 0;
}
///
/// Update Power Control MSR
///
AsmWriteMsr64 (MSR_POWER_CTL, PowerCtl.Uint64);
DEBUG ((DEBUG_INFO, "MSR(1FC) after configuring C1E: 0x%08x\n", PowerCtl.Uint64));
///
/// Program Interrupt response time limits used by processor to decided when to get into
/// package C3
///
DEBUG ((DEBUG_INFO, "Programming the C3 (MSR 0x60A) Latencies \n"));
//
// Package C3 Interrupt response time
//
if (gCpuPowerMgmtTestConfig->CstateLatencyControl0Irtl > 0) {
CStateLatencyControl0.Uint64 = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_0);
DEBUG ((DEBUG_INFO, "MSR(60A) before configuring Latency: 0x%08x\n", CStateLatencyControl0.Uint64));
///
/// Program Interrupt Response Time Unit and Latency for MSR 0x60A
///
CStateLatencyControl0.Bits.Value = gCpuPowerMgmtTestConfig->CstateLatencyControl0Irtl;
CStateLatencyControl0.Bits.Multiplier = gCpuPowerMgmtTestConfig->CstateLatencyControl0TimeUnit;
CStateLatencyControl0.Bits.Valid = 1;
AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_0, CStateLatencyControl0.Uint64);
}
///
/// Program Interrupt response time limits used by processor to decided when to get into
/// package C6 and C7
///
DEBUG ((DEBUG_INFO, "Programming the C6/C7/C8/C9/C10 (MSR 0x60B, 0x60C ,0x633, 0x634, 0x635 IRTL if not auto.\n"));
//
// Package C6/C7 short Interrupt response time
//
if (gCpuPowerMgmtTestConfig->CstateLatencyControl1Irtl > 0) {
CStateLatencyControl1.Uint64 = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_1);
DEBUG ((DEBUG_INFO, "MSR(60B) before configuring Latency: 0x%08x\n", CStateLatencyControl1.Uint64));
///
/// Program Interrupt Response Time Unit and Latency for MSR 0x60B
///
CStateLatencyControl1.Bits.Value = gCpuPowerMgmtTestConfig->CstateLatencyControl1Irtl;
CStateLatencyControl1.Bits.Multiplier = gCpuPowerMgmtTestConfig->CstateLatencyControl1TimeUnit;
CStateLatencyControl1.Bits.Valid = 1;
AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_1, CStateLatencyControl1.Uint64);
}
//
// Package C6/C7 long Interrupt response time
//
if (gCpuPowerMgmtTestConfig->CstateLatencyControl2Irtl > 0) {
CStateLatencyControl2.Uint64 = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_2);
DEBUG ((DEBUG_INFO, "MSR(60C) before configuring Latency: 0x%08x\n", CStateLatencyControl2.Uint64));
///
/// Program Interrupt Response Time Unit and Latency for MSR 0x60C
///
CStateLatencyControl2.Bits.Value = gCpuPowerMgmtTestConfig->CstateLatencyControl2Irtl;
CStateLatencyControl2.Bits.Multiplier = gCpuPowerMgmtTestConfig->CstateLatencyControl2TimeUnit;
CStateLatencyControl2.Bits.Valid = 1;
AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_2, CStateLatencyControl2.Uint64);
}
//
// Package C8 Interrupt response time
//
if (gCpuPowerMgmtTestConfig->CstateLatencyControl3Irtl > 0) {
CStateLatencyControl3.Uint64 = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_3);
DEBUG ((DEBUG_INFO, "MSR(633) before configuring Latency: 0x%08x\n", CStateLatencyControl3.Uint64));
///
/// Program Interrupt Response Time Unit and Latency for MSR 0x633
///
CStateLatencyControl3.Bits.Value = gCpuPowerMgmtTestConfig->CstateLatencyControl3Irtl;
CStateLatencyControl3.Bits.Multiplier = gCpuPowerMgmtTestConfig->CstateLatencyControl3TimeUnit;
CStateLatencyControl3.Bits.Valid = 1;
AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_3, CStateLatencyControl3.Uint64);
}
//
// Package C9 Interrupt response time
//
if (gCpuPowerMgmtTestConfig->CstateLatencyControl4Irtl > 0) {
CStateLatencyControl4.Uint64 = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_4);
DEBUG ((DEBUG_INFO, "MSR(634) before configuring Latency: 0x%08x\n", CStateLatencyControl4.Uint64));
///
/// Program Interrupt Response Time Unit and Latency for MSR 0x634
///
CStateLatencyControl4.Bits.Value = gCpuPowerMgmtTestConfig->CstateLatencyControl4Irtl;
CStateLatencyControl4.Bits.Multiplier = gCpuPowerMgmtTestConfig->CstateLatencyControl4TimeUnit;
CStateLatencyControl4.Bits.Valid = 1;
AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_4, CStateLatencyControl4.Uint64);
}
///
/// Package C10 Interrupt response time
///
if (gCpuPowerMgmtTestConfig->CstateLatencyControl5Irtl > 0) {
CStateLatencyControl5.Uint64 = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_5);
DEBUG ((DEBUG_INFO, "MSR(635) before configuring Latency: 0x%08x\n", CStateLatencyControl5.Uint64));
///
/// Program Interrupt Response Time Unit and Latency for MSR 0x635
///
CStateLatencyControl5.Bits.Value = gCpuPowerMgmtTestConfig->CstateLatencyControl5Irtl;
CStateLatencyControl5.Bits.Multiplier = gCpuPowerMgmtTestConfig->CstateLatencyControl5TimeUnit;
CStateLatencyControl5.Bits.Valid = 1;
AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_5, CStateLatencyControl5.Uint64);
}
}
/**
Enable C-State support as specified by the input flags on a logical processor.
Configure BIOS C1 Coordination (SMI coordination)
Enable IO redirection coordination
Choose proper coordination method
Configure extended C-States
This function must be MP safe.
@param[in out] Buffer Pointer to a ENABLE_CSTATE_PARAMS containing the necessary
information to enable C-States
@retval EFI_SUCCESS Processor C-State support configured successfully.
**/
VOID
EFIAPI
ApSafeEnableCStates (
IN OUT VOID *Buffer
)
{
MSR_CLOCK_CST_CONFIG_CONTROL_REGISTER PmCfgCtrlMsr;
MSR_PMG_IO_CAPTURE_BASE_REGISTER IoCaptAddr;
MSR_IA32_MISC_ENABLE_REGISTER MiscEnable;
UINT16 C3IoAddress;
///
/// Extract parameters from the buffer
///
C3IoAddress = *((UINT16 *) Buffer);
///
/// If C-states are disabled in setup, disable C-states
///
if (!(mPpmFlags & PPM_C_STATES)) {
PmCfgCtrlMsr.Uint64 = AsmReadMsr64 (MSR_CLOCK_CST_CONFIG_CONTROL);
PmCfgCtrlMsr.Bits.MaxPkgCState = 0;
AsmWriteMsr64 (MSR_CLOCK_CST_CONFIG_CONTROL, PmCfgCtrlMsr.Uint64);
return;
}
///
/// Set C-state package limit to the highest C-state enabled
///
PmCfgCtrlMsr.Uint64 = AsmReadMsr64 (MSR_CLOCK_CST_CONFIG_CONTROL);
///
/// mPpmFlags might be override by others. So update the MaxPkgCState based on mPpmFlags setting.
///
if ((mPpmFlags & PPM_C10) && (PmCfgCtrlMsr.Bits.MaxPkgCState >= V_CSTATE_LIMIT_C10)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C10;
} else if ((mPpmFlags & PPM_C9) && (PmCfgCtrlMsr.Bits.MaxPkgCState >= V_CSTATE_LIMIT_C9)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C9;
} else if ((mPpmFlags & PPM_C8) && (PmCfgCtrlMsr.Bits.MaxPkgCState >= V_CSTATE_LIMIT_C8)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C8;
} else if ((mPpmFlags & PPM_C7S) && (PmCfgCtrlMsr.Bits.MaxPkgCState >= V_CSTATE_LIMIT_C7S)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C7S;
} else if ((mPpmFlags & PPM_C7) && (PmCfgCtrlMsr.Bits.MaxPkgCState >= V_CSTATE_LIMIT_C7)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C7;
} else if ((mPpmFlags & PPM_C6) && (PmCfgCtrlMsr.Bits.MaxPkgCState >= V_CSTATE_LIMIT_C6)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C6;
} else if ((mPpmFlags & PPM_C1) && (PmCfgCtrlMsr.Bits.MaxPkgCState >= V_CSTATE_LIMIT_C1)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C1;
}
if (gCpuPowerMgmtTestConfig->PkgCStateLimit != PkgCpuDefault) {
PmCfgCtrlMsr.Bits.MaxPkgCState = 0;
if (gCpuPowerMgmtTestConfig->PkgCStateLimit < PkgCMax) {
PmCfgCtrlMsr.Bits.MaxPkgCState = gCpuPowerMgmtTestConfig->PkgCStateLimit;
} else if ((mPpmFlags & PPM_C10) && (gCpuPowerMgmtTestConfig->PkgCStateLimit == PkgAuto)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C10;
} else if ((mPpmFlags & PPM_C9) && (gCpuPowerMgmtTestConfig->PkgCStateLimit == PkgAuto)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C9;
} else if ((mPpmFlags & PPM_C8) && (gCpuPowerMgmtTestConfig->PkgCStateLimit == PkgAuto)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C8;
} else if ((mPpmFlags & PPM_C7S) && (gCpuPowerMgmtTestConfig->PkgCStateLimit == PkgAuto)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C7S;
} else if ((mPpmFlags & PPM_C7) && (gCpuPowerMgmtTestConfig->PkgCStateLimit == PkgAuto)) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C7;
} else if (mPpmFlags & PPM_C6) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C6;
} else if (mPpmFlags & PPM_C1) {
PmCfgCtrlMsr.Bits.MaxPkgCState = V_CSTATE_LIMIT_C1;
}
}
///
/// Configure C State IO redirection
///
if (gCpuPowerMgmtTestConfig->CstCfgCtrIoMwaitRedirection) {
PmCfgCtrlMsr.Bits.IoMwaitRedirection = 1;
}
//
// Enable TimedMwait
//
if (mPpmFlags & PPM_TIMED_MWAIT) {
PmCfgCtrlMsr.Bits.TimedMwaitEnable = 1;
}
///
/// Configure C-state auto-demotion
///
PmCfgCtrlMsr.Bits.C1StateAutoDemotionEnable = 0;
if (gCpuPowerMgmtTestConfig->C1AutoDemotion) {
///
/// Enable C6/C7 Auto-demotion to C1
///
PmCfgCtrlMsr.Bits.C1StateAutoDemotionEnable = 1;
}
///
/// Configure C-state un-demotion
///
PmCfgCtrlMsr.Bits.Enc1undemotion = 0;
if (gCpuPowerMgmtTestConfig->C1UnDemotion) {
///
/// Enable un-demotion from demoted C1
///
PmCfgCtrlMsr.Bits.Enc1undemotion = 1;
}
///
/// Configure Package C-state Demotion / un-demotion
///
PmCfgCtrlMsr.Bits.Enpkgcautodemotion = 0;
PmCfgCtrlMsr.Bits.Enpkgcundemotion = 0;
if (gCpuPowerMgmtTestConfig->PkgCStateDemotion) {
///
/// Enable Package C-state Demotion
///
PmCfgCtrlMsr.Bits.Enpkgcautodemotion = 1;
}
if (gCpuPowerMgmtTestConfig->PkgCStateUnDemotion) {
///
/// Enable Package C-state un-demotion
///
PmCfgCtrlMsr.Bits.Enpkgcundemotion = 1;
}
AsmWriteMsr64 (MSR_CLOCK_CST_CONFIG_CONTROL, PmCfgCtrlMsr.Uint64);
///
/// Enable MONITOR/MWAIT support
/// (already done on BSP, but must be done on all components.)
///
MiscEnable.Uint64 = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
MiscEnable.Bits.MONITOR = 1;
AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, MiscEnable.Uint64);
///
/// Configuration of I/O capture and I/O coordination SMI MSR.
/// Configure the base port and range in the MSR to match LVL_X settings in ACPI tables
/// Set I/O capture base port and range
///
IoCaptAddr.Uint64 = AsmReadMsr64 (MSR_PMG_IO_CAPTURE_BASE);
///
/// Mask off CST range and set the CST range
///
IoCaptAddr.Bits.CstRange = 0;
if (mPpmFlags & PPM_C10) {
IoCaptAddr.Bits.CstRange |= V_IO_CAPT_LVL7;
} else if (mPpmFlags & PPM_C9) {
IoCaptAddr.Bits.CstRange |= V_IO_CAPT_LVL6;
} else if (mPpmFlags & PPM_C8) {
IoCaptAddr.Bits.CstRange |= V_IO_CAPT_LVL5;
} else if (mPpmFlags & PPM_C7) {
IoCaptAddr.Bits.CstRange |= V_IO_CAPT_LVL4;
} else if (mPpmFlags & PPM_C6) {
IoCaptAddr.Bits.CstRange |= V_IO_CAPT_LVL3;
}
///
/// Set the base CST address
///
IoCaptAddr.Bits.Lvl2b = C3IoAddress;
AsmWriteMsr64 (MSR_PMG_IO_CAPTURE_BASE, IoCaptAddr.Uint64);
return;
}