Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan <jeff....@intel.com> CC: Feng Tian <feng.t...@intel.com> CC: Jiewen Yao <jiewen....@intel.com> CC: Michael Kinney <michael.d.kin...@intel.com> --- UefiCpuPkg/CpuMpPei/PeiMpServices.c | 126 ++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuMpPei/PeiMpServices.h | 62 ++++++++++++++++++ 2 files changed, 188 insertions(+)
diff --git a/UefiCpuPkg/CpuMpPei/PeiMpServices.c b/UefiCpuPkg/CpuMpPei/PeiMpServices.c index 50145b3..bf10a48 100644 --- a/UefiCpuPkg/CpuMpPei/PeiMpServices.c +++ b/UefiCpuPkg/CpuMpPei/PeiMpServices.c @@ -507,6 +507,132 @@ PeiStartupAllAPs ( } /** + This service lets the caller get one enabled AP to execute a caller-provided + function. The caller can request the BSP to wait for the completion + of the AP. This service may only be called from the BSP. + + This function is used to dispatch one enabled AP to the function specified by + Procedure passing in the argument specified by ProcedureArgument. + The execution is in blocking mode. The BSP waits until the AP finishes or + TimeoutInMicroSecondss expires. + + If the timeout specified by TimeoutInMicroseconds expires before the AP returns + from Procedure, then execution of Procedure by the AP is terminated. The AP is + available for subsequent calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() and + EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). + + @param[in] PeiServices General purpose services available to every PEIM. + @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. See type + EFI_AP_PROCEDURE. + @param[in] ProcessorNumber The handle number of the AP. The range is + from 0 to the total number of logical + processors minus 1. The total number of + logical processors can be retrieved by + EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). + @param[in] TimeoutInMicrosecsond 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, specified AP finished before + the timeout expires. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_TIMEOUT In blocking mode, the timeout expired before + the specified AP has finished. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP. + @retval EFI_INVALID_PARAMETER Procedure is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiStartupThisAP ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_MP_SERVICES_PPI *This, + IN EFI_AP_PROCEDURE Procedure, + IN UINTN ProcessorNumber, + IN UINTN TimeoutInMicroseconds, + IN VOID *ProcedureArgument OPTIONAL + ) +{ + PEI_CPU_MP_DATA *PeiCpuMpData; + UINTN CallerNumber; + 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; + } + + if (ProcessorNumber >= PeiCpuMpData->CpuCount) { + return EFI_NOT_FOUND; + } + + if (ProcessorNumber == PeiCpuMpData->BspNumber || Procedure == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether specified AP is disabled + // + if (PeiCpuMpData->CpuData[ProcessorNumber].State == CpuStateDisabled) { + return EFI_INVALID_PARAMETER; + } + + WaitCountNumber = TimeoutInMicroseconds / CPU_CHECK_AP_INTERVAL + 1; + WaitCountIndex = 0; + FinishedCount = &PeiCpuMpData->FinishedCount; + + WakeUpAP (PeiCpuMpData, FALSE, PeiCpuMpData->CpuData[ProcessorNumber].ApicId, Procedure, ProcedureArgument); + + // + // Wait to finish + // + if (TimeoutInMicroseconds == 0) { + while (*FinishedCount < 1) { + CpuPause() ; + } + Status = EFI_SUCCESS; + } else { + Status = EFI_TIMEOUT; + for (WaitCountIndex = 0; WaitCountIndex < WaitCountNumber; WaitCountIndex++) { + MicroSecondDelay (CPU_CHECK_AP_INTERVAL); + if (*FinishedCount >= 1) { + Status = EFI_SUCCESS; + break; + } + } + } + + return Status; +} + + +/** This return the handle number for the calling processor. This service may be called from the BSP and APs. diff --git a/UefiCpuPkg/CpuMpPei/PeiMpServices.h b/UefiCpuPkg/CpuMpPei/PeiMpServices.h index 71f5a04..cafa783 100644 --- a/UefiCpuPkg/CpuMpPei/PeiMpServices.h +++ b/UefiCpuPkg/CpuMpPei/PeiMpServices.h @@ -181,6 +181,68 @@ PeiStartupAllAPs ( IN VOID *ProcedureArgument OPTIONAL ); +/** + This service lets the caller get one enabled AP to execute a caller-provided + function. The caller can request the BSP to wait for the completion + of the AP. This service may only be called from the BSP. + + This function is used to dispatch one enabled AP to the function specified by + Procedure passing in the argument specified by ProcedureArgument. + The execution is in blocking mode. The BSP waits until the AP finishes or + TimeoutInMicroSecondss expires. + + If the timeout specified by TimeoutInMicroseconds expires before the AP returns + from Procedure, then execution of Procedure by the AP is terminated. The AP is + available for subsequent calls to EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() and + EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). + + @param[in] PeiServices General purpose services available to every PEIM. + @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. See type + EFI_AP_PROCEDURE. + @param[in] ProcessorNumber The handle number of the AP. The range is + from 0 to the total number of logical + processors minus 1. The total number of + logical processors can be retrieved by + EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). + @param[in] TimeoutInMicrosecsond 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, specified AP finished before + the timeout expires. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_TIMEOUT In blocking mode, the timeout expired before + the specified AP has finished. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP. + @retval EFI_INVALID_PARAMETER Procedure is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiStartupThisAP ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_MP_SERVICES_PPI *This, + IN EFI_AP_PROCEDURE Procedure, + IN UINTN ProcessorNumber, + IN UINTN TimeoutInMicroseconds, + IN VOID *ProcedureArgument OPTIONAL + ); + /** This return the handle number for the calling processor. This service may be -- 1.9.5.msysgit.0 ------------------------------------------------------------------------------ Don't Limit Your Business. Reach for the Cloud. GigeNET's Cloud Solutions provide you with the tools and support that you need to offload your IT needs and focus on growing your business. Configured For All Businesses. Start Your Cloud Today. https://www.gigenetcloud.com/ _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel