mirror of https://github.com/acidanthera/audk.git
UefiCpuPkg/PiSmmCpuDxeSmm: Enable MM MP Protocol
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1937 Add MM Mp Protocol in PiSmmCpuDxeSmm driver. Cc: Ray Ni <ray.ni@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Signed-off-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
parent
18f169a95c
commit
51dd408ae1
|
@ -136,11 +136,9 @@ ReleaseAllAPs (
|
|||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINTN BspIndex;
|
||||
|
||||
BspIndex = mSmmMpSyncData->BspIndex;
|
||||
for (Index = mMaxNumberOfCpus; Index-- > 0;) {
|
||||
if (Index != BspIndex && *(mSmmMpSyncData->CpuData[Index].Present)) {
|
||||
if (IsPresentAp (Index)) {
|
||||
ReleaseSemaphore (mSmmMpSyncData->CpuData[Index].Run);
|
||||
}
|
||||
}
|
||||
|
@ -347,6 +345,165 @@ ReplaceOSMtrrs (
|
|||
MtrrSetAllMtrrs (&gSmiMtrrs);
|
||||
}
|
||||
|
||||
/**
|
||||
Wheck whether task has been finished by all APs.
|
||||
|
||||
@param BlockMode Whether did it in block mode or non-block mode.
|
||||
|
||||
@retval TRUE Task has been finished by all APs.
|
||||
@retval FALSE Task not has been finished by all APs.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
WaitForAllAPsNotBusy (
|
||||
IN BOOLEAN BlockMode
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
for (Index = mMaxNumberOfCpus; Index-- > 0;) {
|
||||
//
|
||||
// Ignore BSP and APs which not call in SMM.
|
||||
//
|
||||
if (!IsPresentAp(Index)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BlockMode) {
|
||||
AcquireSpinLock(mSmmMpSyncData->CpuData[Index].Busy);
|
||||
ReleaseSpinLock(mSmmMpSyncData->CpuData[Index].Busy);
|
||||
} else {
|
||||
if (AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[Index].Busy)) {
|
||||
ReleaseSpinLock(mSmmMpSyncData->CpuData[Index].Busy);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether it is an present AP.
|
||||
|
||||
@param CpuIndex The AP index which calls this function.
|
||||
|
||||
@retval TRUE It's a present AP.
|
||||
@retval TRUE This is not an AP or it is not present.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsPresentAp (
|
||||
IN UINTN CpuIndex
|
||||
)
|
||||
{
|
||||
return ((CpuIndex != gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu) &&
|
||||
*(mSmmMpSyncData->CpuData[CpuIndex].Present));
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether execute in single AP or all APs.
|
||||
|
||||
Compare two Tokens used by different APs to know whether in StartAllAps call.
|
||||
|
||||
Whether is an valid AP base on AP's Present flag.
|
||||
|
||||
@retval TRUE IN StartAllAps call.
|
||||
@retval FALSE Not in StartAllAps call.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
InStartAllApsCall (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN ApIndex;
|
||||
UINTN ApIndex2;
|
||||
|
||||
for (ApIndex = mMaxNumberOfCpus; ApIndex-- > 0;) {
|
||||
if (IsPresentAp (ApIndex) && (mSmmMpSyncData->CpuData[ApIndex].Token != NULL)) {
|
||||
for (ApIndex2 = ApIndex; ApIndex2-- > 0;) {
|
||||
if (IsPresentAp (ApIndex2) && (mSmmMpSyncData->CpuData[ApIndex2].Token != NULL)) {
|
||||
return mSmmMpSyncData->CpuData[ApIndex2].Token == mSmmMpSyncData->CpuData[ApIndex].Token;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Clean up the status flags used during executing the procedure.
|
||||
|
||||
@param CpuIndex The AP index which calls this function.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReleaseToken (
|
||||
IN UINTN CpuIndex
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
BOOLEAN Released;
|
||||
|
||||
if (InStartAllApsCall ()) {
|
||||
//
|
||||
// In Start All APs mode, make sure all APs have finished task.
|
||||
//
|
||||
if (WaitForAllAPsNotBusy (FALSE)) {
|
||||
//
|
||||
// Clean the flags update in the function call.
|
||||
//
|
||||
Released = FALSE;
|
||||
for (Index = mMaxNumberOfCpus; Index-- > 0;) {
|
||||
//
|
||||
// Only In SMM APs need to be clean up.
|
||||
//
|
||||
if (mSmmMpSyncData->CpuData[Index].Present && mSmmMpSyncData->CpuData[Index].Token != NULL) {
|
||||
if (!Released) {
|
||||
ReleaseSpinLock (mSmmMpSyncData->CpuData[Index].Token);
|
||||
Released = TRUE;
|
||||
}
|
||||
mSmmMpSyncData->CpuData[Index].Token = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// In single AP mode.
|
||||
//
|
||||
if (mSmmMpSyncData->CpuData[CpuIndex].Token != NULL) {
|
||||
ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Token);
|
||||
mSmmMpSyncData->CpuData[CpuIndex].Token = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Free the tokens in the maintained list.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FreeTokens (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Link;
|
||||
PROCEDURE_TOKEN *ProcToken;
|
||||
|
||||
while (!IsListEmpty (&gSmmCpuPrivate->TokenList)) {
|
||||
Link = GetFirstNode (&gSmmCpuPrivate->TokenList);
|
||||
ProcToken = PROCEDURE_TOKEN_FROM_LINK (Link);
|
||||
|
||||
RemoveEntryList (&ProcToken->Link);
|
||||
|
||||
FreePool ((VOID *)ProcToken->ProcedureToken);
|
||||
FreePool (ProcToken);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
SMI handler for BSP.
|
||||
|
||||
|
@ -476,12 +633,7 @@ BSPHandler (
|
|||
//
|
||||
// Make sure all APs have completed their pending none-block tasks
|
||||
//
|
||||
for (Index = mMaxNumberOfCpus; Index-- > 0;) {
|
||||
if (Index != CpuIndex && *(mSmmMpSyncData->CpuData[Index].Present)) {
|
||||
AcquireSpinLock (mSmmMpSyncData->CpuData[Index].Busy);
|
||||
ReleaseSpinLock (mSmmMpSyncData->CpuData[Index].Busy);
|
||||
}
|
||||
}
|
||||
WaitForAllAPsNotBusy (TRUE);
|
||||
|
||||
//
|
||||
// Perform the remaining tasks
|
||||
|
@ -572,6 +724,11 @@ BSPHandler (
|
|||
//
|
||||
WaitForAllAPs (ApCount);
|
||||
|
||||
//
|
||||
// Clean the tokens buffer.
|
||||
//
|
||||
FreeTokens ();
|
||||
|
||||
//
|
||||
// Reset BspIndex to -1, meaning BSP has not been elected.
|
||||
//
|
||||
|
@ -604,6 +761,7 @@ APHandler (
|
|||
UINT64 Timer;
|
||||
UINTN BspIndex;
|
||||
MTRR_SETTINGS Mtrrs;
|
||||
EFI_STATUS ProcedureStatus;
|
||||
|
||||
//
|
||||
// Timeout BSP
|
||||
|
@ -730,14 +888,19 @@ APHandler (
|
|||
//
|
||||
// Invoke the scheduled procedure
|
||||
//
|
||||
(*mSmmMpSyncData->CpuData[CpuIndex].Procedure) (
|
||||
(VOID*)mSmmMpSyncData->CpuData[CpuIndex].Parameter
|
||||
);
|
||||
ProcedureStatus = (*mSmmMpSyncData->CpuData[CpuIndex].Procedure) (
|
||||
(VOID*)mSmmMpSyncData->CpuData[CpuIndex].Parameter
|
||||
);
|
||||
if (mSmmMpSyncData->CpuData[CpuIndex].Status != NULL) {
|
||||
*mSmmMpSyncData->CpuData[CpuIndex].Status = ProcedureStatus;
|
||||
}
|
||||
|
||||
//
|
||||
// Release BUSY
|
||||
//
|
||||
ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);
|
||||
|
||||
ReleaseToken (CpuIndex);
|
||||
}
|
||||
|
||||
if (SmmCpuFeaturesNeedConfigureMtrrs()) {
|
||||
|
@ -906,13 +1069,124 @@ Gen4GPageTable (
|
|||
return (UINT32)(UINTN)PageTable;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether the input token is the current used token.
|
||||
|
||||
@param[in] Token This parameter describes the token that was passed into DispatchProcedure or
|
||||
BroadcastProcedure.
|
||||
|
||||
@retval TRUE The input token is the current used token.
|
||||
@retval FALSE The input token is not the current used token.
|
||||
**/
|
||||
BOOLEAN
|
||||
IsTokenInUse (
|
||||
IN SPIN_LOCK *Token
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Link;
|
||||
PROCEDURE_TOKEN *ProcToken;
|
||||
|
||||
if (Token == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Link = GetFirstNode (&gSmmCpuPrivate->TokenList);
|
||||
while (!IsNull (&gSmmCpuPrivate->TokenList, Link)) {
|
||||
ProcToken = PROCEDURE_TOKEN_FROM_LINK (Link);
|
||||
|
||||
if (ProcToken->ProcedureToken == Token) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Link = GetNextNode (&gSmmCpuPrivate->TokenList, Link);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
create token and save it to the maintain list.
|
||||
|
||||
@retval return the spin lock used as token.
|
||||
|
||||
**/
|
||||
SPIN_LOCK *
|
||||
CreateToken (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PROCEDURE_TOKEN *ProcToken;
|
||||
SPIN_LOCK *CpuToken;
|
||||
UINTN SpinLockSize;
|
||||
|
||||
SpinLockSize = GetSpinLockProperties ();
|
||||
CpuToken = AllocatePool (SpinLockSize);
|
||||
ASSERT (CpuToken != NULL);
|
||||
InitializeSpinLock (CpuToken);
|
||||
AcquireSpinLock (CpuToken);
|
||||
|
||||
ProcToken = AllocatePool (sizeof (PROCEDURE_TOKEN));
|
||||
ASSERT (ProcToken != NULL);
|
||||
ProcToken->Signature = PROCEDURE_TOKEN_SIGNATURE;
|
||||
ProcToken->ProcedureToken = CpuToken;
|
||||
|
||||
InsertTailList (&gSmmCpuPrivate->TokenList, &ProcToken->Link);
|
||||
|
||||
return CpuToken;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks status of specified AP.
|
||||
|
||||
This function checks whether the specified AP has finished the task assigned
|
||||
by StartupThisAP(), and whether timeout expires.
|
||||
|
||||
@param[in] Token This parameter describes the token that was passed into DispatchProcedure or
|
||||
BroadcastProcedure.
|
||||
|
||||
@retval EFI_SUCCESS Specified AP has finished task assigned by StartupThisAPs().
|
||||
@retval EFI_NOT_READY Specified AP has not finished task and timeout has not expired.
|
||||
**/
|
||||
EFI_STATUS
|
||||
IsApReady (
|
||||
IN SPIN_LOCK *Token
|
||||
)
|
||||
{
|
||||
if (AcquireSpinLockOrFail (Token)) {
|
||||
ReleaseSpinLock (Token);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
Schedule a procedure to run on the specified CPU.
|
||||
|
||||
@param[in] Procedure The address of the procedure to run
|
||||
@param[in] CpuIndex Target CPU Index
|
||||
@param[in, out] ProcArguments The parameter to pass to the procedure
|
||||
@param[in] BlockingMode Startup AP in blocking mode or not
|
||||
@param[in,out] ProcArguments The parameter to pass to the procedure
|
||||
@param[in] Token This is an optional parameter that allows the caller to execute the
|
||||
procedure in a blocking or non-blocking fashion. If it is NULL the
|
||||
call is blocking, and the call will not return until the AP has
|
||||
completed the procedure. If the token is not NULL, the call will
|
||||
return immediately. The caller can check whether the procedure has
|
||||
completed with CheckOnProcedure or WaitForProcedure.
|
||||
@param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for the APs to finish
|
||||
execution of Procedure, either for blocking or non-blocking mode.
|
||||
Zero means infinity. If the timeout expires before all APs return
|
||||
from Procedure, then Procedure on the failed APs is terminated. If
|
||||
the timeout expires in blocking mode, the call returns EFI_TIMEOUT.
|
||||
If the timeout expires in non-blocking mode, the timeout determined
|
||||
can be through CheckOnProcedure or WaitForProcedure.
|
||||
Note that timeout support is optional. Whether an implementation
|
||||
supports this feature can be determined via the Attributes data
|
||||
member.
|
||||
@param[in,out] CpuStatus This optional pointer may be used to get the status code returned
|
||||
by Procedure when it completes execution on the target AP, or with
|
||||
EFI_TIMEOUT if the Procedure fails to complete within the optional
|
||||
timeout. The implementation will update this variable with
|
||||
EFI_NOT_READY prior to starting Procedure on the target AP.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER CpuNumber not valid
|
||||
@retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
|
||||
|
@ -923,10 +1197,12 @@ Gen4GPageTable (
|
|||
**/
|
||||
EFI_STATUS
|
||||
InternalSmmStartupThisAp (
|
||||
IN EFI_AP_PROCEDURE Procedure,
|
||||
IN UINTN CpuIndex,
|
||||
IN OUT VOID *ProcArguments OPTIONAL,
|
||||
IN BOOLEAN BlockingMode
|
||||
IN EFI_AP_PROCEDURE2 Procedure,
|
||||
IN UINTN CpuIndex,
|
||||
IN OUT VOID *ProcArguments OPTIONAL,
|
||||
IN MM_COMPLETION *Token,
|
||||
IN UINTN TimeoutInMicroseconds,
|
||||
IN OUT EFI_STATUS *CpuStatus
|
||||
)
|
||||
{
|
||||
if (CpuIndex >= gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus) {
|
||||
|
@ -952,24 +1228,190 @@ InternalSmmStartupThisAp (
|
|||
}
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
if ((TimeoutInMicroseconds != 0) && ((mSmmMp.Attributes & EFI_MM_MP_TIMEOUT_SUPPORTED) == 0)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
if (Procedure == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (BlockingMode) {
|
||||
if (Token == NULL) {
|
||||
AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);
|
||||
} else {
|
||||
if (!AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[CpuIndex].Busy)) {
|
||||
DEBUG((DEBUG_ERROR, "mSmmMpSyncData->CpuData[%d].Busy\n", CpuIndex));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
DEBUG((DEBUG_ERROR, "Can't acquire mSmmMpSyncData->CpuData[%d].Busy\n", CpuIndex));
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
|
||||
*Token = (MM_COMPLETION) CreateToken ();
|
||||
}
|
||||
|
||||
mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure;
|
||||
mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments;
|
||||
if (Token != NULL) {
|
||||
mSmmMpSyncData->CpuData[CpuIndex].Token = (SPIN_LOCK *)(*Token);
|
||||
}
|
||||
mSmmMpSyncData->CpuData[CpuIndex].Status = CpuStatus;
|
||||
if (mSmmMpSyncData->CpuData[CpuIndex].Status != NULL) {
|
||||
*mSmmMpSyncData->CpuData[CpuIndex].Status = EFI_NOT_READY;
|
||||
}
|
||||
|
||||
ReleaseSemaphore (mSmmMpSyncData->CpuData[CpuIndex].Run);
|
||||
|
||||
if (BlockingMode) {
|
||||
if (Token == NULL) {
|
||||
AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);
|
||||
ReleaseSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Worker function to execute a caller provided function on all enabled APs.
|
||||
|
||||
@param[in] Procedure A pointer to the function to be run on
|
||||
enabled APs of the system.
|
||||
@param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
|
||||
APs to return from Procedure, either for
|
||||
blocking or non-blocking mode.
|
||||
@param[in,out] ProcedureArguments The parameter passed into Procedure for
|
||||
all APs.
|
||||
@param[in,out] Token This is an optional parameter that allows the caller to execute the
|
||||
procedure in a blocking or non-blocking fashion. If it is NULL the
|
||||
call is blocking, and the call will not return until the AP has
|
||||
completed the procedure. If the token is not NULL, the call will
|
||||
return immediately. The caller can check whether the procedure has
|
||||
completed with CheckOnProcedure or WaitForProcedure.
|
||||
@param[in,out] CPUStatus This optional pointer may be used to get the status code returned
|
||||
by Procedure when it completes execution on the target AP, or with
|
||||
EFI_TIMEOUT if the Procedure fails to complete within the optional
|
||||
timeout. The implementation will update this variable with
|
||||
EFI_NOT_READY prior to starting Procedure on the target AP.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS In blocking mode, all APs have finished before
|
||||
the timeout expired.
|
||||
@retval EFI_SUCCESS In non-blocking mode, function has been dispatched
|
||||
to all enabled APs.
|
||||
@retval others Failed to Startup all APs.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
InternalSmmStartupAllAPs (
|
||||
IN EFI_AP_PROCEDURE2 Procedure,
|
||||
IN UINTN TimeoutInMicroseconds,
|
||||
IN OUT VOID *ProcedureArguments OPTIONAL,
|
||||
IN OUT MM_COMPLETION *Token,
|
||||
IN OUT EFI_STATUS *CPUStatus
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINTN CpuCount;
|
||||
|
||||
if ((TimeoutInMicroseconds != 0) && ((mSmmMp.Attributes & EFI_MM_MP_TIMEOUT_SUPPORTED) == 0)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
if (Procedure == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CpuCount = 0;
|
||||
for (Index = mMaxNumberOfCpus; Index-- > 0;) {
|
||||
if (IsPresentAp (Index)) {
|
||||
CpuCount ++;
|
||||
|
||||
if (gSmmCpuPrivate->Operation[Index] == SmmCpuRemove) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!AcquireSpinLockOrFail(mSmmMpSyncData->CpuData[Index].Busy)) {
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
ReleaseSpinLock (mSmmMpSyncData->CpuData[Index].Busy);
|
||||
}
|
||||
}
|
||||
if (CpuCount == 0) {
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
if (Token != NULL) {
|
||||
*Token = (MM_COMPLETION) CreateToken ();
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure all BUSY should be acquired.
|
||||
//
|
||||
// Because former code already check mSmmMpSyncData->CpuData[***].Busy for each AP.
|
||||
// Here code always use AcquireSpinLock instead of AcquireSpinLockOrFail for not
|
||||
// block mode.
|
||||
//
|
||||
for (Index = mMaxNumberOfCpus; Index-- > 0;) {
|
||||
if (IsPresentAp (Index)) {
|
||||
AcquireSpinLock (mSmmMpSyncData->CpuData[Index].Busy);
|
||||
}
|
||||
}
|
||||
|
||||
for (Index = mMaxNumberOfCpus; Index-- > 0;) {
|
||||
if (IsPresentAp (Index)) {
|
||||
mSmmMpSyncData->CpuData[Index].Procedure = (EFI_AP_PROCEDURE2) Procedure;
|
||||
mSmmMpSyncData->CpuData[Index].Parameter = ProcedureArguments;
|
||||
if (Token != NULL) {
|
||||
mSmmMpSyncData->CpuData[Index].Token = (SPIN_LOCK *)(*Token);
|
||||
}
|
||||
if (CPUStatus != NULL) {
|
||||
mSmmMpSyncData->CpuData[Index].Status = &CPUStatus[Index];
|
||||
if (mSmmMpSyncData->CpuData[Index].Status != NULL) {
|
||||
*mSmmMpSyncData->CpuData[Index].Status = EFI_NOT_READY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// PI spec requirement:
|
||||
// For every excluded processor, the array entry must contain a value of EFI_NOT_STARTED.
|
||||
//
|
||||
if (CPUStatus != NULL) {
|
||||
CPUStatus[Index] = EFI_NOT_STARTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseAllAPs ();
|
||||
|
||||
if (Token == NULL) {
|
||||
//
|
||||
// Make sure all APs have completed their tasks.
|
||||
//
|
||||
WaitForAllAPsNotBusy (TRUE);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
ISO C99 6.5.2.2 "Function calls", paragraph 9:
|
||||
If the function is defined with a type that is not compatible with
|
||||
the type (of the expression) pointed to by the expression that
|
||||
denotes the called function, the behavior is undefined.
|
||||
|
||||
So add below wrapper function to convert between EFI_AP_PROCEDURE
|
||||
and EFI_AP_PROCEDURE2.
|
||||
|
||||
Wrapper for Procedures.
|
||||
|
||||
@param[in] Buffer Pointer to PROCEDURE_WRAPPER buffer.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ProcedureWrapper (
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
PROCEDURE_WRAPPER *Wrapper;
|
||||
|
||||
Wrapper = Buffer;
|
||||
Wrapper->Procedure (Wrapper->ProcedureArgument);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -995,7 +1437,15 @@ SmmBlockingStartupThisAp (
|
|||
IN OUT VOID *ProcArguments OPTIONAL
|
||||
)
|
||||
{
|
||||
return InternalSmmStartupThisAp(Procedure, CpuIndex, ProcArguments, TRUE);
|
||||
PROCEDURE_WRAPPER Wrapper;
|
||||
|
||||
Wrapper.Procedure = Procedure;
|
||||
Wrapper.ProcedureArgument = ProcArguments;
|
||||
|
||||
//
|
||||
// Use wrapper function to convert EFI_AP_PROCEDURE to EFI_AP_PROCEDURE2.
|
||||
//
|
||||
return InternalSmmStartupThisAp (ProcedureWrapper, CpuIndex, &Wrapper, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1020,7 +1470,22 @@ SmmStartupThisAp (
|
|||
IN OUT VOID *ProcArguments OPTIONAL
|
||||
)
|
||||
{
|
||||
return InternalSmmStartupThisAp(Procedure, CpuIndex, ProcArguments, FeaturePcdGet (PcdCpuSmmBlockStartupThisAp));
|
||||
MM_COMPLETION Token;
|
||||
|
||||
gSmmCpuPrivate->ApWrapperFunc[CpuIndex].Procedure = Procedure;
|
||||
gSmmCpuPrivate->ApWrapperFunc[CpuIndex].ProcedureArgument = ProcArguments;
|
||||
|
||||
//
|
||||
// Use wrapper function to convert EFI_AP_PROCEDURE to EFI_AP_PROCEDURE2.
|
||||
//
|
||||
return InternalSmmStartupThisAp (
|
||||
ProcedureWrapper,
|
||||
CpuIndex,
|
||||
&gSmmCpuPrivate->ApWrapperFunc[CpuIndex],
|
||||
FeaturePcdGet (PcdCpuSmmBlockStartupThisAp) ? NULL : &Token,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1112,6 +1577,13 @@ SmiRendezvous (
|
|||
Cr2 = 0;
|
||||
SaveCr2 (&Cr2);
|
||||
|
||||
//
|
||||
// Call the user register Startup function first.
|
||||
//
|
||||
if (mSmmMpSyncData->StartupProcedure != NULL) {
|
||||
mSmmMpSyncData->StartupProcedure (mSmmMpSyncData->StartupProcArgs);
|
||||
}
|
||||
|
||||
//
|
||||
// Perform CPU specific entry hooks
|
||||
//
|
||||
|
@ -1256,6 +1728,21 @@ Exit:
|
|||
RestoreCr2 (Cr2);
|
||||
}
|
||||
|
||||
/**
|
||||
Allocate buffer for SpinLock and Wrapper function buffer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeDataForMmMp (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
gSmmCpuPrivate->ApWrapperFunc = AllocatePool (sizeof (PROCEDURE_WRAPPER) * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus);
|
||||
ASSERT (gSmmCpuPrivate->ApWrapperFunc != NULL);
|
||||
|
||||
InitializeListHead (&gSmmCpuPrivate->TokenList);
|
||||
}
|
||||
|
||||
/**
|
||||
Allocate buffer for all semaphores and spin locks.
|
||||
|
||||
|
@ -1469,3 +1956,40 @@ RegisterSmmEntry (
|
|||
gSmmCpuPrivate->SmmCoreEntry = SmmEntryPoint;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Register the SMM Foundation entry point.
|
||||
|
||||
@param[in] Procedure A pointer to the code stream to be run on the designated target AP
|
||||
of the system. Type EFI_AP_PROCEDURE is defined below in Volume 2
|
||||
with the related definitions of
|
||||
EFI_MP_SERVICES_PROTOCOL.StartupAllAPs.
|
||||
If caller may pass a value of NULL to deregister any existing
|
||||
startup procedure.
|
||||
@param[in] ProcedureArguments Allows the caller to pass a list of parameters to the code that is
|
||||
run by the AP. It is an optional common mailbox between APs and
|
||||
the caller to share information
|
||||
|
||||
@retval EFI_SUCCESS The Procedure has been set successfully.
|
||||
@retval EFI_INVALID_PARAMETER The Procedure is NULL but ProcedureArguments not NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
RegisterStartupProcedure (
|
||||
IN EFI_AP_PROCEDURE Procedure,
|
||||
IN VOID *ProcedureArguments OPTIONAL
|
||||
)
|
||||
{
|
||||
if (Procedure == NULL && ProcedureArguments != NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
if (mSmmMpSyncData == NULL) {
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
|
||||
mSmmMpSyncData->StartupProcedure = Procedure;
|
||||
mSmmMpSyncData->StartupProcArgs = ProcedureArguments;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ SMM_CPU_PRIVATE_DATA mSmmCpuPrivateData = {
|
|||
mSmmCpuPrivateData.SmmReservedSmramRegion, // SmmConfiguration.SmramReservedRegions
|
||||
RegisterSmmEntry // SmmConfiguration.RegisterSmmEntry
|
||||
},
|
||||
NULL, // pointer to Ap Wrapper Func array
|
||||
{NULL, NULL}, // List_Entry for Tokens.
|
||||
};
|
||||
|
||||
CPU_HOT_PLUG_DATA mCpuHotPlugData = {
|
||||
|
@ -996,6 +998,22 @@ PiCpuSmmEntry (
|
|||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Initialize global buffer for MM MP.
|
||||
//
|
||||
InitializeDataForMmMp ();
|
||||
|
||||
//
|
||||
// Install the SMM Mp Protocol into SMM protocol database
|
||||
//
|
||||
Status = gSmst->SmmInstallProtocolInterface (
|
||||
&mSmmCpuHandle,
|
||||
&gEfiMmMpProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&mSmmMp
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Expose address of CPU Hot Plug Data structure if CPU hot plug is supported.
|
||||
//
|
||||
|
|
|
@ -20,6 +20,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|||
#include <Protocol/SmmReadyToLock.h>
|
||||
#include <Protocol/SmmCpuService.h>
|
||||
#include <Protocol/SmmMemoryAttribute.h>
|
||||
#include <Protocol/MmMp.h>
|
||||
|
||||
#include <Guid/AcpiS3Context.h>
|
||||
#include <Guid/MemoryAttributesTable.h>
|
||||
|
@ -197,6 +198,25 @@ typedef UINT32 SMM_CPU_ARRIVAL_EXCEPTIONS;
|
|||
#define ARRIVAL_EXCEPTION_DELAYED 0x2
|
||||
#define ARRIVAL_EXCEPTION_SMI_DISABLED 0x4
|
||||
|
||||
//
|
||||
// Wrapper used to convert EFI_AP_PROCEDURE2 and EFI_AP_PROCEDURE.
|
||||
//
|
||||
typedef struct {
|
||||
EFI_AP_PROCEDURE Procedure;
|
||||
VOID *ProcedureArgument;
|
||||
} PROCEDURE_WRAPPER;
|
||||
|
||||
#define PROCEDURE_TOKEN_SIGNATURE SIGNATURE_32 ('P', 'R', 'T', 'S')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
SPIN_LOCK *ProcedureToken;
|
||||
} PROCEDURE_TOKEN;
|
||||
|
||||
#define PROCEDURE_TOKEN_FROM_LINK(a) CR (a, PROCEDURE_TOKEN, Link, PROCEDURE_TOKEN_SIGNATURE)
|
||||
|
||||
//
|
||||
// Private structure for the SMM CPU module that is stored in DXE Runtime memory
|
||||
// Contains the SMM Configuration Protocols that is produced.
|
||||
|
@ -219,6 +239,10 @@ typedef struct {
|
|||
EFI_SMM_ENTRY_POINT SmmCoreEntry;
|
||||
|
||||
EFI_SMM_CONFIGURATION_PROTOCOL SmmConfiguration;
|
||||
|
||||
PROCEDURE_WRAPPER *ApWrapperFunc;
|
||||
LIST_ENTRY TokenList;
|
||||
|
||||
} SMM_CPU_PRIVATE_DATA;
|
||||
|
||||
extern SMM_CPU_PRIVATE_DATA *gSmmCpuPrivate;
|
||||
|
@ -226,6 +250,7 @@ extern CPU_HOT_PLUG_DATA mCpuHotPlugData;
|
|||
extern UINTN mMaxNumberOfCpus;
|
||||
extern UINTN mNumberOfCpus;
|
||||
extern EFI_SMM_CPU_PROTOCOL mSmmCpu;
|
||||
extern EFI_MM_MP_PROTOCOL mSmmMp;
|
||||
|
||||
///
|
||||
/// The mode of the CPU at the time an SMI occurs
|
||||
|
@ -363,10 +388,12 @@ SmmRelocationSemaphoreComplete (
|
|||
///
|
||||
typedef struct {
|
||||
SPIN_LOCK *Busy;
|
||||
volatile EFI_AP_PROCEDURE Procedure;
|
||||
volatile EFI_AP_PROCEDURE2 Procedure;
|
||||
volatile VOID *Parameter;
|
||||
volatile UINT32 *Run;
|
||||
volatile BOOLEAN *Present;
|
||||
SPIN_LOCK *Token;
|
||||
EFI_STATUS *Status;
|
||||
} SMM_CPU_DATA_BLOCK;
|
||||
|
||||
typedef enum {
|
||||
|
@ -388,6 +415,8 @@ typedef struct {
|
|||
volatile SMM_CPU_SYNC_MODE EffectiveSyncMode;
|
||||
volatile BOOLEAN SwitchBsp;
|
||||
volatile BOOLEAN *CandidateBsp;
|
||||
EFI_AP_PROCEDURE StartupProcedure;
|
||||
VOID *StartupProcArgs;
|
||||
} SMM_DISPATCHER_MP_SYNC_DATA;
|
||||
|
||||
#define SMM_PSD_OFFSET 0xfb00
|
||||
|
@ -410,6 +439,7 @@ typedef struct {
|
|||
SPIN_LOCK *Busy;
|
||||
volatile UINT32 *Run;
|
||||
volatile BOOLEAN *Present;
|
||||
SPIN_LOCK *Token;
|
||||
} SMM_CPU_SEMAPHORE_CPU;
|
||||
|
||||
///
|
||||
|
@ -1259,4 +1289,165 @@ RestoreCr2 (
|
|||
IN UINTN Cr2
|
||||
);
|
||||
|
||||
/**
|
||||
Schedule a procedure to run on the specified CPU.
|
||||
|
||||
@param[in] Procedure The address of the procedure to run
|
||||
@param[in] CpuIndex Target CPU Index
|
||||
@param[in,out] ProcArguments The parameter to pass to the procedure
|
||||
@param[in,out] Token This is an optional parameter that allows the caller to execute the
|
||||
procedure in a blocking or non-blocking fashion. If it is NULL the
|
||||
call is blocking, and the call will not return until the AP has
|
||||
completed the procedure. If the token is not NULL, the call will
|
||||
return immediately. The caller can check whether the procedure has
|
||||
completed with CheckOnProcedure or WaitForProcedure.
|
||||
@param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for the APs to finish
|
||||
execution of Procedure, either for blocking or non-blocking mode.
|
||||
Zero means infinity. If the timeout expires before all APs return
|
||||
from Procedure, then Procedure on the failed APs is terminated. If
|
||||
the timeout expires in blocking mode, the call returns EFI_TIMEOUT.
|
||||
If the timeout expires in non-blocking mode, the timeout determined
|
||||
can be through CheckOnProcedure or WaitForProcedure.
|
||||
Note that timeout support is optional. Whether an implementation
|
||||
supports this feature can be determined via the Attributes data
|
||||
member.
|
||||
@param[in,out] CPUStatus This optional pointer may be used to get the status code returned
|
||||
by Procedure when it completes execution on the target AP, or with
|
||||
EFI_TIMEOUT if the Procedure fails to complete within the optional
|
||||
timeout. The implementation will update this variable with
|
||||
EFI_NOT_READY prior to starting Procedure on the target AP.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER CpuNumber not valid
|
||||
@retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
|
||||
@retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM
|
||||
@retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy
|
||||
@retval EFI_SUCCESS The procedure has been successfully scheduled
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
InternalSmmStartupThisAp (
|
||||
IN EFI_AP_PROCEDURE2 Procedure,
|
||||
IN UINTN CpuIndex,
|
||||
IN OUT VOID *ProcArguments OPTIONAL,
|
||||
IN MM_COMPLETION *Token,
|
||||
IN UINTN TimeoutInMicroseconds,
|
||||
IN OUT EFI_STATUS *CpuStatus
|
||||
);
|
||||
|
||||
/**
|
||||
Checks whether the input token is the current used token.
|
||||
|
||||
@param[in] Token This parameter describes the token that was passed into DispatchProcedure or
|
||||
BroadcastProcedure.
|
||||
|
||||
@retval TRUE The input token is the current used token.
|
||||
@retval FALSE The input token is not the current used token.
|
||||
**/
|
||||
BOOLEAN
|
||||
IsTokenInUse (
|
||||
IN SPIN_LOCK *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Checks status of specified AP.
|
||||
|
||||
This function checks whether the specified AP has finished the task assigned
|
||||
by StartupThisAP(), and whether timeout expires.
|
||||
|
||||
@param[in] Token This parameter describes the token that was passed into DispatchProcedure or
|
||||
BroadcastProcedure.
|
||||
|
||||
@retval EFI_SUCCESS Specified AP has finished task assigned by StartupThisAPs().
|
||||
@retval EFI_NOT_READY Specified AP has not finished task and timeout has not expired.
|
||||
**/
|
||||
EFI_STATUS
|
||||
IsApReady (
|
||||
IN SPIN_LOCK *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether it is an present AP.
|
||||
|
||||
@param CpuIndex The AP index which calls this function.
|
||||
|
||||
@retval TRUE It's a present AP.
|
||||
@retval TRUE This is not an AP or it is not present.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsPresentAp (
|
||||
IN UINTN CpuIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Worker function to execute a caller provided function on all enabled APs.
|
||||
|
||||
@param[in] Procedure A pointer to the function to be run on
|
||||
enabled APs of the system.
|
||||
@param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
|
||||
APs to return from Procedure, either for
|
||||
blocking or non-blocking mode.
|
||||
@param[in,out] ProcedureArgument The parameter passed into Procedure for
|
||||
all APs.
|
||||
@param[in,out] Token This is an optional parameter that allows the caller to execute the
|
||||
procedure in a blocking or non-blocking fashion. If it is NULL the
|
||||
call is blocking, and the call will not return until the AP has
|
||||
completed the procedure. If the token is not NULL, the call will
|
||||
return immediately. The caller can check whether the procedure has
|
||||
completed with CheckOnProcedure or WaitForProcedure.
|
||||
@param[in,out] CPUStatus This optional pointer may be used to get the status code returned
|
||||
by Procedure when it completes execution on the target AP, or with
|
||||
EFI_TIMEOUT if the Procedure fails to complete within the optional
|
||||
timeout. The implementation will update this variable with
|
||||
EFI_NOT_READY prior to starting Procedure on the target AP.
|
||||
|
||||
@retval EFI_SUCCESS In blocking mode, all APs have finished before
|
||||
the timeout expired.
|
||||
@retval EFI_SUCCESS In non-blocking mode, function has been dispatched
|
||||
to all enabled APs.
|
||||
@retval others Failed to Startup all APs.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
InternalSmmStartupAllAPs (
|
||||
IN EFI_AP_PROCEDURE2 Procedure,
|
||||
IN UINTN TimeoutInMicroseconds,
|
||||
IN OUT VOID *ProcedureArguments OPTIONAL,
|
||||
IN OUT MM_COMPLETION *Token,
|
||||
IN OUT EFI_STATUS *CPUStatus
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Register the SMM Foundation entry point.
|
||||
|
||||
@param[in] Procedure A pointer to the code stream to be run on the designated target AP
|
||||
of the system. Type EFI_AP_PROCEDURE is defined below in Volume 2
|
||||
with the related definitions of
|
||||
EFI_MP_SERVICES_PROTOCOL.StartupAllAPs.
|
||||
If caller may pass a value of NULL to deregister any existing
|
||||
startup procedure.
|
||||
@param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code that is
|
||||
run by the AP. It is an optional common mailbox between APs and
|
||||
the caller to share information
|
||||
|
||||
@retval EFI_SUCCESS The Procedure has been set successfully.
|
||||
@retval EFI_INVALID_PARAMETER The Procedure is NULL but ProcedureArguments not NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
RegisterStartupProcedure (
|
||||
IN EFI_AP_PROCEDURE Procedure,
|
||||
IN VOID *ProcedureArguments OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate buffer for SpinLock and Wrapper function buffer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeDataForMmMp (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
SmmProfileInternal.h
|
||||
SmramSaveState.c
|
||||
SmmCpuMemoryManagement.c
|
||||
SmmMp.h
|
||||
SmmMp.c
|
||||
|
||||
[Sources.Ia32]
|
||||
Ia32/Semaphore.c
|
||||
|
@ -105,6 +107,7 @@
|
|||
gEfiSmmReadyToLockProtocolGuid ## NOTIFY
|
||||
gEfiSmmCpuServiceProtocolGuid ## PRODUCES
|
||||
gEdkiiSmmMemoryAttributeProtocolGuid ## PRODUCES
|
||||
gEfiMmMpProtocolGuid ## PRODUCES
|
||||
|
||||
[Guids]
|
||||
gEfiAcpiVariableGuid ## SOMETIMES_CONSUMES ## HOB # it is used for S3 boot.
|
||||
|
|
|
@ -0,0 +1,344 @@
|
|||
/** @file
|
||||
SMM MP protocol implementation
|
||||
|
||||
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
#include "SmmMp.h"
|
||||
|
||||
///
|
||||
/// SMM MP Protocol instance
|
||||
///
|
||||
EFI_MM_MP_PROTOCOL mSmmMp = {
|
||||
EFI_MM_MP_PROTOCOL_REVISION,
|
||||
0,
|
||||
SmmMpGetNumberOfProcessors,
|
||||
SmmMpDispatchProcedure,
|
||||
SmmMpBroadcastProcedure,
|
||||
SmmMpSetStartupProcedure,
|
||||
SmmMpCheckForProcedure,
|
||||
SmmMpWaitForProcedure
|
||||
};
|
||||
|
||||
/**
|
||||
Service to retrieves the number of logical processor in the platform.
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[out] NumberOfProcessors Pointer to the total number of logical processors in the system,
|
||||
including the BSP and all APs.
|
||||
|
||||
@retval EFI_SUCCESS The number of processors was retrieved successfully
|
||||
@retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpGetNumberOfProcessors (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
OUT UINTN *NumberOfProcessors
|
||||
)
|
||||
{
|
||||
if (NumberOfProcessors == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*NumberOfProcessors = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This service allows the caller to invoke a procedure one of the application processors (AP). This
|
||||
function uses an optional token parameter to support blocking and non-blocking modes. If the token
|
||||
is passed into the call, the function will operate in a non-blocking fashion and the caller can
|
||||
check for completion with CheckOnProcedure or WaitForProcedure.
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[in] Procedure A pointer to the procedure to be run on the designated target
|
||||
AP of the system. Type EFI_AP_PROCEDURE2 is defined below in
|
||||
related definitions.
|
||||
@param[in] CpuNumber The zero-based index of the processor number of the target
|
||||
AP, on which the code stream is supposed to run. If the number
|
||||
points to the calling processor then it will not run the
|
||||
supplied code.
|
||||
@param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for this AP to
|
||||
finish execution of Procedure, either for blocking or
|
||||
non-blocking mode. Zero means infinity. If the timeout
|
||||
expires before this AP returns from Procedure, then Procedure
|
||||
on the AP is terminated. If the timeout expires in blocking
|
||||
mode, the call returns EFI_TIMEOUT. If the timeout expires
|
||||
in non-blocking mode, the timeout determined can be through
|
||||
CheckOnProcedure or WaitForProcedure.
|
||||
Note that timeout support is optional. Whether an
|
||||
implementation supports this feature, can be determined via
|
||||
the Attributes data member.
|
||||
@param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code
|
||||
that is run by the AP. It is an optional common mailbox
|
||||
between APs and the caller to share information.
|
||||
@param[in,out] Token This is parameter is broken into two components:
|
||||
1.Token->Completion is an optional parameter that allows the
|
||||
caller to execute the procedure in a blocking or non-blocking
|
||||
fashion. If it is NULL the call is blocking, and the call will
|
||||
not return until the AP has completed the procedure. If the
|
||||
token is not NULL, the call will return immediately. The caller
|
||||
can check whether the procedure has completed with
|
||||
CheckOnProcedure or WaitForProcedure.
|
||||
2.Token->Status The implementation updates the address pointed
|
||||
at by this variable with the status code returned by Procedure
|
||||
when it completes execution on the target AP, or with EFI_TIMEOUT
|
||||
if the Procedure fails to complete within the optional timeout.
|
||||
The implementation will update this variable with EFI_NOT_READY
|
||||
prior to starting Procedure on the target AP
|
||||
@param[in,out] CPUStatus This optional pointer may be used to get the status code returned
|
||||
by Procedure when it completes execution on the target AP, or with
|
||||
EFI_TIMEOUT if the Procedure fails to complete within the optional
|
||||
timeout. The implementation will update this variable with
|
||||
EFI_NOT_READY prior to starting Procedure on the target AP.
|
||||
|
||||
@retval EFI_SUCCESS In the blocking case, this indicates that Procedure has completed
|
||||
execution on the target AP.
|
||||
In the non-blocking case this indicates that the procedure has
|
||||
been successfully scheduled for execution on the target AP.
|
||||
@retval EFI_INVALID_PARAMETER The input arguments are out of range. Either the target AP is the
|
||||
caller of the function, or the Procedure or Token is NULL
|
||||
@retval EFI_NOT_READY If the target AP is busy executing another procedure
|
||||
@retval EFI_ALREADY_STARTED Token is already in use for another procedure
|
||||
@retval EFI_TIMEOUT In blocking mode, the timeout expired before the specified AP
|
||||
has finished
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate a required resource.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpDispatchProcedure (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
IN EFI_AP_PROCEDURE2 Procedure,
|
||||
IN UINTN CpuNumber,
|
||||
IN UINTN TimeoutInMicroseconds,
|
||||
IN OUT VOID *ProcedureArguments OPTIONAL,
|
||||
IN OUT MM_COMPLETION *Token,
|
||||
IN OUT EFI_STATUS *CPUStatus
|
||||
)
|
||||
{
|
||||
return InternalSmmStartupThisAp (
|
||||
Procedure,
|
||||
CpuNumber,
|
||||
ProcedureArguments,
|
||||
Token,
|
||||
TimeoutInMicroseconds,
|
||||
CPUStatus
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
This service allows the caller to invoke a procedure on all running application processors (AP)
|
||||
except the caller. This function uses an optional token parameter to support blocking and
|
||||
nonblocking modes. If the token is passed into the call, the function will operate in a non-blocking
|
||||
fashion and the caller can check for completion with CheckOnProcedure or WaitForProcedure.
|
||||
|
||||
It is not necessary for the implementation to run the procedure on every processor on the platform.
|
||||
Processors that are powered down in such a way that they cannot respond to interrupts, may be
|
||||
excluded from the broadcast.
|
||||
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[in] Procedure A pointer to the code stream to be run on the APs that have
|
||||
entered MM. Type EFI_AP_PROCEDURE is defined below in related
|
||||
definitions.
|
||||
@param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for the APs to finish
|
||||
execution of Procedure, either for blocking or non-blocking mode.
|
||||
Zero means infinity. If the timeout expires before all APs return
|
||||
from Procedure, then Procedure on the failed APs is terminated. If
|
||||
the timeout expires in blocking mode, the call returns EFI_TIMEOUT.
|
||||
If the timeout expires in non-blocking mode, the timeout determined
|
||||
can be through CheckOnProcedure or WaitForProcedure.
|
||||
Note that timeout support is optional. Whether an implementation
|
||||
supports this feature can be determined via the Attributes data
|
||||
member.
|
||||
@param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code
|
||||
that is run by the AP. It is an optional common mailbox
|
||||
between APs and the caller to share information.
|
||||
@param[in,out] Token This is parameter is broken into two components:
|
||||
1.Token->Completion is an optional parameter that allows the
|
||||
caller to execute the procedure in a blocking or non-blocking
|
||||
fashion. If it is NULL the call is blocking, and the call will
|
||||
not return until the AP has completed the procedure. If the
|
||||
token is not NULL, the call will return immediately. The caller
|
||||
can check whether the procedure has completed with
|
||||
CheckOnProcedure or WaitForProcedure.
|
||||
2.Token->Status The implementation updates the address pointed
|
||||
at by this variable with the status code returned by Procedure
|
||||
when it completes execution on the target AP, or with EFI_TIMEOUT
|
||||
if the Procedure fails to complete within the optional timeout.
|
||||
The implementation will update this variable with EFI_NOT_READY
|
||||
prior to starting Procedure on the target AP
|
||||
@param[in,out] CPUStatus This optional pointer may be used to get the individual status
|
||||
returned by every AP that participated in the broadcast. This
|
||||
parameter if used provides the base address of an array to hold
|
||||
the EFI_STATUS value of each AP in the system. The size of the
|
||||
array can be ascertained by the GetNumberOfProcessors function.
|
||||
As mentioned above, the broadcast may not include every processor
|
||||
in the system. Some implementations may exclude processors that
|
||||
have been powered down in such a way that they are not responsive
|
||||
to interrupts. Additionally the broadcast excludes the processor
|
||||
which is making the BroadcastProcedure call. For every excluded
|
||||
processor, the array entry must contain a value of EFI_NOT_STARTED
|
||||
|
||||
@retval EFI_SUCCESS In the blocking case, this indicates that Procedure has completed
|
||||
execution on the APs.
|
||||
In the non-blocking case this indicates that the procedure has
|
||||
been successfully scheduled for execution on the APs.
|
||||
@retval EFI_INVALID_PARAMETER The Procedure or Token is NULL
|
||||
@retval EFI_NOT_READY If the target AP is busy executing another procedure
|
||||
@retval EFI_ALREADY_STARTED Token is already in use for another procedure
|
||||
@retval EFI_TIMEOUT In blocking mode, the timeout expired before the specified AP
|
||||
has finished.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate a required resource.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpBroadcastProcedure (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
IN EFI_AP_PROCEDURE2 Procedure,
|
||||
IN UINTN TimeoutInMicroseconds,
|
||||
IN OUT VOID *ProcedureArguments OPTIONAL,
|
||||
IN OUT MM_COMPLETION *Token,
|
||||
IN OUT EFI_STATUS *CPUStatus
|
||||
)
|
||||
{
|
||||
return InternalSmmStartupAllAPs(
|
||||
Procedure,
|
||||
TimeoutInMicroseconds,
|
||||
ProcedureArguments,
|
||||
Token,
|
||||
CPUStatus
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
This service allows the caller to set a startup procedure that will be executed when an AP powers
|
||||
up from a state where core configuration and context is lost. The procedure is execution has the
|
||||
following properties:
|
||||
1. The procedure executes before the processor is handed over to the operating system.
|
||||
2. All processors execute the same startup procedure.
|
||||
3. The procedure may run in parallel with other procedures invoked through the functions in this
|
||||
protocol, or with processors that are executing an MM handler or running in the operating system.
|
||||
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[in] Procedure A pointer to the code stream to be run on the designated target AP
|
||||
of the system. Type EFI_AP_PROCEDURE is defined below in Volume 2
|
||||
with the related definitions of
|
||||
EFI_MP_SERVICES_PROTOCOL.StartupAllAPs.
|
||||
If caller may pass a value of NULL to deregister any existing
|
||||
startup procedure.
|
||||
@param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code that is
|
||||
run by the AP. It is an optional common mailbox between APs and
|
||||
the caller to share information
|
||||
|
||||
@retval EFI_SUCCESS The Procedure has been set successfully.
|
||||
@retval EFI_INVALID_PARAMETER The Procedure is NULL but ProcedureArguments not NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpSetStartupProcedure (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
IN EFI_AP_PROCEDURE Procedure,
|
||||
IN OUT VOID *ProcedureArguments OPTIONAL
|
||||
)
|
||||
{
|
||||
return RegisterStartupProcedure (Procedure, ProcedureArguments);
|
||||
}
|
||||
|
||||
/**
|
||||
When non-blocking execution of a procedure on an AP is invoked with DispatchProcedure,
|
||||
via the use of a token, this function can be used to check for completion of the procedure on the AP.
|
||||
The function takes the token that was passed into the DispatchProcedure call. If the procedure
|
||||
is complete, and therefore it is now possible to run another procedure on the same AP, this function
|
||||
returns EFI_SUCESS. In this case the status returned by the procedure that executed on the AP is
|
||||
returned in the token's Status field. If the procedure has not yet completed, then this function
|
||||
returns EFI_NOT_READY.
|
||||
|
||||
When a non-blocking execution of a procedure is invoked with BroadcastProcedure, via the
|
||||
use of a token, this function can be used to check for completion of the procedure on all the
|
||||
broadcast APs. The function takes the token that was passed into the BroadcastProcedure
|
||||
call. If the procedure is complete on all broadcast APs this function returns EFI_SUCESS. In this
|
||||
case the Status field in the token passed into the function reflects the overall result of the
|
||||
invocation, which may be EFI_SUCCESS, if all executions succeeded, or the first observed failure.
|
||||
If the procedure has not yet completed on the broadcast APs, the function returns
|
||||
EFI_NOT_READY.
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[in] Token This parameter describes the token that was passed into
|
||||
DispatchProcedure or BroadcastProcedure.
|
||||
|
||||
@retval EFI_SUCCESS Procedure has completed.
|
||||
@retval EFI_NOT_READY The Procedure has not completed.
|
||||
@retval EFI_INVALID_PARAMETER Token or Token->Completion is NULL
|
||||
@retval EFI_NOT_FOUND Token is not currently in use for a non-blocking call
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpCheckForProcedure (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
IN MM_COMPLETION Token
|
||||
)
|
||||
{
|
||||
if (Token == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!IsTokenInUse ((SPIN_LOCK *)Token)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
return IsApReady ((SPIN_LOCK *)Token);
|
||||
}
|
||||
|
||||
/**
|
||||
When a non-blocking execution of a procedure on an AP is invoked via DispatchProcedure,
|
||||
this function will block the caller until the remote procedure has completed on the designated AP.
|
||||
The non-blocking procedure invocation is identified by the Token parameter, which must match the
|
||||
token that used when DispatchProcedure was called. Upon completion the status returned by
|
||||
the procedure that executed on the AP is used to update the token's Status field.
|
||||
|
||||
When a non-blocking execution of a procedure on an AP is invoked via BroadcastProcedure
|
||||
this function will block the caller until the remote procedure has completed on all of the APs that
|
||||
entered MM. The non-blocking procedure invocation is identified by the Token parameter, which
|
||||
must match the token that used when BroadcastProcedure was called. Upon completion the
|
||||
overall status returned by the procedures that executed on the broadcast AP is used to update the
|
||||
token's Status field. The overall status may be EFI_SUCCESS, if all executions succeeded, or the
|
||||
first observed failure.
|
||||
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[in] Token This parameter describes the token that was passed into
|
||||
DispatchProcedure or BroadcastProcedure.
|
||||
|
||||
@retval EFI_SUCCESS Procedure has completed.
|
||||
@retval EFI_INVALID_PARAMETER Token or Token->Completion is NULL
|
||||
@retval EFI_NOT_FOUND Token is not currently in use for a non-blocking call
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpWaitForProcedure (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
IN MM_COMPLETION Token
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
do {
|
||||
Status = SmmMpCheckForProcedure (This, Token);
|
||||
} while (Status == EFI_NOT_READY);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
@ -0,0 +1,286 @@
|
|||
/** @file
|
||||
Include file for SMM MP protocol implementation.
|
||||
|
||||
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SMM_MP_PROTOCOL_H_
|
||||
#define _SMM_MP_PROTOCOL_H_
|
||||
|
||||
//
|
||||
// SMM MP Protocol function prototypes.
|
||||
//
|
||||
|
||||
/**
|
||||
Service to retrieves the number of logical processor in the platform.
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[out] NumberOfProcessors Pointer to the total number of logical processors in the system,
|
||||
including the BSP and all APs.
|
||||
|
||||
@retval EFI_SUCCESS The number of processors was retrieved successfully
|
||||
@retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL
|
||||
**/
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpGetNumberOfProcessors (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
OUT UINTN *NumberOfProcessors
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
This service allows the caller to invoke a procedure one of the application processors (AP). This
|
||||
function uses an optional token parameter to support blocking and non-blocking modes. If the token
|
||||
is passed into the call, the function will operate in a non-blocking fashion and the caller can
|
||||
check for completion with CheckOnProcedure or WaitForProcedure.
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[in] Procedure A pointer to the procedure to be run on the designated target
|
||||
AP of the system. Type EFI_AP_PROCEDURE2 is defined below in
|
||||
related definitions.
|
||||
@param[in] CpuNumber The zero-based index of the processor number of the target
|
||||
AP, on which the code stream is supposed to run. If the number
|
||||
points to the calling processor then it will not run the
|
||||
supplied code.
|
||||
@param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for this AP to
|
||||
finish execution of Procedure, either for blocking or
|
||||
non-blocking mode. Zero means infinity. If the timeout
|
||||
expires before this AP returns from Procedure, then Procedure
|
||||
on the AP is terminated. If the timeout expires in blocking
|
||||
mode, the call returns EFI_TIMEOUT. If the timeout expires
|
||||
in non-blocking mode, the timeout determined can be through
|
||||
CheckOnProcedure or WaitForProcedure.
|
||||
Note that timeout support is optional. Whether an
|
||||
implementation supports this feature, can be determined via
|
||||
the Attributes data member.
|
||||
@param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code
|
||||
that is run by the AP. It is an optional common mailbox
|
||||
between APs and the caller to share information.
|
||||
@param[in,out] Token This is parameter is broken into two components:
|
||||
1.Token->Completion is an optional parameter that allows the
|
||||
caller to execute the procedure in a blocking or non-blocking
|
||||
fashion. If it is NULL the call is blocking, and the call will
|
||||
not return until the AP has completed the procedure. If the
|
||||
token is not NULL, the call will return immediately. The caller
|
||||
can check whether the procedure has completed with
|
||||
CheckOnProcedure or WaitForProcedure.
|
||||
2.Token->Status The implementation updates the address pointed
|
||||
at by this variable with the status code returned by Procedure
|
||||
when it completes execution on the target AP, or with EFI_TIMEOUT
|
||||
if the Procedure fails to complete within the optional timeout.
|
||||
The implementation will update this variable with EFI_NOT_READY
|
||||
prior to starting Procedure on the target AP
|
||||
@param[in,out] CPUStatus This optional pointer may be used to get the status code returned
|
||||
by Procedure when it completes execution on the target AP, or with
|
||||
EFI_TIMEOUT if the Procedure fails to complete within the optional
|
||||
timeout. The implementation will update this variable with
|
||||
EFI_NOT_READY prior to starting Procedure on the target AP.
|
||||
|
||||
@retval EFI_SUCCESS In the blocking case, this indicates that Procedure has completed
|
||||
execution on the target AP.
|
||||
In the non-blocking case this indicates that the procedure has
|
||||
been successfully scheduled for execution on the target AP.
|
||||
@retval EFI_INVALID_PARAMETER The input arguments are out of range. Either the target AP is the
|
||||
caller of the function, or the Procedure or Token is NULL
|
||||
@retval EFI_NOT_READY If the target AP is busy executing another procedure
|
||||
@retval EFI_ALREADY_STARTED Token is already in use for another procedure
|
||||
@retval EFI_TIMEOUT In blocking mode, the timeout expired before the specified AP
|
||||
has finished
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate a required resource.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpDispatchProcedure (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
IN EFI_AP_PROCEDURE2 Procedure,
|
||||
IN UINTN CpuNumber,
|
||||
IN UINTN TimeoutInMicroseconds,
|
||||
IN OUT VOID *ProcedureArguments OPTIONAL,
|
||||
IN OUT MM_COMPLETION *Token,
|
||||
IN OUT EFI_STATUS *CPUStatus
|
||||
);
|
||||
|
||||
/**
|
||||
This service allows the caller to invoke a procedure on all running application processors (AP)
|
||||
except the caller. This function uses an optional token parameter to support blocking and
|
||||
nonblocking modes. If the token is passed into the call, the function will operate in a non-blocking
|
||||
fashion and the caller can check for completion with CheckOnProcedure or WaitForProcedure.
|
||||
|
||||
It is not necessary for the implementation to run the procedure on every processor on the platform.
|
||||
Processors that are powered down in such a way that they cannot respond to interrupts, may be
|
||||
excluded from the broadcast.
|
||||
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[in] Procedure A pointer to the code stream to be run on the APs that have
|
||||
entered MM. Type EFI_AP_PROCEDURE is defined below in related
|
||||
definitions.
|
||||
@param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for the APs to finish
|
||||
execution of Procedure, either for blocking or non-blocking mode.
|
||||
Zero means infinity. If the timeout expires before all APs return
|
||||
from Procedure, then Procedure on the failed APs is terminated. If
|
||||
the timeout expires in blocking mode, the call returns EFI_TIMEOUT.
|
||||
If the timeout expires in non-blocking mode, the timeout determined
|
||||
can be through CheckOnProcedure or WaitForProcedure.
|
||||
Note that timeout support is optional. Whether an implementation
|
||||
supports this feature can be determined via the Attributes data
|
||||
member.
|
||||
@param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code
|
||||
that is run by the AP. It is an optional common mailbox
|
||||
between APs and the caller to share information.
|
||||
@param[in,out] Token This is parameter is broken into two components:
|
||||
1.Token->Completion is an optional parameter that allows the
|
||||
caller to execute the procedure in a blocking or non-blocking
|
||||
fashion. If it is NULL the call is blocking, and the call will
|
||||
not return until the AP has completed the procedure. If the
|
||||
token is not NULL, the call will return immediately. The caller
|
||||
can check whether the procedure has completed with
|
||||
CheckOnProcedure or WaitForProcedure.
|
||||
2.Token->Status The implementation updates the address pointed
|
||||
at by this variable with the status code returned by Procedure
|
||||
when it completes execution on the target AP, or with EFI_TIMEOUT
|
||||
if the Procedure fails to complete within the optional timeout.
|
||||
The implementation will update this variable with EFI_NOT_READY
|
||||
prior to starting Procedure on the target AP
|
||||
@param[in,out] CPUStatus This optional pointer may be used to get the individual status
|
||||
returned by every AP that participated in the broadcast. This
|
||||
parameter if used provides the base address of an array to hold
|
||||
the EFI_STATUS value of each AP in the system. The size of the
|
||||
array can be ascertained by the GetNumberOfProcessors function.
|
||||
As mentioned above, the broadcast may not include every processor
|
||||
in the system. Some implementations may exclude processors that
|
||||
have been powered down in such a way that they are not responsive
|
||||
to interrupts. Additionally the broadcast excludes the processor
|
||||
which is making the BroadcastProcedure call. For every excluded
|
||||
processor, the array entry must contain a value of EFI_NOT_STARTED
|
||||
|
||||
@retval EFI_SUCCESS In the blocking case, this indicates that Procedure has completed
|
||||
execution on the APs.
|
||||
In the non-blocking case this indicates that the procedure has
|
||||
been successfully scheduled for execution on the APs.
|
||||
@retval EFI_INVALID_PARAMETER The Procedure or Token is NULL
|
||||
@retval EFI_NOT_READY If the target AP is busy executing another procedure
|
||||
@retval EFI_ALREADY_STARTED Token is already in use for another procedure
|
||||
@retval EFI_TIMEOUT In blocking mode, the timeout expired before the specified AP
|
||||
has finished
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate a required resource.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpBroadcastProcedure (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
IN EFI_AP_PROCEDURE2 Procedure,
|
||||
IN UINTN TimeoutInMicroseconds,
|
||||
IN OUT VOID *ProcedureArguments OPTIONAL,
|
||||
IN OUT MM_COMPLETION *Token,
|
||||
IN OUT EFI_STATUS *CPUStatus
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
This service allows the caller to set a startup procedure that will be executed when an AP powers
|
||||
up from a state where core configuration and context is lost. The procedure is execution has the
|
||||
following properties:
|
||||
1. The procedure executes before the processor is handed over to the operating system.
|
||||
2. All processors execute the same startup procedure.
|
||||
3. The procedure may run in parallel with other procedures invoked through the functions in this
|
||||
protocol, or with processors that are executing an MM handler or running in the operating system.
|
||||
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[in] Procedure A pointer to the code stream to be run on the designated target AP
|
||||
of the system. Type EFI_AP_PROCEDURE is defined below in Volume 2
|
||||
with the related definitions of
|
||||
EFI_MP_SERVICES_PROTOCOL.StartupAllAPs.
|
||||
If caller may pass a value of NULL to deregister any existing
|
||||
startup procedure.
|
||||
@param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code that is
|
||||
run by the AP. It is an optional common mailbox between APs and
|
||||
the caller to share information
|
||||
|
||||
@retval EFI_SUCCESS The Procedure has been set successfully.
|
||||
@retval EFI_INVALID_PARAMETER The Procedure is NULL but ProcedureArguments not NULL.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpSetStartupProcedure (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
IN EFI_AP_PROCEDURE Procedure,
|
||||
IN OUT VOID *ProcedureArguments OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
When non-blocking execution of a procedure on an AP is invoked with DispatchProcedure,
|
||||
via the use of a token, this function can be used to check for completion of the procedure on the AP.
|
||||
The function takes the token that was passed into the DispatchProcedure call. If the procedure
|
||||
is complete, and therefore it is now possible to run another procedure on the same AP, this function
|
||||
returns EFI_SUCESS. In this case the status returned by the procedure that executed on the AP is
|
||||
returned in the token's Status field. If the procedure has not yet completed, then this function
|
||||
returns EFI_NOT_READY.
|
||||
|
||||
When a non-blocking execution of a procedure is invoked with BroadcastProcedure, via the
|
||||
use of a token, this function can be used to check for completion of the procedure on all the
|
||||
broadcast APs. The function takes the token that was passed into the BroadcastProcedure
|
||||
call. If the procedure is complete on all broadcast APs this function returns EFI_SUCESS. In this
|
||||
case the Status field in the token passed into the function reflects the overall result of the
|
||||
invocation, which may be EFI_SUCCESS, if all executions succeeded, or the first observed failure.
|
||||
If the procedure has not yet completed on the broadcast APs, the function returns
|
||||
EFI_NOT_READY.
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[in] Token This parameter describes the token that was passed into
|
||||
DispatchProcedure or BroadcastProcedure.
|
||||
|
||||
@retval EFI_SUCCESS Procedure has completed.
|
||||
@retval EFI_NOT_READY The Procedure has not completed.
|
||||
@retval EFI_INVALID_PARAMETER Token or Token->Completion is NULL
|
||||
@retval EFI_NOT_FOUND Token is not currently in use for a non-blocking call
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpCheckForProcedure (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
IN MM_COMPLETION Token
|
||||
);
|
||||
|
||||
/**
|
||||
When a non-blocking execution of a procedure on an AP is invoked via DispatchProcedure,
|
||||
this function will block the caller until the remote procedure has completed on the designated AP.
|
||||
The non-blocking procedure invocation is identified by the Token parameter, which must match the
|
||||
token that used when DispatchProcedure was called. Upon completion the status returned by
|
||||
the procedure that executed on the AP is used to update the token's Status field.
|
||||
|
||||
When a non-blocking execution of a procedure on an AP is invoked via BroadcastProcedure
|
||||
this function will block the caller until the remote procedure has completed on all of the APs that
|
||||
entered MM. The non-blocking procedure invocation is identified by the Token parameter, which
|
||||
must match the token that used when BroadcastProcedure was called. Upon completion the
|
||||
overall status returned by the procedures that executed on the broadcast AP is used to update the
|
||||
token's Status field. The overall status may be EFI_SUCCESS, if all executions succeeded, or the
|
||||
first observed failure.
|
||||
|
||||
|
||||
@param[in] This The EFI_MM_MP_PROTOCOL instance.
|
||||
@param[in] Token This parameter describes the token that was passed into
|
||||
DispatchProcedure or BroadcastProcedure.
|
||||
|
||||
@retval EFI_SUCCESS Procedure has completed.
|
||||
@retval EFI_INVALID_PARAMETER Token or Token->Completion is NULL
|
||||
@retval EFI_NOT_FOUND Token is not currently in use for a non-blocking call
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmMpWaitForProcedure (
|
||||
IN CONST EFI_MM_MP_PROTOCOL *This,
|
||||
IN MM_COMPLETION Token
|
||||
);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue