]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuMpPei/CpuMpPei.c
UefiCpuPkg/CpuMpPei: Place APs in proper loop mode after AP execution
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / CpuMpPei.c
index b8fa5118b45a8058ad10a377ecd99fdf67240e0f..ba82ba42184d606d6dc19256459c775872c31d51 100644 (file)
@@ -273,68 +273,124 @@ ApCFunction (
   UINTN                      ProcessorNumber;\r
   EFI_AP_PROCEDURE           Procedure;\r
   UINTN                      BistData;\r
+  volatile UINT32            *ApStartupSignalBuffer;\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
-      // 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
-      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
-    // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.\r
+    // AP finished executing C code\r
     //\r
-    MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);\r
-    MicrocodeDetect ();\r
-    PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;\r
-  } else {\r
+    InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);\r
+\r
     //\r
-    // Execute AP function if AP is not disabled\r
+    // Place AP is specified loop mode\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
-    // Restore AP's volatile registers saved\r
+    // Clear AP start-up signal\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
-    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
+      // If AP start-up signal is written, AP is waken up\r
+      // otherwise place AP in loop again\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
-  // 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