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