361 lines
15 KiB
C
361 lines
15 KiB
C
/** @file
|
|
Cpu driver, which initializes ACPI
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 2015 - 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/UefiBootServicesTableLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Cpu/IncludePrivate/PowerMgmtNvsStruct.h>
|
|
#include <Protocol/CpuNvsArea.h>
|
|
#include "CpuInitDxe.h"
|
|
#include <Protocol/BiosGuardNvsArea.h>
|
|
#include <Register/CommonMsr.h>
|
|
#include <CpuPowerMgmt.h>
|
|
#include <Library/MsrFruLib.h>
|
|
|
|
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CPU_NVS_AREA_PROTOCOL mCpuNvsAreaProtocol;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED CPU_CONFIG *mCpuConfig = NULL;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED BIOSGUARD_NVS_AREA_PROTOCOL mBiosGuardNvsAreaProtocol;
|
|
|
|
/**
|
|
Initialize Cpu Nvs Area Protocol
|
|
|
|
@param[in] ImageHandle - Image handle of the loaded driver
|
|
|
|
@retval EFI_SUCCESS - thread can be successfully created
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CpuAcpiInit (
|
|
IN EFI_HANDLE ImageHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_PHYSICAL_ADDRESS Area;
|
|
MSR_FLEX_RATIO_REGISTER FlexRatio;
|
|
MSR_TEMPERATURE_TARGET_REGISTER TempTarget;
|
|
UINT8 MaxRefTemp;
|
|
UINT8 Index;
|
|
CPU_INIT_DATA_HOB *CpuInitDataHob;
|
|
VOID *Hob;
|
|
UINTN Pages;
|
|
UINT16 C6Latency = 0;
|
|
UINT16 C7Latency = 0;
|
|
UINT16 C8Latency = 0;
|
|
UINT16 C9Latency = 0;
|
|
UINT16 C10Latency = 0;
|
|
CPU_SKU CpuSku;
|
|
UINT16 ScalingFactorSmallCore = 0;
|
|
UINT16 ScalingFactorBigCore = 0;
|
|
UINT8 MaxNonTurboRatio = 0;
|
|
CPUID_PROCESSOR_FREQUENCY_ECX ProcessorFreq;
|
|
///
|
|
/// Get CPU Init Data Hob
|
|
///
|
|
Hob = GetFirstGuidHob (&gCpuInitDataHobGuid);
|
|
if (Hob == NULL) {
|
|
DEBUG ((DEBUG_ERROR, "CPU Data HOB not available\n"));
|
|
ASSERT (Hob != NULL);
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
CpuInitDataHob = (CPU_INIT_DATA_HOB *)((UINTN) Hob + sizeof (EFI_HOB_GUID_TYPE));
|
|
CpuSku = GetCpuSku ();
|
|
|
|
///
|
|
/// Allocated ACPI NVS type memory for Cpu Nvs Configuration.
|
|
///
|
|
Pages = EFI_SIZE_TO_PAGES (sizeof (CPU_NVS_AREA));
|
|
Area = 0xffffffff; // allocate address below 4G.
|
|
|
|
Status = gBS->AllocatePages (
|
|
AllocateMaxAddress,
|
|
EfiACPIMemoryNVS,
|
|
Pages,
|
|
&Area
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
mCpuNvsAreaProtocol.Area = (CPU_NVS_AREA *)(UINTN) Area;
|
|
ZeroMem ((VOID *)mCpuNvsAreaProtocol.Area, sizeof (CPU_NVS_AREA));
|
|
mCpuNvsAreaProtocol.Area->Cpuid = GetCpuFamily() | GetCpuStepping();
|
|
mCpuNvsAreaProtocol.Area->Revision = CPU_NVS_AREA_REVISION;
|
|
|
|
///
|
|
/// Calculate the number of Oc bins supported. Read in MSR 194h FLEX_RATIO bits (19:17)
|
|
///
|
|
FlexRatio.Uint64 = AsmReadMsr64 (MSR_FLEX_RATIO);
|
|
mCpuNvsAreaProtocol.Area->OcBins = (UINT8) FlexRatio.Bits.OcBins;
|
|
|
|
///
|
|
/// Update NVS ASL items.
|
|
///
|
|
|
|
///
|
|
/// Automatic Thermal Reporting for Thermal Management
|
|
///
|
|
if (CpuInitDataHob->EnableAllThermalFunctions) {
|
|
///
|
|
/// Thermal Reporting for Critical trip
|
|
/// MSR 1A2 bits 23:16 define the temperature that this specific processor can
|
|
/// function upto. It is recommended that this value + 5 be used as default Critical trip point
|
|
/// _CRT.
|
|
///
|
|
TempTarget.Uint64 = AsmReadMsr64 (MSR_TEMPERATURE_TARGET);
|
|
MaxRefTemp = (UINT8) TempTarget.Bits.RefTemp;
|
|
mCpuNvsAreaProtocol.Area->AutoCriticalTripPoint = MaxRefTemp + 5;
|
|
|
|
///
|
|
/// Thermal Reporting for Active Thermal Management
|
|
/// It is recommended that the processor specific value in MSR 1A2 bits 15:8
|
|
/// be used as the highest Active trip point i.e. _AC0.
|
|
///
|
|
mCpuNvsAreaProtocol.Area->AutoActiveTripPoint = MaxRefTemp - (UINT8) TempTarget.Bits.FanTempTargetOfst;
|
|
|
|
///
|
|
/// Thermal Reporting for Passive Thermal Management
|
|
/// On all turbo enabled systems, it is recommended that the ACPI _PSV point be
|
|
/// set to a temperature above the Active cooling temperature and Tcc activation
|
|
/// temperature.
|
|
/// If platform embedded controller will issue PECI commands to reduce power as a
|
|
/// passive thermal action, then it is recommended to use the package's max temperature
|
|
/// for passive thermal control.
|
|
///
|
|
mCpuNvsAreaProtocol.Area->AutoPassiveTripPoint = mCpuNvsAreaProtocol.Area->AutoCriticalTripPoint + 3;
|
|
}
|
|
|
|
///
|
|
/// Update the PPM NVS area PPM flags
|
|
///
|
|
mCpuNvsAreaProtocol.Area->PpmFlags = CpuInitDataHob->PpmFlags;
|
|
|
|
///
|
|
/// For U/Y, hard coded latency values are used instead of calculations. Set values here.
|
|
///
|
|
switch (CpuSku) {
|
|
case EnumCpuUlt:
|
|
case EnumCpuUlx:
|
|
case EnumCpuHalo:
|
|
case EnumCpuTrad:
|
|
C6Latency = C6_LATENCY;
|
|
C7Latency = C7_LATENCY;
|
|
C8Latency = C8_LATENCY;
|
|
C9Latency = C9_LATENCY;
|
|
C10Latency = C10_LATENCY;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
///
|
|
/// Update PPM NVRAM Values for C6
|
|
///
|
|
if (mCpuNvsAreaProtocol.Area->PpmFlags & C6_LONG_LATENCY_ENABLE) {
|
|
mCpuNvsAreaProtocol.Area->C6MwaitValue = MWAIT_C6_1;
|
|
} else {
|
|
mCpuNvsAreaProtocol.Area->C6MwaitValue = MWAIT_C6;
|
|
}
|
|
|
|
|
|
///
|
|
/// Update PPM NVRAM Values for C7 - select the C-state supported among- C7 / C7S
|
|
///
|
|
if (mCpuNvsAreaProtocol.Area->PpmFlags & PPM_C7) { // Is C7 supported ?
|
|
if (mCpuNvsAreaProtocol.Area->PpmFlags & C7_LONG_LATENCY_ENABLE) {
|
|
mCpuNvsAreaProtocol.Area->C7MwaitValue = MWAIT_C7_1;
|
|
} else {
|
|
mCpuNvsAreaProtocol.Area->C7MwaitValue = MWAIT_C7;
|
|
}
|
|
}
|
|
if (mCpuNvsAreaProtocol.Area->PpmFlags & PPM_C7S) { // Is C7S supported ?
|
|
if (mCpuNvsAreaProtocol.Area->PpmFlags & C7s_LONG_LATENCY_ENABLE) {
|
|
mCpuNvsAreaProtocol.Area->C7MwaitValue = MWAIT_C7_3;
|
|
} else {
|
|
mCpuNvsAreaProtocol.Area->C7MwaitValue = MWAIT_C7_2;
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Hard coded values are used instead of calculations. Reinitialize here to simplify the code for C6 and C7.
|
|
///
|
|
|
|
if (C6Latency != 0) {
|
|
mCpuNvsAreaProtocol.Area->C6Latency = C6Latency;
|
|
}
|
|
|
|
if (C7Latency != 0) {
|
|
mCpuNvsAreaProtocol.Area->C7Latency = C7Latency;
|
|
}
|
|
///
|
|
/// Update PPM NVRAM Values for CD - select the deepest C-state supported among- C8 / C9 / C10
|
|
///
|
|
if (mCpuNvsAreaProtocol.Area->PpmFlags & PPM_C10) { // C10 supported
|
|
mCpuNvsAreaProtocol.Area->CDIOLevel = PCH_ACPI_LV7;
|
|
mCpuNvsAreaProtocol.Area->CDPowerValue = C10_POWER;
|
|
mCpuNvsAreaProtocol.Area->CDMwaitValue = MWAIT_CD_2;
|
|
if (C10Latency != 0) {
|
|
mCpuNvsAreaProtocol.Area->CDLatency = C10Latency;
|
|
}
|
|
} else if (mCpuNvsAreaProtocol.Area->PpmFlags & PPM_C9) { // C9 supported
|
|
mCpuNvsAreaProtocol.Area->CDIOLevel = PCH_ACPI_LV6;
|
|
mCpuNvsAreaProtocol.Area->CDPowerValue = C9_POWER;
|
|
mCpuNvsAreaProtocol.Area->CDMwaitValue = MWAIT_CD_1;
|
|
if (C9Latency != 0) {
|
|
mCpuNvsAreaProtocol.Area->CDLatency = C9Latency;
|
|
}
|
|
} else if (mCpuNvsAreaProtocol.Area->PpmFlags & PPM_C8) { // C8 supported
|
|
mCpuNvsAreaProtocol.Area->CDIOLevel = PCH_ACPI_LV5;
|
|
mCpuNvsAreaProtocol.Area->CDPowerValue = C8_POWER;
|
|
mCpuNvsAreaProtocol.Area->CDMwaitValue = MWAIT_CD;
|
|
if (C8Latency != 0) {
|
|
mCpuNvsAreaProtocol.Area->CDLatency = C8Latency;
|
|
}
|
|
}
|
|
|
|
if (mCpuNvsAreaProtocol.Area->PpmFlags & PPM_HWP) {
|
|
mCpuNvsAreaProtocol.Area->HwpEnable = 1;
|
|
}
|
|
|
|
mCpuNvsAreaProtocol.Area->CtdpLevelsSupported =CpuInitDataHob->CtdpLevelsSupported; /// ConfigTdp Number Of Levels.
|
|
mCpuNvsAreaProtocol.Area->ConfigTdpBootModeIndex = CpuInitDataHob->ConfigTdpBootModeIndex; /// CTDP Boot Mode Index
|
|
for (Index = 0; Index < 3; Index++) {
|
|
mCpuNvsAreaProtocol.Area->CtdpTar [Index] = CpuInitDataHob->CtdpTar [Index]; /// CTDP Levels TAR
|
|
mCpuNvsAreaProtocol.Area->CtdpPowerLimit1 [Index] = CpuInitDataHob->CtdpPowerLimit1 [Index]; /// CTDP Levels Power Limit1
|
|
mCpuNvsAreaProtocol.Area->CtdpPowerLimit2 [Index] = CpuInitDataHob->CtdpPowerLimit2 [Index]; /// CTDP Levels Power Limit2
|
|
mCpuNvsAreaProtocol.Area->CtdpPowerLimitWindow [Index] =CpuInitDataHob->CtdpPowerLimitWindow [Index]; /// CTDP Levels Power Limit1 Time Window
|
|
mCpuNvsAreaProtocol.Area->CtdpCtc [Index] = CpuInitDataHob->CtdpCtc [Index]; /// CTDP Levels CTC
|
|
mCpuNvsAreaProtocol.Area->CtdpPpc [Index] = CpuInitDataHob->CtdpPpc [Index]; /// CTDP Levels PPC
|
|
}
|
|
mCpuNvsAreaProtocol.Area->EnableItbm = CpuInitDataHob->EnableItbm; /// Enable/Disable Intel Turbo Boost Max Technology 3.0.
|
|
mCpuNvsAreaProtocol.Area->LowestMaxPerf = CpuInitDataHob->LowestMaxPerf; /// Max ratio of the slowest core.
|
|
mCpuNvsAreaProtocol.Area->ConfigurablePpc = CpuInitDataHob->ConfigurablePpc; /// Max ratio of the slowest core.
|
|
mCpuNvsAreaProtocol.Area->IsNominalFrequencySupported = IsNominalFreqSupported ();
|
|
DEBUG ((DEBUG_INFO, "Is Nominal FreqSupported - 0x%x\n", mCpuNvsAreaProtocol.Area->IsNominalFrequencySupported));
|
|
mCpuNvsAreaProtocol.Area->HeteroStatus = IsHeteroCoreSupported ();
|
|
///
|
|
/// Update the Nominal Freq and Scaling factor
|
|
///
|
|
GetScalingFactor (&ScalingFactorSmallCore, &ScalingFactorBigCore);
|
|
MaxNonTurboRatio = MsrGetMaxNonTurboRatio ();
|
|
AsmCpuid (CPUID_PROCESSOR_FREQUENCY, NULL, NULL, &ProcessorFreq.Uint32, NULL);
|
|
|
|
if (CpuInitDataHob->CtdpLevelsSupported > 1 && CpuInitDataHob->ConfigTdpLevel != 0xFF && CpuInitDataHob->ApplyConfigTdp == 1) {
|
|
mCpuNvsAreaProtocol.Area->ScalingFactorSmallCore = (UINT16) ((mSmallCoreNominalPerformance * ScalingFactorSmallCore) / 100);
|
|
mCpuNvsAreaProtocol.Area->ScalingFactorBigCore = (UINT16) ((MsrGetSelectCtdpRatio (CpuInitDataHob->ConfigTdpLevel) * ScalingFactorBigCore) / 100);
|
|
mCpuNvsAreaProtocol.Area->NominalFrequency = (UINT16) (MsrGetSelectCtdpRatio (CpuInitDataHob->ConfigTdpLevel) * ProcessorFreq.Bits.BusFrequency);
|
|
mCpuNvsAreaProtocol.Area->SmallCoreNominalFrequency = (UINT16) (mSmallCoreNominalPerformance * ProcessorFreq.Bits.BusFrequency);
|
|
mCpuNvsAreaProtocol.Area->ReferencePerformanceBigCore = (UINT16) ((MaxNonTurboRatio * ScalingFactorBigCore) / 100);
|
|
mCpuNvsAreaProtocol.Area->ReferencePerformanceSmallCore = (UINT16) ((mSmallCoreNominalPerformance * ScalingFactorSmallCore) / 100);
|
|
} else {
|
|
mCpuNvsAreaProtocol.Area->ScalingFactorSmallCore = (UINT16) ((mSmallCoreNominalPerformance * ScalingFactorSmallCore) / 100);
|
|
mCpuNvsAreaProtocol.Area->ScalingFactorBigCore = (UINT16) ((MaxNonTurboRatio * ScalingFactorBigCore) / 100);
|
|
mCpuNvsAreaProtocol.Area->NominalFrequency = (UINT16) (MaxNonTurboRatio * ProcessorFreq.Bits.BusFrequency);
|
|
mCpuNvsAreaProtocol.Area->SmallCoreNominalFrequency = (UINT16) (mSmallCoreNominalPerformance * ProcessorFreq.Bits.BusFrequency);
|
|
mCpuNvsAreaProtocol.Area->ReferencePerformanceBigCore = 0;
|
|
mCpuNvsAreaProtocol.Area->ReferencePerformanceSmallCore = 0;
|
|
}
|
|
|
|
mCpuNvsAreaProtocol.Area->CoreType = mCoreTypeBitMap;
|
|
DEBUG ((DEBUG_INFO, "Core Info - 0x%x\n", mCoreTypeBitMap));
|
|
for (Index = 0; Index < mNumberOfProcessors; Index++) {
|
|
mCpuNvsAreaProtocol.Area->CoreModule [Index] = mCoreModuleInfo [Index];
|
|
DEBUG ((DEBUG_INFO, "Processor - 0x%x CoreModule - 0x%x\n", Index, mCpuNvsAreaProtocol.Area->CoreModule [Index]));
|
|
}
|
|
///
|
|
/// Install Cpu Power management GlobalNVS Area protocol
|
|
///
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&ImageHandle,
|
|
&gCpuNvsAreaProtocolGuid,
|
|
&mCpuNvsAreaProtocol,
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Initialize BIOS Guard Nvs Area Protocol
|
|
|
|
@param[in] ImageHandle - Image handle of the loaded driver
|
|
|
|
@retval EFI_SUCCESS - thread can be successfully created
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BiosGuardAcpiInit (
|
|
IN EFI_HANDLE ImageHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Pages;
|
|
EFI_PHYSICAL_ADDRESS Address;
|
|
|
|
///
|
|
/// Allocated ACPI NVS type memory for BiosGuard Nvs Configuration.
|
|
///
|
|
Pages = EFI_SIZE_TO_PAGES (sizeof (BIOSGUARD_NVS_AREA));
|
|
Address = 0xffffffff; // allocate address below 4G.
|
|
|
|
Status = gBS->AllocatePages (
|
|
AllocateMaxAddress,
|
|
EfiACPIMemoryNVS,
|
|
Pages,
|
|
&Address
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "EfiACPIMemoryNVS pages for BIOS Guard NVS not Allocated\n"));
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
mBiosGuardNvsAreaProtocol.Area = (BIOSGUARD_NVS_AREA *)(UINTN) Address;
|
|
ZeroMem ((VOID *)mBiosGuardNvsAreaProtocol.Area, sizeof (BIOSGUARD_NVS_AREA));
|
|
|
|
///
|
|
/// Install BIOS Guard NVS Area protocol
|
|
///
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&ImageHandle,
|
|
&gBiosGuardNvsAreaProtocolGuid,
|
|
&mBiosGuardNvsAreaProtocol,
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
} |