WakeUpAP() is used to wakeup APs per current ApLoopMode and make sure APs wake
up successfully.

Cc: Michael Kinney <michael.d.kin...@intel.com>
Cc: Feng Tian <feng.t...@intel.com>
Cc: Giri P Mudusuru <giri.p.mudus...@intel.com>
Cc: Laszlo Ersek <ler...@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff....@intel.com>
---
 UefiCpuPkg/Library/MpInitLib/MpLib.c | 121 +++++++++++++++++++++++++++++++++++
 UefiCpuPkg/Library/MpInitLib/MpLib.h |  19 ++++++
 2 files changed, 140 insertions(+)

diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c 
b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index 8eff0e4..1cf2549 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -453,6 +453,29 @@ ApCFunction (
 }
 
 /**
+  Wait for AP wakeup and write AP start-up signal till AP is waken up.
+
+  @param[in] ApStartupSignalBuffer  Pointer to AP wakeup signal
+**/
+VOID
+WaitApWakeup (
+  IN volatile UINT32        *ApStartupSignalBuffer
+  )
+{
+  //
+  // If AP is waken up, StartupApSignal should be cleared.
+  // Otherwise, write StartupApSignal again till AP waken up.
+  //
+  while (InterlockedCompareExchange32 (
+          (UINT32 *) ApStartupSignalBuffer,
+          WAKEUP_AP_SIGNAL,
+          WAKEUP_AP_SIGNAL
+          ) != 0) {
+    CpuPause ();
+  }
+}
+
+/**
   This function will fill the exchange info structure.
 
   @param[in] CpuMpData          Pointer to CPU MP Data
@@ -491,6 +514,104 @@ FillExchangeInfoData (
 }
 
 /**
+  This function will be called by BSP to wakeup AP.
+
+  @param[in] CpuMpData          Pointer to CPU MP Data
+  @param[in] Broadcast          TRUE:  Send broadcast IPI to all APs
+                                FALSE: Send IPI to AP by ApicId
+  @param[in] ProcessorNumber    The handle number of specified processor
+  @param[in] Procedure          The function to be invoked by AP
+  @param[in] ProcedureArgument  The argument to be passed into AP function
+**/
+VOID
+WakeUpAP (
+  IN CPU_MP_DATA               *CpuMpData,
+  IN BOOLEAN                   Broadcast,
+  IN UINTN                     ProcessorNumber,
+  IN EFI_AP_PROCEDURE          Procedure,              OPTIONAL
+  IN VOID                      *ProcedureArgument      OPTIONAL
+  )
+{
+  volatile MP_CPU_EXCHANGE_INFO    *ExchangeInfo;
+  UINTN                            Index;
+  CPU_AP_DATA                      *CpuData;
+  BOOLEAN                          ResetVectorRequired;
+
+  CpuMpData->FinishedCount = 0;
+  ResetVectorRequired = FALSE;
+
+  if (CpuMpData->ApLoopMode == ApInHltLoop ||
+      CpuMpData->InitFlag   != ApInitDone) {
+    ResetVectorRequired = TRUE;
+    AllocateResetVector (CpuMpData);
+    FillExchangeInfoData (CpuMpData);
+  } else if (CpuMpData->ApLoopMode == ApInMwaitLoop) {
+    //
+    // Get AP target C-state each time when waking up AP,
+    // for it maybe updated by platform again
+    //
+    CpuMpData->ApTargetCState = PcdGet8 (PcdCpuApTargetCstate);
+  }
+
+  ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
+
+  if (Broadcast) {
+    for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
+      if (Index != CpuMpData->BspNumber) {
+        CpuData = &CpuMpData->CpuData[Index];
+        CpuData->ApFunction         = (UINTN) Procedure;
+        CpuData->ApFunctionArgument = (UINTN) ProcedureArgument;
+        SetApState (CpuData, CpuStateReady);
+        if (CpuMpData->InitFlag != ApInitConfig) {
+          *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
+        }
+      }
+    }
+    if (ResetVectorRequired) {
+      //
+      // Wakeup all APs
+      //
+      SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart);
+    }
+    if (CpuMpData->InitFlag != ApInitConfig) {
+      //
+      // Wait all APs waken up if this is not the 1st broadcast of SIPI
+      //
+      for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
+        CpuData = &CpuMpData->CpuData[Index];
+        if (Index != CpuMpData->BspNumber) {
+          WaitApWakeup (CpuData->StartupApSignal);
+        }
+      }
+    }
+  } else {
+    CpuData = &CpuMpData->CpuData[ProcessorNumber];
+    CpuData->ApFunction         = (UINTN) Procedure;
+    CpuData->ApFunctionArgument = (UINTN) ProcedureArgument;
+    SetApState (CpuData, CpuStateReady);
+    //
+    // Wakeup specified AP
+    //
+    ASSERT (CpuMpData->InitFlag != ApInitConfig);
+    *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
+    if (ResetVectorRequired) {
+      SendInitSipiSipi (
+        CpuData->ApicId,
+        (UINT32) ExchangeInfo->BufferStart
+        );
+    }
+    //
+    // Wait specified AP waken up
+    //
+    WaitApWakeup (CpuData->StartupApSignal);
+  }
+
+  if (ResetVectorRequired) {
+    FreeResetVector (CpuMpData);
+  }
+}
+
+/**
   MP Initialize Library initialization.
 
   This service will allocate AP reset vector and wakeup all APs to do APs
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h 
b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index 81dfc9e..4d47d66 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -258,6 +258,25 @@ FreeResetVector (
   );
 
 /**
+  This function will be called by BSP to wakeup AP.
+
+  @param[in] CpuMpData          Pointer to CPU MP Data
+  @param[in] Broadcast          TRUE:  Send broadcast IPI to all APs
+                                FALSE: Send IPI to AP by ApicId
+  @param[in] ProcessorNumber    The handle number of specified processor
+  @param[in] Procedure          The function to be invoked by AP
+  @param[in] ProcedureArgument  The argument to be passed into AP function
+**/
+VOID
+WakeUpAP (
+  IN CPU_MP_DATA               *CpuMpData,
+  IN BOOLEAN                   Broadcast,
+  IN UINTN                     ProcessorNumber,
+  IN EFI_AP_PROCEDURE          Procedure,              OPTIONAL
+  IN VOID                      *ProcedureArgument      OPTIONAL
+  );
+
+/**
   Initialize global data for MP support.
 
   @param[in] CpuMpData  The pointer to CPU MP Data structure.
-- 
2.7.4.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to