From 20ae57745b19538229ba0670c10e08c13f9e2574 Mon Sep 17 00:00:00 2001 From: Jeff Fan Date: Thu, 21 Jul 2016 21:31:47 +0800 Subject: [PATCH] UefiCpuPkg/MpInitLib: Implementation of MpInitLibStartupThisAP() 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 Cc: Feng Tian Cc: Giri P Mudusuru Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan Reviewed-by: Michael Kinney Tested-by: Laszlo Ersek Tested-by: Michael Kinney --- 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 bd132404cc..75845bd838 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -390,7 +390,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 2691af289a..c10dcd3fcb 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -1719,6 +1719,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. diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index eba6713df8..04ffba566d 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -347,6 +347,39 @@ InitMpGlobalData ( IN CPU_MP_DATA *CpuMpData ); +/** + 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. diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c index 64451596cf..4ea8fa96a1 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c @@ -538,7 +538,18 @@ MpInitLibStartupThisAP ( OUT BOOLEAN *Finished OPTIONAL ) { - return EFI_UNSUPPORTED; + if (WaitEvent != NULL) { + return EFI_UNSUPPORTED; + } + + return StartupThisAPWorker ( + Procedure, + ProcessorNumber, + NULL, + TimeoutInMicroseconds, + ProcedureArgument, + Finished + ); } /** -- 2.39.2