4 Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 UINTN gMaxLogicalProcessorNumber
;
20 UINTN gPollInterval
= 100; // 100 microseconds
22 MP_SYSTEM_DATA mMpSystemData
;
24 VOID
*mCommonStack
= 0;
25 VOID
*mTopOfApCommonStack
= 0;
26 VOID
*mApStackStart
= 0;
28 volatile BOOLEAN mAPsAlreadyInitFinished
= FALSE
;
29 volatile BOOLEAN mStopCheckAllAPsStatus
= TRUE
;
31 EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate
= {
32 GetNumberOfProcessors
,
44 @param CpuData the pointer to CPU_DATA_BLOCK of specified processor
49 IN CPU_DATA_BLOCK
*CpuData
52 while (!AcquireSpinLockOrFail (&CpuData
->CpuDataLock
)) {
58 Release Mp Service Lock.
60 @param CpuData the pointer to CPU_DATA_BLOCK of specified processor
65 IN CPU_DATA_BLOCK
*CpuData
68 ReleaseSpinLock (&CpuData
->CpuDataLock
);
72 Check whether caller processor is BSP.
74 @retval TRUE the caller is BSP
75 @retval FALSE the caller is AP
84 CPU_DATA_BLOCK
*CpuData
;
88 WhoAmI (&mMpServicesTemplate
, &CpuIndex
);
89 CpuData
= &mMpSystemData
.CpuDatas
[CpuIndex
];
91 return CpuData
->Info
.StatusFlag
& PROCESSOR_AS_BSP_BIT
? TRUE
: FALSE
;
95 Get the Application Processors state.
97 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
99 @retval CPU_STATE the AP status
104 IN CPU_DATA_BLOCK
*CpuData
109 GetMpSpinLock (CpuData
);
110 State
= CpuData
->State
;
111 ReleaseMpSpinLock (CpuData
);
117 Set the Application Processors state.
119 @param CpuData The pointer to CPU_DATA_BLOCK of specified AP
120 @param State The AP status
125 IN CPU_DATA_BLOCK
*CpuData
,
129 GetMpSpinLock (CpuData
);
130 CpuData
->State
= State
;
131 ReleaseMpSpinLock (CpuData
);
135 Set the Application Processor prepare to run a function specified
138 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
139 @param Procedure A pointer to the function to be run on enabled APs of the system
140 @param ProcedureArgument Pointer to the optional parameter of the assigned function
145 IN CPU_DATA_BLOCK
*CpuData
,
146 IN EFI_AP_PROCEDURE Procedure
,
147 IN VOID
*ProcedureArgument
150 GetMpSpinLock (CpuData
);
151 CpuData
->Parameter
= ProcedureArgument
;
152 CpuData
->Procedure
= Procedure
;
153 ReleaseMpSpinLock (CpuData
);
157 Check the Application Processors Status whether contains the Flags.
159 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
160 @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION
162 @retval TRUE the AP status includes the StatusFlag
163 @retval FALSE the AP status excludes the StatusFlag
168 IN CPU_DATA_BLOCK
*CpuData
,
174 GetMpSpinLock (CpuData
);
175 Ret
= CpuData
->Info
.StatusFlag
& Flags
;
176 ReleaseMpSpinLock (CpuData
);
182 Bitwise-Or of the Application Processors Status with the Flags.
184 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
185 @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION
190 IN CPU_DATA_BLOCK
*CpuData
,
194 GetMpSpinLock (CpuData
);
195 CpuData
->Info
.StatusFlag
|= Flags
;
196 ReleaseMpSpinLock (CpuData
);
200 Bitwise-AndNot of the Application Processors Status with the Flags.
202 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
203 @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION
207 CpuStatusFlagAndNot (
208 IN CPU_DATA_BLOCK
*CpuData
,
212 GetMpSpinLock (CpuData
);
213 CpuData
->Info
.StatusFlag
&= ~Flags
;
214 ReleaseMpSpinLock (CpuData
);
218 Searches for the next blocking AP.
220 Search for the next AP that is put in blocking state by single-threaded StartupAllAPs().
222 @param NextNumber Pointer to the processor number of the next blocking AP.
224 @retval EFI_SUCCESS The next blocking AP has been found.
225 @retval EFI_NOT_FOUND No blocking AP exists.
229 GetNextBlockedNumber (
230 OUT UINTN
*NextNumber
235 CPU_DATA_BLOCK
*CpuData
;
237 for (Number
= 0; Number
< mMpSystemData
.NumberOfProcessors
; Number
++) {
238 CpuData
= &mMpSystemData
.CpuDatas
[Number
];
239 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
246 CpuState
= GetApState (CpuData
);
247 if (CpuState
== CpuStateBlocked
) {
248 *NextNumber
= Number
;
253 return EFI_NOT_FOUND
;
257 Check if the APs state are finished, and update them to idle state
262 CheckAndUpdateAllAPsToIdleState (
266 UINTN ProcessorNumber
;
268 CPU_DATA_BLOCK
*CpuData
;
272 for (ProcessorNumber
= 0; ProcessorNumber
< mMpSystemData
.NumberOfProcessors
; ProcessorNumber
++) {
273 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
274 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
281 if (!TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
283 // Skip Disabled processors
288 CpuState
= GetApState (CpuData
);
289 if (CpuState
== CpuStateFinished
) {
290 mMpSystemData
.FinishCount
++;
291 if (mMpSystemData
.SingleThread
) {
292 Status
= GetNextBlockedNumber (&NextNumber
);
293 if (!EFI_ERROR (Status
)) {
294 SetApState (&mMpSystemData
.CpuDatas
[NextNumber
], CpuStateReady
);
295 SetApProcedure (&mMpSystemData
.CpuDatas
[NextNumber
],
296 mMpSystemData
.Procedure
,
297 mMpSystemData
.ProcedureArgument
);
301 SetApState (CpuData
, CpuStateIdle
);
307 If the timeout expires before all APs returns from Procedure,
308 we should forcibly terminate the executing AP and fill FailedList back
317 CPU_DATA_BLOCK
*CpuData
;
321 if (mMpSystemData
.FailedList
!= NULL
) {
322 *mMpSystemData
.FailedList
= AllocatePool ((mMpSystemData
.StartCount
- mMpSystemData
.FinishCount
+ 1) * sizeof(UINTN
));
323 ASSERT (*mMpSystemData
.FailedList
!= NULL
);
326 for (Number
= 0; Number
< mMpSystemData
.NumberOfProcessors
; Number
++) {
327 CpuData
= &mMpSystemData
.CpuDatas
[Number
];
328 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
335 if (!TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
337 // Skip Disabled processors
342 CpuState
= GetApState (CpuData
);
343 if (CpuState
!= CpuStateIdle
) {
344 if (mMpSystemData
.FailedList
!= NULL
) {
345 (*mMpSystemData
.FailedList
)[mMpSystemData
.FailedListIndex
++] = Number
;
347 ResetProcessorToIdleState (CpuData
);
351 if (mMpSystemData
.FailedList
!= NULL
) {
352 (*mMpSystemData
.FailedList
)[mMpSystemData
.FailedListIndex
] = END_OF_CPU_LIST
;
357 This service retrieves the number of logical processor in the platform
358 and the number of those logical processors that are enabled on this boot.
359 This service may only be called from the BSP.
361 This function is used to retrieve the following information:
362 - The number of logical processors that are present in the system.
363 - The number of enabled logical processors in the system at the instant
366 Because MP Service Protocol provides services to enable and disable processors
367 dynamically, the number of enabled logical processors may vary during the
368 course of a boot session.
370 If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
371 If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
372 EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
373 is returned in NumberOfProcessors, the number of currently enabled processor
374 is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
376 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
378 @param[out] NumberOfProcessors Pointer to the total number of logical
379 processors in the system, including the BSP
381 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
382 processors that exist in system, including
385 @retval EFI_SUCCESS The number of logical processors and enabled
386 logical processors was retrieved.
387 @retval EFI_DEVICE_ERROR The calling processor is an AP.
388 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
389 @retval EFI_INVALID_PARAMETER NumberOfEnabledProcessors is NULL.
394 GetNumberOfProcessors (
395 IN EFI_MP_SERVICES_PROTOCOL
*This
,
396 OUT UINTN
*NumberOfProcessors
,
397 OUT UINTN
*NumberOfEnabledProcessors
400 if ((NumberOfProcessors
== NULL
) || (NumberOfEnabledProcessors
== NULL
)) {
401 return EFI_INVALID_PARAMETER
;
405 return EFI_DEVICE_ERROR
;
408 *NumberOfProcessors
= mMpSystemData
.NumberOfProcessors
;
409 *NumberOfEnabledProcessors
= mMpSystemData
.NumberOfEnabledProcessors
;
414 Gets detailed MP-related information on the requested processor at the
415 instant this call is made. This service may only be called from the BSP.
417 This service retrieves detailed MP-related information about any processor
418 on the platform. Note the following:
419 - The processor information may change during the course of a boot session.
420 - The information presented here is entirely MP related.
422 Information regarding the number of caches and their sizes, frequency of operation,
423 slot numbers is all considered platform-related information and is not provided
426 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
428 @param[in] ProcessorNumber The handle number of processor.
429 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
430 the requested processor is deposited.
432 @retval EFI_SUCCESS Processor information was returned.
433 @retval EFI_DEVICE_ERROR The calling processor is an AP.
434 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
435 @retval EFI_NOT_FOUND The processor with the handle specified by
436 ProcessorNumber does not exist in the platform.
442 IN EFI_MP_SERVICES_PROTOCOL
*This
,
443 IN UINTN ProcessorNumber
,
444 OUT EFI_PROCESSOR_INFORMATION
*ProcessorInfoBuffer
447 if (ProcessorInfoBuffer
== NULL
) {
448 return EFI_INVALID_PARAMETER
;
452 return EFI_DEVICE_ERROR
;
455 if (ProcessorNumber
>= mMpSystemData
.NumberOfProcessors
) {
456 return EFI_NOT_FOUND
;
459 CopyMem (ProcessorInfoBuffer
, &mMpSystemData
.CpuDatas
[ProcessorNumber
], sizeof (EFI_PROCESSOR_INFORMATION
));
464 This service executes a caller provided function on all enabled APs. APs can
465 run either simultaneously or one at a time in sequence. This service supports
466 both blocking and non-blocking requests. The non-blocking requests use EFI
467 events so the BSP can detect when the APs have finished. This service may only
468 be called from the BSP.
470 This function is used to dispatch all the enabled APs to the function specified
471 by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned
472 immediately and Procedure is not started on any AP.
474 If SingleThread is TRUE, all the enabled APs execute the function specified by
475 Procedure one by one, in ascending order of processor handle number. Otherwise,
476 all the enabled APs execute the function specified by Procedure simultaneously.
478 If WaitEvent is NULL, execution is in blocking mode. The BSP waits until all
479 APs finish or TimeoutInMicroseconds expires. Otherwise, execution is in non-blocking
480 mode, and the BSP returns from this service without waiting for APs. If a
481 non-blocking mode is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
482 is signaled, then EFI_UNSUPPORTED must be returned.
484 If the timeout specified by TimeoutInMicroseconds expires before all APs return
485 from Procedure, then Procedure on the failed APs is terminated. All enabled APs
486 are always available for further calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
487 and EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). If FailedCpuList is not NULL, its
488 content points to the list of processor handle numbers in which Procedure was
491 Note: It is the responsibility of the consumer of the EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
492 to make sure that the nature of the code that is executed on the BSP and the
493 dispatched APs is well controlled. The MP Services Protocol does not guarantee
494 that the Procedure function is MP-safe. Hence, the tasks that can be run in
495 parallel are limited to certain independent tasks and well-controlled exclusive
496 code. EFI services and protocols may not be called by APs unless otherwise
499 In blocking execution mode, BSP waits until all APs finish or
500 TimeoutInMicroseconds expires.
502 In non-blocking execution mode, BSP is freed to return to the caller and then
503 proceed to the next task without having to wait for APs. The following
504 sequence needs to occur in a non-blocking execution mode:
506 -# The caller that intends to use this MP Services Protocol in non-blocking
507 mode creates WaitEvent by calling the EFI CreateEvent() service. The caller
508 invokes EFI_MP_SERVICES_PROTOCOL.StartupAllAPs(). If the parameter WaitEvent
509 is not NULL, then StartupAllAPs() executes in non-blocking mode. It requests
510 the function specified by Procedure to be started on all the enabled APs,
511 and releases the BSP to continue with other tasks.
512 -# The caller can use the CheckEvent() and WaitForEvent() services to check
513 the state of the WaitEvent created in step 1.
514 -# When the APs complete their task or TimeoutInMicroSecondss expires, the MP
515 Service signals WaitEvent by calling the EFI SignalEvent() function. If
516 FailedCpuList is not NULL, its content is available when WaitEvent is
517 signaled. If all APs returned from Procedure prior to the timeout, then
518 FailedCpuList is set to NULL. If not all APs return from Procedure before
519 the timeout, then FailedCpuList is filled in with the list of the failed
520 APs. The buffer is allocated by MP Service Protocol using AllocatePool().
521 It is the caller's responsibility to free the buffer with FreePool() service.
522 -# This invocation of SignalEvent() function informs the caller that invoked
523 EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() that either all the APs completed
524 the specified task or a timeout occurred. The contents of FailedCpuList
525 can be examined to determine which APs did not complete the specified task
526 prior to the timeout.
528 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
530 @param[in] Procedure A pointer to the function to be run on
531 enabled APs of the system. See type
533 @param[in] SingleThread If TRUE, then all the enabled APs execute
534 the function specified by Procedure one by
535 one, in ascending order of processor handle
536 number. If FALSE, then all the enabled APs
537 execute the function specified by Procedure
539 @param[in] WaitEvent The event created by the caller with CreateEvent()
540 service. If it is NULL, then execute in
541 blocking mode. BSP waits until all APs finish
542 or TimeoutInMicroseconds expires. If it's
543 not NULL, then execute in non-blocking mode.
544 BSP requests the function specified by
545 Procedure to be started on all the enabled
546 APs, and go on executing immediately. If
547 all return from Procedure, or TimeoutInMicroseconds
548 expires, this event is signaled. The BSP
549 can use the CheckEvent() or WaitForEvent()
550 services to check the state of event. Type
551 EFI_EVENT is defined in CreateEvent() in
552 the Unified Extensible Firmware Interface
554 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
555 APs to return from Procedure, either for
556 blocking or non-blocking mode. Zero means
557 infinity. If the timeout expires before
558 all APs return from Procedure, then Procedure
559 on the failed APs is terminated. All enabled
560 APs are available for next function assigned
561 by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
562 or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
563 If the timeout expires in blocking mode,
564 BSP returns EFI_TIMEOUT. If the timeout
565 expires in non-blocking mode, WaitEvent
566 is signaled with SignalEvent().
567 @param[in] ProcedureArgument The parameter passed into Procedure for
569 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
570 if all APs finish successfully, then its
571 content is set to NULL. If not all APs
572 finish before timeout expires, then its
573 content is set to address of the buffer
574 holding handle numbers of the failed APs.
575 The buffer is allocated by MP Service Protocol,
576 and it's the caller's responsibility to
577 free the buffer with FreePool() service.
578 In blocking mode, it is ready for consumption
579 when the call returns. In non-blocking mode,
580 it is ready when WaitEvent is signaled. The
581 list of failed CPU is terminated by
584 @retval EFI_SUCCESS In blocking mode, all APs have finished before
586 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
588 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
589 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
591 @retval EFI_DEVICE_ERROR Caller processor is AP.
592 @retval EFI_NOT_STARTED No enabled APs exist in the system.
593 @retval EFI_NOT_READY Any enabled APs are busy.
594 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
595 all enabled APs have finished.
596 @retval EFI_INVALID_PARAMETER Procedure is NULL.
602 IN EFI_MP_SERVICES_PROTOCOL
*This
,
603 IN EFI_AP_PROCEDURE Procedure
,
604 IN BOOLEAN SingleThread
,
605 IN EFI_EVENT WaitEvent OPTIONAL
,
606 IN UINTN TimeoutInMicroseconds
,
607 IN VOID
*ProcedureArgument OPTIONAL
,
608 OUT UINTN
**FailedCpuList OPTIONAL
612 CPU_DATA_BLOCK
*CpuData
;
614 CPU_STATE APInitialState
;
618 if (FailedCpuList
!= NULL
) {
619 *FailedCpuList
= NULL
;
623 return EFI_DEVICE_ERROR
;
626 if (mMpSystemData
.NumberOfProcessors
== 1) {
627 return EFI_NOT_STARTED
;
630 if (Procedure
== NULL
) {
631 return EFI_INVALID_PARAMETER
;
634 for (Number
= 0; Number
< mMpSystemData
.NumberOfProcessors
; Number
++) {
635 CpuData
= &mMpSystemData
.CpuDatas
[Number
];
636 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
643 if (!TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
645 // Skip Disabled processors
650 if (GetApState (CpuData
) != CpuStateIdle
) {
651 return EFI_NOT_READY
;
656 // temporarily stop checkAllAPsStatus for initialize parameters.
658 mStopCheckAllAPsStatus
= TRUE
;
660 mMpSystemData
.Procedure
= Procedure
;
661 mMpSystemData
.ProcedureArgument
= ProcedureArgument
;
662 mMpSystemData
.WaitEvent
= WaitEvent
;
663 mMpSystemData
.Timeout
= TimeoutInMicroseconds
;
664 mMpSystemData
.TimeoutActive
= !!(TimeoutInMicroseconds
);
665 mMpSystemData
.FinishCount
= 0;
666 mMpSystemData
.StartCount
= 0;
667 mMpSystemData
.SingleThread
= SingleThread
;
668 mMpSystemData
.FailedList
= FailedCpuList
;
669 mMpSystemData
.FailedListIndex
= 0;
670 APInitialState
= CpuStateReady
;
672 for (Number
= 0; Number
< mMpSystemData
.NumberOfProcessors
; Number
++) {
673 CpuData
= &mMpSystemData
.CpuDatas
[Number
];
674 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
681 if (!TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
683 // Skip Disabled processors
689 // Get APs prepared, and put failing APs into FailedCpuList
690 // if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready
691 // state 1 by 1, until the previous 1 finished its task
692 // if not "SingleThread", all APs are put to ready state from the beginning
694 if (GetApState (CpuData
) == CpuStateIdle
) {
695 mMpSystemData
.StartCount
++;
697 SetApState (CpuData
, APInitialState
);
699 if (APInitialState
== CpuStateReady
) {
700 SetApProcedure (CpuData
, Procedure
, ProcedureArgument
);
704 APInitialState
= CpuStateBlocked
;
709 mStopCheckAllAPsStatus
= FALSE
;
711 if (WaitEvent
!= NULL
) {
719 CheckAndUpdateAllAPsToIdleState ();
720 if (mMpSystemData
.FinishCount
== mMpSystemData
.StartCount
) {
721 Status
= EFI_SUCCESS
;
728 if (mMpSystemData
.TimeoutActive
&& mMpSystemData
.Timeout
< 0) {
730 Status
= EFI_TIMEOUT
;
734 gBS
->Stall (gPollInterval
);
735 mMpSystemData
.Timeout
-= gPollInterval
;
744 This service lets the caller get one enabled AP to execute a caller-provided
745 function. The caller can request the BSP to either wait for the completion
746 of the AP or just proceed with the next task by using the EFI event mechanism.
747 See EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() for more details on non-blocking
748 execution support. This service may only be called from the BSP.
750 This function is used to dispatch one enabled AP to the function specified by
751 Procedure passing in the argument specified by ProcedureArgument. If WaitEvent
752 is NULL, execution is in blocking mode. The BSP waits until the AP finishes or
753 TimeoutInMicroSecondss expires. Otherwise, execution is in non-blocking mode.
754 BSP proceeds to the next task without waiting for the AP. If a non-blocking mode
755 is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled,
756 then EFI_UNSUPPORTED must be returned.
758 If the timeout specified by TimeoutInMicroseconds expires before the AP returns
759 from Procedure, then execution of Procedure by the AP is terminated. The AP is
760 available for subsequent calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() and
761 EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
763 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
765 @param[in] Procedure A pointer to the function to be run on
766 enabled APs of the system. See type
768 @param[in] ProcessorNumber The handle number of the AP. The range is
769 from 0 to the total number of logical
770 processors minus 1. The total number of
771 logical processors can be retrieved by
772 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
773 @param[in] WaitEvent The event created by the caller with CreateEvent()
774 service. If it is NULL, then execute in
775 blocking mode. BSP waits until all APs finish
776 or TimeoutInMicroseconds expires. If it's
777 not NULL, then execute in non-blocking mode.
778 BSP requests the function specified by
779 Procedure to be started on all the enabled
780 APs, and go on executing immediately. If
781 all return from Procedure or TimeoutInMicroseconds
782 expires, this event is signaled. The BSP
783 can use the CheckEvent() or WaitForEvent()
784 services to check the state of event. Type
785 EFI_EVENT is defined in CreateEvent() in
786 the Unified Extensible Firmware Interface
788 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
789 APs to return from Procedure, either for
790 blocking or non-blocking mode. Zero means
791 infinity. If the timeout expires before
792 all APs return from Procedure, then Procedure
793 on the failed APs is terminated. All enabled
794 APs are available for next function assigned
795 by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
796 or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
797 If the timeout expires in blocking mode,
798 BSP returns EFI_TIMEOUT. If the timeout
799 expires in non-blocking mode, WaitEvent
800 is signaled with SignalEvent().
801 @param[in] ProcedureArgument The parameter passed into Procedure for
803 @param[out] Finished If NULL, this parameter is ignored. In
804 blocking mode, this parameter is ignored.
805 In non-blocking mode, if AP returns from
806 Procedure before the timeout expires, its
807 content is set to TRUE. Otherwise, the
808 value is set to FALSE. The caller can
809 determine if the AP returned from Procedure
810 by evaluating this value.
812 @retval EFI_SUCCESS In blocking mode, specified AP finished before
814 @retval EFI_SUCCESS In non-blocking mode, the function has been
815 dispatched to specified AP.
816 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
817 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
819 @retval EFI_DEVICE_ERROR The calling processor is an AP.
820 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
821 the specified AP has finished.
822 @retval EFI_NOT_READY The specified AP is busy.
823 @retval EFI_NOT_FOUND The processor with the handle specified by
824 ProcessorNumber does not exist.
825 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
826 @retval EFI_INVALID_PARAMETER Procedure is NULL.
832 IN EFI_MP_SERVICES_PROTOCOL
*This
,
833 IN EFI_AP_PROCEDURE Procedure
,
834 IN UINTN ProcessorNumber
,
835 IN EFI_EVENT WaitEvent OPTIONAL
,
836 IN UINTN TimeoutInMicroseconds
,
837 IN VOID
*ProcedureArgument OPTIONAL
,
838 OUT BOOLEAN
*Finished OPTIONAL
841 CPU_DATA_BLOCK
*CpuData
;
845 if (Finished
!= NULL
) {
850 return EFI_DEVICE_ERROR
;
853 if (Procedure
== NULL
) {
854 return EFI_INVALID_PARAMETER
;
857 if (ProcessorNumber
>= mMpSystemData
.NumberOfProcessors
) {
858 return EFI_NOT_FOUND
;
861 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
862 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
) ||
863 !TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
864 return EFI_INVALID_PARAMETER
;
867 if (GetApState (CpuData
) != CpuStateIdle
) {
868 return EFI_NOT_READY
;
872 // temporarily stop checkAllAPsStatus for initialize parameters.
874 mStopCheckAllAPsStatus
= TRUE
;
876 SetApState (CpuData
, CpuStateReady
);
878 SetApProcedure (CpuData
, Procedure
, ProcedureArgument
);
880 CpuData
->Timeout
= TimeoutInMicroseconds
;
881 CpuData
->WaitEvent
= WaitEvent
;
882 CpuData
->TimeoutActive
= !!(TimeoutInMicroseconds
);
883 CpuData
->Finished
= Finished
;
885 mStopCheckAllAPsStatus
= FALSE
;
887 if (WaitEvent
!= NULL
) {
898 if (GetApState (CpuData
) == CpuStateFinished
) {
899 SetApState (CpuData
, CpuStateIdle
);
903 if (CpuData
->TimeoutActive
&& CpuData
->Timeout
< 0) {
904 ResetProcessorToIdleState (CpuData
);
908 gBS
->Stall (gPollInterval
);
909 CpuData
->Timeout
-= gPollInterval
;
916 This service switches the requested AP to be the BSP from that point onward.
917 This service changes the BSP for all purposes. This call can only be performed
920 This service switches the requested AP to be the BSP from that point onward.
921 This service changes the BSP for all purposes. The new BSP can take over the
922 execution of the old BSP and continue seamlessly from where the old one left
923 off. This service may not be supported after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
926 If the BSP cannot be switched prior to the return from this service, then
927 EFI_UNSUPPORTED must be returned.
929 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
930 @param[in] ProcessorNumber The handle number of AP that is to become the new
931 BSP. The range is from 0 to the total number of
932 logical processors minus 1. The total number of
933 logical processors can be retrieved by
934 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
935 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
936 enabled AP. Otherwise, it will be disabled.
938 @retval EFI_SUCCESS BSP successfully switched.
939 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
940 this service returning.
941 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
942 @retval EFI_SUCCESS The calling processor is an AP.
943 @retval EFI_NOT_FOUND The processor with the handle specified by
944 ProcessorNumber does not exist.
945 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
947 @retval EFI_NOT_READY The specified AP is busy.
953 IN EFI_MP_SERVICES_PROTOCOL
*This
,
954 IN UINTN ProcessorNumber
,
955 IN BOOLEAN EnableOldBSP
959 // Current always return unsupported.
961 return EFI_UNSUPPORTED
;
965 This service lets the caller enable or disable an AP from this point onward.
966 This service may only be called from the BSP.
968 This service allows the caller enable or disable an AP from this point onward.
969 The caller can optionally specify the health status of the AP by Health. If
970 an AP is being disabled, then the state of the disabled AP is implementation
971 dependent. If an AP is enabled, then the implementation must guarantee that a
972 complete initialization sequence is performed on the AP, so the AP is in a state
973 that is compatible with an MP operating system. This service may not be supported
974 after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled.
976 If the enable or disable AP operation cannot be completed prior to the return
977 from this service, then EFI_UNSUPPORTED must be returned.
979 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
980 @param[in] ProcessorNumber The handle number of AP that is to become the new
981 BSP. The range is from 0 to the total number of
982 logical processors minus 1. The total number of
983 logical processors can be retrieved by
984 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
985 @param[in] EnableAP Specifies the new state for the processor for
986 enabled, FALSE for disabled.
987 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
988 the new health status of the AP. This flag
989 corresponds to StatusFlag defined in
990 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
991 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
992 bits are ignored. If it is NULL, this parameter
995 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
996 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
997 prior to this service returning.
998 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
999 @retval EFI_DEVICE_ERROR The calling processor is an AP.
1000 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
1002 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
1008 IN EFI_MP_SERVICES_PROTOCOL
*This
,
1009 IN UINTN ProcessorNumber
,
1010 IN BOOLEAN EnableAP
,
1011 IN UINT32
*HealthFlag OPTIONAL
1014 CPU_DATA_BLOCK
*CpuData
;
1017 return EFI_DEVICE_ERROR
;
1020 if (ProcessorNumber
>= mMpSystemData
.NumberOfProcessors
) {
1021 return EFI_NOT_FOUND
;
1024 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
1025 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
1026 return EFI_INVALID_PARAMETER
;
1029 if (GetApState (CpuData
) != CpuStateIdle
) {
1030 return EFI_UNSUPPORTED
;
1034 if (!(TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
))) {
1035 mMpSystemData
.NumberOfEnabledProcessors
++;
1037 CpuStatusFlagOr (CpuData
, PROCESSOR_ENABLED_BIT
);
1039 if (TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
1040 mMpSystemData
.NumberOfEnabledProcessors
--;
1042 CpuStatusFlagAndNot (CpuData
, PROCESSOR_ENABLED_BIT
);
1045 if (HealthFlag
!= NULL
) {
1046 CpuStatusFlagAndNot (CpuData
, (UINT32
)~PROCESSOR_HEALTH_STATUS_BIT
);
1047 CpuStatusFlagOr (CpuData
, (*HealthFlag
& PROCESSOR_HEALTH_STATUS_BIT
));
1054 This return the handle number for the calling processor. This service may be
1055 called from the BSP and APs.
1057 This service returns the processor handle number for the calling processor.
1058 The returned value is in the range from 0 to the total number of logical
1059 processors minus 1. The total number of logical processors can be retrieved
1060 with EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be
1061 called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
1062 is returned. Otherwise, the current processors handle number is returned in
1063 ProcessorNumber, and EFI_SUCCESS is returned.
1065 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
1066 @param[out] ProcessorNumber The handle number of AP that is to become the new
1067 BSP. The range is from 0 to the total number of
1068 logical processors minus 1. The total number of
1069 logical processors can be retrieved by
1070 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
1072 @retval EFI_SUCCESS The current processor handle number was returned
1074 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
1080 IN EFI_MP_SERVICES_PROTOCOL
*This
,
1081 OUT UINTN
*ProcessorNumber
1087 if (ProcessorNumber
== NULL
) {
1088 return EFI_INVALID_PARAMETER
;
1091 ProcessorId
= GetApicId ();
1092 for (Index
= 0; Index
< mMpSystemData
.NumberOfProcessors
; Index
++) {
1093 if (mMpSystemData
.CpuDatas
[Index
].Info
.ProcessorId
== ProcessorId
) {
1098 *ProcessorNumber
= Index
;
1103 Terminate AP's task and set it to idle state.
1105 This function terminates AP's task due to timeout by sending INIT-SIPI,
1106 and sends it to idle state.
1108 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
1112 ResetProcessorToIdleState (
1113 IN CPU_DATA_BLOCK
*CpuData
1116 ResetApStackless ((UINT32
)CpuData
->Info
.ProcessorId
);
1120 Application Processors do loop routine
1121 after switch to its own stack.
1123 @param Context1 A pointer to the context to pass into the function.
1124 @param Context2 A pointer to the context to pass into the function.
1128 ProcessorToIdleState (
1129 IN VOID
*Context1
, OPTIONAL
1130 IN VOID
*Context2 OPTIONAL
1133 UINTN ProcessorNumber
;
1134 CPU_DATA_BLOCK
*CpuData
;
1135 EFI_AP_PROCEDURE Procedure
;
1136 VOID
*ProcedureArgument
;
1138 AsmApDoneWithCommonStack ();
1140 while (!mAPsAlreadyInitFinished
) {
1144 WhoAmI (&mMpServicesTemplate
, &ProcessorNumber
);
1145 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
1148 // Avoid forcibly reset AP caused the AP State is not updated.
1150 GetMpSpinLock (CpuData
);
1151 CpuData
->State
= CpuStateIdle
;
1152 CpuData
->Procedure
= NULL
;
1153 ReleaseMpSpinLock (CpuData
);
1156 GetMpSpinLock (CpuData
);
1157 ProcedureArgument
= CpuData
->Parameter
;
1158 Procedure
= CpuData
->Procedure
;
1159 ReleaseMpSpinLock (CpuData
);
1161 if (Procedure
!= NULL
) {
1162 Procedure (ProcedureArgument
);
1164 GetMpSpinLock (CpuData
);
1165 CpuData
->Procedure
= NULL
;
1166 CpuData
->State
= CpuStateFinished
;
1167 ReleaseMpSpinLock (CpuData
);
1178 Checks AP' status periodically.
1180 This function is triggerred by timer perodically to check the
1181 state of AP forStartupThisAP() executed in non-blocking mode.
1183 @param Event Event triggered.
1184 @param Context Parameter passed with the event.
1194 CPU_DATA_BLOCK
*CpuData
;
1197 CpuData
= (CPU_DATA_BLOCK
*) Context
;
1198 if (CpuData
->TimeoutActive
) {
1199 CpuData
->Timeout
-= gPollInterval
;
1202 CpuState
= GetApState (CpuData
);
1204 if (CpuState
== CpuStateFinished
) {
1205 if (CpuData
->Finished
) {
1206 *CpuData
->Finished
= TRUE
;
1208 SetApState (CpuData
, CpuStateIdle
);
1212 if (CpuData
->TimeoutActive
&& CpuData
->Timeout
< 0) {
1213 if (CpuState
!= CpuStateIdle
&&
1214 CpuData
->Finished
) {
1215 *CpuData
->Finished
= FALSE
;
1217 ResetProcessorToIdleState (CpuData
);
1224 CpuData
->TimeoutActive
= FALSE
;
1225 gBS
->SignalEvent (CpuData
->WaitEvent
);
1226 CpuData
->WaitEvent
= NULL
;
1230 Checks APs' status periodically.
1232 This function is triggerred by timer perodically to check the
1233 state of APs for StartupAllAPs() executed in non-blocking mode.
1235 @param Event Event triggered.
1236 @param Context Parameter passed with the event.
1246 CPU_DATA_BLOCK
*CpuData
;
1250 if (mMpSystemData
.TimeoutActive
) {
1251 mMpSystemData
.Timeout
-= gPollInterval
;
1254 if (mStopCheckAllAPsStatus
) {
1259 // avoid next timer enter.
1261 Status
= gBS
->SetTimer (
1262 mMpSystemData
.CheckAllAPsEvent
,
1266 ASSERT_EFI_ERROR (Status
);
1268 if (mMpSystemData
.WaitEvent
!= NULL
) {
1269 CheckAndUpdateAllAPsToIdleState ();
1273 if (mMpSystemData
.TimeoutActive
&& mMpSystemData
.Timeout
< 0) {
1274 ResetAllFailedAPs();
1278 mMpSystemData
.FinishCount
= mMpSystemData
.StartCount
;
1281 if (mMpSystemData
.FinishCount
!= mMpSystemData
.StartCount
) {
1285 mMpSystemData
.TimeoutActive
= FALSE
;
1286 gBS
->SignalEvent (mMpSystemData
.WaitEvent
);
1287 mMpSystemData
.WaitEvent
= NULL
;
1288 mStopCheckAllAPsStatus
= TRUE
;
1294 // check each AP status for StartupThisAP
1296 for (Number
= 0; Number
< mMpSystemData
.NumberOfProcessors
; Number
++) {
1297 CpuData
= &mMpSystemData
.CpuDatas
[Number
];
1298 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
1305 if (!TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
1307 // Skip Disabled processors
1312 if (CpuData
->WaitEvent
) {
1313 CheckThisAPStatus (NULL
, (VOID
*)CpuData
);
1318 Status
= gBS
->SetTimer (
1319 mMpSystemData
.CheckAllAPsEvent
,
1321 EFI_TIMER_PERIOD_MICROSECONDS (100)
1323 ASSERT_EFI_ERROR (Status
);
1327 Application Processor C code entry point.
1337 UINTN ProcessorNumber
;
1339 if (!mAPsAlreadyInitFinished
) {
1340 FillInProcessorInformation (FALSE
, mMpSystemData
.NumberOfProcessors
);
1341 TopOfApStack
= (UINT8
*)mApStackStart
+ gApStackSize
;
1342 mApStackStart
= TopOfApStack
;
1345 // Store the Stack address, when reset the AP, We can found the original address.
1347 mMpSystemData
.CpuDatas
[mMpSystemData
.NumberOfProcessors
].TopOfStack
= TopOfApStack
;
1348 mMpSystemData
.NumberOfProcessors
++;
1349 mMpSystemData
.NumberOfEnabledProcessors
++;
1351 WhoAmI (&mMpServicesTemplate
, &ProcessorNumber
);
1353 // Get the original stack address.
1355 TopOfApStack
= mMpSystemData
.CpuDatas
[ProcessorNumber
].TopOfStack
;
1359 (SWITCH_STACK_ENTRY_POINT
)(UINTN
)ProcessorToIdleState
,
1366 This function is called by all processors (both BSP and AP) once and collects MP related data.
1368 @param Bsp TRUE if the CPU is BSP
1369 @param ProcessorNumber The specific processor number
1371 @retval EFI_SUCCESS Data for the processor collected and filled in
1375 FillInProcessorInformation (
1377 IN UINTN ProcessorNumber
1380 CPU_DATA_BLOCK
*CpuData
;
1383 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
1384 ProcessorId
= GetApicId ();
1385 CpuData
->Info
.ProcessorId
= ProcessorId
;
1386 CpuData
->Info
.StatusFlag
= PROCESSOR_ENABLED_BIT
| PROCESSOR_HEALTH_STATUS_BIT
;
1388 CpuData
->Info
.StatusFlag
|= PROCESSOR_AS_BSP_BIT
;
1390 CpuData
->Info
.Location
.Package
= ProcessorId
;
1391 CpuData
->Info
.Location
.Core
= 0;
1392 CpuData
->Info
.Location
.Thread
= 0;
1393 CpuData
->State
= Bsp
? CpuStateBuzy
: CpuStateIdle
;
1395 CpuData
->Procedure
= NULL
;
1396 CpuData
->Parameter
= NULL
;
1397 InitializeSpinLock (&CpuData
->CpuDataLock
);
1403 Prepare the System Data.
1405 @retval EFI_SUCCESS the System Data finished initilization.
1415 ZeroMem (&mMpSystemData
, sizeof (MP_SYSTEM_DATA
));
1417 mMpSystemData
.NumberOfProcessors
= 1;
1418 mMpSystemData
.NumberOfEnabledProcessors
= 1;
1420 mMpSystemData
.CpuDatas
= AllocateZeroPool (sizeof (CPU_DATA_BLOCK
) * gMaxLogicalProcessorNumber
);
1421 ASSERT(mMpSystemData
.CpuDatas
!= NULL
);
1423 Status
= gBS
->CreateEvent (
1424 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1428 &mMpSystemData
.CheckAllAPsEvent
1430 ASSERT_EFI_ERROR (Status
);
1433 // Set timer to check all APs status.
1435 Status
= gBS
->SetTimer (
1436 mMpSystemData
.CheckAllAPsEvent
,
1438 EFI_TIMER_PERIOD_MICROSECONDS (100)
1440 ASSERT_EFI_ERROR (Status
);
1445 FillInProcessorInformation (TRUE
, 0);
1451 Initialize Multi-processor support.
1455 InitializeMpSupport (
1459 gMaxLogicalProcessorNumber
= (UINTN
) PcdGet32 (PcdCpuMaxLogicalProcessorNumber
);
1460 if (gMaxLogicalProcessorNumber
< 1) {
1461 DEBUG ((DEBUG_ERROR
, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n"));
1465 if (gMaxLogicalProcessorNumber
== 1) {
1469 gApStackSize
= (UINTN
) PcdGet32 (PcdCpuApStackSize
);
1470 ASSERT ((gApStackSize
& (SIZE_4KB
- 1)) == 0);
1472 mApStackStart
= AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber
* gApStackSize
));
1473 ASSERT (mApStackStart
!= NULL
);
1476 // the first buffer of stack size used for common stack, when the amount of AP
1477 // more than 1, we should never free the common stack which maybe used for AP reset.
1479 mCommonStack
= mApStackStart
;
1480 mTopOfApCommonStack
= (UINT8
*) mApStackStart
+ gApStackSize
;
1481 mApStackStart
= mTopOfApCommonStack
;
1483 InitMpSystemData ();
1485 PrepareAPStartupCode ();
1487 if (mMpSystemData
.NumberOfProcessors
== 1) {
1488 FreeApStartupCode ();
1489 FreePages (mCommonStack
, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber
* gApStackSize
));
1493 mMpSystemData
.CpuDatas
= ReallocatePool (
1494 sizeof (CPU_DATA_BLOCK
) * gMaxLogicalProcessorNumber
,
1495 sizeof (CPU_DATA_BLOCK
) * mMpSystemData
.NumberOfProcessors
,
1496 mMpSystemData
.CpuDatas
);
1498 mAPsAlreadyInitFinished
= TRUE
;
1500 if (mMpSystemData
.NumberOfProcessors
< gMaxLogicalProcessorNumber
) {
1501 FreePages (mApStackStart
, EFI_SIZE_TO_PAGES (
1502 (gMaxLogicalProcessorNumber
- mMpSystemData
.NumberOfProcessors
) *