]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/CpuMp.c
UefiCpuPkg/MpService: avoid dead lock caused by CheckAllAPsStatus
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuMp.c
index 13fcda58597bf25bf622e1ce0a8e7e726f642a71..5d5c7db765972e99c7bc1190304c2772b04e44ff 100644 (file)
@@ -25,7 +25,7 @@ VOID *mCommonStack = 0;
 VOID *mTopOfApCommonStack = 0;\r
 VOID *mApStackStart = 0;\r
 \r
-BOOLEAN mAPsAlreadyInitFinished = FALSE;\r
+volatile BOOLEAN mAPsAlreadyInitFinished = FALSE;\r
 volatile BOOLEAN mStopCheckAllAPsStatus = TRUE;\r
 \r
 EFI_MP_SERVICES_PROTOCOL  mMpServicesTemplate = {\r
@@ -52,6 +52,7 @@ GetMpSpinLock (
   while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) {\r
     CpuPause ();\r
   }\r
+  CpuData->LockSelf = GetApicId ();\r
 }\r
 \r
 /**\r
@@ -631,6 +632,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 +658,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 +716,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 +864,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 +879,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 +1018,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 +1031,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 +1065,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
@@ -1135,10 +1157,21 @@ ProcessorToIdleState (
   EFI_AP_PROCEDURE      Procedure;\r
   VOID                  *ProcedureArgument;\r
 \r
+  AsmApDoneWithCommonStack ();\r
+\r
+  while (!mAPsAlreadyInitFinished) {\r
+    CpuPause ();\r
+  }\r
+\r
   WhoAmI (&mMpServicesTemplate, &ProcessorNumber);\r
   CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
 \r
-  AsmApDoneWithCommonStack ();\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
@@ -1291,20 +1324,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
@@ -1391,6 +1410,7 @@ FillInProcessorInformation (
   CpuData->Procedure        = NULL;\r
   CpuData->Parameter        = NULL;\r
   InitializeSpinLock (&CpuData->CpuDataLock);\r
+  CpuData->LockSelf         = -1;\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -1486,6 +1506,11 @@ InitializeMpSupport (
     return;\r
   }\r
 \r
+  mMpSystemData.CpuDatas = ReallocatePool (\r
+                             sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber,\r
+                             sizeof (CPU_DATA_BLOCK) * mMpSystemData.NumberOfProcessors,\r
+                             mMpSystemData.CpuDatas);\r
+\r
   mAPsAlreadyInitFinished = TRUE;\r
 \r
   if (mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) {\r