UefiCpuPkg: Add PEI/DXE Register CPU Features Library instances
PEI Register CPU Features Library instance is used to register/manager/program CPU features on PEI phase. DXE Register CPU Features Library instance is used to register/manager/program CPU features on DXE phase. v2: Format debug messages. v3: Trim white space at end of line. v4: Remove unused local variable. Cc: Feng Tian <feng.tian@intel.com> Cc: Michael Kinney <michael.d.kinney@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com>
This commit is contained in:
@@ -0,0 +1,745 @@
|
||||
/** @file
|
||||
CPU Features Initialize functions.
|
||||
|
||||
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "RegisterCpuFeatures.h"
|
||||
|
||||
/**
|
||||
Worker function to save PcdCpuFeaturesCapability.
|
||||
|
||||
@param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
|
||||
*/
|
||||
VOID
|
||||
SetCapabilityPcd (
|
||||
IN UINT8 *SupportedFeatureMask
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN BitMaskSize;
|
||||
|
||||
BitMaskSize = PcdGetSize (PcdCpuFeaturesCapability);
|
||||
Status = PcdSetPtrS (PcdCpuFeaturesCapability, &BitMaskSize, SupportedFeatureMask);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
/**
|
||||
Worker function to save PcdCpuFeaturesSetting.
|
||||
|
||||
@param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
|
||||
**/
|
||||
VOID
|
||||
SetSettingPcd (
|
||||
IN UINT8 *SupportedFeatureMask
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN BitMaskSize;
|
||||
|
||||
BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);
|
||||
Status = PcdSetPtrS (PcdCpuFeaturesSetting, &BitMaskSize, SupportedFeatureMask);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
/**
|
||||
Worker function to get PcdCpuFeaturesSupport.
|
||||
|
||||
@return The pointer to CPU feature bits mask buffer.
|
||||
**/
|
||||
UINT8 *
|
||||
GetSupportPcds (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN BitMaskSize;
|
||||
UINT8 *SupportBitMask;
|
||||
|
||||
BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
|
||||
SupportBitMask = AllocateZeroPool (BitMaskSize);
|
||||
SupportBitMask = (UINT8 *) PcdGetPtr (PcdCpuFeaturesSupport);
|
||||
|
||||
return SupportBitMask;
|
||||
}
|
||||
|
||||
/**
|
||||
Worker function to get PcdCpuFeaturesUserConfiguration.
|
||||
|
||||
@return The pointer to CPU feature bits mask buffer.
|
||||
**/
|
||||
UINT8 *
|
||||
GetConfigurationPcds (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN BitMaskSize;
|
||||
UINT8 *SupportBitMask;
|
||||
|
||||
BitMaskSize = PcdGetSize (PcdCpuFeaturesUserConfiguration);
|
||||
SupportBitMask = AllocateZeroPool (BitMaskSize);
|
||||
SupportBitMask = (UINT8 *) PcdGetPtr (PcdCpuFeaturesUserConfiguration);
|
||||
|
||||
return SupportBitMask;
|
||||
}
|
||||
|
||||
/**
|
||||
Collects CPU type and feature information.
|
||||
|
||||
@param[in, out] CpuInfo The pointer to CPU feature information
|
||||
**/
|
||||
VOID
|
||||
FillProcessorInfo (
|
||||
IN OUT REGISTER_CPU_FEATURE_INFORMATION *CpuInfo
|
||||
)
|
||||
{
|
||||
CPUID_VERSION_INFO_EAX Eax;
|
||||
CPUID_VERSION_INFO_ECX Ecx;
|
||||
CPUID_VERSION_INFO_EDX Edx;
|
||||
UINT32 DisplayedFamily;
|
||||
UINT32 DisplayedModel;
|
||||
|
||||
AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, &Ecx.Uint32, &Edx.Uint32);
|
||||
|
||||
DisplayedFamily = Eax.Bits.FamilyId;
|
||||
if (Eax.Bits.FamilyId == 0x0F) {
|
||||
DisplayedFamily |= (Eax.Bits.ExtendedFamilyId << 4);
|
||||
}
|
||||
|
||||
DisplayedModel = Eax.Bits.Model;
|
||||
if (Eax.Bits.FamilyId == 0x06 || Eax.Bits.FamilyId == 0x0f) {
|
||||
DisplayedModel |= (Eax.Bits.ExtendedModelId << 4);
|
||||
}
|
||||
|
||||
CpuInfo->DisplayFamily = DisplayedFamily;
|
||||
CpuInfo->DisplayModel = DisplayedModel;
|
||||
CpuInfo->SteppingId = Eax.Bits.SteppingId;
|
||||
CpuInfo->ProcessorType = Eax.Bits.ProcessorType;
|
||||
CpuInfo->CpuIdVersionInfoEcx.Uint32 = Ecx.Uint32;
|
||||
CpuInfo->CpuIdVersionInfoEdx.Uint32 = Edx.Uint32;
|
||||
}
|
||||
|
||||
/**
|
||||
Prepares for private data used for CPU features.
|
||||
|
||||
@param[in] NumberOfCpus Number of processor in system
|
||||
**/
|
||||
VOID
|
||||
CpuInitDataInitialize (
|
||||
IN UINTN NumberOfCpus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN ProcessorNumber;
|
||||
EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
|
||||
CPU_FEATURES_ENTRY *CpuFeature;
|
||||
CPU_FEATURES_INIT_ORDER *InitOrder;
|
||||
CPU_FEATURES_DATA *CpuFeaturesData;
|
||||
LIST_ENTRY *Entry;
|
||||
|
||||
CpuFeaturesData = GetCpuFeaturesData ();
|
||||
CpuFeaturesData->InitOrder = AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus);
|
||||
ASSERT (CpuFeaturesData->InitOrder != NULL);
|
||||
CpuFeaturesData->BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
|
||||
|
||||
//
|
||||
// Collect CPU Features information
|
||||
//
|
||||
Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
|
||||
while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
|
||||
CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
|
||||
ASSERT (CpuFeature->InitializeFunc != NULL);
|
||||
if (CpuFeature->GetConfigDataFunc != NULL) {
|
||||
CpuFeature->ConfigData = CpuFeature->GetConfigDataFunc (NumberOfCpus);
|
||||
}
|
||||
Entry = Entry->ForwardLink;
|
||||
}
|
||||
|
||||
for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
|
||||
InitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];
|
||||
InitOrder->FeaturesSupportedMask = AllocateZeroPool (CpuFeaturesData->BitMaskSize);
|
||||
InitializeListHead (&InitOrder->OrderList);
|
||||
Status = GetProcessorInformation (ProcessorNumber, &ProcessorInfoBuffer);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
CopyMem (
|
||||
&InitOrder->CpuInfo.ProcessorInfo,
|
||||
&ProcessorInfoBuffer,
|
||||
sizeof (EFI_PROCESSOR_INFORMATION)
|
||||
);
|
||||
}
|
||||
//
|
||||
// Get support and configuration PCDs
|
||||
//
|
||||
CpuFeaturesData->SupportPcds = GetSupportPcds ();
|
||||
CpuFeaturesData->ConfigurationPcds = GetConfigurationPcds ();
|
||||
}
|
||||
|
||||
/**
|
||||
Worker function to do OR operation on CPU feature supported bits mask buffer.
|
||||
|
||||
@param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
|
||||
@param[in] OrFeatureBitMask The feature bit mask to do OR operation
|
||||
**/
|
||||
VOID
|
||||
SupportedMaskOr (
|
||||
IN UINT8 *SupportedFeatureMask,
|
||||
IN UINT8 *OrFeatureBitMask
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINTN BitMaskSize;
|
||||
UINT8 *Data1;
|
||||
UINT8 *Data2;
|
||||
|
||||
BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
|
||||
Data1 = SupportedFeatureMask;
|
||||
Data2 = OrFeatureBitMask;
|
||||
for (Index = 0; Index < BitMaskSize; Index++) {
|
||||
*(Data1++) |= *(Data2++);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Worker function to do AND operation on CPU feature supported bits mask buffer.
|
||||
|
||||
@param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
|
||||
@param[in] AndFeatureBitMask The feature bit mask to do AND operation
|
||||
**/
|
||||
VOID
|
||||
SupportedMaskAnd (
|
||||
IN UINT8 *SupportedFeatureMask,
|
||||
IN UINT8 *AndFeatureBitMask
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINTN BitMaskSize;
|
||||
UINT8 *Data1;
|
||||
UINT8 *Data2;
|
||||
|
||||
BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
|
||||
Data1 = SupportedFeatureMask;
|
||||
Data2 = AndFeatureBitMask;
|
||||
for (Index = 0; Index < BitMaskSize; Index++) {
|
||||
*(Data1++) &= *(Data2++);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Worker function to check if the compared CPU feature set in the CPU feature
|
||||
supported bits mask buffer.
|
||||
|
||||
@param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
|
||||
@param[in] ComparedFeatureBitMask The feature bit mask to be compared
|
||||
|
||||
@retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
|
||||
mask buffer.
|
||||
@retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
|
||||
mask buffer.
|
||||
**/
|
||||
BOOLEAN
|
||||
IsBitMaskMatch (
|
||||
IN UINT8 *SupportedFeatureMask,
|
||||
IN UINT8 *ComparedFeatureBitMask
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINTN BitMaskSize;
|
||||
UINT8 *Data1;
|
||||
UINT8 *Data2;
|
||||
|
||||
BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
|
||||
|
||||
Data1 = SupportedFeatureMask;
|
||||
Data2 = ComparedFeatureBitMask;
|
||||
for (Index = 0; Index < BitMaskSize; Index++) {
|
||||
if (((*(Data1++)) & (*(Data2++))) != 0) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Collects processor data for calling processor.
|
||||
|
||||
@param[in,out] Buffer The pointer to private data buffer.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
CollectProcessorData (
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
UINTN ProcessorNumber;
|
||||
CPU_FEATURES_ENTRY *CpuFeature;
|
||||
REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;
|
||||
LIST_ENTRY *Entry;
|
||||
CPU_FEATURES_DATA *CpuFeaturesData;
|
||||
|
||||
CpuFeaturesData = GetCpuFeaturesData ();
|
||||
ProcessorNumber = GetProcessorIndex ();
|
||||
CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;
|
||||
//
|
||||
// collect processor information
|
||||
//
|
||||
FillProcessorInfo (CpuInfo);
|
||||
Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
|
||||
while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
|
||||
CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
|
||||
if (IsBitMaskMatch (CpuFeaturesData->SupportPcds, CpuFeature->FeatureMask)) {
|
||||
if (CpuFeature->SupportFunc == NULL) {
|
||||
//
|
||||
// If SupportFunc is NULL, then the feature is supported.
|
||||
//
|
||||
SupportedMaskOr (
|
||||
CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,
|
||||
CpuFeature->FeatureMask
|
||||
);
|
||||
} else if (CpuFeature->SupportFunc (ProcessorNumber, CpuInfo, CpuFeature->ConfigData)) {
|
||||
SupportedMaskOr (
|
||||
CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,
|
||||
CpuFeature->FeatureMask
|
||||
);
|
||||
}
|
||||
}
|
||||
Entry = Entry->ForwardLink;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Dump the contents of a CPU register table.
|
||||
|
||||
@param[in] ProcessorNumber The index of the CPU to show the register table contents
|
||||
|
||||
@note This service could be called by BSP only.
|
||||
**/
|
||||
VOID
|
||||
DumpRegisterTableOnProcessor (
|
||||
IN UINTN ProcessorNumber
|
||||
)
|
||||
{
|
||||
CPU_FEATURES_DATA *CpuFeaturesData;
|
||||
UINTN FeatureIndex;
|
||||
CPU_REGISTER_TABLE *RegisterTable;
|
||||
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
|
||||
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;
|
||||
UINT32 DebugPrintErrorLevel;
|
||||
|
||||
DebugPrintErrorLevel = (ProcessorNumber == 0) ? DEBUG_INFO : DEBUG_VERBOSE;
|
||||
CpuFeaturesData = GetCpuFeaturesData ();
|
||||
//
|
||||
// Debug information
|
||||
//
|
||||
RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
|
||||
DEBUG ((DebugPrintErrorLevel, "RegisterTable->TableLength = %d\n", RegisterTable->TableLength));
|
||||
|
||||
RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
|
||||
|
||||
for (FeatureIndex = 0; FeatureIndex < RegisterTable->TableLength; FeatureIndex++) {
|
||||
RegisterTableEntry = &RegisterTableEntryHead[FeatureIndex];
|
||||
switch (RegisterTableEntry->RegisterType) {
|
||||
case Msr:
|
||||
DEBUG ((
|
||||
DebugPrintErrorLevel,
|
||||
"Processor: %d: MSR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
|
||||
ProcessorNumber,
|
||||
RegisterTableEntry->Index,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitLength,
|
||||
RegisterTableEntry->Value
|
||||
));
|
||||
break;
|
||||
case ControlRegister:
|
||||
DEBUG ((
|
||||
DebugPrintErrorLevel,
|
||||
"Processor: %d: CR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
|
||||
ProcessorNumber,
|
||||
RegisterTableEntry->Index,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitLength,
|
||||
RegisterTableEntry->Value
|
||||
));
|
||||
break;
|
||||
case MemoryMapped:
|
||||
DEBUG ((
|
||||
DebugPrintErrorLevel,
|
||||
"Processor: %d: MMIO: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
|
||||
ProcessorNumber,
|
||||
RegisterTableEntry->Index,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitLength,
|
||||
RegisterTableEntry->Value
|
||||
));
|
||||
break;
|
||||
case CacheControl:
|
||||
DEBUG ((
|
||||
DebugPrintErrorLevel,
|
||||
"Processor: %d: CACHE: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
|
||||
ProcessorNumber,
|
||||
RegisterTableEntry->Index,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitLength,
|
||||
RegisterTableEntry->Value
|
||||
));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Analysis register CPU features on each processor and save CPU setting in CPU register table.
|
||||
|
||||
@param[in] NumberOfCpus Number of processor in system
|
||||
|
||||
**/
|
||||
VOID
|
||||
AnalysisProcessorFeatures (
|
||||
IN UINTN NumberOfCpus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN ProcessorNumber;
|
||||
CPU_FEATURES_ENTRY *CpuFeature;
|
||||
CPU_FEATURES_ENTRY *CpuFeatureInOrder;
|
||||
CPU_FEATURES_INIT_ORDER *CpuInitOrder;
|
||||
REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;
|
||||
LIST_ENTRY *Entry;
|
||||
CPU_FEATURES_DATA *CpuFeaturesData;
|
||||
|
||||
CpuFeaturesData = GetCpuFeaturesData ();
|
||||
CpuFeaturesData->CapabilityPcds = AllocatePool (CpuFeaturesData->BitMaskSize);
|
||||
SetMem (CpuFeaturesData->CapabilityPcds, CpuFeaturesData->BitMaskSize, 0xFF);
|
||||
for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
|
||||
CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];
|
||||
//
|
||||
// Calculate the last capability on all processors
|
||||
//
|
||||
SupportedMaskAnd (CpuFeaturesData->CapabilityPcds, CpuInitOrder->FeaturesSupportedMask);
|
||||
}
|
||||
//
|
||||
// Calculate the last setting
|
||||
//
|
||||
|
||||
CpuFeaturesData->SettingPcds = AllocateCopyPool (CpuFeaturesData->BitMaskSize, CpuFeaturesData->CapabilityPcds);
|
||||
SupportedMaskAnd (CpuFeaturesData->SettingPcds, CpuFeaturesData->ConfigurationPcds);
|
||||
|
||||
//
|
||||
// Save PCDs and display CPU PCDs
|
||||
//
|
||||
SetCapabilityPcd (CpuFeaturesData->CapabilityPcds);
|
||||
SetSettingPcd (CpuFeaturesData->SettingPcds);
|
||||
|
||||
//
|
||||
// Dump the last CPU feature list
|
||||
//
|
||||
DEBUG_CODE (
|
||||
DEBUG ((DEBUG_INFO, "Last CPU features list...\n"));
|
||||
Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
|
||||
while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
|
||||
CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
|
||||
if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcds)) {
|
||||
if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->SettingPcds)) {
|
||||
DEBUG ((DEBUG_INFO, "[Enable ] "));
|
||||
} else {
|
||||
DEBUG ((DEBUG_INFO, "[Disable ] "));
|
||||
}
|
||||
} else {
|
||||
DEBUG ((DEBUG_INFO, "[Unsupport] "));
|
||||
}
|
||||
DumpCpuFeature (CpuFeature);
|
||||
Entry = Entry->ForwardLink;
|
||||
}
|
||||
DEBUG ((DEBUG_INFO, "PcdCpuFeaturesSupport:\n"));
|
||||
DumpCpuFeatureMask (CpuFeaturesData->SupportPcds);
|
||||
DEBUG ((DEBUG_INFO, "PcdCpuFeaturesUserConfiguration:\n"));
|
||||
DumpCpuFeatureMask (CpuFeaturesData->ConfigurationPcds);
|
||||
DEBUG ((DEBUG_INFO, "PcdCpuFeaturesCapability:\n"));
|
||||
DumpCpuFeatureMask (CpuFeaturesData->CapabilityPcds);
|
||||
DEBUG ((DEBUG_INFO, "PcdCpuFeaturesSetting:\n"));
|
||||
DumpCpuFeatureMask (CpuFeaturesData->SettingPcds);
|
||||
);
|
||||
|
||||
for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
|
||||
CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];
|
||||
Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
|
||||
while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
|
||||
//
|
||||
// Insert each feature into processor's order list
|
||||
//
|
||||
CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
|
||||
if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcds)) {
|
||||
CpuFeatureInOrder = AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY), CpuFeature);
|
||||
InsertTailList (&CpuInitOrder->OrderList, &CpuFeatureInOrder->Link);
|
||||
}
|
||||
Entry = Entry->ForwardLink;
|
||||
}
|
||||
//
|
||||
// Go through ordered feature list to initialize CPU features
|
||||
//
|
||||
CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;
|
||||
Entry = GetFirstNode (&CpuInitOrder->OrderList);
|
||||
while (!IsNull (&CpuInitOrder->OrderList, Entry)) {
|
||||
CpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
|
||||
if (IsBitMaskMatch (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->SettingPcds)) {
|
||||
Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, TRUE);
|
||||
} else {
|
||||
Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, FALSE);
|
||||
}
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
Entry = Entry->ForwardLink;
|
||||
}
|
||||
//
|
||||
// Dump the RegisterTable
|
||||
//
|
||||
DumpRegisterTableOnProcessor (ProcessorNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the CPU registers from a register table.
|
||||
|
||||
@param[in] ProcessorNumber The index of the CPU executing this function.
|
||||
|
||||
@note This service could be called by BSP/APs.
|
||||
**/
|
||||
VOID
|
||||
ProgramProcessorRegister (
|
||||
IN UINTN ProcessorNumber
|
||||
)
|
||||
{
|
||||
CPU_FEATURES_DATA *CpuFeaturesData;
|
||||
CPU_REGISTER_TABLE *RegisterTable;
|
||||
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
|
||||
UINTN Index;
|
||||
UINTN Value;
|
||||
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;
|
||||
|
||||
CpuFeaturesData = GetCpuFeaturesData ();
|
||||
RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
|
||||
|
||||
//
|
||||
// Traverse Register Table of this logical processor
|
||||
//
|
||||
RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
|
||||
|
||||
for (Index = 0; Index < RegisterTable->TableLength; Index++) {
|
||||
|
||||
RegisterTableEntry = &RegisterTableEntryHead[Index];
|
||||
|
||||
//
|
||||
// Check the type of specified register
|
||||
//
|
||||
switch (RegisterTableEntry->RegisterType) {
|
||||
//
|
||||
// The specified register is Control Register
|
||||
//
|
||||
case ControlRegister:
|
||||
switch (RegisterTableEntry->Index) {
|
||||
case 0:
|
||||
Value = AsmReadCr0 ();
|
||||
Value = (UINTN) BitFieldWrite64 (
|
||||
Value,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
RegisterTableEntry->Value
|
||||
);
|
||||
AsmWriteCr0 (Value);
|
||||
break;
|
||||
case 2:
|
||||
Value = AsmReadCr2 ();
|
||||
Value = (UINTN) BitFieldWrite64 (
|
||||
Value,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
RegisterTableEntry->Value
|
||||
);
|
||||
AsmWriteCr2 (Value);
|
||||
break;
|
||||
case 3:
|
||||
Value = AsmReadCr3 ();
|
||||
Value = (UINTN) BitFieldWrite64 (
|
||||
Value,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
RegisterTableEntry->Value
|
||||
);
|
||||
AsmWriteCr3 (Value);
|
||||
break;
|
||||
case 4:
|
||||
Value = AsmReadCr4 ();
|
||||
Value = (UINTN) BitFieldWrite64 (
|
||||
Value,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
RegisterTableEntry->Value
|
||||
);
|
||||
AsmWriteCr4 (Value);
|
||||
break;
|
||||
case 8:
|
||||
//
|
||||
// Do we need to support CR8?
|
||||
//
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//
|
||||
// The specified register is Model Specific Register
|
||||
//
|
||||
case Msr:
|
||||
//
|
||||
// Get lock to avoid Package/Core scope MSRs programming issue in parallel execution mode
|
||||
//
|
||||
AcquireSpinLock (&CpuFeaturesData->MsrLock);
|
||||
if (RegisterTableEntry->ValidBitLength >= 64) {
|
||||
//
|
||||
// If length is not less than 64 bits, then directly write without reading
|
||||
//
|
||||
AsmWriteMsr64 (
|
||||
RegisterTableEntry->Index,
|
||||
RegisterTableEntry->Value
|
||||
);
|
||||
} else {
|
||||
//
|
||||
// Set the bit section according to bit start and length
|
||||
//
|
||||
AsmMsrBitFieldWrite64 (
|
||||
RegisterTableEntry->Index,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
RegisterTableEntry->Value
|
||||
);
|
||||
}
|
||||
ReleaseSpinLock (&CpuFeaturesData->MsrLock);
|
||||
break;
|
||||
//
|
||||
// MemoryMapped operations
|
||||
//
|
||||
case MemoryMapped:
|
||||
AcquireSpinLock (&CpuFeaturesData->MemoryMappedLock);
|
||||
MmioBitFieldWrite32 (
|
||||
RegisterTableEntry->Index,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
(UINT32)RegisterTableEntry->Value
|
||||
);
|
||||
ReleaseSpinLock (&CpuFeaturesData->MemoryMappedLock);
|
||||
break;
|
||||
//
|
||||
// Enable or disable cache
|
||||
//
|
||||
case CacheControl:
|
||||
//
|
||||
// If value of the entry is 0, then disable cache. Otherwise, enable cache.
|
||||
//
|
||||
if (RegisterTableEntry->Value == 0) {
|
||||
AsmDisableCache ();
|
||||
} else {
|
||||
AsmEnableCache ();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Programs registers for the calling processor.
|
||||
|
||||
@param[in,out] Buffer The pointer to private data buffer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SetProcessorRegister (
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
UINTN ProcessorNumber;
|
||||
|
||||
ProcessorNumber = GetProcessorIndex ();
|
||||
ProgramProcessorRegister (ProcessorNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
Performs CPU features detection.
|
||||
|
||||
This service will invoke MP service to check CPU features'
|
||||
capabilities on BSP/APs.
|
||||
|
||||
@note This service could be called by BSP only.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
CpuFeaturesDetect (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN NumberOfCpus;
|
||||
UINTN NumberOfEnabledProcessors;
|
||||
|
||||
GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);
|
||||
|
||||
CpuInitDataInitialize (NumberOfCpus);
|
||||
|
||||
//
|
||||
// Wakeup all APs for data collection.
|
||||
//
|
||||
StartupAPsWorker (CollectProcessorData);
|
||||
|
||||
//
|
||||
// Collect data on BSP
|
||||
//
|
||||
CollectProcessorData (NULL);
|
||||
|
||||
AnalysisProcessorFeatures (NumberOfCpus);
|
||||
}
|
||||
|
||||
/**
|
||||
Performs CPU features Initialization.
|
||||
|
||||
This service will invoke MP service to perform CPU features
|
||||
initialization on BSP/APs per user configuration.
|
||||
|
||||
@note This service could be called by BSP only.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
CpuFeaturesInitialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
CPU_FEATURES_DATA *CpuFeaturesData;
|
||||
UINTN OldBspNumber;
|
||||
|
||||
CpuFeaturesData = GetCpuFeaturesData ();
|
||||
|
||||
OldBspNumber = GetProcessorIndex();
|
||||
CpuFeaturesData->BspNumber = OldBspNumber;
|
||||
//
|
||||
// Wakeup all APs for programming.
|
||||
//
|
||||
StartupAPsWorker (SetProcessorRegister);
|
||||
//
|
||||
// Programming BSP
|
||||
//
|
||||
SetProcessorRegister (NULL);
|
||||
//
|
||||
// Switch to new BSP if required
|
||||
//
|
||||
if (CpuFeaturesData->BspNumber != OldBspNumber) {
|
||||
SwitchNewBsp (CpuFeaturesData->BspNumber);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user