summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UefiCpuPkg/CpuDxe/CpuMp.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c
index da3686e278..f3a5a24b0f 100644
--- a/UefiCpuPkg/CpuDxe/CpuMp.c
+++ b/UefiCpuPkg/CpuDxe/CpuMp.c
@@ -313,6 +313,47 @@ CheckAndUpdateAllAPsToIdleState (
}
/**
+ Check if all APs are in state CpuStateSleeping.
+
+ Return TRUE if all APs are in the CpuStateSleeping state. Do not
+ check the state of the BSP or any disabled APs.
+
+ @retval TRUE All APs are in CpuStateSleeping state.
+ @retval FALSE One or more APs are not in CpuStateSleeping state.
+
+**/
+BOOLEAN
+CheckAllAPsSleeping (
+ VOID
+ )
+{
+ UINTN ProcessorNumber;
+ CPU_DATA_BLOCK *CpuData;
+
+ for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {
+ CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
+ if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
+ //
+ // Skip BSP
+ //
+ continue;
+ }
+
+ if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
+ //
+ // Skip Disabled processors
+ //
+ continue;
+ }
+
+ if (GetApState (CpuData) != CpuStateSleeping) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**
If the timeout expires before all APs returns from Procedure,
we should forcibly terminate the executing AP and fill FailedList back
by StartupAllAPs().
@@ -1634,7 +1675,8 @@ InitializeMpSupport (
VOID
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ UINTN Timeout;
gMaxLogicalProcessorNumber = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
if (gMaxLogicalProcessorNumber < 1) {
@@ -1683,9 +1725,25 @@ InitializeMpSupport (
sizeof (CPU_DATA_BLOCK) * mMpSystemData.NumberOfProcessors,
mMpSystemData.CpuDatas);
+ //
+ // Release all APs to complete initialization and enter idle loop
+ //
mAPsAlreadyInitFinished = TRUE;
//
+ // Wait for all APs to enter idle loop.
+ //
+ Timeout = 0;
+ do {
+ if (CheckAllAPsSleeping ()) {
+ break;
+ }
+ gBS->Stall (gPollInterval);
+ Timeout += gPollInterval;
+ } while (Timeout <= PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));
+ ASSERT (Timeout <= PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));
+
+ //
// Update CPU healthy information from Guided HOB
//
CollectBistDataFromHob ();