]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
UefiCpuPkg/RegisterCpuFeaturesLib: Add logic to support semaphore type.
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / CpuFeaturesInitialize.c
index ba3fb3250fccef850f6dd0f50a7a74693db58f63..7a5939c966dfa2844ed6614182549d8bc7fb53ce 100644 (file)
@@ -14,6 +14,9 @@
 \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
@@ -145,6 +148,19 @@ CpuInitDataInitialize (
   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
@@ -163,6 +179,17 @@ CpuInitDataInitialize (
     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
@@ -175,7 +202,76 @@ CpuInitDataInitialize (
       &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
@@ -310,7 +406,7 @@ CollectProcessorData (
   LIST_ENTRY                           *Entry;\r
   CPU_FEATURES_DATA                    *CpuFeaturesData;\r
 \r
-  CpuFeaturesData = GetCpuFeaturesData ();\r
+  CpuFeaturesData = (CPU_FEATURES_DATA *)Buffer;\r
   ProcessorNumber = GetProcessorIndex ();\r
   CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;\r
   //\r
@@ -416,6 +512,15 @@ DumpRegisterTableOnProcessor (
         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 (RegisterTableEntry->Value, InvalidDepType)]\r
+        ));\r
+      break;\r
+\r
     default:\r
       break;\r
     }\r
@@ -441,6 +546,11 @@ AnalysisProcessorFeatures (
   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
 \r
   CpuFeaturesData = GetCpuFeaturesData ();\r
   CpuFeaturesData->CapabilityPcd = AllocatePool (CpuFeaturesData->BitMaskSize);\r
@@ -517,8 +627,15 @@ AnalysisProcessorFeatures (
     //\r
     CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;\r
     Entry = GetFirstNode (&CpuInitOrder->OrderList);\r
+    NextEntry = Entry->ForwardLink;\r
     while (!IsNull (&CpuInitOrder->OrderList, Entry)) {\r
       CpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
+      if (!IsNull (&CpuInitOrder->OrderList, NextEntry)) {\r
+        NextCpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (NextEntry);\r
+      } else {\r
+        NextCpuFeatureInOrder = NULL;\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
@@ -532,6 +649,8 @@ AnalysisProcessorFeatures (
             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
@@ -542,9 +661,36 @@ AnalysisProcessorFeatures (
             DEBUG ((DEBUG_WARN, "Warning :: Failed to disable Feature: Mask = "));\r
             DumpCpuFeatureMask (CpuFeatureInOrder->FeatureMask);\r
           }\r
+        } else {\r
+          Success = TRUE;\r
         }\r
       }\r
-      Entry = Entry->ForwardLink;\r
+\r
+      if (Success) {\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);\r
+        if (NextCpuFeatureInOrder != NULL) {\r
+          AfterDep  = DetectFeatureScope (NextCpuFeatureInOrder, FALSE);\r
+        } else {\r
+          AfterDep = NoneDepType;\r
+        }\r
+        //\r
+        // Assume only one of the depend is valid.\r
+        //\r
+        ASSERT (!(BeforeDep > ThreadDepType && AfterDep > ThreadDepType));\r
+        if (BeforeDep > ThreadDepType) {\r
+          CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber, Semaphore, 0, BeforeDep);\r
+        }\r
+        if (AfterDep > ThreadDepType) {\r
+          CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber, Semaphore, 0, AfterDep);\r
+        }\r
+      }\r
+\r
+      Entry     = Entry->ForwardLink;\r
+      NextEntry = Entry->ForwardLink;\r
     }\r
 \r
     //\r
@@ -561,27 +707,77 @@ AnalysisProcessorFeatures (
   }\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]  ProcessorNumber  The index of the CPU executing this function.\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 UINTN  ProcessorNumber\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_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
+  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
@@ -592,6 +788,21 @@ ProgramProcessorRegister (
 \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
@@ -654,10 +865,6 @@ ProgramProcessorRegister (
     // 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
@@ -677,20 +884,19 @@ ProgramProcessorRegister (
           RegisterTableEntry->Value\r
           );\r
       }\r
-      ReleaseSpinLock (&CpuFeaturesData->MsrLock);\r
       break;\r
     //\r
     // MemoryMapped operations\r
     //\r
     case MemoryMapped:\r
-      AcquireSpinLock (&CpuFeaturesData->MemoryMappedLock);\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 (&CpuFeaturesData->MemoryMappedLock);\r
+      ReleaseSpinLock (&CpuFlags->MemoryMappedLock);\r
       break;\r
     //\r
     // Enable or disable cache\r
@@ -706,6 +912,90 @@ ProgramProcessorRegister (
       }\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
@@ -724,10 +1014,36 @@ SetProcessorRegister (
   IN OUT VOID            *Buffer\r
   )\r
 {\r
-  UINTN                  ProcessorNumber;\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
-  ProcessorNumber = GetProcessorIndex ();\r
-  ProgramProcessorRegister (ProcessorNumber);\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
+  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
@@ -746,6 +1062,9 @@ CpuFeaturesDetect (
 {\r
   UINTN                  NumberOfCpus;\r
   UINTN                  NumberOfEnabledProcessors;\r
+  CPU_FEATURES_DATA      *CpuFeaturesData;\r
+\r
+  CpuFeaturesData = GetCpuFeaturesData();\r
 \r
   GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);\r
 \r
@@ -754,49 +1073,13 @@ CpuFeaturesDetect (
   //\r
   // Wakeup all APs for data collection.\r
   //\r
-  StartupAPsWorker (CollectProcessorData);\r
+  StartupAPsWorker (CollectProcessorData, NULL);\r
 \r
   //\r
   // Collect data on BSP\r
   //\r
-  CollectProcessorData (NULL);\r
+  CollectProcessorData (CpuFeaturesData);\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