summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c')
-rw-r--r--UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c1502
1 files changed, 751 insertions, 751 deletions
diff --git a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
index e0fe38c935..5e11b2b21c 100644
--- a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
+++ b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
@@ -1,751 +1,751 @@
-/** @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);
- ASSERT (SupportBitMask != NULL);
- 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);
- ASSERT (SupportBitMask != NULL);
- 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);
- ASSERT (InitOrder->FeaturesSupportedMask != NULL);
- 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: %lx, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
- ProcessorNumber,
- RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32),
- 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);
- ASSERT (CpuFeaturesData->CapabilityPcds != NULL);
- 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);
- ASSERT (CpuFeaturesData->SettingPcds != NULL);
- 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);
- ASSERT (CpuFeatureInOrder != NULL);
- 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 (
- (UINTN)(RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32)),
- 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);
- }
-}
+/** @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);
+ ASSERT (SupportBitMask != NULL);
+ 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);
+ ASSERT (SupportBitMask != NULL);
+ 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);
+ ASSERT (InitOrder->FeaturesSupportedMask != NULL);
+ 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: %lx, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
+ ProcessorNumber,
+ RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32),
+ 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);
+ ASSERT (CpuFeaturesData->CapabilityPcds != NULL);
+ 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);
+ ASSERT (CpuFeaturesData->SettingPcds != NULL);
+ 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);
+ ASSERT (CpuFeatureInOrder != NULL);
+ 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 (
+ (UINTN)(RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32)),
+ 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);
+ }
+}