[Patch v4 33/46] UefiCpuPkg/MpInitLib: Implementation of MpInitLibStartupThisAP()


Jeff Fan <jeff.fan@...>
 

v4:
1. Simply the internal function StartupThisAPWorker()'s comment
header due to it is duplicated with MpInitLibStartupThisAP().

v3:
1. Use CamelCase for mStopCheckAllApsStatus and
CheckAndUpdateApsStatus().

Cc: Michael Kinney <michael.d.kinney@...>
Cc: Feng Tian <feng.tian@...>
Cc: Giri P Mudusuru <giri.p.mudusuru@...>
Cc: Laszlo Ersek <lersek@...>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@...>
---
UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 20 +++++-
UefiCpuPkg/Library/MpInitLib/MpLib.c | 112 ++++++++++++++++++++++++++++++++
UefiCpuPkg/Library/MpInitLib/MpLib.h | 33 ++++++++++
UefiCpuPkg/Library/MpInitLib/PeiMpLib.c | 13 +++-
4 files changed, 176 insertions(+), 2 deletions(-)

diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
index ce45249..11676a6 100644
--- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
@@ -387,7 +387,25 @@ MpInitLibStartupThisAP (
OUT BOOLEAN *Finished OPTIONAL
)
{
- return EFI_UNSUPPORTED;
+ EFI_STATUS Status;
+
+ //
+ // temporarily stop checkAllApsStatus for avoid resource dead-lock.
+ //
+ mStopCheckAllApsStatus = TRUE;
+
+ Status = StartupThisAPWorker (
+ Procedure,
+ ProcessorNumber,
+ WaitEvent,
+ TimeoutInMicroseconds,
+ ProcedureArgument,
+ Finished
+ );
+
+ mStopCheckAllApsStatus = FALSE;
+
+ return Status;
}

/**
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index f6e15e8..6e800a7 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -1725,6 +1725,118 @@ MpInitLibGetNumberOfProcessors (


/**
+ Worker function to let the caller get one enabled AP to execute a caller-provided
+ function.
+
+ @param[in] Procedure A pointer to the function to be run on
+ enabled APs of the system.
+ @param[in] ProcessorNumber The handle number of the AP.
+ @param[in] WaitEvent The event created by the caller with CreateEvent()
+ service.
+ @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for
+ APs to return from Procedure, either for
+ blocking or non-blocking mode.
+ @param[in] ProcedureArgument The parameter passed into Procedure for
+ all APs.
+ @param[out] Finished If AP returns from Procedure before the
+ timeout expires, its content is set to TRUE.
+ Otherwise, the value is set to FALSE.
+
+ @retval EFI_SUCCESS In blocking mode, specified AP finished before
+ the timeout expires.
+ @retval others Failed to Startup AP.
+
+**/
+EFI_STATUS
+StartupThisAPWorker (
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroseconds,
+ IN VOID *ProcedureArgument OPTIONAL,
+ OUT BOOLEAN *Finished OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ CPU_MP_DATA *CpuMpData;
+ CPU_AP_DATA *CpuData;
+ UINTN CallerNumber;
+
+ CpuMpData = GetCpuMpData ();
+
+ if (Finished != NULL) {
+ *Finished = FALSE;
+ }
+
+ //
+ // Check whether caller processor is BSP
+ //
+ MpInitLibWhoAmI (&CallerNumber);
+ if (CallerNumber != CpuMpData->BspNumber) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check whether processor with the handle specified by ProcessorNumber exists
+ //
+ if (ProcessorNumber >= CpuMpData->CpuCount) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check whether specified processor is BSP
+ //
+ if (ProcessorNumber == CpuMpData->BspNumber) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check parameter Procedure
+ //
+ if (Procedure == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Update AP state
+ //
+ CheckAndUpdateApsStatus ();
+
+ //
+ // Check whether specified AP is disabled
+ //
+ if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateDisabled) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If WaitEvent is not NULL, execute in non-blocking mode.
+ // BSP saves data for CheckAPsStatus(), and returns EFI_SUCCESS.
+ // CheckAPsStatus() will check completion and timeout periodically.
+ //
+ CpuData = &CpuMpData->CpuData[ProcessorNumber];
+ CpuData->WaitEvent = WaitEvent;
+ CpuData->Finished = Finished;
+ CpuData->ExpectedTime = CalculateTimeout (TimeoutInMicroseconds, &CpuData->CurrentTime);
+ CpuData->TotalTime = 0;
+
+ WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument);
+
+ //
+ // If WaitEvent is NULL, execute in blocking mode.
+ // BSP checks AP's state until it finishes or TimeoutInMicrosecsond expires.
+ //
+ Status = EFI_SUCCESS;
+ if (WaitEvent == NULL) {
+ do {
+ Status = CheckThisAP (ProcessorNumber);
+ } while (Status == EFI_NOT_READY);
+ }
+
+ return Status;
+}
+
+/**
Get pointer to CPU MP Data structure from GUIDed HOB.

@return The pointer to CPU MP Data structure.
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index 17ebbcf..96ce1fc 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -323,6 +323,39 @@ InitMpGlobalData (
);

/**
+ Worker function to let the caller get one enabled AP to execute a caller-provided
+ function.
+
+ @param[in] Procedure A pointer to the function to be run on
+ enabled APs of the system.
+ @param[in] ProcessorNumber The handle number of the AP.
+ @param[in] WaitEvent The event created by the caller with CreateEvent()
+ service.
+ @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for
+ APs to return from Procedure, either for
+ blocking or non-blocking mode.
+ @param[in] ProcedureArgument The parameter passed into Procedure for
+ all APs.
+ @param[out] Finished If AP returns from Procedure before the
+ timeout expires, its content is set to TRUE.
+ Otherwise, the value is set to FALSE.
+
+ @retval EFI_SUCCESS In blocking mode, specified AP finished before
+ the timeout expires.
+ @retval others Failed to Startup AP.
+
+**/
+EFI_STATUS
+StartupThisAPWorker (
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroseconds,
+ IN VOID *ProcedureArgument OPTIONAL,
+ OUT BOOLEAN *Finished OPTIONAL
+ );
+
+/**
Worker function to switch the requested AP to be the BSP from that point onward.

@param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
index 3a8a4d1..141697d 100644
--- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
@@ -535,7 +535,18 @@ MpInitLibStartupThisAP (
OUT BOOLEAN *Finished OPTIONAL
)
{
- return EFI_UNSUPPORTED;
+ if (WaitEvent != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return StartupThisAPWorker (
+ Procedure,
+ ProcessorNumber,
+ NULL,
+ TimeoutInMicroseconds,
+ ProcedureArgument,
+ Finished
+ );
}

/**
--
2.7.4.windows.1

Join devel@edk2.groups.io to automatically receive all group messages.