]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
UefiCpuPkg/RegisterCpuFeaturesLib: Supports test then write new value logic.
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / CpuFeaturesInitialize.c
index 9ce68302762850b3402a0b550c427f0ce683ee64..0a4fcff033a3cb30641cb061321b3c776ba512c1 100644 (file)
@@ -2,39 +2,28 @@
   CPU Features Initialize functions.\r
 \r
   Copyright (c) 2017 - 2019, 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
+  SPDX-License-Identifier: BSD-2-Clause-Patent\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
-  @param[in]  FeatureMaskSize       CPU feature bits mask buffer size.\r
+  @param[in]  BitMaskSize           CPU feature bits mask buffer size.\r
 \r
 **/\r
 VOID\r
 SetCapabilityPcd (\r
   IN UINT8               *SupportedFeatureMask,\r
-  IN UINT32              FeatureMaskSize\r
+  IN UINTN               BitMaskSize\r
   )\r
 {\r
   EFI_STATUS             Status;\r
-  UINTN                  BitMaskSize;\r
-\r
-  BitMaskSize = PcdGetSize (PcdCpuFeaturesCapability);\r
-  ASSERT (FeatureMaskSize == BitMaskSize);\r
 \r
   Status = PcdSetPtrS (PcdCpuFeaturesCapability, &BitMaskSize, SupportedFeatureMask);\r
   ASSERT_EFI_ERROR (Status);\r
@@ -44,16 +33,16 @@ SetCapabilityPcd (
   Worker function to save PcdCpuFeaturesSetting.\r
 \r
   @param[in]  SupportedFeatureMask  The pointer to CPU feature bits mask buffer\r
+  @param[in]  BitMaskSize           CPU feature bits mask buffer size.\r
 **/\r
 VOID\r
 SetSettingPcd (\r
-  IN UINT8               *SupportedFeatureMask\r
+  IN UINT8               *SupportedFeatureMask,\r
+  IN UINTN               BitMaskSize\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
@@ -245,11 +234,6 @@ CpuInitDataInitialize (
   ASSERT (CpuFeaturesData->CpuFlags.CoreSemaphoreCount != NULL);\r
   CpuFeaturesData->CpuFlags.PackageSemaphoreCount = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount);\r
   ASSERT (CpuFeaturesData->CpuFlags.PackageSemaphoreCount != NULL);\r
-\r
-  //\r
-  // Get support and configuration PCDs\r
-  //\r
-  CpuFeaturesData->SupportPcd       = GetSupportPcd ();\r
 }\r
 \r
 /**\r
@@ -257,19 +241,20 @@ CpuInitDataInitialize (
 \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
+  @param[in]  BitMaskSize           The CPU feature bits mask buffer size.\r
+\r
 **/\r
 VOID\r
 SupportedMaskOr (\r
   IN UINT8               *SupportedFeatureMask,\r
-  IN UINT8               *OrFeatureBitMask\r
+  IN UINT8               *OrFeatureBitMask,\r
+  IN UINT32              BitMaskSize\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
@@ -282,19 +267,20 @@ SupportedMaskOr (
 \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
+  @param[in]  BitMaskSize           CPU feature bits mask buffer size.\r
+\r
 **/\r
 VOID\r
 SupportedMaskAnd (\r
   IN       UINT8               *SupportedFeatureMask,\r
-  IN CONST UINT8               *AndFeatureBitMask\r
+  IN CONST UINT8               *AndFeatureBitMask,\r
+  IN       UINT32              BitMaskSize\r
   )\r
 {\r
   UINTN                  Index;\r
-  UINTN                  BitMaskSize;\r
   UINT8                  *Data1;\r
   CONST UINT8            *Data2;\r
 \r
-  BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
   Data1 = SupportedFeatureMask;\r
   Data2 = AndFeatureBitMask;\r
   for (Index = 0; Index < BitMaskSize; Index++) {\r
@@ -307,19 +293,19 @@ SupportedMaskAnd (
 \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
+  @param[in]  BitMaskSize           CPU feature bits mask buffer size.\r
 **/\r
 VOID\r
 SupportedMaskCleanBit (\r
   IN UINT8               *SupportedFeatureMask,\r
-  IN UINT8               *AndFeatureBitMask\r
+  IN UINT8               *AndFeatureBitMask,\r
+  IN UINT32              BitMaskSize\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
@@ -333,6 +319,7 @@ SupportedMaskCleanBit (
 \r
   @param[in]  SupportedFeatureMask   The pointer to CPU feature bits mask buffer\r
   @param[in]  ComparedFeatureBitMask The feature bit mask to be compared\r
+  @param[in]  BitMaskSize            CPU feature bits mask buffer size.\r
 \r
   @retval TRUE   The ComparedFeatureBitMask is set in CPU feature supported bits\r
                  mask buffer.\r
@@ -342,16 +329,14 @@ SupportedMaskCleanBit (
 BOOLEAN\r
 IsBitMaskMatch (\r
   IN UINT8               *SupportedFeatureMask,\r
-  IN UINT8               *ComparedFeatureBitMask\r
+  IN UINT8               *ComparedFeatureBitMask,\r
+  IN UINT32              BitMaskSize\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
@@ -389,21 +374,21 @@ CollectProcessorData (
   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
+    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
+        CpuFeaturesData->BitMaskSize\r
+        );\r
+    } else if (CpuFeature->SupportFunc (ProcessorNumber, CpuInfo, CpuFeature->ConfigData)) {\r
+      SupportedMaskOr (\r
+        CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,\r
+        CpuFeature->FeatureMask,\r
+        CpuFeaturesData->BitMaskSize\r
+        );\r
     }\r
     Entry = Entry->ForwardLink;\r
   }\r
@@ -567,14 +552,14 @@ AnalysisProcessorFeatures (
     //\r
     // Calculate the last capability on all processors\r
     //\r
-    SupportedMaskAnd (CpuFeaturesData->CapabilityPcd, CpuInitOrder->FeaturesSupportedMask);\r
+    SupportedMaskAnd (CpuFeaturesData->CapabilityPcd, CpuInitOrder->FeaturesSupportedMask, CpuFeaturesData->BitMaskSize);\r
   }\r
   //\r
   // Calculate the last setting\r
   //\r
   CpuFeaturesData->SettingPcd = AllocateCopyPool (CpuFeaturesData->BitMaskSize, CpuFeaturesData->CapabilityPcd);\r
   ASSERT (CpuFeaturesData->SettingPcd != NULL);\r
-  SupportedMaskAnd (CpuFeaturesData->SettingPcd, PcdGetPtr (PcdCpuFeaturesSetting));\r
+  SupportedMaskAnd (CpuFeaturesData->SettingPcd, PcdGetPtr (PcdCpuFeaturesSetting), CpuFeaturesData->BitMaskSize);\r
 \r
   //\r
   // Dump the last CPU feature list\r
@@ -584,8 +569,8 @@ AnalysisProcessorFeatures (
     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
+      if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcd, CpuFeaturesData->BitMaskSize)) {\r
+        if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->SettingPcd, CpuFeaturesData->BitMaskSize)) {\r
           DEBUG ((DEBUG_INFO, "[Enable   ] "));\r
         } else {\r
           DEBUG ((DEBUG_INFO, "[Disable  ] "));\r
@@ -593,24 +578,22 @@ AnalysisProcessorFeatures (
       } else {\r
         DEBUG ((DEBUG_INFO, "[Unsupport] "));\r
       }\r
-      DumpCpuFeature (CpuFeature);\r
+      DumpCpuFeature (CpuFeature, CpuFeaturesData->BitMaskSize);\r
       Entry = Entry->ForwardLink;\r
     }\r
-    DEBUG ((DEBUG_INFO, "PcdCpuFeaturesSupport:\n"));\r
-    DumpCpuFeatureMask (CpuFeaturesData->SupportPcd);\r
     DEBUG ((DEBUG_INFO, "PcdCpuFeaturesCapability:\n"));\r
-    DumpCpuFeatureMask (CpuFeaturesData->CapabilityPcd);\r
+    DumpCpuFeatureMask (CpuFeaturesData->CapabilityPcd, CpuFeaturesData->BitMaskSize);\r
     DEBUG ((DEBUG_INFO, "Origin PcdCpuFeaturesSetting:\n"));\r
-    DumpCpuFeatureMask (PcdGetPtr (PcdCpuFeaturesSetting));\r
+    DumpCpuFeatureMask (PcdGetPtr (PcdCpuFeaturesSetting), CpuFeaturesData->BitMaskSize);\r
     DEBUG ((DEBUG_INFO, "Final PcdCpuFeaturesSetting:\n"));\r
-    DumpCpuFeatureMask (CpuFeaturesData->SettingPcd);\r
+    DumpCpuFeatureMask (CpuFeaturesData->SettingPcd, CpuFeaturesData->BitMaskSize);\r
   );\r
 \r
   //\r
   // Save PCDs and display CPU PCDs\r
   //\r
   SetCapabilityPcd (CpuFeaturesData->CapabilityPcd, CpuFeaturesData->BitMaskSize);\r
-  SetSettingPcd (CpuFeaturesData->SettingPcd);\r
+  SetSettingPcd (CpuFeaturesData->SettingPcd, CpuFeaturesData->BitMaskSize);\r
 \r
   for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
     CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\r
@@ -620,7 +603,7 @@ AnalysisProcessorFeatures (
       // 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
+      if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcd, CpuFeaturesData->BitMaskSize)) {\r
         CpuFeatureInOrder = AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY), CpuFeature);\r
         ASSERT (CpuFeatureInOrder != NULL);\r
         InsertTailList (&CpuInitOrder->OrderList, &CpuFeatureInOrder->Link);\r
@@ -636,18 +619,18 @@ AnalysisProcessorFeatures (
       CpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
 \r
       Success = FALSE;\r
-      if (IsBitMaskMatch (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->SettingPcd)) {\r
+      if (IsBitMaskMatch (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->SettingPcd, CpuFeaturesData->BitMaskSize)) {\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
+          SupportedMaskCleanBit (CpuFeaturesData->SettingPcd, CpuFeatureInOrder->FeatureMask, CpuFeaturesData->BitMaskSize);\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
+            DumpCpuFeatureMask (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->BitMaskSize);\r
           }\r
         } else {\r
           Success = TRUE;\r
@@ -659,7 +642,7 @@ AnalysisProcessorFeatures (
             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
+            DumpCpuFeatureMask (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->BitMaskSize);\r
           }\r
         } else {\r
           Success = TRUE;\r
@@ -711,7 +694,7 @@ AnalysisProcessorFeatures (
     // again during initialize the features.\r
     //\r
     DEBUG ((DEBUG_INFO, "Dump final value for PcdCpuFeaturesSetting:\n"));\r
-    DumpCpuFeatureMask (CpuFeaturesData->SettingPcd);\r
+    DumpCpuFeatureMask (CpuFeaturesData->SettingPcd, CpuFeaturesData->BitMaskSize);\r
 \r
     //\r
     // Dump the RegisterTable\r
@@ -761,6 +744,58 @@ LibWaitForSemaphore (
              ) != Value);\r
 }\r
 \r
+/**\r
+  Read / write CR value.\r
+\r
+  @param[in]      CrIndex         The CR index which need to read/write.\r
+  @param[in]      Read            Read or write. TRUE is read.\r
+  @param[in,out]  CrValue         CR value.\r
+\r
+  @retval    EFI_SUCCESS means read/write success, else return EFI_UNSUPPORTED.\r
+**/\r
+UINTN\r
+ReadWriteCr (\r
+  IN     UINT32       CrIndex,\r
+  IN     BOOLEAN      Read,\r
+  IN OUT UINTN        *CrValue\r
+  )\r
+{\r
+  switch (CrIndex) {\r
+  case 0:\r
+    if (Read) {\r
+      *CrValue = AsmReadCr0 ();\r
+    } else {\r
+      AsmWriteCr0 (*CrValue);\r
+    }\r
+    break;\r
+  case 2:\r
+    if (Read) {\r
+      *CrValue = AsmReadCr2 ();\r
+    } else {\r
+      AsmWriteCr2 (*CrValue);\r
+    }\r
+    break;\r
+  case 3:\r
+    if (Read) {\r
+      *CrValue = AsmReadCr3 ();\r
+    } else {\r
+      AsmWriteCr3 (*CrValue);\r
+    }\r
+    break;\r
+  case 4:\r
+    if (Read) {\r
+      *CrValue = AsmReadCr4 ();\r
+    } else {\r
+      AsmWriteCr4 (*CrValue);\r
+    }\r
+    break;\r
+  default:\r
+    return EFI_UNSUPPORTED;;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Initialize the CPU registers from a register table.\r
 \r
@@ -788,9 +823,10 @@ ProgramProcessorRegister (
   UINT32                    PackageThreadsCount;\r
   UINT32                    CurrentThread;\r
   UINTN                     ProcessorIndex;\r
-  UINTN                     ThreadIndex;\r
   UINTN                     ValidThreadCount;\r
   UINT32                    *ValidCoreCountPerPackage;\r
+  EFI_STATUS                Status;\r
+  UINT64                    CurrentValue;\r
 \r
   //\r
   // Traverse Register Table of this logical processor\r
@@ -801,26 +837,6 @@ ProgramProcessorRegister (
 \r
     RegisterTableEntry = &RegisterTableEntryHead[Index];\r
 \r
-    DEBUG_CODE_BEGIN ();\r
-      //\r
-      // Wait for the AP to release the MSR spin lock.\r
-      //\r
-      while (!AcquireSpinLockOrFail (&CpuFlags->ConsoleLogLock)) {\r
-        CpuPause ();\r
-      }\r
-      ThreadIndex = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount +\r
-              ApLocation->Core * CpuStatus->MaxThreadCount +\r
-              ApLocation->Thread;\r
-      DEBUG ((\r
-        DEBUG_INFO,\r
-        "Processor = %08lu, Index %08lu, 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
@@ -829,60 +845,51 @@ ProgramProcessorRegister (
     // 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
+      Status = ReadWriteCr (RegisterTableEntry->Index, TRUE, &Value);\r
+      if (EFI_ERROR (Status)) {\r
         break;\r
       }\r
+      if (RegisterTableEntry->TestThenWrite) {\r
+        CurrentValue = BitFieldRead64 (\r
+                         Value,\r
+                         RegisterTableEntry->ValidBitStart,\r
+                         RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1\r
+                         );\r
+        if (CurrentValue == RegisterTableEntry->Value) {\r
+          break;\r
+        }\r
+      }\r
+      Value = (UINTN) BitFieldWrite64 (\r
+                        Value,\r
+                        RegisterTableEntry->ValidBitStart,\r
+                        RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
+                        RegisterTableEntry->Value\r
+                        );\r
+      ReadWriteCr (RegisterTableEntry->Index, FALSE, &Value);\r
       break;\r
+\r
     //\r
     // The specified register is Model Specific Register\r
     //\r
     case Msr:\r
+      if (RegisterTableEntry->TestThenWrite) {\r
+        Value = (UINTN)AsmReadMsr64 (RegisterTableEntry->Index);\r
+        if (RegisterTableEntry->ValidBitLength >= 64) {\r
+          if (Value == RegisterTableEntry->Value) {\r
+            break;\r
+          }\r
+        } else {\r
+          CurrentValue = BitFieldRead64 (\r
+                           Value,\r
+                           RegisterTableEntry->ValidBitStart,\r
+                           RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1\r
+                           );\r
+          if (CurrentValue == RegisterTableEntry->Value) {\r
+            break;\r
+          }\r
+        }\r
+      }\r
+\r
       if (RegisterTableEntry->ValidBitLength >= 64) {\r
         //\r
         // If length is not less than 64 bits, then directly write without reading\r
@@ -1086,10 +1093,12 @@ CpuFeaturesDetect (
 \r
   CpuInitDataInitialize ();\r
 \r
-  //\r
-  // Wakeup all APs for data collection.\r
-  //\r
-  StartupAPsWorker (CollectProcessorData, NULL);\r
+  if (CpuFeaturesData->NumberOfCpus > 1) {\r
+    //\r
+    // Wakeup all APs for data collection.\r
+    //\r
+    StartupAllAPsWorker (CollectProcessorData, NULL);\r
+  }\r
 \r
   //\r
   // Collect data on BSP\r