Revision: 18826
          http://sourceforge.net/p/edk2/code/18826
Author:   vanjeff
Date:     2015-11-17 04:52:28 +0000 (Tue, 17 Nov 2015)
Log Message:
-----------
UefiCpuPkg: CpuDxe: Wait for APs to enter idle loop

Address a race condition in first call to StartupAllAPs() with
SingleThread set to TRUE in the MP initialization.  If the APs
have not entered their idle loop before StartupAllAPs() is called,
then some of the APs will be in an unexpected state, and
StartupAllAPs() will hang.  This is the hang condition that is
only seen when SingleThread parameter is set to TRUE and
StartupAllAPs() is called very shortly after mAPsAlreadyInitFinished
is set to TRUE that releases the APs to complete their initialization.

An internal function has been added to check if all APs are in the
sleeping state in their idle loop.  On the first call to
StartupAllAPs(), this internal function is used in a loop to make
sure the APs are in a state that is compatible with the use of
StartupAllAPs().  PcdCpuApInitTimeOutInMicroSeconds is used as the
maximum wait time for the APs to enter their idle loop.  If all
APs have not entered their idle loop within the timeout, then
an ASSERT() is generated.

(Sync patch r18631 from main trunk.)

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Kinney <[email protected]>
Cc: Jeff Fan <[email protected]>
Cc: Laszlo Ersek <[email protected]>
Reviewed-by: Laszlo Ersek <[email protected]>
Reviewed-by: Jeff Fan <[email protected]>

Revision Links:
--------------
    http://sourceforge.net/p/edk2/code/18631

Modified Paths:
--------------
    branches/UDK2015/UefiCpuPkg/CpuDxe/CpuMp.c

Modified: branches/UDK2015/UefiCpuPkg/CpuDxe/CpuMp.c
===================================================================
--- branches/UDK2015/UefiCpuPkg/CpuDxe/CpuMp.c  2015-11-17 04:51:37 UTC (rev 
18825)
+++ branches/UDK2015/UefiCpuPkg/CpuDxe/CpuMp.c  2015-11-17 04:52:28 UTC (rev 
18826)
@@ -313,6 +313,47 @@
 }
 
 /**
+  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 @@
   VOID
   )
 {
-  EFI_STATUS Status;
+  EFI_STATUS     Status;
+  UINTN          Timeout;
 
   gMaxLogicalProcessorNumber = (UINTN) PcdGet32 
(PcdCpuMaxLogicalProcessorNumber);
   if (gMaxLogicalProcessorNumber < 1) {
@@ -1683,9 +1725,25 @@
                              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 ();


------------------------------------------------------------------------------
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to