BSP will send broadcast INIT Startup IPI to all APs and collect APs count and
BIST information.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff....@intel.com>
CC: Feng Tian <feng.t...@intel.com>
CC: Jiewen Yao <jiewen....@intel.com>
CC: Michael Kinney <michael.d.kin...@intel.com>
---
 UefiCpuPkg/CpuMpPei/CpuMpPei.c   | 119 +++++++++++++++++++++++++++++++++++++++
 UefiCpuPkg/CpuMpPei/CpuMpPei.h   |   7 +++
 UefiCpuPkg/CpuMpPei/CpuMpPei.inf |   3 +
 3 files changed, 129 insertions(+)

diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.c b/UefiCpuPkg/CpuMpPei/CpuMpPei.c
index 45243d8..8367f05 100644
--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.c
+++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.c
@@ -39,6 +39,91 @@ GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = {
   };
 
 /**
+  This function will be called from AP reset code if BSP uses WakeUpAP.
+
+  @param ExchangeInfo     Pointer to the MP exchange info buffer
+  @param NumApsExecuting  Number of curret executing AP
+**/
+VOID
+EFIAPI
+ApCFunction (
+  IN MP_CPU_EXCHANGE_INFO      *ExchangeInfo,
+  IN UINTN                     NumApsExecuting
+  )
+{
+  PEI_CPU_MP_DATA            *PeiCpuMpData;
+  UINTN                      BistData;
+
+  PeiCpuMpData = ExchangeInfo->PeiCpuMpData;
+  if (PeiCpuMpData->InitFlag) {
+    //
+    // This is first time AP wakeup, get BIST inforamtion from AP stack
+    //
+    BistData = *(UINTN *) (PeiCpuMpData->Buffer + NumApsExecuting * 
PeiCpuMpData->CpuApStackSize - sizeof (UINTN));
+    PeiCpuMpData->CpuData[NumApsExecuting].ApicId        = GetInitialApicId ();
+    PeiCpuMpData->CpuData[NumApsExecuting].Health.Uint32 = (UINT32) BistData;
+  }
+
+  //
+  // AP finished executing C code
+  //
+  InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);
+
+}
+
+/**
+  This function will be called by BSP to wakeup AP.
+
+  @param PeiCpuMpData       Pointer to PEI CPU MP Data
+  @param Broadcast          TRUE:  Send broadcast IPI to all APs
+                            FALSE: Send IPI to AP by ApicId
+  @param ApicId             Apic ID for the processor to be waked
+  @param Procedure          The function to be invoked by AP
+  @param ProcedureArgument  The argument to be passed into AP function
+**/
+VOID
+WakeUpAP (
+  IN PEI_CPU_MP_DATA           *PeiCpuMpData,
+  IN BOOLEAN                   Broadcast,
+  IN UINT32                    ApicId,
+  IN EFI_AP_PROCEDURE          Procedure,              OPTIONAL
+  IN VOID                      *ProcedureArgument      OPTIONAL
+  )
+{
+  volatile MP_CPU_EXCHANGE_INFO    *ExchangeInfo;
+
+  PeiCpuMpData->ApFunction         = (UINTN) Procedure;
+  PeiCpuMpData->ApFunctionArgument = (UINTN) ProcedureArgument;
+  PeiCpuMpData->FinishedCount      = 0;
+
+  ExchangeInfo                     = PeiCpuMpData->MpCpuExchangeInfo;
+  ExchangeInfo->Lock               = 0;
+  ExchangeInfo->StackStart         = PeiCpuMpData->Buffer;
+  ExchangeInfo->StackSize          = PeiCpuMpData->CpuApStackSize;
+  ExchangeInfo->BufferStart        = PeiCpuMpData->WakeupBuffer;
+  ExchangeInfo->PmodeOffset        = PeiCpuMpData->AddressMap.PModeEntryOffset;
+  ExchangeInfo->LmodeOffset        = PeiCpuMpData->AddressMap.LModeEntryOffset;
+  ExchangeInfo->Cr3                = AsmReadCr3 ();
+  ExchangeInfo->CFunction          = (UINTN) ApCFunction;
+  ExchangeInfo->NumApsExecuting    = 0;
+  ExchangeInfo->PeiCpuMpData       = PeiCpuMpData;
+
+  //
+  // Get the BSP's data of GDT and IDT
+  //
+  CopyMem ((VOID *)&ExchangeInfo->GdtrProfile, &mGdt, sizeof(mGdt));
+  AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile);
+
+  if (Broadcast) {
+    SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart);
+  } else {
+    SendInitSipiSipi (ApicId, (UINT32) ExchangeInfo->BufferStart);
+  }
+
+  return ;
+}
+
+/**
   Get available system memory below 1MB by specified size.
 
   @param  WakeupBufferSize   Wakeup buffer size required
@@ -132,6 +217,35 @@ BackupAndPrepareWakeupBuffer(
     );
 }
 /**
+  This function will get CPU count in the system.
+
+  @param PeiCpuMpData        Pointer to PEI CPU MP Data
+
+  @return  AP processor count
+**/
+UINT32
+CountProcessorNumber (
+  IN PEI_CPU_MP_DATA            *PeiCpuMpData
+  )
+{
+
+  //
+  // Send broadcast IPI to APs to wakeup APs
+  //
+  PeiCpuMpData->InitFlag = 1;
+  WakeUpAP (PeiCpuMpData, TRUE, 0, NULL, NULL);
+  //
+  // Wait for AP task to complete and then exit.
+  //
+  MicroSecondDelay (PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));
+  PeiCpuMpData->InitFlag  = 0;
+  PeiCpuMpData->CpuCount += (UINT32) 
PeiCpuMpData->MpCpuExchangeInfo->NumApsExecuting;
+
+  DEBUG ((EFI_D_INFO, "CpuMpPei: Find %d processors in system.\n", 
PeiCpuMpData->CpuCount));
+  return PeiCpuMpData->CpuCount;
+}
+
+/**
   Prepare for AP wakeup buffer and copy AP reset code into it.
 
   Get wakeup buffer below 1MB. Allocate memory for CPU MP Data and APs Stack.
@@ -213,6 +327,7 @@ CpuMpPeimInit (
 {
 
   PEI_CPU_MP_DATA      *PeiCpuMpData;
+  UINT32               ProcessorCount;
 
   //
   // Load new GDT table on BSP
@@ -222,6 +337,10 @@ CpuMpPeimInit (
   // Get wakeup buffer and copy AP reset code in it
   //
   PeiCpuMpData = PrepareAPStartupVector ();
+  //
+  // Count processor number and collect processor information
+  //
+  ProcessorCount = CountProcessorNumber (PeiCpuMpData);
 
   return EFI_SUCCESS;
 }
diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.h b/UefiCpuPkg/CpuMpPei/CpuMpPei.h
index 1219e4e..3194f1f 100644
--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.h
+++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.h
@@ -27,6 +27,8 @@
 #include <Library/PcdLib.h>
 #include <Library/PeimEntryPoint.h>
 #include <Library/PeiServicesLib.h>
+#include <Library/SynchronizationLib.h>
+#include <Library/TimerLib.h>
 #include <Library/UefiCpuLib.h>
 //
 // AP state
@@ -85,6 +87,7 @@ typedef struct {
   UINTN                 NumApsExecuting;
   UINTN                 LmodeOffset;
   UINTN                 Cr3;
+  PEI_CPU_MP_DATA       *PeiCpuMpData;
 } MP_CPU_EXCHANGE_INFO;
 
 #pragma pack()
@@ -108,6 +111,10 @@ struct _PEI_CPU_MP_DATA {
   UINTN                          WakeupBuffer;
   UINTN                          BackupBuffer;
   UINTN                          BackupBufferSize;
+  UINTN                          ApFunction;
+  UINTN                          ApFunctionArgument;
+  volatile UINT32                FinishedCount;
+  BOOLEAN                        InitFlag;
   PEI_CPU_DATA                   *CpuData;
   volatile MP_CPU_EXCHANGE_INFO  *MpCpuExchangeInfo;
 };
diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
index a04556f..4d7ba3e 100644
--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
+++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
@@ -56,11 +56,14 @@
   PcdLib
   PeimEntryPoint
   PeiServicesLib
+  SynchronizationLib
+  TimerLib
   UefiCpuLib
 
 
 [Pcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
 
 [Depex]
-- 
1.9.5.msysgit.0


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to