]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/CpuMp.c
MdePkg/BaseLib: Support IA32 processors without CLFLUSH
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuMp.c
index f864de1f6f4db3eb31d5a5fb472a24826a014ecf..fa0ef37b92ed04d220a1e9d2700609f0d95c4f7b 100644 (file)
@@ -20,7 +20,8 @@ UINTN gApStackSize;
 UINTN gPollInterval = 100; // 100 microseconds\r
 \r
 MP_SYSTEM_DATA mMpSystemData;\r
-EFI_HANDLE     mMpServiceHandle = NULL;\r
+EFI_HANDLE     mMpServiceHandle       = NULL;\r
+EFI_EVENT      mExitBootServicesEvent = (EFI_EVENT)NULL;\r
 \r
 VOID *mCommonStack = 0;\r
 VOID *mTopOfApCommonStack = 0;\r
@@ -177,7 +178,7 @@ TestCpuStatusFlag (
   Ret = CpuData->Info.StatusFlag & Flags;\r
   ReleaseMpSpinLock (CpuData);\r
 \r
-  return !!(Ret);\r
+  return (BOOLEAN) (Ret != 0);\r
 }\r
 \r
 /**\r
@@ -297,9 +298,15 @@ CheckAndUpdateAllAPsToIdleState (
           SetApProcedure (&mMpSystemData.CpuDatas[NextNumber],\r
                           mMpSystemData.Procedure,\r
                           mMpSystemData.ProcedureArgument);\r
+          //\r
+          // If this AP previous state is blocked, we should\r
+          // wake up this AP by sent a SIPI. and avoid\r
+          // re-involve the sleeping state. we must call\r
+          // SetApProcedure() first.\r
+          //\r
+          ResetProcessorToIdleState (&mMpSystemData.CpuDatas[NextNumber]);\r
         }\r
       }\r
-\r
       SetApState (CpuData, CpuStateIdle);\r
     }\r
   }\r
@@ -342,7 +349,8 @@ ResetAllFailedAPs (
     }\r
 \r
     CpuState = GetApState (CpuData);\r
-    if (CpuState != CpuStateIdle) {\r
+    if (CpuState != CpuStateIdle &&\r
+        CpuState != CpuStateSleeping) {\r
       if (mMpSystemData.FailedList != NULL) {\r
         (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex++] = Number;\r
       }\r
@@ -614,6 +622,7 @@ StartupAllAPs (
   CPU_DATA_BLOCK        *CpuData;\r
   UINTN                 Number;\r
   CPU_STATE             APInitialState;\r
+  CPU_STATE             CpuState;\r
 \r
   CpuData = NULL;\r
 \r
@@ -654,7 +663,9 @@ StartupAllAPs (
       continue;\r
     }\r
 \r
-    if (GetApState (CpuData) != CpuStateIdle) {\r
+    CpuState = GetApState (CpuData);\r
+    if (CpuState != CpuStateIdle &&\r
+        CpuState != CpuStateSleeping) {\r
       return EFI_NOT_READY;\r
     }\r
   }\r
@@ -663,7 +674,7 @@ StartupAllAPs (
   mMpSystemData.ProcedureArgument = ProcedureArgument;\r
   mMpSystemData.WaitEvent         = WaitEvent;\r
   mMpSystemData.Timeout           = TimeoutInMicroseconds;\r
-  mMpSystemData.TimeoutActive     = !!(TimeoutInMicroseconds);\r
+  mMpSystemData.TimeoutActive     = (BOOLEAN) (TimeoutInMicroseconds != 0);\r
   mMpSystemData.FinishCount       = 0;\r
   mMpSystemData.StartCount        = 0;\r
   mMpSystemData.SingleThread      = SingleThread;\r
@@ -693,13 +704,24 @@ StartupAllAPs (
     // state 1 by 1, until the previous 1 finished its task\r
     // if not "SingleThread", all APs are put to ready state from the beginning\r
     //\r
-    if (GetApState (CpuData) == CpuStateIdle) {\r
+    CpuState = GetApState (CpuData);\r
+    if (CpuState == CpuStateIdle ||\r
+        CpuState == CpuStateSleeping) {\r
       mMpSystemData.StartCount++;\r
 \r
       SetApState (CpuData, APInitialState);\r
 \r
       if (APInitialState == CpuStateReady) {\r
         SetApProcedure (CpuData, Procedure, ProcedureArgument);\r
+        //\r
+        // If this AP previous state is Sleeping, we should\r
+        // wake up this AP by sent a SIPI. and avoid\r
+        // re-involve the sleeping state. we must call\r
+        // SetApProcedure() first.\r
+        //\r
+        if (CpuState == CpuStateSleeping) {\r
+          ResetProcessorToIdleState (CpuData);\r
+        }\r
       }\r
 \r
       if (SingleThread) {\r
@@ -846,6 +868,7 @@ StartupThisAP (
   )\r
 {\r
   CPU_DATA_BLOCK        *CpuData;\r
+  CPU_STATE             CpuState;\r
 \r
   CpuData = NULL;\r
 \r
@@ -876,17 +899,28 @@ StartupThisAP (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (GetApState (CpuData) != CpuStateIdle) {\r
+  CpuState = GetApState (CpuData);\r
+  if (CpuState != CpuStateIdle &&\r
+      CpuState != CpuStateSleeping) {\r
     return EFI_NOT_READY;\r
   }\r
 \r
   SetApState (CpuData, CpuStateReady);\r
 \r
   SetApProcedure (CpuData, Procedure, ProcedureArgument);\r
+  //\r
+  // If this AP previous state is Sleeping, we should\r
+  // wake up this AP by sent a SIPI. and avoid\r
+  // re-involve the sleeping state. we must call\r
+  // SetApProcedure() first.\r
+  //\r
+  if (CpuState == CpuStateSleeping) {\r
+    ResetProcessorToIdleState (CpuData);\r
+  }\r
 \r
   CpuData->Timeout = TimeoutInMicroseconds;\r
   CpuData->WaitEvent = WaitEvent;\r
-  CpuData->TimeoutActive = !!(TimeoutInMicroseconds);\r
+  CpuData->TimeoutActive = (BOOLEAN) (TimeoutInMicroseconds != 0);\r
   CpuData->Finished = Finished;\r
 \r
   mStopCheckAllAPsStatus = FALSE;\r
@@ -1020,6 +1054,7 @@ EnableDisableAP (
 {\r
   CPU_DATA_BLOCK *CpuData;\r
   BOOLEAN        TempStopCheckState;\r
+  CPU_STATE      CpuState;\r
 \r
   CpuData = NULL;\r
   TempStopCheckState = FALSE;\r
@@ -1045,7 +1080,9 @@ EnableDisableAP (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (GetApState (CpuData) != CpuStateIdle) {\r
+  CpuState = GetApState (CpuData);\r
+  if (CpuState != CpuStateIdle &&\r
+      CpuState != CpuStateSleeping) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
@@ -1156,7 +1193,7 @@ ProcessorToIdleState (
   UINTN                 ProcessorNumber;\r
   CPU_DATA_BLOCK        *CpuData;\r
   EFI_AP_PROCEDURE      Procedure;\r
-  VOID                  *ProcedureArgument;\r
+  volatile VOID         *ProcedureArgument;\r
 \r
   AsmApDoneWithCommonStack ();\r
 \r
@@ -1175,11 +1212,14 @@ ProcessorToIdleState (
   }\r
 \r
   //\r
-  // Avoid forcibly reset AP caused the AP State is not updated.\r
+  // Avoid forcibly reset AP caused the timeout AP State is not\r
+  // updated.\r
   //\r
   GetMpSpinLock (CpuData);\r
+  if (CpuData->State == CpuStateBusy) {\r
+    CpuData->Procedure = NULL;\r
+  }\r
   CpuData->State = CpuStateIdle;\r
-  CpuData->Procedure = NULL;\r
   ReleaseMpSpinLock (CpuData);\r
 \r
   while (TRUE) {\r
@@ -1189,12 +1229,28 @@ ProcessorToIdleState (
     ReleaseMpSpinLock (CpuData);\r
 \r
     if (Procedure != NULL) {\r
-      Procedure (ProcedureArgument);\r
+      SetApState (CpuData, CpuStateBusy);\r
+\r
+      Procedure ((VOID*) ProcedureArgument);\r
 \r
       GetMpSpinLock (CpuData);\r
       CpuData->Procedure = NULL;\r
       CpuData->State = CpuStateFinished;\r
       ReleaseMpSpinLock (CpuData);\r
+    } else {\r
+      //\r
+      // if no procedure to execution, we simply put AP\r
+      // into sleeping state, and waiting BSP sent SIPI.\r
+      //\r
+      GetMpSpinLock (CpuData);\r
+      if (CpuData->State == CpuStateIdle) {\r
+          CpuData->State = CpuStateSleeping;\r
+      }\r
+      ReleaseMpSpinLock (CpuData);\r
+    }\r
+\r
+    if (GetApState (CpuData) == CpuStateSleeping) {\r
+      CpuSleep ();\r
     }\r
 \r
     CpuPause ();\r
@@ -1406,7 +1462,7 @@ FillInProcessorInformation (
   CpuData->Info.Location.Package = ProcessorId;\r
   CpuData->Info.Location.Core    = 0;\r
   CpuData->Info.Location.Thread  = 0;\r
-  CpuData->State = Bsp ? CpuStateBuzy : CpuStateIdle;\r
+  CpuData->State = Bsp ? CpuStateBusy : CpuStateIdle;\r
 \r
   CpuData->Procedure        = NULL;\r
   CpuData->Parameter        = NULL;\r
@@ -1464,6 +1520,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
@@ -1531,4 +1609,13 @@ InitializeMpSupport (
                                 (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