}\r
}\r
\r
+/**\r
+ Check if all APs are in state CpuStateSleeping.\r
+\r
+ Return TRUE if all APs are in the CpuStateSleeping state. Do not\r
+ check the state of the BSP or any disabled APs.\r
+\r
+ @retval TRUE All APs are in CpuStateSleeping state.\r
+ @retval FALSE One or more APs are not in CpuStateSleeping state.\r
+\r
+**/\r
+BOOLEAN\r
+CheckAllAPsSleeping (\r
+ VOID\r
+ )\r
+{\r
+ UINTN ProcessorNumber;\r
+ CPU_DATA_BLOCK *CpuData;\r
+\r
+ for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {\r
+ CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
+ if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
+ //\r
+ // Skip BSP\r
+ //\r
+ continue;\r
+ }\r
+\r
+ if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {\r
+ //\r
+ // Skip Disabled processors\r
+ //\r
+ continue;\r
+ }\r
+\r
+ if (GetApState (CpuData) != CpuStateSleeping) {\r
+ return FALSE;\r
+ }\r
+ }\r
+ return TRUE;\r
+}\r
+\r
/**\r
If the timeout expires before all APs returns from Procedure,\r
we should forcibly terminate the executing AP and fill FailedList back\r
goto Done;\r
}\r
\r
- gBS->Stall (gPollInterval);\r
+ MicroSecondDelay (gPollInterval);\r
mMpSystemData.Timeout -= gPollInterval;\r
}\r
\r
return EFI_TIMEOUT;\r
}\r
\r
- gBS->Stall (gPollInterval);\r
+ MicroSecondDelay (gPollInterval);\r
CpuData->Timeout -= gPollInterval;\r
}\r
\r
SendInitIpiAllExcludingSelf ();\r
}\r
\r
+/**\r
+ A minimal wrapper function that allows MtrrSetAllMtrrs() to be passed to\r
+ EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() as Procedure.\r
+\r
+ @param[in] Buffer Pointer to an MTRR_SETTINGS object, to be passed to\r
+ MtrrSetAllMtrrs().\r
+**/\r
+VOID\r
+EFIAPI\r
+SetMtrrsFromBuffer (\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ MtrrSetAllMtrrs (Buffer);\r
+}\r
+\r
/**\r
Initialize Multi-processor support.\r
\r
VOID\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ MTRR_SETTINGS MtrrSettings;\r
+ UINTN Timeout;\r
\r
gMaxLogicalProcessorNumber = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);\r
if (gMaxLogicalProcessorNumber < 1) {\r
return;\r
}\r
\r
- if (gMaxLogicalProcessorNumber == 1) {\r
- return;\r
- }\r
\r
- gApStackSize = (UINTN) PcdGet32 (PcdCpuApStackSize);\r
- ASSERT ((gApStackSize & (SIZE_4KB - 1)) == 0);\r
\r
- mApStackStart = AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));\r
- ASSERT (mApStackStart != NULL);\r
+ InitMpSystemData ();\r
\r
//\r
- // the first buffer of stack size used for common stack, when the amount of AP\r
- // more than 1, we should never free the common stack which maybe used for AP reset.\r
+ // Only perform AP detection if PcdCpuMaxLogicalProcessorNumber is greater than 1\r
//\r
- mCommonStack = mApStackStart;\r
- mTopOfApCommonStack = (UINT8*) mApStackStart + gApStackSize;\r
- mApStackStart = mTopOfApCommonStack;\r
+ if (gMaxLogicalProcessorNumber > 1) {\r
\r
- InitMpSystemData ();\r
+ gApStackSize = (UINTN) PcdGet32 (PcdCpuApStackSize);\r
+ ASSERT ((gApStackSize & (SIZE_4KB - 1)) == 0);\r
+\r
+ mApStackStart = AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));\r
+ ASSERT (mApStackStart != NULL);\r
+\r
+ //\r
+ // the first buffer of stack size used for common stack, when the amount of AP\r
+ // more than 1, we should never free the common stack which maybe used for AP reset.\r
+ //\r
+ mCommonStack = mApStackStart;\r
+ mTopOfApCommonStack = (UINT8*) mApStackStart + gApStackSize;\r
+ mApStackStart = mTopOfApCommonStack;\r
\r
- PrepareAPStartupCode ();\r
+ PrepareAPStartupCode ();\r
\r
- StartApsStackless ();\r
+ StartApsStackless ();\r
+ }\r
\r
DEBUG ((DEBUG_INFO, "Detect CPU count: %d\n", mMpSystemData.NumberOfProcessors));\r
if (mMpSystemData.NumberOfProcessors == 1) {\r
FreeApStartupCode ();\r
- FreePages (mCommonStack, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));\r
- return;\r
+ if (mCommonStack != NULL) {\r
+ FreePages (mCommonStack, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));\r
+ }\r
}\r
\r
mMpSystemData.CpuDatas = ReallocatePool (\r
sizeof (CPU_DATA_BLOCK) * mMpSystemData.NumberOfProcessors,\r
mMpSystemData.CpuDatas);\r
\r
+ //\r
+ // Release all APs to complete initialization and enter idle loop\r
+ //\r
mAPsAlreadyInitFinished = TRUE;\r
\r
+ //\r
+ // Wait for all APs to enter idle loop.\r
+ //\r
+ Timeout = 0;\r
+ do {\r
+ if (CheckAllAPsSleeping ()) {\r
+ break;\r
+ }\r
+ MicroSecondDelay (gPollInterval);\r
+ Timeout += gPollInterval;\r
+ } while (Timeout <= PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));\r
+ ASSERT (Timeout <= PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));\r
+\r
//\r
// Update CPU healthy information from Guided HOB\r
//\r
CollectBistDataFromHob ();\r
\r
+ //\r
+ // Synchronize MTRR settings to APs.\r
+ //\r
+ MtrrGetAllMtrrs (&MtrrSettings);\r
+ Status = mMpServicesTemplate.StartupAllAPs (\r
+ &mMpServicesTemplate, // This\r
+ SetMtrrsFromBuffer, // Procedure\r
+ TRUE, // SingleThread\r
+ NULL, // WaitEvent\r
+ 0, // TimeoutInMicrosecsond\r
+ &MtrrSettings, // ProcedureArgument\r
+ NULL // FailedCpuList\r
+ );\r
+ ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_STARTED);\r
+\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&mMpServiceHandle,\r
&gEfiMpServiceProtocolGuid, &mMpServicesTemplate,\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- if (mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) {\r
- FreePages (mApStackStart, EFI_SIZE_TO_PAGES (\r
- (gMaxLogicalProcessorNumber - mMpSystemData.NumberOfProcessors) *\r
- gApStackSize));\r
+ if (mMpSystemData.NumberOfProcessors > 1 && mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) {\r
+ if (mApStackStart != NULL) {\r
+ FreePages (mApStackStart, EFI_SIZE_TO_PAGES (\r
+ (gMaxLogicalProcessorNumber - mMpSystemData.NumberOfProcessors) *\r
+ gApStackSize));\r
+ }\r
}\r
\r
Status = gBS->CreateEvent (\r