]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/CpuMpPei: Wakeup APs and collect AP count
authorJeff Fan <jeff.fan@intel.com>
Wed, 15 Jul 2015 03:38:35 +0000 (03:38 +0000)
committervanjeff <vanjeff@Edk2>
Wed, 15 Jul 2015 03:38:35 +0000 (03:38 +0000)
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.fan@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17997 6f19259b-4bc3-4df7-8a09-765794883524

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

index 45243d804ee8fb7ac1a0306b5ef97f7b5dc068b4..8367f0573f22a394f3dd8338b12678495b5b5ed5 100644 (file)
@@ -38,6 +38,91 @@ GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = {
   (UINTN) mGdtEntries
   };
 
   (UINTN) mGdtEntries
   };
 
+/**
+  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.
 
 /**
   Get available system memory below 1MB by specified size.
 
@@ -131,6 +216,35 @@ BackupAndPrepareWakeupBuffer(
     PeiCpuMpData->AddressMap.RendezvousFunnelSize
     );
 }
     PeiCpuMpData->AddressMap.RendezvousFunnelSize
     );
 }
+/**
+  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.
 
 /**
   Prepare for AP wakeup buffer and copy AP reset code into it.
 
@@ -213,6 +327,7 @@ CpuMpPeimInit (
 {
 
   PEI_CPU_MP_DATA      *PeiCpuMpData;
 {
 
   PEI_CPU_MP_DATA      *PeiCpuMpData;
+  UINT32               ProcessorCount;
 
   //
   // Load new GDT table on BSP
 
   //
   // Load new GDT table on BSP
@@ -222,6 +337,10 @@ CpuMpPeimInit (
   // Get wakeup buffer and copy AP reset code in it
   //
   PeiCpuMpData = PrepareAPStartupVector ();
   // 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;
 }
 
   return EFI_SUCCESS;
 }
index 1219e4ea5aafcc53c39e48c7e663eeb7c6579f61..3194f1f0fa338f336ca0fae0752cb739b98d1acf 100644 (file)
@@ -27,6 +27,8 @@
 #include <Library/PcdLib.h>
 #include <Library/PeimEntryPoint.h>
 #include <Library/PeiServicesLib.h>
 #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
 #include <Library/UefiCpuLib.h>
 //
 // AP state
@@ -85,6 +87,7 @@ typedef struct {
   UINTN                 NumApsExecuting;
   UINTN                 LmodeOffset;
   UINTN                 Cr3;
   UINTN                 NumApsExecuting;
   UINTN                 LmodeOffset;
   UINTN                 Cr3;
+  PEI_CPU_MP_DATA       *PeiCpuMpData;
 } MP_CPU_EXCHANGE_INFO;
 
 #pragma pack()
 } MP_CPU_EXCHANGE_INFO;
 
 #pragma pack()
@@ -108,6 +111,10 @@ struct _PEI_CPU_MP_DATA {
   UINTN                          WakeupBuffer;
   UINTN                          BackupBuffer;
   UINTN                          BackupBufferSize;
   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;
 };
   PEI_CPU_DATA                   *CpuData;
   volatile MP_CPU_EXCHANGE_INFO  *MpCpuExchangeInfo;
 };
index a04556fb0255c482143b457b63f8b90e42da4b68..4d7ba3e1283e481cf7e50f9d414a45e8a8f228ac 100644 (file)
   PcdLib
   PeimEntryPoint
   PeiServicesLib
   PcdLib
   PeimEntryPoint
   PeiServicesLib
+  SynchronizationLib
+  TimerLib
   UefiCpuLib
 
 
 [Pcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
   UefiCpuLib
 
 
 [Pcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
 
 [Depex]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
 
 [Depex]