]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/CpuMpPei: Place APs in proper loop mode after AP execution
authorJeff Fan <jeff.fan@intel.com>
Fri, 18 Dec 2015 03:25:32 +0000 (03:25 +0000)
committervanjeff <vanjeff@Edk2>
Fri, 18 Dec 2015 03:25:32 +0000 (03:25 +0000)
After AP function is executed, we will place AP in proper loop mode. Because AP
maybe waken up by SMI or other reasons. We need to read signature in monitor
buffer to check if APs is waken up by BSP. If it is not waken up by BSP, we will
continue to place them into proper loop mode.

Contributed-under: TianoCore Contribution Agreement 1.0
Cc: Feng Tian <feng.tian@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Tested-by: Michael Kinney <michael.d.kinney@intel.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19345 6f19259b-4bc3-4df7-8a09-765794883524

UefiCpuPkg/CpuMpPei/CpuMpPei.c
UefiCpuPkg/CpuMpPei/CpuMpPei.h
UefiCpuPkg/CpuMpPei/CpuMpPei.inf

index b8fa5118b45a8058ad10a377ecd99fdf67240e0f..ba82ba42184d606d6dc19256459c775872c31d51 100644 (file)
@@ -273,68 +273,124 @@ ApCFunction (
   UINTN                      ProcessorNumber;\r
   EFI_AP_PROCEDURE           Procedure;\r
   UINTN                      BistData;\r
   UINTN                      ProcessorNumber;\r
   EFI_AP_PROCEDURE           Procedure;\r
   UINTN                      BistData;\r
+  volatile UINT32            *ApStartupSignalBuffer;\r
 \r
   PeiCpuMpData = ExchangeInfo->PeiCpuMpData;\r
 \r
   PeiCpuMpData = ExchangeInfo->PeiCpuMpData;\r
-  if (PeiCpuMpData->InitFlag) {\r
-    ProcessorNumber = NumApsExecuting;\r
-    //\r
-    // Sync BSP's Control registers to APs\r
-    //\r
-    RestoreVolatileRegisters (&PeiCpuMpData->CpuData[0].VolatileRegisters, FALSE);\r
-    //\r
-    // This is first time AP wakeup, get BIST information from AP stack\r
-    //\r
-    BistData = *(UINTN *) (PeiCpuMpData->Buffer + ProcessorNumber * PeiCpuMpData->CpuApStackSize - sizeof (UINTN));\r
-    PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 = (UINT32) BistData;\r
-    PeiCpuMpData->CpuData[ProcessorNumber].ApicId = GetInitialApicId ();\r
-    if (PeiCpuMpData->CpuData[ProcessorNumber].ApicId >= 0xFF) {\r
+  while (TRUE) {\r
+    if (PeiCpuMpData->InitFlag) {\r
+      ProcessorNumber = NumApsExecuting;\r
+      //\r
+      // Sync BSP's Control registers to APs\r
+      //\r
+      RestoreVolatileRegisters (&PeiCpuMpData->CpuData[0].VolatileRegisters, FALSE);\r
+      //\r
+      // This is first time AP wakeup, get BIST information from AP stack\r
+      //\r
+      BistData = *(UINTN *) (PeiCpuMpData->Buffer + ProcessorNumber * PeiCpuMpData->CpuApStackSize - sizeof (UINTN));\r
+      PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 = (UINT32) BistData;\r
+      PeiCpuMpData->CpuData[ProcessorNumber].ApicId = GetInitialApicId ();\r
+      if (PeiCpuMpData->CpuData[ProcessorNumber].ApicId >= 0xFF) {\r
+        //\r
+        // Set x2APIC mode if there are any logical processor reporting\r
+        // an APIC ID of 255 or greater.\r
+        //\r
+        AcquireSpinLock(&PeiCpuMpData->MpLock);\r
+        PeiCpuMpData->X2ApicEnable = TRUE;\r
+        ReleaseSpinLock(&PeiCpuMpData->MpLock);\r
+      }\r
+      //\r
+      // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.\r
+      //\r
+      MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);\r
+      MicrocodeDetect ();\r
+      PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;\r
+    } else {\r
       //\r
       //\r
-      // Set x2APIC mode if there are any logical processor reporting\r
-      // an APIC ID of 255 or greater.\r
+      // Execute AP function if AP is not disabled\r
       //\r
       //\r
-      AcquireSpinLock(&PeiCpuMpData->MpLock);\r
-      PeiCpuMpData->X2ApicEnable = TRUE;\r
-      ReleaseSpinLock(&PeiCpuMpData->MpLock);\r
+      GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);\r
+      if (PeiCpuMpData->ApLoopMode == ApInHltLoop) {\r
+        //\r
+        // Restore AP's volatile registers saved\r
+        //\r
+        RestoreVolatileRegisters (&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);\r
+      }\r
+\r
+      if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&\r
+          (PeiCpuMpData->ApFunction != 0)) {\r
+        PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;\r
+        Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;\r
+        //\r
+        // Invoke AP function here\r
+        //\r
+        Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);\r
+        //\r
+        // Re-get the processor number due to BSP/AP maybe exchange in AP function\r
+        //\r
+        GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);\r
+        PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;\r
+      }\r
     }\r
     }\r
+\r
     //\r
     //\r
-    // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.\r
+    // AP finished executing C code\r
     //\r
     //\r
-    MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);\r
-    MicrocodeDetect ();\r
-    PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;\r
-  } else {\r
+    InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);\r
+\r
     //\r
     //\r
-    // Execute AP function if AP is not disabled\r
+    // Place AP is specified loop mode\r
     //\r
     //\r
-    GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);\r
+    if (PeiCpuMpData->ApLoopMode == ApInHltLoop) {\r
+      //\r
+      // Save AP volatile registers\r
+      //\r
+      SaveVolatileRegisters (&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters);\r
+      //\r
+      // Place AP in Hlt-loop\r
+      //\r
+      while (TRUE) {\r
+        DisableInterrupts ();\r
+        CpuSleep ();\r
+        CpuPause ();\r
+      }\r
+    }\r
+    ApStartupSignalBuffer = PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal;\r
     //\r
     //\r
-    // Restore AP's volatile registers saved\r
+    // Clear AP start-up signal\r
     //\r
     //\r
-    RestoreVolatileRegisters (&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);\r
+    *ApStartupSignalBuffer = 0;\r
+    while (TRUE) {\r
+      DisableInterrupts ();\r
+      if (PeiCpuMpData->ApLoopMode == ApInMwaitLoop) {\r
+        //\r
+        // Place AP in Mwait-loop\r
+        //\r
+        AsmMonitor ((UINTN)ApStartupSignalBuffer, 0, 0);\r
+        if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) {\r
+          //\r
+          // If AP start-up signal is not set, place AP into\r
+          // the maximum C-state\r
+          //\r
+          AsmMwait (PeiCpuMpData->ApTargetCState << 4, 0);\r
+        }\r
+      } else if (PeiCpuMpData->ApLoopMode == ApInRunLoop) {\r
+        //\r
+        // Place AP in Run-loop\r
+        //\r
+        CpuPause ();\r
+      } else {\r
+        ASSERT (FALSE);\r
+      }\r
 \r
 \r
-    if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&\r
-        (PeiCpuMpData->ApFunction != 0)) {\r
-      PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;\r
-      Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;\r
       //\r
       //\r
-      // Invoke AP function here\r
+      // If AP start-up signal is written, AP is waken up\r
+      // otherwise place AP in loop again\r
       //\r
       //\r
-      Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);\r
-      PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;\r
+      if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {\r
+        break;\r
+      }\r
     }\r
   }\r
     }\r
   }\r
-\r
-  //\r
-  // AP finished executing C code\r
-  //\r
-  InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);\r
-\r
-  //\r
-  // Save AP volatile registers\r
-  //\r
-  SaveVolatileRegisters (&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters);\r
-\r
-  AsmCliHltLoop ();\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
index a22bae7005426f270000b5417de4f1e311f4817f..47038c282533734ada8b122011fb9076fb86881a 100644 (file)
@@ -38,6 +38,7 @@
 #include <Library/SynchronizationLib.h>\r
 #include <Library/TimerLib.h>\r
 #include <Library/UefiCpuLib.h>\r
 #include <Library/SynchronizationLib.h>\r
 #include <Library/TimerLib.h>\r
 #include <Library/UefiCpuLib.h>\r
+#include <Library/CpuLib.h>\r
 \r
 #include "Microcode.h"\r
 \r
 \r
 #include "Microcode.h"\r
 \r
@@ -50,6 +51,8 @@ typedef enum {
   CpuStateDisabled\r
 } CPU_STATE;\r
 \r
   CpuStateDisabled\r
 } CPU_STATE;\r
 \r
+#define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')\r
+\r
 typedef enum {\r
   ApInHltLoop   = 1,\r
   ApInMwaitLoop = 2,\r
 typedef enum {\r
   ApInHltLoop   = 1,\r
   ApInMwaitLoop = 2,\r
index 4a5cfe75ff954e6b3e63c6f8dc100b7e6931c8a5..ec353aed7d500e5e932605b808c7a2821eec4e71 100644 (file)
@@ -66,6 +66,7 @@
   SynchronizationLib\r
   TimerLib\r
   UefiCpuLib\r
   SynchronizationLib\r
   TimerLib\r
   UefiCpuLib\r
+  CpuLib\r
 \r
 [Ppis]\r
   gEfiPeiMpServicesPpiGuid                      ## PRODUCES\r
 \r
 [Ppis]\r
   gEfiPeiMpServicesPpiGuid                      ## PRODUCES\r