}\r
\r
\r
+/**\r
+ Worker function to execute a caller provided function on all enabled APs.\r
+\r
+ @param[in] Procedure A pointer to the function to be run on\r
+ enabled APs of the system.\r
+ @param[in] SingleThread If TRUE, then all the enabled APs execute\r
+ the function specified by Procedure one by\r
+ one, in ascending order of processor handle\r
+ number. If FALSE, then all the enabled APs\r
+ execute the function specified by Procedure\r
+ simultaneously.\r
+ @param[in] WaitEvent The event created by the caller with CreateEvent()\r
+ service.\r
+ @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for\r
+ APs to return from Procedure, either for\r
+ blocking or non-blocking mode.\r
+ @param[in] ProcedureArgument The parameter passed into Procedure for\r
+ all APs.\r
+ @param[out] FailedCpuList If all APs finish successfully, then its\r
+ content is set to NULL. If not all APs\r
+ finish before timeout expires, then its\r
+ content is set to address of the buffer\r
+ holding handle numbers of the failed APs.\r
+\r
+ @retval EFI_SUCCESS In blocking mode, all APs have finished before\r
+ the timeout expired.\r
+ @retval EFI_SUCCESS In non-blocking mode, function has been dispatched\r
+ to all enabled APs.\r
+ @retval others Failed to Startup all APs.\r
+\r
+**/\r
+EFI_STATUS\r
+StartupAllAPsWorker (\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN BOOLEAN SingleThread,\r
+ IN EFI_EVENT WaitEvent OPTIONAL,\r
+ IN UINTN TimeoutInMicroseconds,\r
+ IN VOID *ProcedureArgument OPTIONAL,\r
+ OUT UINTN **FailedCpuList OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CPU_MP_DATA *CpuMpData;\r
+ UINTN ProcessorCount;\r
+ UINTN ProcessorNumber;\r
+ UINTN CallerNumber;\r
+ CPU_AP_DATA *CpuData;\r
+ BOOLEAN HasEnabledAp;\r
+ CPU_STATE ApState;\r
+\r
+ CpuMpData = GetCpuMpData ();\r
+\r
+ if (FailedCpuList != NULL) {\r
+ *FailedCpuList = NULL;\r
+ }\r
+\r
+ if (CpuMpData->CpuCount == 1) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ if (Procedure == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check whether caller processor is BSP\r
+ //\r
+ MpInitLibWhoAmI (&CallerNumber);\r
+ if (CallerNumber != CpuMpData->BspNumber) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // Update AP state\r
+ //\r
+ CheckAndUpdateApsStatus ();\r
+\r
+ ProcessorCount = CpuMpData->CpuCount;\r
+ HasEnabledAp = FALSE;\r
+ //\r
+ // Check whether all enabled APs are idle.\r
+ // If any enabled AP is not idle, return EFI_NOT_READY.\r
+ //\r
+ for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {\r
+ CpuData = &CpuMpData->CpuData[ProcessorNumber];\r
+ if (ProcessorNumber != CpuMpData->BspNumber) {\r
+ ApState = GetApState (CpuData);\r
+ if (ApState != CpuStateDisabled) {\r
+ HasEnabledAp = TRUE;\r
+ if (ApState != CpuStateIdle) {\r
+ //\r
+ // If any enabled APs are busy, return EFI_NOT_READY.\r
+ //\r
+ return EFI_NOT_READY;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!HasEnabledAp) {\r
+ //\r
+ // If no enabled AP exists, return EFI_NOT_STARTED.\r
+ //\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ CpuMpData->StartCount = 0;\r
+ for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {\r
+ CpuData = &CpuMpData->CpuData[ProcessorNumber];\r
+ CpuData->Waiting = FALSE;\r
+ if (ProcessorNumber != CpuMpData->BspNumber) {\r
+ if (CpuData->State == CpuStateIdle) {\r
+ //\r
+ // Mark this processor as responsible for current calling.\r
+ //\r
+ CpuData->Waiting = TRUE;\r
+ CpuMpData->StartCount++;\r
+ }\r
+ }\r
+ }\r
+\r
+ CpuMpData->Procedure = Procedure;\r
+ CpuMpData->ProcArguments = ProcedureArgument;\r
+ CpuMpData->SingleThread = SingleThread;\r
+ CpuMpData->FinishedCount = 0;\r
+ CpuMpData->RunningCount = 0;\r
+ CpuMpData->FailedCpuList = FailedCpuList;\r
+ CpuMpData->ExpectedTime = CalculateTimeout (\r
+ TimeoutInMicroseconds,\r
+ &CpuMpData->CurrentTime\r
+ );\r
+ CpuMpData->TotalTime = 0;\r
+ CpuMpData->WaitEvent = WaitEvent;\r
+\r
+ if (!SingleThread) {\r
+ WakeUpAP (CpuMpData, TRUE, 0, Procedure, ProcedureArgument);\r
+ } else {\r
+ for (ProcessorNumber = 0; ProcessorNumber < ProcessorCount; ProcessorNumber++) {\r
+ if (ProcessorNumber == CallerNumber) {\r
+ continue;\r
+ }\r
+ if (CpuMpData->CpuData[ProcessorNumber].Waiting) {\r
+ WakeUpAP (CpuMpData, FALSE, ProcessorNumber, Procedure, ProcedureArgument);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ if (WaitEvent == NULL) {\r
+ do {\r
+ Status = CheckAllAPs ();\r
+ } while (Status == EFI_NOT_READY);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
/**\r
Worker function to let the caller get one enabled AP to execute a caller-provided\r
function.\r
IN CPU_MP_DATA *CpuMpData\r
);\r
\r
+/**\r
+ Worker function to execute a caller provided function on all enabled APs.\r
+\r
+ @param[in] Procedure A pointer to the function to be run on\r
+ enabled APs of the system.\r
+ @param[in] SingleThread If TRUE, then all the enabled APs execute\r
+ the function specified by Procedure one by\r
+ one, in ascending order of processor handle\r
+ number. If FALSE, then all the enabled APs\r
+ execute the function specified by Procedure\r
+ simultaneously.\r
+ @param[in] WaitEvent The event created by the caller with CreateEvent()\r
+ service.\r
+ @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for\r
+ APs to return from Procedure, either for\r
+ blocking or non-blocking mode.\r
+ @param[in] ProcedureArgument The parameter passed into Procedure for\r
+ all APs.\r
+ @param[out] FailedCpuList If all APs finish successfully, then its\r
+ content is set to NULL. If not all APs\r
+ finish before timeout expires, then its\r
+ content is set to address of the buffer\r
+ holding handle numbers of the failed APs.\r
+\r
+ @retval EFI_SUCCESS In blocking mode, all APs have finished before\r
+ the timeout expired.\r
+ @retval EFI_SUCCESS In non-blocking mode, function has been dispatched\r
+ to all enabled APs.\r
+ @retval others Failed to Startup all APs.\r
+\r
+**/\r
+EFI_STATUS\r
+StartupAllAPsWorker (\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN BOOLEAN SingleThread,\r
+ IN EFI_EVENT WaitEvent OPTIONAL,\r
+ IN UINTN TimeoutInMicroseconds,\r
+ IN VOID *ProcedureArgument OPTIONAL,\r
+ OUT UINTN **FailedCpuList OPTIONAL\r
+ );\r
+\r
/**\r
Worker function to let the caller get one enabled AP to execute a caller-provided\r
function.\r