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