979 lines
28 KiB
C
979 lines
28 KiB
C
/** @file
|
|
CPU feature control module
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 1999 - 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/ReportStatusCodeLib.h>
|
|
|
|
#include "Features.h"
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/IoLib.h>
|
|
#include <Library/CpuPlatformLib.h>
|
|
#include <Library/PmcLib.h>
|
|
#include <Library/PeiPmcPolicyLib.h>
|
|
#include <Library/PmcPrivateLib.h>
|
|
#include <Library/TimerLib.h>
|
|
#include <Library/CpuCommonLib.h>
|
|
#include <Library/BiosGuardInit.h>
|
|
#include <CpuInitDataHob.h>
|
|
#include <Library/ConfigBlockLib.h>
|
|
#include <Library/PostCodeLib.h>
|
|
#include <Library/CpuInfoFruLib.h>
|
|
#include <Library/PeiOcLib.h>
|
|
#include <Library/PeiCpuInitFruLib.h>
|
|
#include <Library/MsrFruLib.h>
|
|
#include <Library/MeInitLib.h>
|
|
#include <Library/RegisterCpuFeaturesLib.h>
|
|
#include <Library/CpuFeatures.h>
|
|
|
|
//
|
|
// Global variables
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED EDKII_PEI_MP_SERVICES2_PPI *mMpServices2Ppi = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED SI_POLICY_PPI *mSiPolicyPpi = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CPU_TEST_CONFIG *mCpuTestConfig = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CPU_CONFIG *mCpuConfig = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CPU_POWER_MGMT_BASIC_CONFIG *mCpuPowerMgmtBasicConfig = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CPU_POWER_MGMT_CUSTOM_CONFIG *mCpuPowerMgmtCustomConfig = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CPU_CONFIG_LIB_PREMEM_CONFIG *mCpuConfigLibPreMemConfig = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED OVERCLOCKING_PREMEM_CONFIG *mOverClockingConfig = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED VTD_CONFIG *mVtdConfig = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CPU_POWER_MGMT_TEST_CONFIG *mCpuPowerMgmtTestConfig = NULL;
|
|
|
|
|
|
///
|
|
/// Values for Trace Hub Acpi Base Address
|
|
///
|
|
UINT64 mTraceHubAcpiBaseAddress = 0;
|
|
BOOLEAN mTraceHubFeatureEnable = FALSE;
|
|
|
|
UINT8 mSmallCoreCount = 0;
|
|
UINT64 mPrmrrBase;
|
|
UINT64 mPrmrrMask;
|
|
|
|
STATIC EFI_PEI_PPI_DESCRIPTOR mPeiCpuFeaturesSetDonePpiList = {
|
|
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
|
&gEdkiiCpuFeaturesSetDoneGuid,
|
|
NULL
|
|
};
|
|
|
|
//
|
|
// Setting for AP init.
|
|
//
|
|
BOOLEAN mPmTimerEmulationEnable = FALSE;
|
|
|
|
/**
|
|
Perform BIOS uCode PM_TMR Emulation Configuration by configuring MSR 121h and setting
|
|
the ACPI Timer Disable Bit
|
|
|
|
The uCode emulation of the ACPI Timer allows disabling of the ACPI Timer to have no
|
|
impact on the system, with the exception that TMR_STS will not be set. All aligned
|
|
32-bit reads to the ACPI Timer port are valid and will behave as if the ACPI timer
|
|
remains enabled.
|
|
**/
|
|
VOID
|
|
BiosUcodePmTmrEmulationMsrCfg (
|
|
VOID
|
|
)
|
|
{
|
|
MSR_BIOS_UCODE_PM_TMR_EMULATION_CFG_REGISTER UcodePmTmrEmulation;
|
|
UINT32 CorrectionFactor;
|
|
UINT32 Data32;
|
|
|
|
// EPOC {21:20,17}
|
|
// 000 24MHz
|
|
// 001 19.2MHz
|
|
// 010 38.4MHz
|
|
Data32 = PmcGetCpuEpoc ();
|
|
if ((Data32 >> N_PMC_PWRM_CPU_EPOC_DATA_17) & 0x1) {
|
|
CorrectionFactor = V_BIOS_UCODE_PM_TMR_EMULATION_CFG_CORRECTION_FACTOR_19_MHZ;
|
|
} else {
|
|
if ((Data32 >> N_PMC_PWRM_CPU_EPOC_DATA_20) & 0x1){
|
|
CorrectionFactor = V_BIOS_UCODE_PM_TMR_EMULATION_CFG_CORRECTION_FACTOR_38_MHZ;
|
|
} else {
|
|
CorrectionFactor = V_BIOS_UCODE_PM_TMR_EMULATION_CFG_CORRECTION_FACTOR_24_MHZ;
|
|
}
|
|
}
|
|
|
|
UcodePmTmrEmulation.Uint64 = 0;
|
|
UcodePmTmrEmulation.Bits.CorrectionFactor = CorrectionFactor;
|
|
UcodePmTmrEmulation.Bits.RspDelayLoopCount = V_BIOS_UCODE_PM_TMR_EMULATION_CFG_DELAY_VALUE;
|
|
UcodePmTmrEmulation.Bits.Valid = 1;
|
|
UcodePmTmrEmulation.Bits.EmulatedIoPort = PmcGetAcpiBase () + R_ACPI_IO_PM1_TMR;
|
|
if (IsBsp ()) {
|
|
DEBUG ((DEBUG_INFO, "ACPI Timer Emulation Config, writing 0x%lx to MSR 121h.\n", UcodePmTmrEmulation.Uint64));
|
|
}
|
|
AsmWriteMsr64 (MSR_BIOS_UCODE_PM_TMR_EMULATION_CFG, UcodePmTmrEmulation.Uint64);
|
|
}
|
|
|
|
/**
|
|
X2APIC need VT-d support, check VT-d value to enable X2APIC mode.
|
|
|
|
@retval 0x01 - X2APIC mode enabled.
|
|
@retval 0x00 - X2APIC mode disabled.
|
|
**/
|
|
static
|
|
UINT8
|
|
IsX2apicModeEnabled (
|
|
VOID
|
|
)
|
|
{
|
|
static UINT8 IsX2apicMode = 0xFF;
|
|
if (IsX2apicMode != 0xFF) {
|
|
return IsX2apicMode;
|
|
}
|
|
if ((mVtdConfig != NULL) && (!mVtdConfig->VtdDisable) && (mCpuConfig->X2ApicSupport)) {
|
|
IsX2apicMode = 0x01;
|
|
} else {
|
|
IsX2apicMode = 0x00;
|
|
}
|
|
return IsX2apicMode;
|
|
}
|
|
|
|
/**
|
|
Worker function to add CPU feature to User Configuration.
|
|
|
|
@param[in] Feature CPU feature index.
|
|
@param[in, out] CpuFeaturesUserSetting Pointer to CPU features user setting.
|
|
@param[in] CpuFeaturesUserSettingSize CPU features user setting size.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
AddCpuFeaturesConfiguration (
|
|
IN UINT32 Feature,
|
|
IN UINT8 *CpuConfiguration,
|
|
IN UINTN CpuConfigurationSize
|
|
)
|
|
{
|
|
ASSERT ((Feature >> 3) < CpuConfigurationSize);
|
|
CpuConfiguration[Feature >> 3] |= (1 << (Feature & 0x07));
|
|
}
|
|
|
|
/**
|
|
Function that uses DEBUG() macros to display the contents of a a CPU feature bit mask.
|
|
|
|
@param[in] FeatureMask A pointer to the CPU feature bit mask.
|
|
@param[in] BitMaskSize CPU feature bits mask buffer size.
|
|
|
|
**/
|
|
VOID
|
|
DumpCpuFeatureMask (
|
|
IN UINT8 *FeatureMask,
|
|
IN UINTN BitMaskSize
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINT8 *Data8;
|
|
|
|
Data8 = (UINT8 *) FeatureMask;
|
|
for (Index = 0; Index < BitMaskSize; Index++) {
|
|
DEBUG ((DEBUG_INFO, " %02x ", *Data8++));
|
|
}
|
|
DEBUG ((DEBUG_INFO, "\n"));
|
|
}
|
|
|
|
/**
|
|
Get Trace Hub Acpi Base address for BSP
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
GetTraceHubAcpiBaseAddressForBsp (
|
|
VOID
|
|
)
|
|
{
|
|
///
|
|
/// Get Trace Hub ACPI base address from BSP
|
|
///
|
|
mTraceHubAcpiBaseAddress = AsmReadMsr64 (MSR_NPK_STH_ACPIBAR_BASE);
|
|
DEBUG ((DEBUG_INFO, "TraceHubAcpiBaseAddress = %x\n", mTraceHubAcpiBaseAddress));
|
|
|
|
///
|
|
/// Check the pass in Trace Hub ACPI base if equal zero.
|
|
///
|
|
if (mTraceHubAcpiBaseAddress != 0) {
|
|
mTraceHubFeatureEnable = TRUE;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
This function is to set MemoryControlSplitLock Disable
|
|
**/
|
|
VOID
|
|
DisableMemoryControlSplitLock (
|
|
VOID
|
|
)
|
|
{
|
|
MSR_MEMORY_CONTROL_REGISTER MsrMemoryControl;
|
|
MsrMemoryControl.Uint64 = AsmReadMsr64 (MSR_MEMORY_CONTROL);
|
|
MsrMemoryControl.Bits.SplitLockDisable = 1;
|
|
AsmWriteMsr64 (MSR_MEMORY_CONTROL, MsrMemoryControl.Uint64);
|
|
}
|
|
|
|
/**
|
|
Set PcdCpuFeaturesSetting and install the gEdkiiCpuFeaturesSetDoneGuid
|
|
PPI which is depended by CpuFeaturesPei driver.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
SetPcdCpuFeaturesSetting (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 *CpuConfiguration;
|
|
UINTN CpuConfigurationSize;
|
|
Status = EFI_SUCCESS;
|
|
|
|
CpuConfiguration = (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting);
|
|
CpuConfigurationSize = PcdGetSize (PcdCpuFeaturesSetting);
|
|
DEBUG ((DEBUG_INFO, "CpuConfiguration = "));
|
|
DumpCpuFeatureMask (CpuConfiguration, CpuConfigurationSize);
|
|
if (mCpuTestConfig->MachineCheckEnable) {
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_MCE, CpuConfiguration, CpuConfigurationSize);
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_MCA, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
if ((mCpuConfig->AesEnable)
|
|
) {
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_AESNI, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
if (mCpuTestConfig->MonitorMwaitEnable) {
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_MWAIT, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
if (IsX2apicModeEnabled () == 0x01) {
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_X2APIC, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
if (mCpuPowerMgmtBasicConfig->HdcControl){
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_HDC, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
if (mCpuTestConfig->MlcStreamerPrefetcher) {
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_MLC_STREAMER_PREFETCHER, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
if (mCpuTestConfig->MlcSpatialPrefetcher) {
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_MLC_SPATIAL_PREFETCHER, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_APIC_TPR_UPDATE_MESSAGE, CpuConfiguration, CpuConfigurationSize);
|
|
if (mCpuTestConfig->ThreeStrikeCounterDisable == 0) {
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_THREE_STRIKE_COUNTER, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_LOCK_FEATURE_CONTROL_REGISTER, CpuConfiguration, CpuConfigurationSize);
|
|
if (mCpuConfigLibPreMemConfig->VmxEnable) {
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_VMX, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
if ((mCpuConfig->TxtEnable)
|
|
) {
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_SMX, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
///
|
|
/// Identify if EndOfManufacturing (EOM).
|
|
///
|
|
if ((mCpuConfig->PpinSupport == 1) || ((mCpuConfig->PpinSupport == 2) && (!IsEom ()))) {
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_PPIN, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
if (mCpuTestConfig->ProcessorTraceEnable) {
|
|
PcdSet32S (PcdCpuProcTraceMemSize, mCpuTestConfig->ProcessorTraceMemSize);
|
|
PcdSet8S (PcdCpuProcTraceOutputScheme, (UINT8)mCpuTestConfig->ProcessorTraceOutputScheme);
|
|
AddCpuFeaturesConfiguration (CPU_FEATURE_PROC_TRACE, CpuConfiguration, CpuConfigurationSize);
|
|
}
|
|
//
|
|
// Set CPU Configuration PCD
|
|
//
|
|
Status = PcdSetPtrS (
|
|
PcdCpuFeaturesSetting,
|
|
&CpuConfigurationSize,
|
|
CpuConfiguration
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
//
|
|
// CpuFeatures Pei driver could be dispatched after this PPI is installed.
|
|
//
|
|
Status = PeiServicesInstallPpi (&mPeiCpuFeaturesSetDonePpiList);
|
|
ASSERT_EFI_ERROR (Status);
|
|
DEBUG ((DEBUG_INFO, "InstallPpi gEdkiiCpuFeaturesSetDoneGuid : %r\n", Status));
|
|
return;
|
|
}
|
|
|
|
/**
|
|
This function syncs the PRMRR MSR settings to remaining cores.
|
|
|
|
@param[in] IsBspInt Check to see if the executing thread is BSP
|
|
**/
|
|
VOID
|
|
SyncPrmrrMsr (
|
|
IN BOOLEAN IsBspInt
|
|
)
|
|
{
|
|
if (IsBspInt) {
|
|
//
|
|
// Read PRMRR MSRs that were set by MRC
|
|
//
|
|
mPrmrrBase = AsmReadMsr64 (MSR_PRMRR_BASE_0);
|
|
mPrmrrMask = AsmReadMsr64 (MSR_PRMRR_MASK);
|
|
DEBUG ((DEBUG_INFO, "PRMRR MSR: %016lx, %016lx\n", mPrmrrBase, mPrmrrMask));
|
|
}
|
|
//
|
|
// Sync the BSP PRMRR MSR values to other cores.
|
|
//
|
|
if (!IsBspInt && !IsSecondaryThread ()) {
|
|
AsmWriteMsr64 (MSR_PRMRR_BASE_0, mPrmrrBase);
|
|
AsmWriteMsr64 (MSR_PRMRR_MASK, mPrmrrMask);
|
|
}
|
|
}
|
|
|
|
/**
|
|
This function is to enable/disable AVX Instructions
|
|
|
|
@param[in] AvxDisable
|
|
**/
|
|
VOID
|
|
MsrSetAvx (
|
|
IN BOOLEAN AvxDisable
|
|
)
|
|
{
|
|
MSR_BIOS_AVX_DIS_REGISTER BiosAvxDisableMsr;
|
|
|
|
UINT32 Index = 0;
|
|
UINT64 Value = 0;
|
|
|
|
if (IsCpuSupportXsave () == TRUE) {
|
|
BiosAvxDisableMsr.Uint64 = AsmReadMsr64 (MSR_BIOS_AVX_DIS);
|
|
//
|
|
// Set MSR when setup setting of AvxDisable was changed
|
|
//
|
|
if (BiosAvxDisableMsr.Bits.AvxDis != AvxDisable) {
|
|
if (AvxDisable == TRUE) {
|
|
///
|
|
/// Set OSXSAVE bit in CR4 to enable xgetbv/xsetbv instruction
|
|
///
|
|
AsmWriteCr4 (AsmReadCr4 () | BIT18);
|
|
|
|
Value = AsmXGetBv (Index);
|
|
///
|
|
/// Clear Xcr0 bit 2 for disable AVX/AVX2
|
|
/// Clear Xcr0 bit 7,6,5 for disable AVX3
|
|
///
|
|
Value &= (UINT64) ~(BIT2 | BIT5 | BIT6 | BIT7);
|
|
AsmXSetBv (Index, Value);
|
|
///
|
|
/// Clear OSXSAVE bit in CR4 to disable xgetbv/xsetbv instruction
|
|
///
|
|
AsmWriteCr4 (AsmReadCr4 () & (~BIT18));
|
|
|
|
BiosAvxDisableMsr.Bits.AvxDis = 1;
|
|
} else {
|
|
BiosAvxDisableMsr.Bits.AvxDis = 0;
|
|
}
|
|
AsmWriteMsr64 (MSR_BIOS_AVX_DIS, BiosAvxDisableMsr.Uint64);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
This function is to enable/disable AVX3 Instructions
|
|
**/
|
|
VOID
|
|
MsrSetAvx3 (
|
|
)
|
|
{
|
|
MSR_BIOS_AVX_DIS_REGISTER BiosAvxDisableMsr;
|
|
|
|
UINT32 Index = 0;
|
|
UINT64 Value = 0;
|
|
UINT8 CoreType = 0;
|
|
|
|
DetectCoreType (&CoreType);
|
|
|
|
if (IsCpuSupportXsave () == TRUE) {
|
|
BiosAvxDisableMsr.Uint64 = AsmReadMsr64 (MSR_BIOS_AVX_DIS);
|
|
//
|
|
// If all Avx was disabled, skip to set Avx3
|
|
//
|
|
if (BiosAvxDisableMsr.Bits.AvxDis == 0) {
|
|
//
|
|
// Set Avx3 to disable since it is not supported
|
|
//
|
|
if (BiosAvxDisableMsr.Bits.Avx3Dis != TRUE) {
|
|
if (CoreType == CPUID_CORE_TYPE_INTEL_CORE) {
|
|
///
|
|
/// Set OSXSAVE bit in CR4 to enable xgetbv/xsetbv instruction
|
|
///
|
|
AsmWriteCr4 (AsmReadCr4 () | BIT18);
|
|
|
|
Value = AsmXGetBv (Index);
|
|
///
|
|
/// Clear Xcr0 bit 7,6,5 for disable AVX3
|
|
///
|
|
Value &= (UINT64) ~(BIT5 | BIT6 | BIT7);
|
|
AsmXSetBv (Index, Value);
|
|
///
|
|
/// Clear OSXSAVE bit in CR4 to disable xgetbv/xsetbv instruction
|
|
///
|
|
AsmWriteCr4 (AsmReadCr4 () & (~BIT18));
|
|
|
|
BiosAvxDisableMsr.Bits.Avx3Dis = 1;
|
|
}
|
|
AsmWriteMsr64 (MSR_BIOS_AVX_DIS, BiosAvxDisableMsr.Uint64);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Program all processor features basing on desired settings
|
|
|
|
@param[in] Buffer - A pointer to a buffer used to pass Cpu Policy PPI
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
ProgramProcessorFeature (
|
|
IN VOID *Buffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOLEAN IsBspInt;
|
|
SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi;
|
|
CPU_SECURITY_PREMEM_CONFIG *CpuSecurityPreMemConfig;
|
|
MSR_MTRRCAP_REGISTER MtrrCap;
|
|
STATIC BOOLEAN IsSimics;
|
|
STATIC BOOLEAN IsHsle;
|
|
|
|
IsBspInt = IsBsp ();
|
|
SiPreMemPolicyPpi = ((SI_PREMEM_POLICY_PPI *) Buffer);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gCpuSecurityPreMemConfigGuid, (VOID *) &CpuSecurityPreMemConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
///
|
|
/// Get Trace Hub Acpi Base address for BSP
|
|
///
|
|
if (IsBspInt) {
|
|
GetTraceHubAcpiBaseAddressForBsp ();
|
|
}
|
|
|
|
if (!IsBspInt) {
|
|
///
|
|
/// This is to program Trace Hub ACPI base address for all the threads
|
|
///
|
|
if (mTraceHubFeatureEnable) {
|
|
AsmWriteMsr64 (MSR_NPK_STH_ACPIBAR_BASE, mTraceHubAcpiBaseAddress);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Enable or disable Crashlog, Gprs dump on CPU Core by MSR
|
|
//
|
|
MsrEnableCpuCrashLog ((BOOLEAN)(mCpuConfigLibPreMemConfig->CrashLogEnable));
|
|
MsrSetCrashLogGprsMask ((BOOLEAN)(mCpuConfigLibPreMemConfig->CrashLogEnable), (UINT8)(mCpuConfigLibPreMemConfig->CrashLogGprs));
|
|
|
|
///
|
|
/// Program XApic register if not in X2APIC mode
|
|
///
|
|
if (IsX2apicModeEnabled () == 0x00) {
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_INFO, "Program xAPIC\n"));
|
|
}
|
|
ProgramXApic (IsBspInt);
|
|
}
|
|
|
|
if (IsBspInt && IsC6DramSupported ()) {
|
|
if (SetC6Dram (CpuSecurityPreMemConfig->EnableC6Dram)) {
|
|
DEBUG ((DEBUG_INFO, "C6DRAM is Enabled.\n"));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Same MSR offset definition MSR_IA32_MTRRCAP 0x000000FE in ArchitecturalMsr.h
|
|
//
|
|
MtrrCap.Uint64 = AsmReadMsr64 (MSR_MTRRCAP);
|
|
if (MtrrCap.Bits.Prmrr != 0) {
|
|
///
|
|
/// Initialize Core PRMRRs.
|
|
///
|
|
SyncPrmrrMsr (IsBspInt);
|
|
}
|
|
|
|
///
|
|
/// Configure BIOS uCode PM_TMR Emulation MSR 121h on all logical processors (BSP & APs).
|
|
/// Only enable this when PCH PM Timer is disabled.
|
|
///
|
|
if (mPmTimerEmulationEnable) {
|
|
BiosUcodePmTmrEmulationMsrCfg ();
|
|
}
|
|
|
|
|
|
if (mCpuConfig->AcSplitLock) {
|
|
//
|
|
// Disable Memory Control Split Lock
|
|
//
|
|
DisableMemoryControlSplitLock ();
|
|
}
|
|
|
|
if (IsBspInt) {
|
|
IsSimics = IsSimicsEnvironment ();
|
|
IsHsle = IsHSLEEnvironment ();
|
|
}
|
|
|
|
if (!IsSimics && !IsHsle) {
|
|
//
|
|
// Enable RAR Timer
|
|
//
|
|
MsrEnableRarTimer ();
|
|
|
|
if (IsAvxSetSupported ()) {
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_INFO, "Initialize AVX Instructions\n"));
|
|
}
|
|
//
|
|
// Enable/Disable AVX Instructions
|
|
//
|
|
MsrSetAvx ((BOOLEAN) mCpuConfig->AvxDisable);
|
|
MsrSetAvx3 ();
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Initialize CPU Data Hob
|
|
|
|
@param[in] SiPreMemPolicyPpi - A pointer to SiPreMemPolicyPpi used to pass SI_PREMEM_POLICY_PPI
|
|
|
|
@retval EFI_SUCCESS The driver installed/initialized correctly.
|
|
@retval EFI_OUT_OF_RESOURCES Allocation of the hob failed.
|
|
**/
|
|
EFI_STATUS
|
|
InitializeCpuDataHob (
|
|
IN SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi
|
|
)
|
|
{
|
|
CPU_INIT_DATA_HOB CpuInitDataHob;
|
|
VOID *Hob;
|
|
UINT8 VfPointIndex;
|
|
UINT8 PerCoreRatioIndex;
|
|
|
|
DEBUG ((DEBUG_INFO, "InitializeCpuDataHob Start \n"));
|
|
PostCode (0xC43);
|
|
|
|
///
|
|
/// Initial cpu data into one hob, it will be used by MP CPU DXE.
|
|
///
|
|
ZeroMem (&CpuInitDataHob, sizeof (CPU_INIT_DATA_HOB));
|
|
|
|
CpuInitDataHob.CoreVfPointCount = mOverClockingConfig->CoreVfPointCount;
|
|
for (VfPointIndex = 0; VfPointIndex < CpuInitDataHob.CoreVfPointCount; VfPointIndex++) {
|
|
CpuInitDataHob.CoreVfPointRatio[VfPointIndex] = mOverClockingConfig->CoreVfPointRatio[VfPointIndex];
|
|
}
|
|
|
|
CpuInitDataHob.RingVfPointCount = mOverClockingConfig->RingVfPointCount;
|
|
for (VfPointIndex = 0; VfPointIndex < CpuInitDataHob.RingVfPointCount; VfPointIndex++) {
|
|
CpuInitDataHob.RingVfPointRatio[VfPointIndex] = mOverClockingConfig->RingVfPointRatio[VfPointIndex];
|
|
}
|
|
|
|
///
|
|
/// Initialize auto thermal reporting when EnableAllThermalFunctions is enabled from BIOS setup.
|
|
///
|
|
CpuInitDataHob.EnableAllThermalFunctions = (UINT8) mCpuPowerMgmtTestConfig->EnableAllThermalFunctions;
|
|
|
|
///
|
|
/// Initialize Per Core OC ratio
|
|
///
|
|
CpuInitDataHob.PerCoreRatioOverride = (UINT8) mOverClockingConfig->PerCoreRatioOverride;
|
|
if (CpuInitDataHob.PerCoreRatioOverride) {
|
|
for (PerCoreRatioIndex = 0; PerCoreRatioIndex < CPU_MAX_BIG_CORES; PerCoreRatioIndex++) {
|
|
CpuInitDataHob.PerCoreRatio[PerCoreRatioIndex] = mOverClockingConfig->PerCoreRatio[PerCoreRatioIndex];
|
|
}
|
|
for (PerCoreRatioIndex = 0; PerCoreRatioIndex < CPU_MAX_ATOM_CLUSTERS; PerCoreRatioIndex++) {
|
|
CpuInitDataHob.PerAtomClusterRatio[PerCoreRatioIndex] = mOverClockingConfig->AtomClusterRatio[PerCoreRatioIndex];
|
|
}
|
|
}
|
|
Hob = BuildGuidDataHob (
|
|
&gCpuInitDataHobGuid,
|
|
(VOID *) &CpuInitDataHob,
|
|
(UINTN) sizeof (CPU_INIT_DATA_HOB)
|
|
);
|
|
ASSERT (Hob != NULL);
|
|
|
|
DEBUG ((DEBUG_INFO, "InitializeCpuDataHob Done \n"));
|
|
PostCode (0xC44);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Set the BIOS DONE MSR
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
ApSafeSetBiosDone (
|
|
VOID
|
|
)
|
|
{
|
|
MSR_BIOS_DONE_REGISTER MsrBiosDone;
|
|
MsrBiosDone.Uint64 = AsmReadMsr64 (MSR_BIOS_DONE);
|
|
MsrBiosDone.Bits.EnableIaUntrusted = 1;
|
|
AsmWriteMsr64 (MSR_BIOS_DONE, MsrBiosDone.Uint64);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Set the BIOS DONE MSR for all Enabled Cores
|
|
**/
|
|
VOID
|
|
SetBiosDone (
|
|
VOID
|
|
)
|
|
{
|
|
///
|
|
/// Set the BIOS DONE MSR before second patch load
|
|
///
|
|
DEBUG ((DEBUG_INFO, "SetBiosDone Start\n"));
|
|
ApSafeSetBiosDone ();
|
|
mMpServices2Ppi->StartupAllAPs (
|
|
mMpServices2Ppi,
|
|
(EFI_AP_PROCEDURE) ApSafeSetBiosDone,
|
|
FALSE,
|
|
0,
|
|
NULL
|
|
);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Re-load microcode patch.
|
|
|
|
@param[in] Buffer - A pointer to buffer which need to append the element
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
ReloadMicrocodePatch (
|
|
VOID
|
|
)
|
|
{
|
|
BOOLEAN IsBspVal;
|
|
STATIC BOOLEAN IsSimics;
|
|
STATIC BOOLEAN IsHsle;
|
|
|
|
IsBspVal = IsBsp ();
|
|
|
|
if (IsBspVal) {
|
|
DEBUG ((DEBUG_INFO, "ReloadMicrocodePatch: second patch load started\n"));
|
|
}
|
|
|
|
///
|
|
/// Init XMM
|
|
///
|
|
XmmInit ();
|
|
|
|
if (IsX2apicModeEnabled () == 0x00) {
|
|
if (IsBspVal) {
|
|
ProgramXApic (TRUE);
|
|
} else {
|
|
ProgramXApic (FALSE);
|
|
}
|
|
}
|
|
|
|
InitializeMicrocode (
|
|
(CPU_MICROCODE_HEADER *) (UINTN) mCpuConfig->MicrocodePatchAddress,
|
|
mCpuConfig->MicrocodePatchRegionSize
|
|
);
|
|
|
|
if (IsBspVal) {
|
|
IsSimics = IsSimicsEnvironment ();
|
|
IsHsle = IsHSLEEnvironment ();
|
|
}
|
|
|
|
DEBUG_CODE_BEGIN ();
|
|
if (IsBspVal && !IsSimics && !IsHsle) {
|
|
if (!MsrIsMcu2ndPatchSuccess ()) {
|
|
DEBUG ((DEBUG_INFO, "ReloadMicrocodePatch: Second patch didn't load.\n"));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "ReloadMicrocodePatch: Second patch load success.\n"));
|
|
}
|
|
}
|
|
DEBUG_CODE_END ();
|
|
}
|
|
|
|
/**
|
|
This function gets the total number of Small cores
|
|
**/
|
|
STATIC
|
|
VOID
|
|
GetNumberOfSmallCores (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 CoreType;
|
|
CoreType = 0;
|
|
DetectCoreType (&CoreType);
|
|
if (CoreType == CPUID_CORE_TYPE_INTEL_ATOM) {
|
|
mSmallCoreCount++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Activate the Key Locker MSR
|
|
**/
|
|
STATIC
|
|
VOID
|
|
ActivateKeyLocker (
|
|
VOID
|
|
)
|
|
{
|
|
MSR_PRMRR_MASK_REGISTER MsrPrmrrMask;
|
|
MSR_BIOS_UPGD_TRIG_REGISTER MsrBiosUpgdTrig;
|
|
|
|
//
|
|
// Activate the keylocker only when PRMRR MASK VLD Bit is set.
|
|
//
|
|
MsrPrmrrMask.Uint64 = AsmReadMsr64 (MSR_PRMRR_MASK);
|
|
//
|
|
// Check if PRMRR Valid bit is set
|
|
//
|
|
if (MsrPrmrrMask.Bits.Vld != 0) {
|
|
//
|
|
// BIOS Should do read and write back the MSR to do a Keylocker Activation from ucode.
|
|
//
|
|
MsrBiosUpgdTrig.Uint64 = AsmReadMsr64 (MSR_BIOS_UPGD_TRIG);
|
|
AsmWriteMsr64 (MSR_BIOS_UPGD_TRIG, MsrBiosUpgdTrig.Uint64);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Finalization of settings post Microcode patch reload
|
|
**/
|
|
VOID
|
|
ApSafePostMicrocodePatchInit (
|
|
VOID
|
|
)
|
|
{
|
|
if (IsKeyLockerSupported () && (mSmallCoreCount != 0)) {
|
|
ActivateKeyLocker ();
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
This function handles Cpu Initialization routine at the end of PEI
|
|
|
|
@retval EFI_STATUS - Always return EFI_SUCCESS
|
|
**/
|
|
EFI_STATUS
|
|
CpuInitAtEndOfPei (
|
|
VOID
|
|
)
|
|
{
|
|
if (mCpuConfig->SkipMpInit == 0) {
|
|
DEBUG ((DEBUG_INFO, "ReloadMicrocodePatch Start\n"));
|
|
PostCode (0xC80);
|
|
|
|
///
|
|
/// Reload Microcode Patch
|
|
///
|
|
ReloadMicrocodePatch ();
|
|
|
|
DEBUG ((DEBUG_INFO, "ReloadMicrocodePatch Done\n"));
|
|
PostCode (0xC81);
|
|
|
|
DEBUG ((DEBUG_INFO, "ApSafePostMicrocodePatchInit Start\n"));
|
|
PostCode (0xC82);
|
|
|
|
ApSafePostMicrocodePatchInit ();
|
|
mMpServices2Ppi->StartupAllAPs (
|
|
mMpServices2Ppi,
|
|
(EFI_AP_PROCEDURE) ApSafePostMicrocodePatchInit,
|
|
FALSE,
|
|
0,
|
|
NULL
|
|
);
|
|
DEBUG ((DEBUG_INFO, "ApSafePostMicrocodePatchInit Done\n"));
|
|
}
|
|
|
|
PostCode (0xC83);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Initialize processor features, performance and power management features, BIOS Guard, and Overclocking etc features before RESET_CPL at post-memory phase.
|
|
|
|
@param[in] SiPolicyPpi The SI Policy PPI instance
|
|
|
|
@retval EFI_SUCCESS The driver installed/initialized correctly.
|
|
**/
|
|
EFI_STATUS
|
|
CpuInit (
|
|
IN SI_POLICY_PPI *SiPolicyPpi
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi;
|
|
UINTN NumberOfProcessors;
|
|
UINTN NumberOfEnabledProcessors;
|
|
MSR_LTCTRLSTS_REGISTER MsrLtCtrlSts;
|
|
MSR_FLEX_RATIO_REGISTER FlexRatioMsr;
|
|
|
|
DEBUG ((DEBUG_INFO, "CpuInit Start \n"));
|
|
PostCode (0xC15);
|
|
|
|
DEBUG ((DEBUG_INFO, "Cpu Initialization in PostMem start\n"));
|
|
|
|
mSiPolicyPpi = SiPolicyPpi;
|
|
|
|
Status = PeiServicesLocatePpi (
|
|
&gSiPreMemPolicyPpiGuid,
|
|
0,
|
|
NULL,
|
|
(VOID **) &SiPreMemPolicyPpi
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuConfigGuid, (VOID *) &mCpuConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuTestConfigGuid, (VOID *) &mCpuTestConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtBasicConfigGuid, (VOID *) &mCpuPowerMgmtBasicConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPolicyPpi, &gCpuPowerMgmtCustomConfigGuid, (VOID *) &mCpuPowerMgmtCustomConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gCpuConfigLibPreMemConfigGuid, (VOID *) &mCpuConfigLibPreMemConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gOverclockingPreMemConfigGuid, (VOID *) &mOverClockingConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gVtdConfigGuid, (VOID *) &mVtdConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = GetConfigBlock ((VOID*) SiPolicyPpi, &gCpuPowerMgmtTestConfigGuid, (VOID*) &mCpuPowerMgmtTestConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
|
|
if (mCpuConfig->SkipMpInit == 0) {
|
|
///
|
|
/// Locate CpuMpCpu MpService Ppi
|
|
///
|
|
Status = PeiServicesLocatePpi (
|
|
&gEdkiiPeiMpServices2PpiGuid,
|
|
0,
|
|
NULL,
|
|
(VOID **) &mMpServices2Ppi
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
///
|
|
/// Fill Cpu MP system data
|
|
///
|
|
mMpServices2Ppi->GetNumberOfProcessors (mMpServices2Ppi, (UINTN *)&NumberOfProcessors, (UINTN *)&NumberOfEnabledProcessors);
|
|
|
|
DEBUG ((DEBUG_INFO, "ProgramProcessorFeature Start \n"));
|
|
PostCode (0xC18);
|
|
|
|
DEBUG ((DEBUG_INFO, "Set the Cpu Features for CpuFeaturesPei driver\n"));
|
|
SetPcdCpuFeaturesSetting ();
|
|
|
|
///
|
|
/// Check if PM_TMR emulation is required.
|
|
///
|
|
if (PmcIsPchPmTimerEnabled () == FALSE) {
|
|
mPmTimerEmulationEnable = TRUE;
|
|
}
|
|
|
|
///
|
|
/// Program processor supported features on BSP and on all APs
|
|
///
|
|
ProgramProcessorFeature (SiPreMemPolicyPpi);
|
|
mMpServices2Ppi->StartupAllAPs (
|
|
mMpServices2Ppi,
|
|
(EFI_AP_PROCEDURE) ProgramProcessorFeature,
|
|
FALSE,
|
|
0,
|
|
(VOID *)SiPreMemPolicyPpi
|
|
);
|
|
|
|
DEBUG ((DEBUG_INFO, "ProgramProcessorFeature Done\n"));
|
|
PostCode (0xC19);
|
|
|
|
///
|
|
/// Get total number of small cores present in platform
|
|
///
|
|
GetNumberOfSmallCores ();
|
|
mMpServices2Ppi->StartupAllAPs (
|
|
mMpServices2Ppi,
|
|
(EFI_AP_PROCEDURE) GetNumberOfSmallCores,
|
|
TRUE,
|
|
0,
|
|
NULL
|
|
);
|
|
DEBUG ((DEBUG_INFO, "Small Core Count - %x\n", mSmallCoreCount));
|
|
}
|
|
|
|
|
|
///
|
|
/// Program the OverClocking Lock Bit before 2nd patch load
|
|
///
|
|
if (mOverClockingConfig != NULL) {
|
|
FlexRatioMsr.Uint64 = AsmReadMsr64 (MSR_FLEX_RATIO);
|
|
FlexRatioMsr.Bits.OcLock = mOverClockingConfig->OcLock;
|
|
AsmWriteMsr64 (MSR_FLEX_RATIO, FlexRatioMsr.Uint64);
|
|
}
|
|
|
|
///
|
|
/// Initialize performance and power management features before RESET_CPL at post-memory phase.
|
|
///
|
|
CpuInitPreResetCpl (SiPolicyPpi);
|
|
|
|
if (mCpuConfig->SkipMpInit == 0) {
|
|
///
|
|
/// Setting the MSR_LTCTRLSTS bit.
|
|
///
|
|
MsrLtCtrlSts.Uint64 = AsmReadMsr64 (MSR_LTCTRLSTS);
|
|
MsrLtCtrlSts.Bits.Configlock = 1;
|
|
AsmWriteMsr64 (MSR_LTCTRLSTS, MsrLtCtrlSts.Uint64);
|
|
|
|
///
|
|
/// Initialize CPU Data Hob
|
|
///
|
|
InitializeCpuDataHob (SiPreMemPolicyPpi);
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "Cpu Initialize performance and power management features before RESET_CPL Done\n"));
|
|
|
|
DEBUG ((DEBUG_INFO, "CpuInit Done \n"));
|
|
PostCode (0xC4F);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|