mirror of https://github.com/acidanthera/audk.git
UefiCpuPkg/CpuMpPei: Implementation of PeiStartupAllAPs ()
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@18008 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
bf55f5b274
commit
60ca9e8c18
|
@ -133,6 +133,8 @@ ApCFunction (
|
|||
)
|
||||
{
|
||||
PEI_CPU_MP_DATA *PeiCpuMpData;
|
||||
UINTN ProcessorNumber;
|
||||
EFI_AP_PROCEDURE Procedure;
|
||||
UINTN BistData;
|
||||
|
||||
PeiCpuMpData = ExchangeInfo->PeiCpuMpData;
|
||||
|
@ -148,6 +150,18 @@ ApCFunction (
|
|||
//
|
||||
MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);
|
||||
MicrocodeDetect ();
|
||||
} else {
|
||||
//
|
||||
// Execute AP function if AP is not disabled
|
||||
//
|
||||
GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
|
||||
if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&
|
||||
(PeiCpuMpData->ApFunction != 0)) {
|
||||
PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;
|
||||
Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;
|
||||
Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);
|
||||
PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -153,6 +153,25 @@ AsmInitializeGdt (
|
|||
);
|
||||
|
||||
|
||||
/**
|
||||
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
|
||||
);
|
||||
|
||||
/**
|
||||
Get CPU MP Data pointer from the Guided HOB.
|
||||
|
||||
|
@ -163,6 +182,21 @@ GetMpHobData (
|
|||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Find the current Processor number by APIC ID.
|
||||
|
||||
@param PeiCpuMpData Pointer to PEI CPU MP Data
|
||||
@param 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 PEI_CPU_MP_DATA *PeiCpuMpData,
|
||||
OUT UINTN *ProcessorNumber
|
||||
);
|
||||
|
||||
/**
|
||||
Collects BIST data from PPI.
|
||||
|
||||
|
|
|
@ -314,6 +314,189 @@ PeiGetProcessorInfo (
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This service executes a caller provided function on all enabled APs. APs can
|
||||
run either simultaneously or one at a time in sequence. This service supports
|
||||
both blocking requests only. This service may only
|
||||
be called from the BSP.
|
||||
|
||||
This function is used to dispatch all the enabled APs to the function specified
|
||||
by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned
|
||||
immediately and Procedure is not started on any AP.
|
||||
|
||||
If SingleThread is TRUE, all the enabled APs execute the function specified by
|
||||
Procedure one by one, in ascending order of processor handle number. Otherwise,
|
||||
all the enabled APs execute the function specified by Procedure simultaneously.
|
||||
|
||||
If the timeout specified by TimeoutInMicroSeconds expires before all APs return
|
||||
from Procedure, then Procedure on the failed APs is terminated. All enabled APs
|
||||
are always available for further calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
|
||||
and EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If FailedCpuList is not NULL, its
|
||||
content points to the list of processor handle numbers in which Procedure was
|
||||
terminated.
|
||||
|
||||
Note: It is the responsibility of the consumer of the EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
|
||||
to make sure that the nature of the code that is executed on the BSP and the
|
||||
dispatched APs is well controlled. The MP Services Ppi does not guarantee
|
||||
that the Procedure function is MP-safe. Hence, the tasks that can be run in
|
||||
parallel are limited to certain independent tasks and well-controlled exclusive
|
||||
code. PEI services and Ppis may not be called by APs unless otherwise
|
||||
specified.
|
||||
|
||||
In blocking execution mode, BSP waits until all APs finish or
|
||||
TimeoutInMicroSeconds expires.
|
||||
|
||||
@param[in] PeiServices An indirect pointer to the PEI Services Table
|
||||
published by the PEI Foundation.
|
||||
@param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
|
||||
@param[in] Procedure A pointer to the function to be run on enabled APs of
|
||||
the system.
|
||||
@param[in] SingleThread If TRUE, then all the enabled APs execute the function
|
||||
specified by Procedure one by one, in ascending order
|
||||
of processor handle number. If FALSE, then all the
|
||||
enabled APs execute the function specified by Procedure
|
||||
simultaneously.
|
||||
@param[in] TimeoutInMicroSeconds
|
||||
Indicates the time limit in microseconds for APs to
|
||||
return from Procedure, for blocking mode only. Zero
|
||||
means infinity. If the timeout expires before all APs
|
||||
return from Procedure, then Procedure on the failed APs
|
||||
is terminated. All enabled APs are available for next
|
||||
function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
|
||||
or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
|
||||
timeout expires in blocking mode, BSP returns
|
||||
EFI_TIMEOUT.
|
||||
@param[in] ProcedureArgument The parameter passed into Procedure for all APs.
|
||||
|
||||
@retval EFI_SUCCESS In blocking mode, all APs have finished before the
|
||||
timeout expired.
|
||||
@retval EFI_DEVICE_ERROR Caller processor is AP.
|
||||
@retval EFI_NOT_STARTED No enabled APs exist in the system.
|
||||
@retval EFI_NOT_READY Any enabled APs are busy.
|
||||
@retval EFI_TIMEOUT In blocking mode, the timeout expired before all
|
||||
enabled APs have finished.
|
||||
@retval EFI_INVALID_PARAMETER Procedure is NULL.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeiStartupAllAPs (
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_MP_SERVICES_PPI *This,
|
||||
IN EFI_AP_PROCEDURE Procedure,
|
||||
IN BOOLEAN SingleThread,
|
||||
IN UINTN TimeoutInMicroSeconds,
|
||||
IN VOID *ProcedureArgument OPTIONAL
|
||||
)
|
||||
{
|
||||
PEI_CPU_MP_DATA *PeiCpuMpData;
|
||||
UINTN ProcessorNumber;
|
||||
UINTN Index;
|
||||
UINTN CallerNumber;
|
||||
BOOLEAN HasEnabledAp;
|
||||
BOOLEAN HasEnabledIdleAp;
|
||||
volatile UINT32 *FinishedCount;
|
||||
EFI_STATUS Status;
|
||||
UINTN WaitCountIndex;
|
||||
UINTN WaitCountNumber;
|
||||
|
||||
PeiCpuMpData = GetMpHobData ();
|
||||
if (PeiCpuMpData == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether caller processor is BSP
|
||||
//
|
||||
PeiWhoAmI (PeiServices, This, &CallerNumber);
|
||||
if (CallerNumber != PeiCpuMpData->BspNumber) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
ProcessorNumber = PeiCpuMpData->CpuCount;
|
||||
|
||||
HasEnabledAp = FALSE;
|
||||
HasEnabledIdleAp = FALSE;
|
||||
for (Index = 0; Index < ProcessorNumber; Index ++) {
|
||||
if (Index == CallerNumber) {
|
||||
//
|
||||
// Skip BSP
|
||||
//
|
||||
continue;
|
||||
}
|
||||
if (PeiCpuMpData->CpuData[Index].State != CpuStateDisabled) {
|
||||
HasEnabledAp = TRUE;
|
||||
if (PeiCpuMpData->CpuData[Index].State != CpuStateBusy) {
|
||||
HasEnabledIdleAp = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!HasEnabledAp) {
|
||||
//
|
||||
// If no enabled AP exists, return EFI_NOT_STARTED.
|
||||
//
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
if (!HasEnabledIdleAp) {
|
||||
//
|
||||
// If any enabled APs are busy, return EFI_NOT_READY.
|
||||
//
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
|
||||
WaitCountNumber = TimeoutInMicroSeconds / CPU_CHECK_AP_INTERVAL + 1;
|
||||
WaitCountIndex = 0;
|
||||
FinishedCount = &PeiCpuMpData->FinishedCount;
|
||||
if (!SingleThread) {
|
||||
WakeUpAP (PeiCpuMpData, TRUE, 0, Procedure, ProcedureArgument);
|
||||
//
|
||||
// Wait to finish
|
||||
//
|
||||
if (TimeoutInMicroSeconds == 0) {
|
||||
while (*FinishedCount < ProcessorNumber - 1) {
|
||||
CpuPause ();
|
||||
}
|
||||
Status = EFI_SUCCESS;
|
||||
} else {
|
||||
Status = EFI_TIMEOUT;
|
||||
for (WaitCountIndex = 0; WaitCountIndex < WaitCountNumber; WaitCountIndex++) {
|
||||
MicroSecondDelay (CPU_CHECK_AP_INTERVAL);
|
||||
if (*FinishedCount >= ProcessorNumber - 1) {
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Status = EFI_SUCCESS;
|
||||
for (Index = 0; Index < ProcessorNumber; Index++) {
|
||||
if (Index == CallerNumber) {
|
||||
continue;
|
||||
}
|
||||
WakeUpAP (PeiCpuMpData, FALSE, PeiCpuMpData->CpuData[Index].ApicId, Procedure, ProcedureArgument);
|
||||
//
|
||||
// Wait to finish
|
||||
//
|
||||
if (TimeoutInMicroSeconds == 0) {
|
||||
while (*FinishedCount < 1) {
|
||||
CpuPause ();
|
||||
}
|
||||
} else {
|
||||
for (WaitCountIndex = 0; WaitCountIndex < WaitCountNumber; WaitCountIndex++) {
|
||||
MicroSecondDelay (CPU_CHECK_AP_INTERVAL);
|
||||
if (*FinishedCount >= 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (WaitCountIndex == WaitCountNumber) {
|
||||
Status = EFI_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This return the handle number for the calling processor. This service may be
|
||||
called from the BSP and APs.
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
|
||||
#include "CpuMpPei.h"
|
||||
|
||||
|
||||
#define CPU_CHECK_AP_INTERVAL 0x100 // 100 microseconds
|
||||
|
||||
/**
|
||||
This service retrieves the number of logical processor in the platform
|
||||
and the number of those logical processors that are enabled on this boot.
|
||||
|
@ -95,6 +98,80 @@ PeiGetProcessorInfo (
|
|||
OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
This service executes a caller provided function on all enabled APs. APs can
|
||||
run either simultaneously or one at a time in sequence. This service supports
|
||||
both blocking requests only. This service may only
|
||||
be called from the BSP.
|
||||
|
||||
This function is used to dispatch all the enabled APs to the function specified
|
||||
by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned
|
||||
immediately and Procedure is not started on any AP.
|
||||
|
||||
If SingleThread is TRUE, all the enabled APs execute the function specified by
|
||||
Procedure one by one, in ascending order of processor handle number. Otherwise,
|
||||
all the enabled APs execute the function specified by Procedure simultaneously.
|
||||
|
||||
If the timeout specified by TimeoutInMicroSeconds expires before all APs return
|
||||
from Procedure, then Procedure on the failed APs is terminated. All enabled APs
|
||||
are always available for further calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
|
||||
and EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If FailedCpuList is not NULL, its
|
||||
content points to the list of processor handle numbers in which Procedure was
|
||||
terminated.
|
||||
|
||||
Note: It is the responsibility of the consumer of the EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
|
||||
to make sure that the nature of the code that is executed on the BSP and the
|
||||
dispatched APs is well controlled. The MP Services Ppi does not guarantee
|
||||
that the Procedure function is MP-safe. Hence, the tasks that can be run in
|
||||
parallel are limited to certain independent tasks and well-controlled exclusive
|
||||
code. PEI services and Ppis may not be called by APs unless otherwise
|
||||
specified.
|
||||
|
||||
In blocking execution mode, BSP waits until all APs finish or
|
||||
TimeoutInMicroSeconds expires.
|
||||
|
||||
@param[in] PeiServices An indirect pointer to the PEI Services Table
|
||||
published by the PEI Foundation.
|
||||
@param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
|
||||
@param[in] Procedure A pointer to the function to be run on enabled APs of
|
||||
the system.
|
||||
@param[in] SingleThread If TRUE, then all the enabled APs execute the function
|
||||
specified by Procedure one by one, in ascending order
|
||||
of processor handle number. If FALSE, then all the
|
||||
enabled APs execute the function specified by Procedure
|
||||
simultaneously.
|
||||
@param[in] TimeoutInMicroSeconds
|
||||
Indicates the time limit in microseconds for APs to
|
||||
return from Procedure, for blocking mode only. Zero
|
||||
means infinity. If the timeout expires before all APs
|
||||
return from Procedure, then Procedure on the failed APs
|
||||
is terminated. All enabled APs are available for next
|
||||
function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs()
|
||||
or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the
|
||||
timeout expires in blocking mode, BSP returns
|
||||
EFI_TIMEOUT.
|
||||
@param[in] ProcedureArgument The parameter passed into Procedure for all APs.
|
||||
|
||||
@retval EFI_SUCCESS In blocking mode, all APs have finished before the
|
||||
timeout expired.
|
||||
@retval EFI_DEVICE_ERROR Caller processor is AP.
|
||||
@retval EFI_NOT_STARTED No enabled APs exist in the system.
|
||||
@retval EFI_NOT_READY Any enabled APs are busy.
|
||||
@retval EFI_TIMEOUT In blocking mode, the timeout expired before all
|
||||
enabled APs have finished.
|
||||
@retval EFI_INVALID_PARAMETER Procedure is NULL.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeiStartupAllAPs (
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_MP_SERVICES_PPI *This,
|
||||
IN EFI_AP_PROCEDURE Procedure,
|
||||
IN BOOLEAN SingleThread,
|
||||
IN UINTN TimeoutInMicroSeconds,
|
||||
IN VOID *ProcedureArgument OPTIONAL
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
This return the handle number for the calling processor. This service may be
|
||||
|
|
Loading…
Reference in New Issue