748 lines
25 KiB
C
748 lines
25 KiB
C
/** @file
|
|
This driver handle msdm OA data between variable and SPI ROM
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2021, Insyde Software Corporation. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
/** @file
|
|
Cpu driver, which initializes CPU and implements CPU Architecture
|
|
Protocol as defined in Framework specification.
|
|
|
|
@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/BaseLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/IoLib.h>
|
|
#include <Protocol/MpService.h>
|
|
#include "CpuInitDxe.h"
|
|
#include "BiosGuard.h"
|
|
#include <Library/BootGuardLibVer1.h>
|
|
#include <Library/CpuCommonLib.h>
|
|
#include <Library/MsrFruLib.h>
|
|
#include <Library/CpuInfoFruLib.h>
|
|
#include <Library/CpuCacheInfoLib.h>
|
|
#include <PowerMgmtNvsStruct.h>
|
|
#include <Protocol/DxeSmmReadyToLock.h>
|
|
#include <Register/CommonMsr.h>
|
|
//[-start-210318-IB11790410-add]//
|
|
#include <Library/VariableLib.h>
|
|
//[-end-210318-IB11790410-add]//
|
|
//
|
|
// Private GUIDs for BIOS Guard initializes
|
|
//
|
|
extern EFI_GUID gBiosGuardHobGuid;
|
|
EFI_MP_SERVICES_PROTOCOL *mMpService;
|
|
|
|
UINT32 mCoreTypeBitMap = 0;
|
|
UINT8 mNumBigCore = 0;
|
|
UINT8 mNumSmallCore = 0;
|
|
UINT8 mBigCoreThreads = 0;
|
|
UINT8 mSmallCoreThreads = 0;
|
|
UINT8 *mCoreModuleInfo = NULL;
|
|
UINTN mNumberOfProcessors = 0;
|
|
UINTN mNumberOfEnabledProcessors = 0;
|
|
UINT8 mSmallCoreNominalPerformance = 0;
|
|
static BOOLEAN mSmallCoreNominalPerformanceUpdated = FALSE;
|
|
///
|
|
/// The Cpu Init Data Hob
|
|
///
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CPU_INIT_DATA_HOB *mCpuInitDataHob = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED FVID_TABLE *mFvidTable = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CPU_INFO_PROTOCOL *mCpuInfo;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED UINTN mCommonFeatures;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSiliconFeatures;
|
|
|
|
/**
|
|
Set all APs to deepest C-State before ready to boot for better power saving
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
RequestDeepestCStateForAps (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
CPUID_MONITOR_MWAIT_ECX MonitorMwaitEcx;
|
|
CPUID_MONITOR_MWAIT_EDX MonitorMwaitEdx;
|
|
UINT8 MaxCstate;
|
|
MSR_BROADWELL_PKG_CST_CONFIG_CONTROL_REGISTER Msr;
|
|
UINT32 SubStates;
|
|
|
|
///
|
|
/// APs should be at deepest C-State before ready to boot for better power saving,
|
|
/// if boot to DOS/EFI_SHARE or any operating system that running only single thread.
|
|
///
|
|
/// BIOS should use CPUID.(EAX=5) Monitor/Mwait Leaf and also check MSR E2h[3:0] Package C-state limit to determine
|
|
/// if the processor supports MONITOR/MWAIT extensions for various C-states and sub C-states.
|
|
///
|
|
Msr.Uint64 = AsmReadMsr64 (MSR_BROADWELL_PKG_CST_CONFIG_CONTROL);
|
|
GetSubCStateSupported ((UINT32 *)&MonitorMwaitEcx, (UINT32 *)&MonitorMwaitEdx);
|
|
MaxCstate = 0;
|
|
SubStates = 0;
|
|
if (MonitorMwaitEcx.Bits.ExtensionsSupported) {
|
|
switch (Msr.Bits.Limit) {
|
|
case V_CSTATE_LIMIT_C10:
|
|
SubStates = MonitorMwaitEdx.Bits.C7States;
|
|
MaxCstate = 0x60;
|
|
break;
|
|
|
|
case V_CSTATE_LIMIT_C9:
|
|
SubStates = MonitorMwaitEdx.Bits.C6States;
|
|
MaxCstate = 0x50;
|
|
break;
|
|
|
|
case V_CSTATE_LIMIT_C8:
|
|
SubStates = MonitorMwaitEdx.Bits.C5States;
|
|
MaxCstate = 0x40;
|
|
break;
|
|
|
|
case V_CSTATE_LIMIT_C7S:
|
|
SubStates = MonitorMwaitEdx.Bits.C4States;
|
|
MaxCstate = 0x30;
|
|
break;
|
|
|
|
case V_CSTATE_LIMIT_C7:
|
|
SubStates = MonitorMwaitEdx.Bits.C4States;
|
|
MaxCstate = 0x30;
|
|
break;
|
|
|
|
case V_CSTATE_LIMIT_C6:
|
|
SubStates = MonitorMwaitEdx.Bits.C3States;
|
|
MaxCstate = 0x20;
|
|
break;
|
|
|
|
case V_CSTATE_LIMIT_C3:
|
|
SubStates = MonitorMwaitEdx.Bits.C2States;
|
|
MaxCstate = 0x10;
|
|
break;
|
|
|
|
case V_CSTATE_LIMIT_C1:
|
|
SubStates = MonitorMwaitEdx.Bits.C1States;
|
|
MaxCstate = 0x00;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
///
|
|
/// If Substates opcode is greater than 1 than add that info to the MaxCstate Opcode.
|
|
///
|
|
if (SubStates > 1) {
|
|
MaxCstate |= (UINT8) SubStates - 1;
|
|
}
|
|
|
|
///
|
|
/// Update Target C State EAX[7:4] value alone in PcdCpuApTargetCstate
|
|
///
|
|
PcdSet8S (PcdCpuApTargetCstate, MaxCstate >> 4);
|
|
}
|
|
|
|
/**
|
|
CpuInitOnReadyToLockCallback - Callback will be triggered when OnReadyToLock event is signaled
|
|
- Create SMBIOS Table type - FviSmbiosType
|
|
- Drop into SMM to register IOTRAP for BIOS Guard tools interface
|
|
|
|
@param[in] Event - A pointer to the Event that triggered the callback.
|
|
@param[in] Context - A pointer to private data registered with the callback function.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
CpuInitOnReadyToLockCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
BIOSGUARD_HOB *BiosGuardHobPtr;
|
|
MSR_BIOS_INFO_FLAGS_REGISTER MsrBiosInfoFlags;
|
|
EFI_STATUS Status;
|
|
VOID *DxeSmmReadyToLock;
|
|
//[-start-210318-IB11790410-add]//
|
|
UINT64 BiosInfoFlagsData;
|
|
//[-end-210318-IB11790410-add]//
|
|
///
|
|
/// Account for the initial call from EfiCreateProtocolNotifyEvent
|
|
///
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiDxeSmmReadyToLockProtocolGuid,
|
|
NULL,
|
|
&DxeSmmReadyToLock
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
///
|
|
/// Close the event
|
|
///
|
|
gBS->CloseEvent (Event);
|
|
|
|
///
|
|
/// Enable BIOS Guard Flash Wear-Out Protection mitigation.
|
|
///
|
|
BiosGuardHobPtr = GetFirstGuidHob (&gBiosGuardHobGuid);
|
|
if (BiosGuardHobPtr != NULL) {
|
|
if (BiosGuardHobPtr->Bgpdt.BiosGuardAttr & EnumFlashwearoutProtection) {
|
|
MsrBiosInfoFlags.Uint64 = AsmReadMsr64 (MSR_BIOS_INFO_FLAGS);
|
|
MsrBiosInfoFlags.Bits.BiosInfoFlagsData = 1;
|
|
AsmWriteMsr64 (MSR_BIOS_INFO_FLAGS, MsrBiosInfoFlags.Uint64);
|
|
//[-start-210318-IB11790410-add]//
|
|
BiosInfoFlagsData = 1;
|
|
Status = CommonSetVariable (
|
|
L"BiosInfoFlagData",
|
|
&gBiosInfoFlagGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
|
sizeof (UINT64),
|
|
&BiosInfoFlagsData
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
} else {
|
|
SetVariableToSensitiveVariable (
|
|
L"BiosInfoFlagData",
|
|
&gBiosInfoFlagGuid,
|
|
0,
|
|
0,
|
|
NULL
|
|
);
|
|
//[-end-210318-IB11790410-add]//
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Collect Cpu Cache Infomation
|
|
|
|
@param[in] CPU_INFO_PROTOCOL *CpuInfo - Pointer to the CPU_INFO_PROTOCOL Structure
|
|
|
|
@retval EFI_SUCCESS - Collect information Successfully.
|
|
@retval EFI_NOT_FOUND - Specified HOB can not be found.
|
|
@retval EFI_INVALID_PARAMETER - Input buffer is invalid.
|
|
**/
|
|
EFI_STATUS
|
|
CollectCpuCacheInfo (
|
|
IN CPU_INFO_PROTOCOL *CpuInfo
|
|
)
|
|
{
|
|
EFI_HOB_GUID_TYPE *CacheInfoHob;
|
|
CPU_CACHE_INFO *CacheInfoData;
|
|
UINTN CacheInfoDataSize;
|
|
UINT8 CoreType;
|
|
UINT8 CacheCount;
|
|
UINT8 SmallCoreCacheCount;
|
|
UINT8 BigCoreCacheCount;
|
|
UINT8 Index;
|
|
|
|
CacheInfoHob = GetFirstGuidHob (&gCpuCacheInfoHobGuid);
|
|
if (CacheInfoHob == NULL) {
|
|
DEBUG ((DEBUG_ERROR, "CPU Cache info HOB not available\n"));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
CacheInfoData = GET_GUID_HOB_DATA (CacheInfoHob);
|
|
CacheInfoDataSize = GET_GUID_HOB_DATA_SIZE (CacheInfoHob);
|
|
|
|
CoreType = 0;
|
|
CacheCount = 0;
|
|
SmallCoreCacheCount = 0;
|
|
BigCoreCacheCount = 0;
|
|
|
|
for (Index = 0; Index < CacheInfoDataSize / sizeof (*CacheInfoData); Index++) {
|
|
switch (CacheInfoData[Index].CoreType) {
|
|
case CORE_TYPE_NON_HYBRID:
|
|
if (mNumBigCore != 0 && mNumSmallCore == 0) {
|
|
CoreType = BIG_CORE;
|
|
CacheCount = BigCoreCacheCount;
|
|
BigCoreCacheCount++;
|
|
} else if (mNumBigCore == 0 && mNumSmallCore != 0) {
|
|
CoreType = SMALL_CORE;
|
|
CacheCount = SmallCoreCacheCount;
|
|
SmallCoreCacheCount ++;
|
|
} else {
|
|
ASSERT (FALSE);
|
|
}
|
|
break;
|
|
|
|
case CPUID_CORE_TYPE_INTEL_ATOM:
|
|
CoreType = SMALL_CORE;
|
|
CacheCount = SmallCoreCacheCount;
|
|
SmallCoreCacheCount++;
|
|
break;
|
|
|
|
case CPUID_CORE_TYPE_INTEL_CORE:
|
|
CoreType = BIG_CORE;
|
|
CacheCount = BigCoreCacheCount;
|
|
BigCoreCacheCount++;
|
|
break;
|
|
|
|
default:
|
|
DEBUG ((DEBUG_ERROR, "CPU Core type not available\n"));
|
|
ASSERT (FALSE);
|
|
break;
|
|
}
|
|
|
|
CpuInfo->CpuInfo[CoreType].CacheInfo[CacheCount].Type = (UINT8) CacheInfoData[Index].CacheType;
|
|
CpuInfo->CpuInfo[CoreType].CacheInfo[CacheCount].Level = (UINT8) CacheInfoData[Index].CacheLevel;
|
|
CpuInfo->CpuInfo[CoreType].CacheInfo[CacheCount].Associativity = CacheInfoData[Index].CacheWays + 1;
|
|
CpuInfo->CpuInfo[CoreType].CacheInfo[CacheCount].Size = CacheInfoData[Index].CacheSizeinKB;
|
|
}
|
|
|
|
//
|
|
// Subtract 1 because there are 2 counts for L1 (Data and Code).
|
|
//
|
|
if (SmallCoreCacheCount > 0) {
|
|
CpuInfo->CpuInfo[SMALL_CORE].MaxCacheSupported = SmallCoreCacheCount - 1;
|
|
}
|
|
if (BigCoreCacheCount > 0) {
|
|
CpuInfo->CpuInfo[BIG_CORE].MaxCacheSupported = BigCoreCacheCount - 1;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Collect Core Type Cpu Infomation
|
|
|
|
@param[in] VOID *Buffer - Pointer to the CORE_INFORMATION Structure
|
|
|
|
@retval EFI_SUCCESS - Successfully prepared.
|
|
@retval EFI_INVALID_PARAMETER - Input Buffer is invalid.
|
|
**/
|
|
EFI_STATUS
|
|
CollectCoreTypeCpuInfo (
|
|
IN VOID *Buffer
|
|
)
|
|
{
|
|
CPU_INFO *CoreInfo;
|
|
CHAR8 *BrandString;
|
|
UINT32 CpuSignature;
|
|
UINT8 VfPointIndex;
|
|
CPUID_BRAND_STRING_DATA BrandStringEax;
|
|
CPUID_BRAND_STRING_DATA BrandStringEbx;
|
|
CPUID_BRAND_STRING_DATA BrandStringEcx;
|
|
CPUID_BRAND_STRING_DATA BrandStringEdx;
|
|
CPUID_EXTENDED_TOPOLOGY_EBX ExtendedTopologyEbx;
|
|
CPUID_VERSION_INFO_ECX VersionInfoEcx;
|
|
CPUID_VERSION_INFO_EDX VersionInfoEdx;
|
|
|
|
CoreInfo = (CPU_INFO *) Buffer;
|
|
BrandString = CoreInfo->BrandString;
|
|
if (BrandString == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
///
|
|
/// Get Brand string
|
|
///
|
|
AsmCpuid (CPUID_BRAND_STRING1, &BrandStringEax.Uint32, &BrandStringEbx.Uint32, &BrandStringEcx.Uint32, &BrandStringEdx.Uint32);
|
|
*(UINT32*) BrandString = BrandStringEax.Uint32; BrandString += 4;
|
|
*(UINT32*) BrandString = BrandStringEbx.Uint32; BrandString += 4;
|
|
*(UINT32*) BrandString = BrandStringEcx.Uint32; BrandString += 4;
|
|
*(UINT32*) BrandString = BrandStringEdx.Uint32; BrandString += 4;
|
|
|
|
AsmCpuid (CPUID_BRAND_STRING2, &BrandStringEax.Uint32, &BrandStringEbx.Uint32, &BrandStringEcx.Uint32, &BrandStringEdx.Uint32);
|
|
*(UINT32*) BrandString = BrandStringEax.Uint32; BrandString += 4;
|
|
*(UINT32*) BrandString = BrandStringEbx.Uint32; BrandString += 4;
|
|
*(UINT32*) BrandString = BrandStringEcx.Uint32; BrandString += 4;
|
|
*(UINT32*) BrandString = BrandStringEdx.Uint32; BrandString += 4;
|
|
|
|
AsmCpuid (CPUID_BRAND_STRING3, &BrandStringEax.Uint32, &BrandStringEbx.Uint32, &BrandStringEcx.Uint32, &BrandStringEdx.Uint32);
|
|
*(UINT32*) BrandString = BrandStringEax.Uint32; BrandString += 4;
|
|
*(UINT32*) BrandString = BrandStringEbx.Uint32; BrandString += 4;
|
|
*(UINT32*) BrandString = BrandStringEcx.Uint32; BrandString += 4;
|
|
*(UINT32*) BrandString = BrandStringEdx.Uint32; BrandString += 4;
|
|
*BrandString = '\0';
|
|
///
|
|
/// Remove leading spaces. After removing leading spaces, the Brand String can not be freed. However, it should never be freed.
|
|
///
|
|
while (*CoreInfo->BrandString == ' ') {
|
|
++CoreInfo->BrandString;
|
|
}
|
|
|
|
///
|
|
/// Get information on enabled threads, cores, dies and package for the CPU(s) on this platform
|
|
///
|
|
AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, NULL, &ExtendedTopologyEbx.Uint32, NULL, NULL);
|
|
CoreInfo->NumSupportedThreadsPerCore = (UINT8) ExtendedTopologyEbx.Uint32;
|
|
|
|
CoreInfo->Voltage = 0;
|
|
CoreInfo->NumberOfPStates = mFvidTable[0].FvidHeader.EistStates;
|
|
CoreInfo->CoreVfPointCount = mCpuInitDataHob->CoreVfPointCount;
|
|
for (VfPointIndex = 0; VfPointIndex < mCpuInitDataHob->CoreVfPointCount; VfPointIndex++) {
|
|
CoreInfo->CoreVfPointRatio[VfPointIndex] = mCpuInitDataHob->CoreVfPointRatio[VfPointIndex];
|
|
}
|
|
|
|
CoreInfo->RingVfPointCount = mCpuInitDataHob->RingVfPointCount;
|
|
for (VfPointIndex = 0; VfPointIndex < mCpuInitDataHob->RingVfPointCount; VfPointIndex++) {
|
|
CoreInfo->RingVfPointRatio[VfPointIndex] = mCpuInitDataHob->RingVfPointRatio[VfPointIndex];
|
|
}
|
|
///
|
|
/// Gather CPU info
|
|
///
|
|
AsmCpuid (CPUID_VERSION_INFO, &CpuSignature, NULL, &VersionInfoEcx.Uint32, &VersionInfoEdx.Uint32);
|
|
CoreInfo->CpuSignature = CpuSignature;
|
|
CoreInfo->Features = LShiftU64 (VersionInfoEcx.Uint32, 32) + VersionInfoEdx.Uint32;
|
|
if (mCpuInitDataHob->CtdpLevelsSupported > 1 && mCpuInitDataHob->ConfigTdpLevel != 0xFF && mCpuInitDataHob->ApplyConfigTdp == 1) {
|
|
CoreInfo->IntendedFreq = MsrGetSelectCtdpRatio (mCpuInitDataHob->ConfigTdpLevel) * 100;
|
|
} else {
|
|
CoreInfo->IntendedFreq = MsrGetMaxNonTurboRatio () * 100;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Update the Core Infomation for Small Core and Big Core
|
|
This is executed across all threads
|
|
**/
|
|
VOID
|
|
UpdateCoreInformation (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 CoreType;
|
|
UINT8 ModuleId;
|
|
UINTN ApNumber;
|
|
MSR_IA32_HWP_CAPABILITIES_REGISTER MsrHwpCapabilities;
|
|
|
|
Status = mMpService->WhoAmI (mMpService, &ApNumber);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
CoreType = 0;
|
|
DetectCoreType (&CoreType);
|
|
ModuleId = (UINT8) (GetCpuApicId () >> 3);
|
|
|
|
//
|
|
// CoreModule Information has the module ID of the running core and Num of processors in the Module
|
|
// BITS 7:4 has the Num of processors in that module.
|
|
// BITS 3:0 denotes the ModuleID of that core
|
|
//
|
|
mCoreModuleInfo [ApNumber] = ModuleId;
|
|
if (CoreType == CPUID_CORE_TYPE_INTEL_ATOM) {
|
|
if (mNumSmallCore == 0) {
|
|
CollectCoreTypeCpuInfo (&mCpuInfo->CpuInfo[SMALL_CORE]);
|
|
}
|
|
mSmallCoreThreads ++;
|
|
if (!IsSecondaryThread ()) {
|
|
mNumSmallCore ++;
|
|
}
|
|
if (IsHwpSupported () && (mSmallCoreNominalPerformanceUpdated == FALSE)) {
|
|
MsrHwpCapabilities.Uint64 = AsmReadMsr64 (MSR_IA32_HWP_CAPABILITIES);
|
|
mSmallCoreNominalPerformance = (UINT8) MsrHwpCapabilities.Bits.Guaranteed_Performance;
|
|
mSmallCoreNominalPerformanceUpdated = TRUE;
|
|
}
|
|
} else if (CoreType == CPUID_CORE_TYPE_INTEL_CORE) {
|
|
if (mNumBigCore == 0) {
|
|
CollectCoreTypeCpuInfo (&mCpuInfo->CpuInfo[BIG_CORE]);
|
|
}
|
|
mBigCoreThreads ++;
|
|
if (!IsSecondaryThread ()) {
|
|
mNumBigCore ++;
|
|
}
|
|
//
|
|
// If detected Core is BIG, then respective BIT position will be SET.
|
|
//
|
|
mCoreTypeBitMap |= (1 << ApNumber);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Initialize CPU info.
|
|
|
|
@retval EFI_SUCCESS - Successfully prepared.
|
|
@retval EFI_OUT_OF_RESOURCES - Not enough memory to complete the function.
|
|
**/
|
|
EFI_STATUS
|
|
InitCpuInfo (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE Handle;
|
|
UINT8 Index;
|
|
UINT8 Index2;
|
|
UINT8 ModuleIdNum;
|
|
MSR_IA32_PM_ENABLE_REGISTER MsrPmEnable;
|
|
|
|
Handle = NULL;
|
|
|
|
mCpuInfo = AllocateZeroPool (sizeof (CPU_INFO_PROTOCOL));
|
|
if (mCpuInfo == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
mCpuInfo->CpuInfo = (CPU_INFO*) AllocateZeroPool (CORE_TYPE_NUM * sizeof (CPU_INFO));
|
|
if (mCpuInfo->CpuInfo == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
for (Index = 0; Index < CORE_TYPE_NUM; Index ++) {
|
|
mCpuInfo->CpuInfo[Index].BrandString = AllocateZeroPool (MAX_BRANDSTRING_SIZE);
|
|
if (mCpuInfo->CpuInfo[Index].BrandString == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
mCpuInfo->CpuInfo[Index].CacheInfo = (CACHE_DESCRIPTOR_INFO *) AllocateZeroPool (MAX_CACHE_LEVEL_COUNT * sizeof (CACHE_DESCRIPTOR_INFO));
|
|
if (mCpuInfo->CpuInfo[Index].CacheInfo == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
}
|
|
|
|
if (IsHwpSupported ()) {
|
|
MsrPmEnable.Uint64 = AsmReadMsr64 (MSR_IA32_PM_ENABLE);
|
|
MsrPmEnable.Bits.HWP_ENABLE = 1;
|
|
AsmWriteMsr64 (MSR_IA32_PM_ENABLE, MsrPmEnable.Uint64);
|
|
}
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiMpServiceProtocolGuid,
|
|
NULL,
|
|
(VOID **) &mMpService
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = mMpService->GetNumberOfProcessors (mMpService, &mNumberOfProcessors, &mNumberOfEnabledProcessors);
|
|
DEBUG ((DEBUG_INFO, "Total num of Processors - 0x%x. Enabled Processors - 0x%x\n", mNumberOfProcessors, mNumberOfEnabledProcessors));
|
|
mCoreModuleInfo = AllocateZeroPool (mNumberOfProcessors);
|
|
if (mCoreModuleInfo == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
UpdateCoreInformation ();
|
|
mMpService->StartupAllAPs (
|
|
mMpService, // This
|
|
(EFI_AP_PROCEDURE) UpdateCoreInformation, // Procedure
|
|
TRUE, // SingleThread
|
|
NULL, // WaitEvent
|
|
0, // TimeoutInMicrosecsond
|
|
NULL, // ProcedureArgument
|
|
NULL // FailedCpuList
|
|
);
|
|
DEBUG ((DEBUG_INFO, "Total Enabled Big Core - 0x%x, Total Enabled Small Core - 0x%x\n", mNumBigCore, mNumSmallCore));
|
|
DEBUG ((DEBUG_INFO, "Total Enabled Big Core Threads - 0x%x, Total Enabled Small Core Threads- 0x%x\n",mBigCoreThreads, mSmallCoreThreads));
|
|
|
|
ModuleIdNum = 0;
|
|
for (Index = 0; Index < mNumberOfEnabledProcessors; Index ++) {
|
|
for (Index2 = 0; Index2 < mNumberOfEnabledProcessors; Index2 ++) {
|
|
if ((mCoreModuleInfo[Index] & 0xF) == (mCoreModuleInfo[Index2] & 0xF)) {
|
|
ModuleIdNum ++;
|
|
}
|
|
}
|
|
mCoreModuleInfo[Index] |= ModuleIdNum << 4;
|
|
ModuleIdNum = 0;
|
|
}
|
|
if (IsHwpSupported ()) {
|
|
MsrPmEnable.Uint64 = AsmReadMsr64 (MSR_IA32_PM_ENABLE);
|
|
MsrPmEnable.Bits.HWP_ENABLE = 0;
|
|
AsmWriteMsr64 (MSR_IA32_PM_ENABLE, MsrPmEnable.Uint64);
|
|
}
|
|
|
|
CollectCpuCacheInfo (mCpuInfo);
|
|
|
|
if (mNumSmallCore != 0) {
|
|
mCpuInfo->CpuInfo[SMALL_CORE].NumHts = mSmallCoreThreads / mNumSmallCore;
|
|
mCpuInfo->CpuInfo[SMALL_CORE].NumCores = mNumSmallCore;
|
|
}
|
|
else {
|
|
mCpuInfo->CpuInfo[SMALL_CORE].NumHts = 0;
|
|
mCpuInfo->CpuInfo[SMALL_CORE].NumCores = 0;
|
|
}
|
|
|
|
if (mNumBigCore != 0) {
|
|
mCpuInfo->CpuInfo[BIG_CORE].NumHts = mBigCoreThreads / mNumBigCore;
|
|
mCpuInfo->CpuInfo[BIG_CORE].NumCores = mNumBigCore;
|
|
}
|
|
else {
|
|
mCpuInfo->CpuInfo[BIG_CORE].NumHts = 0;
|
|
mCpuInfo->CpuInfo[BIG_CORE].NumCores = 0;
|
|
}
|
|
|
|
mCpuInfo->Revision = CPU_INFO_PROTOCOL_REVISION;
|
|
mCpuInfo->CpuCommonFeatures = mCommonFeatures | (mSiliconFeatures << 10);
|
|
|
|
/// Update per core OC ratio information
|
|
if (mCpuInitDataHob->PerCoreRatioOverride) {
|
|
mCpuInfo->CpuInfo[SMALL_CORE].PerCoreRatioOverride = (UINT8) mCpuInitDataHob->PerCoreRatioOverride;
|
|
mCpuInfo->CpuInfo[BIG_CORE].PerCoreRatioOverride = (UINT8) mCpuInitDataHob->PerCoreRatioOverride;
|
|
for (Index = 0; Index < CPU_MAX_BIG_CORES; Index++) {
|
|
mCpuInfo->CpuInfo[BIG_CORE].PerCoreRatio[Index] = mCpuInitDataHob->PerCoreRatio[Index];
|
|
}
|
|
for (Index = 0; Index < CPU_MAX_ATOM_CLUSTERS; Index++) {
|
|
mCpuInfo->CpuInfo[SMALL_CORE].PerCoreRatio[Index] = mCpuInitDataHob->PerAtomClusterRatio[Index];
|
|
}
|
|
}
|
|
///
|
|
/// Install CPU info protocol
|
|
///
|
|
gBS->InstallMultipleProtocolInterfaces (
|
|
&Handle,
|
|
&gCpuInfoProtocolGuid,
|
|
mCpuInfo,
|
|
NULL
|
|
);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Initialize the state information for the CPU Architectural Protocol
|
|
|
|
@param[in] ImageHandle - Image handle of the loaded driver
|
|
@param[in] SystemTable - Pointer to the System Table
|
|
|
|
@retval EFI_SUCCESS - Thread was successfully created
|
|
@retval EFI_OUT_OF_RESOURCES - Can not allocate protocol data structure
|
|
@retval EFI_DEVICE_ERROR - Can not create the thread
|
|
@retval EFI_NOT_FOUND - Can not locate CPU Data HOB
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InitializeCpu (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VOID *Hob;
|
|
EFI_EVENT LegacyBootEvent;
|
|
EFI_EVENT ExitBootServicesEvent;
|
|
VOID *Registration;
|
|
MSR_MISC_PWR_MGMT_REGISTER MiscPowerManagement;
|
|
BOOLEAN HdcSupported;
|
|
#if FixedPcdGetBool(PcdBiosGuardEnable) == 1
|
|
BIOSGUARD_HOB *BiosGuardHobPtr;
|
|
#endif
|
|
|
|
///
|
|
/// Get CPU Init Data Hob
|
|
///
|
|
Hob = GetFirstGuidHob (&gCpuInitDataHobGuid);
|
|
if (Hob == NULL) {
|
|
DEBUG ((DEBUG_ERROR, "CPU Data HOB not available\n"));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
MiscPowerManagement.Uint64 = AsmReadMsr64 (MSR_MISC_PWR_MGMT);
|
|
HdcSupported = (MiscPowerManagement.Bits.EnableSdc != 0);
|
|
mCpuInitDataHob = (CPU_INIT_DATA_HOB *) ((UINTN) Hob + sizeof (EFI_HOB_GUID_TYPE));
|
|
mSiliconFeatures = ((HdcSupported) << N_HDC_SUPPORT) & B_HDC_SUPPORT;
|
|
mFvidTable = (FVID_TABLE *) &(mCpuInitDataHob->FvidTable);
|
|
|
|
///
|
|
/// Initialize DxeCpuInfo protocol instance and gather CPU information
|
|
///
|
|
Status = InitCpuInfo ();
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "Failed to initialize DxeCpuInfo\n"));
|
|
}
|
|
|
|
///
|
|
/// Create an OnReadyToLock protocol callback event for BIOS Guard.
|
|
/// This function causes CpuInitOnReadyToLockCallback() to be executed,
|
|
/// Ensure CpuInitOnReadyToLockCallback() accounts for this initial call.
|
|
///
|
|
EfiCreateProtocolNotifyEvent (
|
|
&gEfiDxeSmmReadyToLockProtocolGuid,
|
|
TPL_CALLBACK,
|
|
CpuInitOnReadyToLockCallback,
|
|
NULL,
|
|
&Registration
|
|
);
|
|
|
|
CpuAcpiInit (ImageHandle);
|
|
|
|
#if FixedPcdGetBool(PcdBiosGuardEnable) == 1
|
|
///
|
|
/// Get Bios Guard Config Hob
|
|
///
|
|
BiosGuardHobPtr = GetFirstGuidHob (&gBiosGuardHobGuid);
|
|
if (BiosGuardHobPtr != NULL) {
|
|
///
|
|
/// Determine if BGUP is to be placed in TSEG
|
|
/// If the size allocated to Bios Guard in DPR is 0, BGUP will be stored in TSEG
|
|
/// Otherwise, BGUP will use the memory allocated within DPR and
|
|
/// will initialize the Bios Guard NVS related variables
|
|
///
|
|
DEBUG ((DEBUG_INFO, "\n BiosGuardMemSize :%x \n",BiosGuardHobPtr->BiosGuardMemSize));
|
|
if (BiosGuardHobPtr->BiosGuardMemSize != 0) {
|
|
BiosGuardAcpiInit (ImageHandle);
|
|
}
|
|
} else {
|
|
DEBUG ((DEBUG_ERROR, "Bios Guard Config HOB not available, Bios Guard NVS variables not initialized\n"));
|
|
}
|
|
#endif
|
|
|
|
TxtNvsUpdate ();
|
|
//
|
|
// Set PCD to request deepest C-states in monitor/mwait right before boot.
|
|
// Use TPL_NOTIFY signal to trigger callback before TPL_CALLBACK signal used by
|
|
// UefiCpuPkg to put APs in deep sleep before giving control to OS.
|
|
//
|
|
|
|
Status = gBS->CreateEvent (
|
|
EVT_SIGNAL_EXIT_BOOT_SERVICES,
|
|
TPL_NOTIFY,
|
|
RequestDeepestCStateForAps,
|
|
NULL,
|
|
&ExitBootServicesEvent
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = gBS->CreateEventEx (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_NOTIFY,
|
|
RequestDeepestCStateForAps,
|
|
NULL,
|
|
&gEfiEventLegacyBootGuid,
|
|
&LegacyBootEvent
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|