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