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
This commit is contained in:
Jeff Fan 2015-07-15 03:38:35 +00:00 committed by vanjeff
parent f79fcf4522
commit 7d51bf5c4e
3 changed files with 129 additions and 0 deletions

View File

@ -38,6 +38,91 @@ GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = {
(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.
@ -131,6 +216,35 @@ BackupAndPrepareWakeupBuffer(
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.
@ -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;
}

View File

@ -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;
};

View File

@ -56,11 +56,14 @@
PcdLib
PeimEntryPoint
PeiServicesLib
SynchronizationLib
TimerLib
UefiCpuLib
[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds
gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
[Depex]