/** @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
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
//\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
//\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
//\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
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
}\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
\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
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
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
// 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
//\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
// 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
//\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
} 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
}\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
\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
}\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
\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
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