mirror of https://github.com/acidanthera/audk.git
UefiCpuPkg/MpInitLib: Add ApWakeupFunction() executed by assembly code
ApWakeupFunction() is the first C function executed from AP reset vector. When APs waken up at the first time, it will sync BSP's MTRR setting and load microcode on APs and collect APs' BIST information. When AP tasked finished, it will place APs it one loop specified by ApLoopMode. v5: 1. Rename ApCFunction to ApWakeupFunction to meet naming convention. Cc: Michael Kinney <michael.d.kinney@intel.com> Cc: Feng Tian <feng.tian@intel.com> Cc: Giri P Mudusuru <giri.p.mudusuru@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Michael Kinney <michael.d.kinney@intel.com> Tested-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Michael Kinney <michael.d.kinney@intel.com>
This commit is contained in:
parent
ed66e0e3f4
commit
b8b04307eb
|
@ -174,6 +174,59 @@ GetApLoopMode (
|
|||
|
||||
return ApLoopMode;
|
||||
}
|
||||
|
||||
/**
|
||||
Do sync on APs.
|
||||
|
||||
@param[in, out] Buffer Pointer to private data buffer.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ApInitializeSync (
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
CPU_MP_DATA *CpuMpData;
|
||||
|
||||
CpuMpData = (CPU_MP_DATA *) Buffer;
|
||||
//
|
||||
// Sync BSP's MTRR table to AP
|
||||
//
|
||||
MtrrSetAllMtrrs (&CpuMpData->MtrrTable);
|
||||
//
|
||||
// Load microcode on AP
|
||||
//
|
||||
MicrocodeDetect (CpuMpData);
|
||||
}
|
||||
|
||||
/**
|
||||
Find the current Processor number by APIC ID.
|
||||
|
||||
@param[in] CpuMpData Pointer to PEI CPU MP Data
|
||||
@param[in] ProcessorNumber Return the pocessor number found
|
||||
|
||||
@retval EFI_SUCCESS ProcessorNumber is found and returned.
|
||||
@retval EFI_NOT_FOUND ProcessorNumber is not found.
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetProcessorNumber (
|
||||
IN CPU_MP_DATA *CpuMpData,
|
||||
OUT UINTN *ProcessorNumber
|
||||
)
|
||||
{
|
||||
UINTN TotalProcessorNumber;
|
||||
UINTN Index;
|
||||
|
||||
TotalProcessorNumber = CpuMpData->CpuCount;
|
||||
for (Index = 0; Index < TotalProcessorNumber; Index ++) {
|
||||
if (CpuMpData->CpuData[Index].ApicId == GetApicId ()) {
|
||||
*ProcessorNumber = Index;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize CPU AP Data when AP is wakeup at the first time.
|
||||
|
||||
|
@ -208,6 +261,151 @@ InitializeApData (
|
|||
SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
|
||||
}
|
||||
|
||||
/**
|
||||
This function will be called from AP reset code if BSP uses WakeUpAP.
|
||||
|
||||
@param[in] ExchangeInfo Pointer to the MP exchange info buffer
|
||||
@param[in] NumApsExecuting Number of current executing AP
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ApWakeupFunction (
|
||||
IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,
|
||||
IN UINTN NumApsExecuting
|
||||
)
|
||||
{
|
||||
CPU_MP_DATA *CpuMpData;
|
||||
UINTN ProcessorNumber;
|
||||
EFI_AP_PROCEDURE Procedure;
|
||||
VOID *Parameter;
|
||||
UINT32 BistData;
|
||||
volatile UINT32 *ApStartupSignalBuffer;
|
||||
|
||||
//
|
||||
// AP finished assembly code and begin to execute C code
|
||||
//
|
||||
CpuMpData = ExchangeInfo->CpuMpData;
|
||||
|
||||
ProgramVirtualWireMode ();
|
||||
|
||||
while (TRUE) {
|
||||
if (CpuMpData->InitFlag == ApInitConfig) {
|
||||
//
|
||||
// Add CPU number
|
||||
//
|
||||
InterlockedIncrement ((UINT32 *) &CpuMpData->CpuCount);
|
||||
ProcessorNumber = NumApsExecuting;
|
||||
//
|
||||
// This is first time AP wakeup, get BIST information from AP stack
|
||||
//
|
||||
BistData = *(UINT32 *) (CpuMpData->Buffer + ProcessorNumber * CpuMpData->CpuApStackSize - sizeof (UINTN));
|
||||
//
|
||||
// Do some AP initialize sync
|
||||
//
|
||||
ApInitializeSync (CpuMpData);
|
||||
//
|
||||
// Sync BSP's Control registers to APs
|
||||
//
|
||||
RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);
|
||||
InitializeApData (CpuMpData, ProcessorNumber, BistData);
|
||||
ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
|
||||
} else {
|
||||
//
|
||||
// Execute AP function if AP is ready
|
||||
//
|
||||
GetProcessorNumber (CpuMpData, &ProcessorNumber);
|
||||
//
|
||||
// Clear AP start-up signal when AP waken up
|
||||
//
|
||||
ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
|
||||
InterlockedCompareExchange32 (
|
||||
(UINT32 *) ApStartupSignalBuffer,
|
||||
WAKEUP_AP_SIGNAL,
|
||||
0
|
||||
);
|
||||
if (CpuMpData->ApLoopMode == ApInHltLoop) {
|
||||
//
|
||||
// Restore AP's volatile registers saved
|
||||
//
|
||||
RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);
|
||||
}
|
||||
|
||||
if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) {
|
||||
Procedure = (EFI_AP_PROCEDURE)CpuMpData->CpuData[ProcessorNumber].ApFunction;
|
||||
Parameter = (VOID *) CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument;
|
||||
if (Procedure != NULL) {
|
||||
SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateBusy);
|
||||
//
|
||||
// Invoke AP function here
|
||||
//
|
||||
Procedure (Parameter);
|
||||
//
|
||||
// Re-get the CPU APICID and Initial APICID
|
||||
//
|
||||
CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId ();
|
||||
CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();
|
||||
}
|
||||
SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// AP finished executing C code
|
||||
//
|
||||
InterlockedIncrement ((UINT32 *) &CpuMpData->FinishedCount);
|
||||
|
||||
//
|
||||
// Place AP is specified loop mode
|
||||
//
|
||||
if (CpuMpData->ApLoopMode == ApInHltLoop) {
|
||||
//
|
||||
// Save AP volatile registers
|
||||
//
|
||||
SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
|
||||
//
|
||||
// Place AP in HLT-loop
|
||||
//
|
||||
while (TRUE) {
|
||||
DisableInterrupts ();
|
||||
CpuSleep ();
|
||||
CpuPause ();
|
||||
}
|
||||
}
|
||||
while (TRUE) {
|
||||
DisableInterrupts ();
|
||||
if (CpuMpData->ApLoopMode == ApInMwaitLoop) {
|
||||
//
|
||||
// Place AP in MWAIT-loop
|
||||
//
|
||||
AsmMonitor ((UINTN) ApStartupSignalBuffer, 0, 0);
|
||||
if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) {
|
||||
//
|
||||
// Check AP start-up signal again.
|
||||
// If AP start-up signal is not set, place AP into
|
||||
// the specified C-state
|
||||
//
|
||||
AsmMwait (CpuMpData->ApTargetCState << 4, 0);
|
||||
}
|
||||
} else if (CpuMpData->ApLoopMode == ApInRunLoop) {
|
||||
//
|
||||
// Place AP in Run-loop
|
||||
//
|
||||
CpuPause ();
|
||||
} else {
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// If AP start-up signal is written, AP is waken up
|
||||
// otherwise place AP in loop again
|
||||
//
|
||||
if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
MP Initialize Library initialization.
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include <Library/MtrrLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
|
||||
#define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')
|
||||
|
||||
#define CPU_INIT_MP_LIB_HOB_GUID \
|
||||
{ \
|
||||
0x58eb6a19, 0x3699, 0x4c68, { 0xa8, 0x36, 0xda, 0xcd, 0x8e, 0xdc, 0xad, 0x4a } \
|
||||
|
|
Loading…
Reference in New Issue