mirror of https://github.com/acidanthera/audk.git
UefiCpuPkg/MpInitLib: Add WakeUpAP()
WakeUpAP() is used to wakeup APs per current ApLoopMode and make sure APs wake up successfully. 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
7c3f2a1253
commit
96f5920d1d
|
@ -447,6 +447,29 @@ ApWakeupFunction (
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Wait for AP wakeup and write AP start-up signal till AP is waken up.
|
||||
|
||||
@param[in] ApStartupSignalBuffer Pointer to AP wakeup signal
|
||||
**/
|
||||
VOID
|
||||
WaitApWakeup (
|
||||
IN volatile UINT32 *ApStartupSignalBuffer
|
||||
)
|
||||
{
|
||||
//
|
||||
// If AP is waken up, StartupApSignal should be cleared.
|
||||
// Otherwise, write StartupApSignal again till AP waken up.
|
||||
//
|
||||
while (InterlockedCompareExchange32 (
|
||||
(UINT32 *) ApStartupSignalBuffer,
|
||||
WAKEUP_AP_SIGNAL,
|
||||
WAKEUP_AP_SIGNAL
|
||||
) != 0) {
|
||||
CpuPause ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This function will fill the exchange info structure.
|
||||
|
||||
|
@ -485,6 +508,104 @@ FillExchangeInfoData (
|
|||
AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile);
|
||||
}
|
||||
|
||||
/**
|
||||
This function will be called by BSP to wakeup AP.
|
||||
|
||||
@param[in] CpuMpData Pointer to CPU MP Data
|
||||
@param[in] Broadcast TRUE: Send broadcast IPI to all APs
|
||||
FALSE: Send IPI to AP by ApicId
|
||||
@param[in] ProcessorNumber The handle number of specified processor
|
||||
@param[in] Procedure The function to be invoked by AP
|
||||
@param[in] ProcedureArgument The argument to be passed into AP function
|
||||
**/
|
||||
VOID
|
||||
WakeUpAP (
|
||||
IN CPU_MP_DATA *CpuMpData,
|
||||
IN BOOLEAN Broadcast,
|
||||
IN UINTN ProcessorNumber,
|
||||
IN EFI_AP_PROCEDURE Procedure, OPTIONAL
|
||||
IN VOID *ProcedureArgument OPTIONAL
|
||||
)
|
||||
{
|
||||
volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;
|
||||
UINTN Index;
|
||||
CPU_AP_DATA *CpuData;
|
||||
BOOLEAN ResetVectorRequired;
|
||||
|
||||
CpuMpData->FinishedCount = 0;
|
||||
ResetVectorRequired = FALSE;
|
||||
|
||||
if (CpuMpData->ApLoopMode == ApInHltLoop ||
|
||||
CpuMpData->InitFlag != ApInitDone) {
|
||||
ResetVectorRequired = TRUE;
|
||||
AllocateResetVector (CpuMpData);
|
||||
FillExchangeInfoData (CpuMpData);
|
||||
} else if (CpuMpData->ApLoopMode == ApInMwaitLoop) {
|
||||
//
|
||||
// Get AP target C-state each time when waking up AP,
|
||||
// for it maybe updated by platform again
|
||||
//
|
||||
CpuMpData->ApTargetCState = PcdGet8 (PcdCpuApTargetCstate);
|
||||
}
|
||||
|
||||
ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
|
||||
|
||||
if (Broadcast) {
|
||||
for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
|
||||
if (Index != CpuMpData->BspNumber) {
|
||||
CpuData = &CpuMpData->CpuData[Index];
|
||||
CpuData->ApFunction = (UINTN) Procedure;
|
||||
CpuData->ApFunctionArgument = (UINTN) ProcedureArgument;
|
||||
SetApState (CpuData, CpuStateReady);
|
||||
if (CpuMpData->InitFlag != ApInitConfig) {
|
||||
*(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ResetVectorRequired) {
|
||||
//
|
||||
// Wakeup all APs
|
||||
//
|
||||
SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart);
|
||||
}
|
||||
if (CpuMpData->InitFlag != ApInitConfig) {
|
||||
//
|
||||
// Wait all APs waken up if this is not the 1st broadcast of SIPI
|
||||
//
|
||||
for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
|
||||
CpuData = &CpuMpData->CpuData[Index];
|
||||
if (Index != CpuMpData->BspNumber) {
|
||||
WaitApWakeup (CpuData->StartupApSignal);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CpuData = &CpuMpData->CpuData[ProcessorNumber];
|
||||
CpuData->ApFunction = (UINTN) Procedure;
|
||||
CpuData->ApFunctionArgument = (UINTN) ProcedureArgument;
|
||||
SetApState (CpuData, CpuStateReady);
|
||||
//
|
||||
// Wakeup specified AP
|
||||
//
|
||||
ASSERT (CpuMpData->InitFlag != ApInitConfig);
|
||||
*(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
|
||||
if (ResetVectorRequired) {
|
||||
SendInitSipiSipi (
|
||||
CpuData->ApicId,
|
||||
(UINT32) ExchangeInfo->BufferStart
|
||||
);
|
||||
}
|
||||
//
|
||||
// Wait specified AP waken up
|
||||
//
|
||||
WaitApWakeup (CpuData->StartupApSignal);
|
||||
}
|
||||
|
||||
if (ResetVectorRequired) {
|
||||
FreeResetVector (CpuMpData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
MP Initialize Library initialization.
|
||||
|
||||
|
|
|
@ -282,6 +282,25 @@ FreeResetVector (
|
|||
IN CPU_MP_DATA *CpuMpData
|
||||
);
|
||||
|
||||
/**
|
||||
This function will be called by BSP to wakeup AP.
|
||||
|
||||
@param[in] CpuMpData Pointer to CPU MP Data
|
||||
@param[in] Broadcast TRUE: Send broadcast IPI to all APs
|
||||
FALSE: Send IPI to AP by ApicId
|
||||
@param[in] ProcessorNumber The handle number of specified processor
|
||||
@param[in] Procedure The function to be invoked by AP
|
||||
@param[in] ProcedureArgument The argument to be passed into AP function
|
||||
**/
|
||||
VOID
|
||||
WakeUpAP (
|
||||
IN CPU_MP_DATA *CpuMpData,
|
||||
IN BOOLEAN Broadcast,
|
||||
IN UINTN ProcessorNumber,
|
||||
IN EFI_AP_PROCEDURE Procedure, OPTIONAL
|
||||
IN VOID *ProcedureArgument OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize global data for MP support.
|
||||
|
||||
|
|
Loading…
Reference in New Issue