]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/CpuMp.c
UefiCpuPkg/CpuDxe: Put APs in wait for SIPI state at ExitBootServices
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuMp.c
index 10065762a243b00c03bfcae41baaf0401da6b81d..b65300c773c6b5ce1ec43daf33c178924bdc5a95 100644 (file)
@@ -20,6 +20,8 @@ UINTN gApStackSize;
 UINTN gPollInterval = 100; // 100 microseconds\r
 \r
 MP_SYSTEM_DATA mMpSystemData;\r
+EFI_HANDLE     mMpServiceHandle       = NULL;\r
+EFI_EVENT      mExitBootServicesEvent = (EFI_EVENT)NULL;\r
 \r
 VOID *mCommonStack = 0;\r
 VOID *mTopOfApCommonStack = 0;\r
@@ -52,6 +54,7 @@ GetMpSpinLock (
   while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) {\r
     CpuPause ();\r
   }\r
+  CpuData->LockSelf = GetApicId ();\r
 }\r
 \r
 /**\r
@@ -631,6 +634,11 @@ StartupAllAPs (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  //\r
+  // temporarily stop checkAllAPsStatus for avoid resource dead-lock.\r
+  //\r
+  mStopCheckAllAPsStatus = TRUE;\r
+\r
   for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {\r
     CpuData = &mMpSystemData.CpuDatas[Number];\r
     if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
@@ -652,11 +660,6 @@ StartupAllAPs (
     }\r
   }\r
 \r
-  //\r
-  // temporarily stop checkAllAPsStatus for initialize parameters.\r
-  //\r
-  mStopCheckAllAPsStatus = TRUE;\r
-\r
   mMpSystemData.Procedure         = Procedure;\r
   mMpSystemData.ProcedureArgument = ProcedureArgument;\r
   mMpSystemData.WaitEvent         = WaitEvent;\r
@@ -715,6 +718,11 @@ StartupAllAPs (
     return EFI_SUCCESS;\r
   }\r
 \r
+  //\r
+  // Blocking temporarily stop CheckAllAPsStatus()\r
+  //\r
+  mStopCheckAllAPsStatus = TRUE;\r
+\r
   while (TRUE) {\r
     CheckAndUpdateAllAPsToIdleState ();\r
     if (mMpSystemData.FinishCount == mMpSystemData.StartCount) {\r
@@ -858,6 +866,11 @@ StartupThisAP (
     return EFI_NOT_FOUND;\r
   }\r
 \r
+  //\r
+  // temporarily stop checkAllAPsStatus for avoid resource dead-lock.\r
+  //\r
+  mStopCheckAllAPsStatus = TRUE;\r
+\r
   CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
   if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT) ||\r
       !TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {\r
@@ -868,11 +881,6 @@ StartupThisAP (
     return EFI_NOT_READY;\r
   }\r
 \r
-  //\r
-  // temporarily stop checkAllAPsStatus for initialize parameters.\r
-  //\r
-  mStopCheckAllAPsStatus = TRUE;\r
-\r
   SetApState (CpuData, CpuStateReady);\r
 \r
   SetApProcedure (CpuData, Procedure, ProcedureArgument);\r
@@ -1012,6 +1020,10 @@ EnableDisableAP (
   )\r
 {\r
   CPU_DATA_BLOCK *CpuData;\r
+  BOOLEAN        TempStopCheckState;\r
+\r
+  CpuData = NULL;\r
+  TempStopCheckState = FALSE;\r
 \r
   if (!IsBSP ()) {\r
     return EFI_DEVICE_ERROR;\r
@@ -1021,6 +1033,14 @@ EnableDisableAP (
     return EFI_NOT_FOUND;\r
   }\r
 \r
+  //\r
+  // temporarily stop checkAllAPsStatus for initialize parameters.\r
+  //\r
+  if (!mStopCheckAllAPsStatus) {\r
+    mStopCheckAllAPsStatus = TRUE;\r
+    TempStopCheckState = TRUE;\r
+  }\r
+\r
   CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
   if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1047,6 +1067,10 @@ EnableDisableAP (
     CpuStatusFlagOr (CpuData, (*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT));\r
   }\r
 \r
+  if (TempStopCheckState) {\r
+    mStopCheckAllAPsStatus = FALSE;\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -1144,6 +1168,13 @@ ProcessorToIdleState (
   WhoAmI (&mMpServicesTemplate, &ProcessorNumber);\r
   CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
 \r
+  //\r
+  // Avoid forcibly reset AP caused the AP got lock not release.\r
+  //\r
+  if (CpuData->LockSelf == (INTN) GetApicId ()) {\r
+    ReleaseSpinLock (&CpuData->CpuDataLock);\r
+  }\r
+\r
   //\r
   // Avoid forcibly reset AP caused the AP State is not updated.\r
   //\r
@@ -1295,20 +1326,6 @@ CheckAllAPsStatus (
   //\r
   for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {\r
     CpuData = &mMpSystemData.CpuDatas[Number];\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 (CpuData->WaitEvent) {\r
       CheckThisAPStatus (NULL, (VOID *)CpuData);\r
     }\r
@@ -1395,6 +1412,7 @@ FillInProcessorInformation (
   CpuData->Procedure        = NULL;\r
   CpuData->Parameter        = NULL;\r
   InitializeSpinLock (&CpuData->CpuDataLock);\r
+  CpuData->LockSelf         = -1;\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -1447,6 +1465,28 @@ InitMpSystemData (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Callback function for ExitBootServices.\r
+\r
+  @param  Event                 Event whose notification function is being invoked.\r
+  @param  Context               The pointer to the notification function's context,\r
+                                which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ExitBootServicesCallback (\r
+  IN EFI_EVENT                Event,\r
+  IN VOID                     *Context\r
+  )\r
+{\r
+  //\r
+  // Avoid APs access invalid buff datas which allocated by BootServices,\r
+  // so we send INIT IPI to APs to let them wait for SIPI state.\r
+  //\r
+  SendInitIpiAllExcludingSelf ();\r
+}\r
+\r
 /**\r
   Initialize Multi-processor support.\r
 \r
@@ -1456,6 +1496,8 @@ InitializeMpSupport (
   VOID\r
   )\r
 {\r
+  EFI_STATUS Status;\r
+\r
   gMaxLogicalProcessorNumber = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);\r
   if (gMaxLogicalProcessorNumber < 1) {\r
     DEBUG ((DEBUG_ERROR, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n"));\r
@@ -1484,6 +1526,9 @@ InitializeMpSupport (
 \r
   PrepareAPStartupCode ();\r
 \r
+  StartApsStackless ();\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
@@ -1497,9 +1542,25 @@ InitializeMpSupport (
 \r
   mAPsAlreadyInitFinished = TRUE;\r
 \r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &mMpServiceHandle,\r
+                  &gEfiMpServiceProtocolGuid,  &mMpServicesTemplate,\r
+                  NULL\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
   }\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
+                  TPL_CALLBACK,\r
+                  ExitBootServicesCallback,\r
+                  NULL,\r
+                  &mExitBootServicesEvent\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
 }\r