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