]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
UefiCpuPkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / CpuS3.c
index ba5cc0194c2d2121e1efdc1a3cb0a424e3349e1e..0d723336e4d68cf7e657037176fbc0af109a8f20 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Code for Processor S3 restoration\r
 \r
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>\r
 SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
@@ -235,11 +235,11 @@ ProgramProcessorRegister (
   CPU_REGISTER_TABLE_ENTRY  *RegisterTableEntryHead;\r
   volatile UINT32           *SemaphorePtr;\r
   UINT32                    FirstThread;\r
-  UINT32                    PackageThreadsCount;\r
   UINT32                    CurrentThread;\r
+  UINT32                    CurrentCore;\r
   UINTN                     ProcessorIndex;\r
-  UINTN                     ValidThreadCount;\r
-  UINT32                    *ValidCoreCountPerPackage;\r
+  UINT32                    *ThreadCountPerPackage;\r
+  UINT8                     *ThreadCountPerCore;\r
   EFI_STATUS                Status;\r
   UINT64                    CurrentValue;\r
 \r
@@ -372,35 +372,52 @@ ProgramProcessorRegister (
       //\r
       ASSERT (\r
         (ApLocation != NULL) &&\r
-        (CpuStatus->ValidCoreCountPerPackage != 0) &&\r
+        (CpuStatus->ThreadCountPerPackage != 0) &&\r
+        (CpuStatus->ThreadCountPerCore != 0) &&\r
         (CpuFlags->CoreSemaphoreCount != NULL) &&\r
         (CpuFlags->PackageSemaphoreCount != NULL)\r
         );\r
       switch (RegisterTableEntry->Value) {\r
       case CoreDepType:\r
         SemaphorePtr = CpuFlags->CoreSemaphoreCount;\r
+        ThreadCountPerCore = (UINT8 *)(UINTN)CpuStatus->ThreadCountPerCore;\r
+\r
+        CurrentCore = ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core;\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
+        FirstThread   = CurrentCore * CpuStatus->MaxThreadCount;\r
         CurrentThread = FirstThread + ApLocation->Thread;\r
+\r
+        //\r
+        // Different cores may have different valid threads in them. If driver maintail clearly\r
+        // thread index in different cores, the logic will be much complicated.\r
+        // Here driver just simply records the max thread number in all cores and use it as expect\r
+        // thread number for all cores.\r
+        // In below two steps logic, first current thread will Release semaphore for each thread\r
+        // in current core. Maybe some threads are not valid in this core, but driver don't\r
+        // care. Second, driver will let current thread wait semaphore for all valid threads in\r
+        // current core. 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 Core that this thread has ready.\r
+        // First Notify ALL THREADs in current Core that this thread is ready.\r
         //\r
         for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
           S3ReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);\r
         }\r
         //\r
-        // Second, check whether all valid threads in current core have ready.\r
+        // Second, check whether all VALID THREADs (not all threads) in current core are ready.\r
         //\r
-        for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
+        for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerCore[CurrentCore]; ProcessorIndex ++) {\r
           S3WaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
         }\r
         break;\r
 \r
       case PackageDepType:\r
         SemaphorePtr = CpuFlags->PackageSemaphoreCount;\r
-        ValidCoreCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ValidCoreCountPerPackage;\r
+        ThreadCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ThreadCountPerPackage;\r
         //\r
         // Get Offset info for the first thread in the package which current thread belongs to.\r
         //\r
@@ -408,18 +425,13 @@ ProgramProcessorRegister (
         //\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
+        // Different packages may have different valid threads in them. If driver maintail clearly\r
+        // thread index in different packages, the logic will be much complicated.\r
+        // Here driver just simply records the max thread number in all packages and use it as expect\r
+        // thread 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
@@ -428,15 +440,15 @@ ProgramProcessorRegister (
         //\r
 \r
         //\r
-        // First Notify all threads in current package that this thread has ready.\r
+        // First Notify ALL THREADS in current package that this thread is ready.\r
         //\r
-        for (ProcessorIndex = 0; ProcessorIndex < PackageThreadsCount ; ProcessorIndex ++) {\r
+        for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount; ProcessorIndex ++) {\r
           S3ReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);\r
         }\r
         //\r
-        // Second, check whether all valid threads in current package have ready.\r
+        // Second, check whether VALID THREADS (not all threads) in current package are ready.\r
         //\r
-        for (ProcessorIndex = 0; ProcessorIndex < ValidThreadCount; ProcessorIndex ++) {\r
+        for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerPackage[ApLocation->Package]; ProcessorIndex ++) {\r
           S3WaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
         }\r
         break;\r
@@ -464,16 +476,22 @@ SetRegister (
   IN BOOLEAN                 PreSmmRegisterTable\r
   )\r
 {\r
+  CPU_FEATURE_INIT_DATA     *FeatureInitData;\r
   CPU_REGISTER_TABLE        *RegisterTable;\r
   CPU_REGISTER_TABLE        *RegisterTables;\r
   UINT32                    InitApicId;\r
   UINTN                     ProcIndex;\r
   UINTN                     Index;\r
 \r
+  FeatureInitData = &mAcpiCpuData.CpuFeatureInitData;\r
+\r
   if (PreSmmRegisterTable) {\r
-    RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.PreSmmInitRegisterTable;\r
+    RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)FeatureInitData->PreSmmInitRegisterTable;\r
   } else {\r
-    RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable;\r
+    RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)FeatureInitData->RegisterTable;\r
+  }\r
+  if (RegisterTables == NULL) {\r
+    return;\r
   }\r
 \r
   InitApicId = GetInitialApicId ();\r
@@ -488,18 +506,18 @@ SetRegister (
   }\r
   ASSERT (RegisterTable != NULL);\r
 \r
-  if (mAcpiCpuData.ApLocation != 0) {\r
+  if (FeatureInitData->ApLocation != 0) {\r
     ProgramProcessorRegister (\r
       RegisterTable,\r
-      (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)mAcpiCpuData.ApLocation + ProcIndex,\r
-      &mAcpiCpuData.CpuStatus,\r
+      (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)FeatureInitData->ApLocation + ProcIndex,\r
+      &FeatureInitData->CpuStatus,\r
       &mCpuFlags\r
       );\r
   } else {\r
     ProgramProcessorRegister (\r
       RegisterTable,\r
       NULL,\r
-      &mAcpiCpuData.CpuStatus,\r
+      &FeatureInitData->CpuStatus,\r
       &mCpuFlags\r
       );\r
   }\r
@@ -616,7 +634,12 @@ InitializeCpuBeforeRebase (
 \r
   PrepareApStartupVector (mAcpiCpuData.StartupVector);\r
 \r
-  mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1;\r
+  if (FeaturePcdGet (PcdCpuHotPlugSupport)) {\r
+    ASSERT (mNumberOfCpus <= mAcpiCpuData.NumberOfCpus);\r
+  } else {\r
+    ASSERT (mNumberOfCpus == mAcpiCpuData.NumberOfCpus);\r
+  }\r
+  mNumberToFinish = (UINT32)(mNumberOfCpus - 1);\r
   mExchangeInfo->ApFunction  = (VOID *) (UINTN) InitializeAp;\r
 \r
   //\r
@@ -646,7 +669,12 @@ InitializeCpuAfterRebase (
   VOID\r
   )\r
 {\r
-  mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1;\r
+  if (FeaturePcdGet (PcdCpuHotPlugSupport)) {\r
+    ASSERT (mNumberOfCpus <= mAcpiCpuData.NumberOfCpus);\r
+  } else {\r
+    ASSERT (mNumberOfCpus == mAcpiCpuData.NumberOfCpus);\r
+  }\r
+  mNumberToFinish = (UINT32)(mNumberOfCpus - 1);\r
 \r
   //\r
   // Signal that SMM base relocation is complete and to continue initialization for all APs.\r
@@ -723,7 +751,7 @@ SmmRestoreCpu (
   IA32_IDT_GATE_DESCRIPTOR      IdtEntryTable[EXCEPTION_VECTOR_NUMBER];\r
   EFI_STATUS                    Status;\r
 \r
-  DEBUG ((EFI_D_INFO, "SmmRestoreCpu()\n"));\r
+  DEBUG ((DEBUG_INFO, "SmmRestoreCpu()\n"));\r
 \r
   mSmmS3Flag = TRUE;\r
 \r
@@ -731,7 +759,7 @@ SmmRestoreCpu (
   // See if there is enough context to resume PEI Phase\r
   //\r
   if (mSmmS3ResumeState == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "No context to return to PEI Phase\n"));\r
+    DEBUG ((DEBUG_ERROR, "No context to return to PEI Phase\n"));\r
     CpuDeadLoop ();\r
   }\r
 \r
@@ -794,17 +822,17 @@ SmmRestoreCpu (
   //\r
   mRestoreSmmConfigurationInS3 = TRUE;\r
 \r
-  DEBUG (( EFI_D_INFO, "SMM S3 Return CS                = %x\n", SmmS3ResumeState->ReturnCs));\r
-  DEBUG (( EFI_D_INFO, "SMM S3 Return Entry Point       = %x\n", SmmS3ResumeState->ReturnEntryPoint));\r
-  DEBUG (( EFI_D_INFO, "SMM S3 Return Context1          = %x\n", SmmS3ResumeState->ReturnContext1));\r
-  DEBUG (( EFI_D_INFO, "SMM S3 Return Context2          = %x\n", SmmS3ResumeState->ReturnContext2));\r
-  DEBUG (( EFI_D_INFO, "SMM S3 Return Stack Pointer     = %x\n", SmmS3ResumeState->ReturnStackPointer));\r
+  DEBUG (( DEBUG_INFO, "SMM S3 Return CS                = %x\n", SmmS3ResumeState->ReturnCs));\r
+  DEBUG (( DEBUG_INFO, "SMM S3 Return Entry Point       = %x\n", SmmS3ResumeState->ReturnEntryPoint));\r
+  DEBUG (( DEBUG_INFO, "SMM S3 Return Context1          = %x\n", SmmS3ResumeState->ReturnContext1));\r
+  DEBUG (( DEBUG_INFO, "SMM S3 Return Context2          = %x\n", SmmS3ResumeState->ReturnContext2));\r
+  DEBUG (( DEBUG_INFO, "SMM S3 Return Stack Pointer     = %x\n", SmmS3ResumeState->ReturnStackPointer));\r
 \r
   //\r
   // If SMM is in 32-bit mode, then use SwitchStack() to resume PEI Phase\r
   //\r
   if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) {\r
-    DEBUG ((EFI_D_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));\r
+    DEBUG ((DEBUG_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));\r
 \r
     SwitchStack (\r
       (SWITCH_STACK_ENTRY_POINT)(UINTN)SmmS3ResumeState->ReturnEntryPoint,\r
@@ -818,7 +846,7 @@ SmmRestoreCpu (
   // If SMM is in 64-bit mode, then use AsmDisablePaging64() to resume PEI Phase\r
   //\r
   if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {\r
-    DEBUG ((EFI_D_INFO, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n"));\r
+    DEBUG ((DEBUG_INFO, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n"));\r
     //\r
     // Disable interrupt of Debug timer, since new IDT table is for IA32 and will not work in long mode.\r
     //\r
@@ -839,7 +867,7 @@ SmmRestoreCpu (
   //\r
   // Can not resume PEI Phase\r
   //\r
-  DEBUG ((EFI_D_ERROR, "No context to return to PEI Phase\n"));\r
+  DEBUG ((DEBUG_ERROR, "No context to return to PEI Phase\n"));\r
   CpuDeadLoop ();\r
 }\r
 \r
@@ -876,8 +904,8 @@ InitSmmS3ResumeState (
   } else {\r
     SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);\r
 \r
-    DEBUG ((EFI_D_INFO, "SMM S3 SMRAM Structure = %x\n", SmramDescriptor));\r
-    DEBUG ((EFI_D_INFO, "SMM S3 Structure = %x\n", SmramDescriptor->CpuStart));\r
+    DEBUG ((DEBUG_INFO, "SMM S3 SMRAM Structure = %x\n", SmramDescriptor));\r
+    DEBUG ((DEBUG_INFO, "SMM S3 Structure = %x\n", SmramDescriptor->CpuStart));\r
 \r
     SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;\r
     ZeroMem (SmmS3ResumeState, sizeof (SMM_S3_RESUME_STATE));\r
@@ -926,7 +954,7 @@ InitSmmS3ResumeState (
 }\r
 \r
 /**\r
-  Copy register table from ACPI NVS memory into SMRAM.\r
+  Copy register table from non-SMRAM into SMRAM.\r
 \r
   @param[in] DestinationRegisterTableList  Points to destination register table.\r
   @param[in] SourceRegisterTableList       Points to source register table.\r
@@ -945,7 +973,8 @@ CopyRegisterTable (
 \r
   CopyMem (DestinationRegisterTableList, SourceRegisterTableList, NumberOfCpus * sizeof (CPU_REGISTER_TABLE));\r
   for (Index = 0; Index < NumberOfCpus; Index++) {\r
-    if (DestinationRegisterTableList[Index].AllocatedSize != 0) {\r
+    if (DestinationRegisterTableList[Index].TableLength != 0) {\r
+      DestinationRegisterTableList[Index].AllocatedSize = DestinationRegisterTableList[Index].TableLength * sizeof (CPU_REGISTER_TABLE_ENTRY);\r
       RegisterTableEntry = AllocateCopyPool (\r
         DestinationRegisterTableList[Index].AllocatedSize,\r
         (VOID *)(UINTN)SourceRegisterTableList[Index].RegisterTableEntry\r
@@ -956,6 +985,99 @@ CopyRegisterTable (
   }\r
 }\r
 \r
+/**\r
+  Check whether the register table is empty or not.\r
+\r
+  @param[in] RegisterTable  Point to the register table.\r
+  @param[in] NumberOfCpus   Number of CPUs.\r
+\r
+  @retval TRUE              The register table is empty.\r
+  @retval FALSE             The register table is not empty.\r
+**/\r
+BOOLEAN\r
+IsRegisterTableEmpty (\r
+  IN CPU_REGISTER_TABLE     *RegisterTable,\r
+  IN UINT32                 NumberOfCpus\r
+  )\r
+{\r
+  UINTN                     Index;\r
+\r
+  if (RegisterTable != NULL) {\r
+    for (Index = 0; Index < NumberOfCpus; Index++) {\r
+      if (RegisterTable[Index].TableLength != 0) {\r
+        return FALSE;\r
+      }\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Copy the data used to initialize processor register into SMRAM.\r
+\r
+  @param[in,out]  CpuFeatureInitDataDst   Pointer to the destination CPU_FEATURE_INIT_DATA structure.\r
+  @param[in]      CpuFeatureInitDataSrc   Pointer to the source CPU_FEATURE_INIT_DATA structure.\r
+\r
+**/\r
+VOID\r
+CopyCpuFeatureInitDatatoSmram (\r
+  IN OUT CPU_FEATURE_INIT_DATA    *CpuFeatureInitDataDst,\r
+  IN     CPU_FEATURE_INIT_DATA    *CpuFeatureInitDataSrc\r
+  )\r
+{\r
+  CPU_STATUS_INFORMATION    *CpuStatus;\r
+\r
+  if (!IsRegisterTableEmpty ((CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataSrc->PreSmmInitRegisterTable, mAcpiCpuData.NumberOfCpus)) {\r
+    CpuFeatureInitDataDst->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));\r
+    ASSERT (CpuFeatureInitDataDst->PreSmmInitRegisterTable != 0);\r
+\r
+    CopyRegisterTable (\r
+      (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataDst->PreSmmInitRegisterTable,\r
+      (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataSrc->PreSmmInitRegisterTable,\r
+      mAcpiCpuData.NumberOfCpus\r
+      );\r
+  }\r
+\r
+  if (!IsRegisterTableEmpty ((CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataSrc->RegisterTable, mAcpiCpuData.NumberOfCpus)) {\r
+    CpuFeatureInitDataDst->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));\r
+    ASSERT (CpuFeatureInitDataDst->RegisterTable != 0);\r
+\r
+    CopyRegisterTable (\r
+      (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataDst->RegisterTable,\r
+      (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataSrc->RegisterTable,\r
+      mAcpiCpuData.NumberOfCpus\r
+      );\r
+  }\r
+\r
+  CpuStatus = &CpuFeatureInitDataDst->CpuStatus;\r
+  CopyMem (CpuStatus, &CpuFeatureInitDataSrc->CpuStatus, sizeof (CPU_STATUS_INFORMATION));\r
+\r
+  if (CpuFeatureInitDataSrc->CpuStatus.ThreadCountPerPackage != 0) {\r
+    CpuStatus->ThreadCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (\r
+                                            sizeof (UINT32) * CpuStatus->PackageCount,\r
+                                            (UINT32 *)(UINTN)CpuFeatureInitDataSrc->CpuStatus.ThreadCountPerPackage\r
+                                            );\r
+    ASSERT (CpuStatus->ThreadCountPerPackage != 0);\r
+  }\r
+\r
+  if (CpuFeatureInitDataSrc->CpuStatus.ThreadCountPerCore != 0) {\r
+    CpuStatus->ThreadCountPerCore = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (\r
+                                            sizeof (UINT8) * (CpuStatus->PackageCount * CpuStatus->MaxCoreCount),\r
+                                            (UINT32 *)(UINTN)CpuFeatureInitDataSrc->CpuStatus.ThreadCountPerCore\r
+                                            );\r
+    ASSERT (CpuStatus->ThreadCountPerCore != 0);\r
+  }\r
+\r
+  if (CpuFeatureInitDataSrc->ApLocation != 0) {\r
+    CpuFeatureInitDataDst->ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (\r
+                                mAcpiCpuData.NumberOfCpus * sizeof (EFI_CPU_PHYSICAL_LOCATION),\r
+                                (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)CpuFeatureInitDataSrc->ApLocation\r
+                                );\r
+    ASSERT (CpuFeatureInitDataDst->ApLocation != 0);\r
+  }\r
+}\r
+\r
 /**\r
   Get ACPI CPU data.\r
 \r
@@ -1010,31 +1132,13 @@ GetAcpiCpuData (
 \r
   CopyMem ((VOID *)(UINTN)mAcpiCpuData.IdtrProfile, (VOID *)(UINTN)AcpiCpuData->IdtrProfile, sizeof (IA32_DESCRIPTOR));\r
 \r
-  mAcpiCpuData.PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));\r
-  ASSERT (mAcpiCpuData.PreSmmInitRegisterTable != 0);\r
-\r
-  CopyRegisterTable (\r
-    (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.PreSmmInitRegisterTable,\r
-    (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->PreSmmInitRegisterTable,\r
-    mAcpiCpuData.NumberOfCpus\r
-    );\r
-\r
-  mAcpiCpuData.RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));\r
-  ASSERT (mAcpiCpuData.RegisterTable != 0);\r
-\r
-  CopyRegisterTable (\r
-    (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable,\r
-    (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable,\r
-    mAcpiCpuData.NumberOfCpus\r
-    );\r
-\r
   //\r
   // Copy AP's GDT, IDT and Machine Check handler into SMRAM.\r
   //\r
   Gdtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.GdtrProfile;\r
   Idtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.IdtrProfile;\r
 \r
-  GdtForAp = AllocatePool ((Gdtr->Limit + 1) + (Idtr->Limit + 1) +  mAcpiCpuData.ApMachineCheckHandlerSize);\r
+  GdtForAp = AllocatePool ((Gdtr->Limit + 1) + (Idtr->Limit + 1) + mAcpiCpuData.ApMachineCheckHandlerSize);\r
   ASSERT (GdtForAp != NULL);\r
   IdtForAp = (VOID *) ((UINTN)GdtForAp + (Gdtr->Limit + 1));\r
   MachineCheckHandlerForAp = (VOID *) ((UINTN)IdtForAp + (Idtr->Limit + 1));\r
@@ -1047,35 +1151,32 @@ GetAcpiCpuData (
   Idtr->Base = (UINTN)IdtForAp;\r
   mAcpiCpuData.ApMachineCheckHandlerBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MachineCheckHandlerForAp;\r
 \r
-  CpuStatus = &mAcpiCpuData.CpuStatus;\r
-  CopyMem (CpuStatus, &AcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMATION));\r
-  if (AcpiCpuData->CpuStatus.ValidCoreCountPerPackage != 0) {\r
-    CpuStatus->ValidCoreCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (\r
-                                            sizeof (UINT32) * CpuStatus->PackageCount,\r
-                                            (UINT32 *)(UINTN)AcpiCpuData->CpuStatus.ValidCoreCountPerPackage\r
-                                            );\r
-    ASSERT (CpuStatus->ValidCoreCountPerPackage != 0);\r
-  }\r
-  if (AcpiCpuData->ApLocation != 0) {\r
-    mAcpiCpuData.ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (\r
-                                mAcpiCpuData.NumberOfCpus * sizeof (EFI_CPU_PHYSICAL_LOCATION),\r
-                                (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->ApLocation\r
-                                );\r
-    ASSERT (mAcpiCpuData.ApLocation != 0);\r
-  }\r
-  if (CpuStatus->PackageCount != 0) {\r
+  ZeroMem (&mAcpiCpuData.CpuFeatureInitData, sizeof (CPU_FEATURE_INIT_DATA));\r
+\r
+  if (!PcdGetBool (PcdCpuFeaturesInitOnS3Resume)) {\r
+    //\r
+    // If the CPU features will not be initialized by CpuFeaturesPei module during\r
+    // next ACPI S3 resume, copy the CPU features initialization data into SMRAM,\r
+    // which will be consumed in SmmRestoreCpu during next S3 resume.\r
+    //\r
+    CopyCpuFeatureInitDatatoSmram (&mAcpiCpuData.CpuFeatureInitData, &AcpiCpuData->CpuFeatureInitData);\r
+\r
+    CpuStatus = &mAcpiCpuData.CpuFeatureInitData.CpuStatus;\r
+\r
     mCpuFlags.CoreSemaphoreCount = AllocateZeroPool (\r
                                      sizeof (UINT32) * CpuStatus->PackageCount *\r
                                      CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount\r
                                      );\r
     ASSERT (mCpuFlags.CoreSemaphoreCount != NULL);\r
+\r
     mCpuFlags.PackageSemaphoreCount = AllocateZeroPool (\r
                                         sizeof (UINT32) * CpuStatus->PackageCount *\r
                                         CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount\r
                                         );\r
     ASSERT (mCpuFlags.PackageSemaphoreCount != NULL);\r
+\r
+    InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.MemoryMappedLock);\r
   }\r
-  InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.MemoryMappedLock);\r
 }\r
 \r
 /**\r