-/** @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 - 2018, 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
+CHAR16 *mDependTypeStr[] = {L"None", L"Thread", L"Core", L"Package", L"Invalid" };\r
+CHAR16 *mRegisterTypeStr[] = {L"MSR", L"CR", L"MMIO", L"CACHE", L"SEMAP", L"INVALID" };\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
+ UINT32 Core;\r
+ UINT32 Package;\r
+ UINT32 Thread;\r
+ EFI_CPU_PHYSICAL_LOCATION *Location;\r
+ BOOLEAN *CoresVisited;\r
+ UINTN Index;\r
+ ACPI_CPU_DATA *AcpiCpuData;\r
+ CPU_STATUS_INFORMATION *CpuStatus;\r
+ UINT32 *ValidCoreCountPerPackage;\r
+\r
+ Core = 0;\r
+ Package = 0;\r
+ Thread = 0;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData ();\r
+ CpuFeaturesData->InitOrder = AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus);\r
+ ASSERT (CpuFeaturesData->InitOrder != NULL);\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
+ CpuFeaturesData->NumberOfCpus = (UINT32) NumberOfCpus;\r
+\r
+ AcpiCpuData = GetAcpiCpuData ();\r
+ ASSERT (AcpiCpuData != NULL);\r
+ CpuFeaturesData->AcpiCpuData= AcpiCpuData;\r
+\r
+ CpuStatus = &AcpiCpuData->CpuStatus;\r
+ Location = AllocateZeroPool (sizeof (EFI_CPU_PHYSICAL_LOCATION) * NumberOfCpus);\r
+ ASSERT (Location != NULL);\r
+ AcpiCpuData->ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)Location;\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
+ CopyMem (\r
+ &Location[ProcessorNumber],\r
+ &ProcessorInfoBuffer.Location,\r
+ sizeof (EFI_CPU_PHYSICAL_LOCATION)\r
+ );\r
+\r
+ //\r
+ // Collect CPU package count info.\r
+ //\r
+ if (Package < ProcessorInfoBuffer.Location.Package) {\r
+ Package = ProcessorInfoBuffer.Location.Package;\r
+ }\r
+ //\r
+ // Collect CPU max core count info.\r
+ //\r
+ if (Core < ProcessorInfoBuffer.Location.Core) {\r
+ Core = ProcessorInfoBuffer.Location.Core;\r
+ }\r
+ //\r
+ // Collect CPU max thread count info.\r
+ //\r
+ if (Thread < ProcessorInfoBuffer.Location.Thread) {\r
+ Thread = ProcessorInfoBuffer.Location.Thread;\r
+ }\r
+ }\r
+ CpuStatus->PackageCount = Package + 1;\r
+ CpuStatus->MaxCoreCount = Core + 1;\r
+ CpuStatus->MaxThreadCount = Thread + 1;\r
+ DEBUG ((DEBUG_INFO, "Processor Info: Package: %d, MaxCore : %d, MaxThread: %d\n",\r
+ CpuStatus->PackageCount,\r
+ CpuStatus->MaxCoreCount,\r
+ CpuStatus->MaxThreadCount));\r
+\r
+ //\r
+ // Collect valid core count in each package because not all cores are valid.\r
+ //\r
+ ValidCoreCountPerPackage= AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount);\r
+ ASSERT (ValidCoreCountPerPackage != 0);\r
+ CpuStatus->ValidCoreCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)ValidCoreCountPerPackage;\r
+ CoresVisited = AllocatePool (sizeof (BOOLEAN) * CpuStatus->MaxCoreCount);\r
+ ASSERT (CoresVisited != NULL);\r
+\r
+ for (Index = 0; Index < CpuStatus->PackageCount; Index ++ ) {\r
+ ZeroMem (CoresVisited, sizeof (BOOLEAN) * CpuStatus->MaxCoreCount);\r
+ //\r
+ // Collect valid cores in Current package.\r
+ //\r
+ for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
+ Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;\r
+ if (Location->Package == Index && !CoresVisited[Location->Core] ) {\r
+ //\r
+ // The ValidCores position for Location->Core is valid.\r
+ // The possible values in ValidCores[Index] are 0 or 1.\r
+ // FALSE means no valid threads in this Core.\r
+ // TRUE means have valid threads in this core, no matter the thead count is 1 or more.\r
+ //\r
+ CoresVisited[Location->Core] = TRUE;\r
+ ValidCoreCountPerPackage[Index]++;\r
+ }\r
+ }\r
+ }\r
+ FreePool (CoresVisited);\r
+\r
+ for (Index = 0; Index <= Package; Index++) {\r
+ DEBUG ((DEBUG_INFO, "Package: %d, Valid Core : %d\n", Index, ValidCoreCountPerPackage[Index]));\r
+ }\r
+\r
+ CpuFeaturesData->CpuFlags.SemaphoreCount = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount);\r
+ ASSERT (CpuFeaturesData->CpuFlags.SemaphoreCount != NULL);\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 = (CPU_FEATURES_DATA *)Buffer;\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
+ case Semaphore:\r
+ DEBUG ((\r
+ DebugPrintErrorLevel,\r
+ "Processor: %d: Semaphore: Scope Value: %s\r\n",\r
+ ProcessorNumber,\r
+ mDependTypeStr[MIN ((UINT32)RegisterTableEntry->Value, InvalidDepType)]\r
+ ));\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Get the biggest dependence type.\r
+ PackageDepType > CoreDepType > ThreadDepType > NoneDepType.\r
+\r
+ @param[in] BeforeDep Before dependence type.\r
+ @param[in] AfterDep After dependence type.\r
+ @param[in] NoneNeibBeforeDep Before dependence type for not neighborhood features.\r
+ @param[in] NoneNeibAfterDep After dependence type for not neighborhood features.\r
+\r
+ @retval Return the biggest dependence type.\r
+**/\r
+CPU_FEATURE_DEPENDENCE_TYPE\r
+BiggestDep (\r
+ IN CPU_FEATURE_DEPENDENCE_TYPE BeforeDep,\r
+ IN CPU_FEATURE_DEPENDENCE_TYPE AfterDep,\r
+ IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep,\r
+ IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep\r
+ )\r
+{\r
+ CPU_FEATURE_DEPENDENCE_TYPE Bigger;\r
+\r
+ Bigger = MAX (BeforeDep, AfterDep);\r
+ Bigger = MAX (Bigger, NoneNeibBeforeDep);\r
+ return MAX(Bigger, NoneNeibAfterDep);\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
+ LIST_ENTRY *NextEntry;\r
+ CPU_FEATURES_ENTRY *NextCpuFeatureInOrder;\r
+ BOOLEAN Success;\r
+ CPU_FEATURE_DEPENDENCE_TYPE BeforeDep;\r
+ CPU_FEATURE_DEPENDENCE_TYPE AfterDep;\r
+ CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep;\r
+ CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep;\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
+\r
+ Success = FALSE;\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
+ } else {\r
+ Success = TRUE;\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
+ } else {\r
+ Success = TRUE;\r
+ }\r
+ }\r
+\r
+ if (Success) {\r
+ NextEntry = Entry->ForwardLink;\r
+ if (!IsNull (&CpuInitOrder->OrderList, NextEntry)) {\r
+ NextCpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (NextEntry);\r
+\r
+ //\r
+ // If feature has dependence with the next feature (ONLY care core/package dependency).\r
+ // and feature initialize succeed, add sync semaphere here.\r
+ //\r
+ BeforeDep = DetectFeatureScope (CpuFeatureInOrder, TRUE, NextCpuFeatureInOrder->FeatureMask);\r
+ AfterDep = DetectFeatureScope (NextCpuFeatureInOrder, FALSE, CpuFeatureInOrder->FeatureMask);\r
+ //\r
+ // Check whether next feature has After type dependence with not neighborhood CPU\r
+ // Features in former CPU features.\r
+ //\r
+ NoneNeibAfterDep = DetectNoneNeighborhoodFeatureScope(NextCpuFeatureInOrder, FALSE, &CpuInitOrder->OrderList);\r
+ } else {\r
+ BeforeDep = NoneDepType;\r
+ AfterDep = NoneDepType;\r
+ NoneNeibAfterDep = NoneDepType;\r
+ }\r
+ //\r
+ // Check whether current feature has Before type dependence with none neighborhood\r
+ // CPU features in after Cpu features.\r
+ //\r
+ NoneNeibBeforeDep = DetectNoneNeighborhoodFeatureScope(CpuFeatureInOrder, TRUE, &CpuInitOrder->OrderList);\r
+\r
+ //\r
+ // Get the biggest dependence and add semaphore for it.\r
+ // PackageDepType > CoreDepType > ThreadDepType > NoneDepType.\r
+ //\r
+ BeforeDep = BiggestDep(BeforeDep, AfterDep, NoneNeibBeforeDep, NoneNeibAfterDep);\r
+ if (BeforeDep > ThreadDepType) {\r
+ CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber, Semaphore, 0, BeforeDep);\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
+ Increment semaphore by 1.\r
+\r
+ @param Sem IN: 32-bit unsigned integer\r
+\r
+**/\r
+VOID\r
+LibReleaseSemaphore (\r
+ IN OUT volatile UINT32 *Sem\r
+ )\r
+{\r
+ InterlockedIncrement (Sem);\r
+}\r
+\r
+/**\r
+ Decrement the semaphore by 1 if it is not zero.\r
+\r
+ Performs an atomic decrement operation for semaphore.\r
+ The compare exchange operation must be performed using\r
+ MP safe mechanisms.\r
+\r
+ @param Sem IN: 32-bit unsigned integer\r
+\r
+**/\r
+VOID\r
+LibWaitForSemaphore (\r
+ IN OUT volatile UINT32 *Sem\r
+ )\r
+{\r
+ UINT32 Value;\r
+\r
+ do {\r
+ Value = *Sem;\r
+ } while (Value == 0 ||\r
+ InterlockedCompareExchange32 (\r
+ Sem,\r
+ Value,\r
+ Value - 1\r
+ ) != Value);\r
+}\r
+\r
+/**\r
+ Initialize the CPU registers from a register table.\r
+\r
+ @param[in] RegisterTable The register table for this AP.\r
+ @param[in] ApLocation AP location info for this ap.\r
+ @param[in] CpuStatus CPU status info for this CPU.\r
+ @param[in] CpuFlags Flags data structure used when program the register.\r
+\r
+ @note This service could be called by BSP/APs.\r
+**/\r
+VOID\r
+ProgramProcessorRegister (\r
+ IN CPU_REGISTER_TABLE *RegisterTable,\r
+ IN EFI_CPU_PHYSICAL_LOCATION *ApLocation,\r
+ IN CPU_STATUS_INFORMATION *CpuStatus,\r
+ IN PROGRAM_CPU_REGISTER_FLAGS *CpuFlags\r
+ )\r
+{\r
+ CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
+ UINTN Index;\r
+ UINTN Value;\r
+ CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;\r
+ volatile UINT32 *SemaphorePtr;\r
+ UINT32 FirstThread;\r
+ UINT32 PackageThreadsCount;\r
+ UINT32 CurrentThread;\r
+ UINTN ProcessorIndex;\r
+ UINTN ThreadIndex;\r
+ UINTN ValidThreadCount;\r
+ UINT32 *ValidCoreCountPerPackage;\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
+ DEBUG_CODE_BEGIN ();\r
+ AcquireSpinLock (&CpuFlags->ConsoleLogLock);\r
+ ThreadIndex = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount +\r
+ ApLocation->Core * CpuStatus->MaxThreadCount +\r
+ ApLocation->Thread;\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "Processor = %lu, Entry Index %lu, Type = %s!\n",\r
+ (UINT64)ThreadIndex,\r
+ (UINT64)Index,\r
+ mRegisterTypeStr[MIN ((REGISTER_TYPE)RegisterTableEntry->RegisterType, InvalidReg)]\r
+ ));\r
+ ReleaseSpinLock (&CpuFlags->ConsoleLogLock);\r
+ DEBUG_CODE_END ();\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
+ 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
+ break;\r
+ //\r
+ // MemoryMapped operations\r
+ //\r
+ case MemoryMapped:\r
+ AcquireSpinLock (&CpuFlags->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 (&CpuFlags->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
+ case Semaphore:\r
+ // Semaphore works logic like below:\r
+ //\r
+ // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);\r
+ // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);\r
+ //\r
+ // All threads (T0...Tn) waits in P() line and continues running\r
+ // together.\r
+ //\r
+ //\r
+ // T0 T1 ... Tn\r
+ //\r
+ // V(0...n) V(0...n) ... V(0...n)\r
+ // n * P(0) n * P(1) ... n * P(n)\r
+ //\r
+ SemaphorePtr = CpuFlags->SemaphoreCount;\r
+ switch (RegisterTableEntry->Value) {\r
+ case CoreDepType:\r
+ //\r
+ // Get Offset info for the first thread in the core which current thread belongs to.\r
+ //\r
+ FirstThread = (ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core) * CpuStatus->MaxThreadCount;\r
+ CurrentThread = FirstThread + ApLocation->Thread;\r
+ //\r
+ // First Notify all threads in current Core that this thread has ready.\r
+ //\r
+ for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
+ LibReleaseSemaphore ((UINT32 *) &SemaphorePtr[FirstThread + ProcessorIndex]);\r
+ }\r
+ //\r
+ // Second, check whether all valid threads in current core have ready.\r
+ //\r
+ for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
+ LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
+ }\r
+ break;\r
+\r
+ case PackageDepType:\r
+ ValidCoreCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ValidCoreCountPerPackage;\r
+ //\r
+ // Get Offset info for the first thread in the package which current thread belongs to.\r
+ //\r
+ FirstThread = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount;\r
+ //\r
+ // Get the possible threads count for current package.\r
+ //\r
+ PackageThreadsCount = CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount;\r
+ CurrentThread = FirstThread + CpuStatus->MaxThreadCount * ApLocation->Core + ApLocation->Thread;\r
+ //\r
+ // Get the valid thread count for current package.\r
+ //\r
+ ValidThreadCount = CpuStatus->MaxThreadCount * ValidCoreCountPerPackage[ApLocation->Package];\r
+\r
+ //\r
+ // Different packages may have different valid cores in them. If driver maintail clearly\r
+ // cores number in different packages, the logic will be much complicated.\r
+ // Here driver just simply records the max core number in all packages and use it as expect\r
+ // core number for all packages.\r
+ // In below two steps logic, first current thread will Release semaphore for each thread\r
+ // in current package. Maybe some threads are not valid in this package, but driver don't\r
+ // care. Second, driver will let current thread wait semaphore for all valid threads in\r
+ // current package. Because only the valid threads will do release semaphore for this\r
+ // thread, driver here only need to wait the valid thread count.\r
+ //\r
+\r
+ //\r
+ // First Notify ALL THREADS in current package that this thread has ready.\r
+ //\r
+ for (ProcessorIndex = 0; ProcessorIndex < PackageThreadsCount ; ProcessorIndex ++) {\r
+ LibReleaseSemaphore ((UINT32 *) &SemaphorePtr[FirstThread + ProcessorIndex]);\r
+ }\r
+ //\r
+ // Second, check whether VALID THREADS (not all threads) in current package have ready.\r
+ //\r
+ for (ProcessorIndex = 0; ProcessorIndex < ValidThreadCount; ProcessorIndex ++) {\r
+ LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\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
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+ CPU_REGISTER_TABLE *RegisterTable;\r
+ CPU_REGISTER_TABLE *RegisterTables;\r
+ UINT32 InitApicId;\r
+ UINTN ProcIndex;\r
+ UINTN Index;\r
+ ACPI_CPU_DATA *AcpiCpuData;\r
+\r
+ CpuFeaturesData = (CPU_FEATURES_DATA *) Buffer;\r
+ AcpiCpuData = CpuFeaturesData->AcpiCpuData;\r
+\r
+ RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable;\r
+\r
+ InitApicId = GetInitialApicId ();\r
+ RegisterTable = NULL;\r
+ ProcIndex = (UINTN)-1;\r
+ for (Index = 0; Index < AcpiCpuData->NumberOfCpus; Index++) {\r
+ if (RegisterTables[Index].InitialApicId == InitApicId) {\r
+ RegisterTable = &RegisterTables[Index];\r
+ ProcIndex = Index;\r
+ break;\r
+ }\r
+ }\r
+ ASSERT (RegisterTable != NULL);\r
+\r
+ ProgramProcessorRegister (\r
+ RegisterTable,\r
+ (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->ApLocation + ProcIndex,\r
+ &AcpiCpuData->CpuStatus,\r
+ &CpuFeaturesData->CpuFlags\r
+ );\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
+ CPU_FEATURES_DATA *CpuFeaturesData;\r
+\r
+ CpuFeaturesData = GetCpuFeaturesData();\r
+\r
+ GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);\r
+\r
+ CpuInitDataInitialize (NumberOfCpus);\r
+\r
+ //\r
+ // Wakeup all APs for data collection.\r
+ //\r
+ StartupAPsWorker (CollectProcessorData, NULL);\r
+\r
+ //\r
+ // Collect data on BSP\r
+ //\r
+ CollectProcessorData (CpuFeaturesData);\r
+\r
+ AnalysisProcessorFeatures (NumberOfCpus);\r
+}\r
+\r