diff options
author | Jeff Fan <jeff.fan@intel.com> | 2015-07-15 03:38:35 +0000 |
---|---|---|
committer | vanjeff <vanjeff@Edk2> | 2015-07-15 03:38:35 +0000 |
commit | 7d51bf5c4e029bdc4c755b8591188b685c3d2927 (patch) | |
tree | 3939f08aab54eec22a074732cdac8494e4bd4fc2 /UefiCpuPkg | |
parent | f79fcf45227b9f002b6a8aebdf2dc6e4cd353760 (diff) | |
download | edk2-7d51bf5c4e029bdc4c755b8591188b685c3d2927.zip edk2-7d51bf5c4e029bdc4c755b8591188b685c3d2927.tar.gz edk2-7d51bf5c4e029bdc4c755b8591188b685c3d2927.tar.bz2 |
UefiCpuPkg/CpuMpPei: Wakeup APs and collect AP count
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
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r-- | UefiCpuPkg/CpuMpPei/CpuMpPei.c | 119 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/CpuMpPei.h | 7 | ||||
-rw-r--r-- | UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 3 |
3 files changed, 129 insertions, 0 deletions
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] |