4 Copyright (c) 2008 - 2015, 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
;
23 EFI_HANDLE mMpServiceHandle
= NULL
;
24 EFI_EVENT mExitBootServicesEvent
= (EFI_EVENT
)NULL
;
26 VOID
*mCommonStack
= 0;
27 VOID
*mTopOfApCommonStack
= 0;
28 VOID
*mApStackStart
= 0;
30 volatile BOOLEAN mAPsAlreadyInitFinished
= FALSE
;
31 volatile BOOLEAN mStopCheckAllAPsStatus
= TRUE
;
33 EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate
= {
34 GetNumberOfProcessors
,
46 @param CpuData the pointer to CPU_DATA_BLOCK of specified processor
51 IN CPU_DATA_BLOCK
*CpuData
54 while (!AcquireSpinLockOrFail (&CpuData
->CpuDataLock
)) {
57 CpuData
->LockSelf
= GetApicId ();
61 Release Mp Service Lock.
63 @param CpuData the pointer to CPU_DATA_BLOCK of specified processor
68 IN CPU_DATA_BLOCK
*CpuData
71 ReleaseSpinLock (&CpuData
->CpuDataLock
);
75 Check whether caller processor is BSP.
77 @retval TRUE the caller is BSP
78 @retval FALSE the caller is AP
87 CPU_DATA_BLOCK
*CpuData
;
91 WhoAmI (&mMpServicesTemplate
, &CpuIndex
);
92 CpuData
= &mMpSystemData
.CpuDatas
[CpuIndex
];
94 return CpuData
->Info
.StatusFlag
& PROCESSOR_AS_BSP_BIT
? TRUE
: FALSE
;
98 Get the Application Processors state.
100 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
102 @retval CPU_STATE the AP status
107 IN CPU_DATA_BLOCK
*CpuData
112 GetMpSpinLock (CpuData
);
113 State
= CpuData
->State
;
114 ReleaseMpSpinLock (CpuData
);
120 Set the Application Processors state.
122 @param CpuData The pointer to CPU_DATA_BLOCK of specified AP
123 @param State The AP status
128 IN CPU_DATA_BLOCK
*CpuData
,
132 GetMpSpinLock (CpuData
);
133 CpuData
->State
= State
;
134 ReleaseMpSpinLock (CpuData
);
138 Set the Application Processor prepare to run a function specified
141 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
142 @param Procedure A pointer to the function to be run on enabled APs of the system
143 @param ProcedureArgument Pointer to the optional parameter of the assigned function
148 IN CPU_DATA_BLOCK
*CpuData
,
149 IN EFI_AP_PROCEDURE Procedure
,
150 IN VOID
*ProcedureArgument
153 GetMpSpinLock (CpuData
);
154 CpuData
->Parameter
= ProcedureArgument
;
155 CpuData
->Procedure
= Procedure
;
156 ReleaseMpSpinLock (CpuData
);
160 Check the Application Processors Status whether contains the Flags.
162 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
163 @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION
165 @retval TRUE the AP status includes the StatusFlag
166 @retval FALSE the AP status excludes the StatusFlag
171 IN CPU_DATA_BLOCK
*CpuData
,
177 GetMpSpinLock (CpuData
);
178 Ret
= CpuData
->Info
.StatusFlag
& Flags
;
179 ReleaseMpSpinLock (CpuData
);
181 return (BOOLEAN
) (Ret
!= 0);
185 Bitwise-Or of the Application Processors Status with the Flags.
187 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
188 @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION
193 IN CPU_DATA_BLOCK
*CpuData
,
197 GetMpSpinLock (CpuData
);
198 CpuData
->Info
.StatusFlag
|= Flags
;
199 ReleaseMpSpinLock (CpuData
);
203 Bitwise-AndNot of the Application Processors Status with the Flags.
205 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
206 @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION
210 CpuStatusFlagAndNot (
211 IN CPU_DATA_BLOCK
*CpuData
,
215 GetMpSpinLock (CpuData
);
216 CpuData
->Info
.StatusFlag
&= ~Flags
;
217 ReleaseMpSpinLock (CpuData
);
221 Searches for the next blocking AP.
223 Search for the next AP that is put in blocking state by single-threaded StartupAllAPs().
225 @param NextNumber Pointer to the processor number of the next blocking AP.
227 @retval EFI_SUCCESS The next blocking AP has been found.
228 @retval EFI_NOT_FOUND No blocking AP exists.
232 GetNextBlockedNumber (
233 OUT UINTN
*NextNumber
238 CPU_DATA_BLOCK
*CpuData
;
240 for (Number
= 0; Number
< mMpSystemData
.NumberOfProcessors
; Number
++) {
241 CpuData
= &mMpSystemData
.CpuDatas
[Number
];
242 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
249 CpuState
= GetApState (CpuData
);
250 if (CpuState
== CpuStateBlocked
) {
251 *NextNumber
= Number
;
256 return EFI_NOT_FOUND
;
260 Check if the APs state are finished, and update them to idle state
265 CheckAndUpdateAllAPsToIdleState (
269 UINTN ProcessorNumber
;
271 CPU_DATA_BLOCK
*CpuData
;
275 for (ProcessorNumber
= 0; ProcessorNumber
< mMpSystemData
.NumberOfProcessors
; ProcessorNumber
++) {
276 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
277 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
284 if (!TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
286 // Skip Disabled processors
291 CpuState
= GetApState (CpuData
);
292 if (CpuState
== CpuStateFinished
) {
293 mMpSystemData
.FinishCount
++;
294 if (mMpSystemData
.SingleThread
) {
295 Status
= GetNextBlockedNumber (&NextNumber
);
296 if (!EFI_ERROR (Status
)) {
297 SetApState (&mMpSystemData
.CpuDatas
[NextNumber
], CpuStateReady
);
298 SetApProcedure (&mMpSystemData
.CpuDatas
[NextNumber
],
299 mMpSystemData
.Procedure
,
300 mMpSystemData
.ProcedureArgument
);
302 // If this AP previous state is blocked, we should
303 // wake up this AP by sent a SIPI. and avoid
304 // re-involve the sleeping state. we must call
305 // SetApProcedure() first.
307 ResetProcessorToIdleState (&mMpSystemData
.CpuDatas
[NextNumber
]);
310 SetApState (CpuData
, CpuStateIdle
);
316 If the timeout expires before all APs returns from Procedure,
317 we should forcibly terminate the executing AP and fill FailedList back
326 CPU_DATA_BLOCK
*CpuData
;
330 if (mMpSystemData
.FailedList
!= NULL
) {
331 *mMpSystemData
.FailedList
= AllocatePool ((mMpSystemData
.StartCount
- mMpSystemData
.FinishCount
+ 1) * sizeof(UINTN
));
332 ASSERT (*mMpSystemData
.FailedList
!= NULL
);
335 for (Number
= 0; Number
< mMpSystemData
.NumberOfProcessors
; Number
++) {
336 CpuData
= &mMpSystemData
.CpuDatas
[Number
];
337 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
344 if (!TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
346 // Skip Disabled processors
351 CpuState
= GetApState (CpuData
);
352 if (CpuState
!= CpuStateIdle
&&
353 CpuState
!= CpuStateSleeping
) {
354 if (mMpSystemData
.FailedList
!= NULL
) {
355 (*mMpSystemData
.FailedList
)[mMpSystemData
.FailedListIndex
++] = Number
;
357 ResetProcessorToIdleState (CpuData
);
361 if (mMpSystemData
.FailedList
!= NULL
) {
362 (*mMpSystemData
.FailedList
)[mMpSystemData
.FailedListIndex
] = END_OF_CPU_LIST
;
367 This service retrieves the number of logical processor in the platform
368 and the number of those logical processors that are enabled on this boot.
369 This service may only be called from the BSP.
371 This function is used to retrieve the following information:
372 - The number of logical processors that are present in the system.
373 - The number of enabled logical processors in the system at the instant
376 Because MP Service Protocol provides services to enable and disable processors
377 dynamically, the number of enabled logical processors may vary during the
378 course of a boot session.
380 If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
381 If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
382 EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
383 is returned in NumberOfProcessors, the number of currently enabled processor
384 is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
386 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
388 @param[out] NumberOfProcessors Pointer to the total number of logical
389 processors in the system, including the BSP
391 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
392 processors that exist in system, including
395 @retval EFI_SUCCESS The number of logical processors and enabled
396 logical processors was retrieved.
397 @retval EFI_DEVICE_ERROR The calling processor is an AP.
398 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
399 @retval EFI_INVALID_PARAMETER NumberOfEnabledProcessors is NULL.
404 GetNumberOfProcessors (
405 IN EFI_MP_SERVICES_PROTOCOL
*This
,
406 OUT UINTN
*NumberOfProcessors
,
407 OUT UINTN
*NumberOfEnabledProcessors
410 if ((NumberOfProcessors
== NULL
) || (NumberOfEnabledProcessors
== NULL
)) {
411 return EFI_INVALID_PARAMETER
;
415 return EFI_DEVICE_ERROR
;
418 *NumberOfProcessors
= mMpSystemData
.NumberOfProcessors
;
419 *NumberOfEnabledProcessors
= mMpSystemData
.NumberOfEnabledProcessors
;
424 Gets detailed MP-related information on the requested processor at the
425 instant this call is made. This service may only be called from the BSP.
427 This service retrieves detailed MP-related information about any processor
428 on the platform. Note the following:
429 - The processor information may change during the course of a boot session.
430 - The information presented here is entirely MP related.
432 Information regarding the number of caches and their sizes, frequency of operation,
433 slot numbers is all considered platform-related information and is not provided
436 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
438 @param[in] ProcessorNumber The handle number of processor.
439 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
440 the requested processor is deposited.
442 @retval EFI_SUCCESS Processor information was returned.
443 @retval EFI_DEVICE_ERROR The calling processor is an AP.
444 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
445 @retval EFI_NOT_FOUND The processor with the handle specified by
446 ProcessorNumber does not exist in the platform.
452 IN EFI_MP_SERVICES_PROTOCOL
*This
,
453 IN UINTN ProcessorNumber
,
454 OUT EFI_PROCESSOR_INFORMATION
*ProcessorInfoBuffer
457 if (ProcessorInfoBuffer
== NULL
) {
458 return EFI_INVALID_PARAMETER
;
462 return EFI_DEVICE_ERROR
;
465 if (ProcessorNumber
>= mMpSystemData
.NumberOfProcessors
) {
466 return EFI_NOT_FOUND
;
469 CopyMem (ProcessorInfoBuffer
, &mMpSystemData
.CpuDatas
[ProcessorNumber
], sizeof (EFI_PROCESSOR_INFORMATION
));
474 This service executes a caller provided function on all enabled APs. APs can
475 run either simultaneously or one at a time in sequence. This service supports
476 both blocking and non-blocking requests. The non-blocking requests use EFI
477 events so the BSP can detect when the APs have finished. This service may only
478 be called from the BSP.
480 This function is used to dispatch all the enabled APs to the function specified
481 by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned
482 immediately and Procedure is not started on any AP.
484 If SingleThread is TRUE, all the enabled APs execute the function specified by
485 Procedure one by one, in ascending order of processor handle number. Otherwise,
486 all the enabled APs execute the function specified by Procedure simultaneously.
488 If WaitEvent is NULL, execution is in blocking mode. The BSP waits until all
489 APs finish or TimeoutInMicroseconds expires. Otherwise, execution is in non-blocking
490 mode, and the BSP returns from this service without waiting for APs. If a
491 non-blocking mode is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
492 is signaled, then EFI_UNSUPPORTED must be returned.
494 If the timeout specified by TimeoutInMicroseconds expires before all APs return
495 from Procedure, then Procedure on the failed APs is terminated. All enabled APs
496 are always available for further calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
497 and EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). If FailedCpuList is not NULL, its
498 content points to the list of processor handle numbers in which Procedure was
501 Note: It is the responsibility of the consumer of the EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
502 to make sure that the nature of the code that is executed on the BSP and the
503 dispatched APs is well controlled. The MP Services Protocol does not guarantee
504 that the Procedure function is MP-safe. Hence, the tasks that can be run in
505 parallel are limited to certain independent tasks and well-controlled exclusive
506 code. EFI services and protocols may not be called by APs unless otherwise
509 In blocking execution mode, BSP waits until all APs finish or
510 TimeoutInMicroseconds expires.
512 In non-blocking execution mode, BSP is freed to return to the caller and then
513 proceed to the next task without having to wait for APs. The following
514 sequence needs to occur in a non-blocking execution mode:
516 -# The caller that intends to use this MP Services Protocol in non-blocking
517 mode creates WaitEvent by calling the EFI CreateEvent() service. The caller
518 invokes EFI_MP_SERVICES_PROTOCOL.StartupAllAPs(). If the parameter WaitEvent
519 is not NULL, then StartupAllAPs() executes in non-blocking mode. It requests
520 the function specified by Procedure to be started on all the enabled APs,
521 and releases the BSP to continue with other tasks.
522 -# The caller can use the CheckEvent() and WaitForEvent() services to check
523 the state of the WaitEvent created in step 1.
524 -# When the APs complete their task or TimeoutInMicroSecondss expires, the MP
525 Service signals WaitEvent by calling the EFI SignalEvent() function. If
526 FailedCpuList is not NULL, its content is available when WaitEvent is
527 signaled. If all APs returned from Procedure prior to the timeout, then
528 FailedCpuList is set to NULL. If not all APs return from Procedure before
529 the timeout, then FailedCpuList is filled in with the list of the failed
530 APs. The buffer is allocated by MP Service Protocol using AllocatePool().
531 It is the caller's responsibility to free the buffer with FreePool() service.
532 -# This invocation of SignalEvent() function informs the caller that invoked
533 EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() that either all the APs completed
534 the specified task or a timeout occurred. The contents of FailedCpuList
535 can be examined to determine which APs did not complete the specified task
536 prior to the timeout.
538 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
540 @param[in] Procedure A pointer to the function to be run on
541 enabled APs of the system. See type
543 @param[in] SingleThread If TRUE, then all the enabled APs execute
544 the function specified by Procedure one by
545 one, in ascending order of processor handle
546 number. If FALSE, then all the enabled APs
547 execute the function specified by Procedure
549 @param[in] WaitEvent The event created by the caller with CreateEvent()
550 service. If it is NULL, then execute in
551 blocking mode. BSP waits until all APs finish
552 or TimeoutInMicroseconds expires. If it's
553 not NULL, then execute in non-blocking mode.
554 BSP requests the function specified by
555 Procedure to be started on all the enabled
556 APs, and go on executing immediately. If
557 all return from Procedure, or TimeoutInMicroseconds
558 expires, this event is signaled. The BSP
559 can use the CheckEvent() or WaitForEvent()
560 services to check the state of event. Type
561 EFI_EVENT is defined in CreateEvent() in
562 the Unified Extensible Firmware Interface
564 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
565 APs to return from Procedure, either for
566 blocking or non-blocking mode. Zero means
567 infinity. If the timeout expires before
568 all APs return from Procedure, then Procedure
569 on the failed APs is terminated. All enabled
570 APs are available for next function assigned
571 by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
572 or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
573 If the timeout expires in blocking mode,
574 BSP returns EFI_TIMEOUT. If the timeout
575 expires in non-blocking mode, WaitEvent
576 is signaled with SignalEvent().
577 @param[in] ProcedureArgument The parameter passed into Procedure for
579 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
580 if all APs finish successfully, then its
581 content is set to NULL. If not all APs
582 finish before timeout expires, then its
583 content is set to address of the buffer
584 holding handle numbers of the failed APs.
585 The buffer is allocated by MP Service Protocol,
586 and it's the caller's responsibility to
587 free the buffer with FreePool() service.
588 In blocking mode, it is ready for consumption
589 when the call returns. In non-blocking mode,
590 it is ready when WaitEvent is signaled. The
591 list of failed CPU is terminated by
594 @retval EFI_SUCCESS In blocking mode, all APs have finished before
596 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
598 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
599 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
601 @retval EFI_DEVICE_ERROR Caller processor is AP.
602 @retval EFI_NOT_STARTED No enabled APs exist in the system.
603 @retval EFI_NOT_READY Any enabled APs are busy.
604 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
605 all enabled APs have finished.
606 @retval EFI_INVALID_PARAMETER Procedure is NULL.
612 IN EFI_MP_SERVICES_PROTOCOL
*This
,
613 IN EFI_AP_PROCEDURE Procedure
,
614 IN BOOLEAN SingleThread
,
615 IN EFI_EVENT WaitEvent OPTIONAL
,
616 IN UINTN TimeoutInMicroseconds
,
617 IN VOID
*ProcedureArgument OPTIONAL
,
618 OUT UINTN
**FailedCpuList OPTIONAL
622 CPU_DATA_BLOCK
*CpuData
;
624 CPU_STATE APInitialState
;
629 if (FailedCpuList
!= NULL
) {
630 *FailedCpuList
= NULL
;
634 return EFI_DEVICE_ERROR
;
637 if (mMpSystemData
.NumberOfProcessors
== 1) {
638 return EFI_NOT_STARTED
;
641 if (Procedure
== NULL
) {
642 return EFI_INVALID_PARAMETER
;
646 // temporarily stop checkAllAPsStatus for avoid resource dead-lock.
648 mStopCheckAllAPsStatus
= TRUE
;
650 for (Number
= 0; Number
< mMpSystemData
.NumberOfProcessors
; Number
++) {
651 CpuData
= &mMpSystemData
.CpuDatas
[Number
];
652 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
659 if (!TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
661 // Skip Disabled processors
666 CpuState
= GetApState (CpuData
);
667 if (CpuState
!= CpuStateIdle
&&
668 CpuState
!= CpuStateSleeping
) {
669 return EFI_NOT_READY
;
673 mMpSystemData
.Procedure
= Procedure
;
674 mMpSystemData
.ProcedureArgument
= ProcedureArgument
;
675 mMpSystemData
.WaitEvent
= WaitEvent
;
676 mMpSystemData
.Timeout
= TimeoutInMicroseconds
;
677 mMpSystemData
.TimeoutActive
= (BOOLEAN
) (TimeoutInMicroseconds
!= 0);
678 mMpSystemData
.FinishCount
= 0;
679 mMpSystemData
.StartCount
= 0;
680 mMpSystemData
.SingleThread
= SingleThread
;
681 mMpSystemData
.FailedList
= FailedCpuList
;
682 mMpSystemData
.FailedListIndex
= 0;
683 APInitialState
= CpuStateReady
;
685 for (Number
= 0; Number
< mMpSystemData
.NumberOfProcessors
; Number
++) {
686 CpuData
= &mMpSystemData
.CpuDatas
[Number
];
687 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
694 if (!TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
696 // Skip Disabled processors
702 // Get APs prepared, and put failing APs into FailedCpuList
703 // if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready
704 // state 1 by 1, until the previous 1 finished its task
705 // if not "SingleThread", all APs are put to ready state from the beginning
707 CpuState
= GetApState (CpuData
);
708 if (CpuState
== CpuStateIdle
||
709 CpuState
== CpuStateSleeping
) {
710 mMpSystemData
.StartCount
++;
712 SetApState (CpuData
, APInitialState
);
714 if (APInitialState
== CpuStateReady
) {
715 SetApProcedure (CpuData
, Procedure
, ProcedureArgument
);
717 // If this AP previous state is Sleeping, we should
718 // wake up this AP by sent a SIPI. and avoid
719 // re-involve the sleeping state. we must call
720 // SetApProcedure() first.
722 if (CpuState
== CpuStateSleeping
) {
723 ResetProcessorToIdleState (CpuData
);
728 APInitialState
= CpuStateBlocked
;
733 mStopCheckAllAPsStatus
= FALSE
;
735 if (WaitEvent
!= NULL
) {
743 // Blocking temporarily stop CheckAllAPsStatus()
745 mStopCheckAllAPsStatus
= TRUE
;
748 CheckAndUpdateAllAPsToIdleState ();
749 if (mMpSystemData
.FinishCount
== mMpSystemData
.StartCount
) {
750 Status
= EFI_SUCCESS
;
757 if (mMpSystemData
.TimeoutActive
&& mMpSystemData
.Timeout
< 0) {
759 Status
= EFI_TIMEOUT
;
763 gBS
->Stall (gPollInterval
);
764 mMpSystemData
.Timeout
-= gPollInterval
;
773 This service lets the caller get one enabled AP to execute a caller-provided
774 function. The caller can request the BSP to either wait for the completion
775 of the AP or just proceed with the next task by using the EFI event mechanism.
776 See EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() for more details on non-blocking
777 execution support. This service may only be called from the BSP.
779 This function is used to dispatch one enabled AP to the function specified by
780 Procedure passing in the argument specified by ProcedureArgument. If WaitEvent
781 is NULL, execution is in blocking mode. The BSP waits until the AP finishes or
782 TimeoutInMicroSecondss expires. Otherwise, execution is in non-blocking mode.
783 BSP proceeds to the next task without waiting for the AP. If a non-blocking mode
784 is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled,
785 then EFI_UNSUPPORTED must be returned.
787 If the timeout specified by TimeoutInMicroseconds expires before the AP returns
788 from Procedure, then execution of Procedure by the AP is terminated. The AP is
789 available for subsequent calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() and
790 EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
792 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
794 @param[in] Procedure A pointer to the function to be run on
795 enabled APs of the system. See type
797 @param[in] ProcessorNumber The handle number of the AP. The range is
798 from 0 to the total number of logical
799 processors minus 1. The total number of
800 logical processors can be retrieved by
801 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
802 @param[in] WaitEvent The event created by the caller with CreateEvent()
803 service. If it is NULL, then execute in
804 blocking mode. BSP waits until all APs finish
805 or TimeoutInMicroseconds expires. If it's
806 not NULL, then execute in non-blocking mode.
807 BSP requests the function specified by
808 Procedure to be started on all the enabled
809 APs, and go on executing immediately. If
810 all return from Procedure or TimeoutInMicroseconds
811 expires, this event is signaled. The BSP
812 can use the CheckEvent() or WaitForEvent()
813 services to check the state of event. Type
814 EFI_EVENT is defined in CreateEvent() in
815 the Unified Extensible Firmware Interface
817 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
818 APs to return from Procedure, either for
819 blocking or non-blocking mode. Zero means
820 infinity. If the timeout expires before
821 all APs return from Procedure, then Procedure
822 on the failed APs is terminated. All enabled
823 APs are available for next function assigned
824 by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
825 or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
826 If the timeout expires in blocking mode,
827 BSP returns EFI_TIMEOUT. If the timeout
828 expires in non-blocking mode, WaitEvent
829 is signaled with SignalEvent().
830 @param[in] ProcedureArgument The parameter passed into Procedure for
832 @param[out] Finished If NULL, this parameter is ignored. In
833 blocking mode, this parameter is ignored.
834 In non-blocking mode, if AP returns from
835 Procedure before the timeout expires, its
836 content is set to TRUE. Otherwise, the
837 value is set to FALSE. The caller can
838 determine if the AP returned from Procedure
839 by evaluating this value.
841 @retval EFI_SUCCESS In blocking mode, specified AP finished before
843 @retval EFI_SUCCESS In non-blocking mode, the function has been
844 dispatched to specified AP.
845 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
846 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
848 @retval EFI_DEVICE_ERROR The calling processor is an AP.
849 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
850 the specified AP has finished.
851 @retval EFI_NOT_READY The specified AP is busy.
852 @retval EFI_NOT_FOUND The processor with the handle specified by
853 ProcessorNumber does not exist.
854 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
855 @retval EFI_INVALID_PARAMETER Procedure is NULL.
861 IN EFI_MP_SERVICES_PROTOCOL
*This
,
862 IN EFI_AP_PROCEDURE Procedure
,
863 IN UINTN ProcessorNumber
,
864 IN EFI_EVENT WaitEvent OPTIONAL
,
865 IN UINTN TimeoutInMicroseconds
,
866 IN VOID
*ProcedureArgument OPTIONAL
,
867 OUT BOOLEAN
*Finished OPTIONAL
870 CPU_DATA_BLOCK
*CpuData
;
875 if (Finished
!= NULL
) {
880 return EFI_DEVICE_ERROR
;
883 if (Procedure
== NULL
) {
884 return EFI_INVALID_PARAMETER
;
887 if (ProcessorNumber
>= mMpSystemData
.NumberOfProcessors
) {
888 return EFI_NOT_FOUND
;
892 // temporarily stop checkAllAPsStatus for avoid resource dead-lock.
894 mStopCheckAllAPsStatus
= TRUE
;
896 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
897 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
) ||
898 !TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
899 return EFI_INVALID_PARAMETER
;
902 CpuState
= GetApState (CpuData
);
903 if (CpuState
!= CpuStateIdle
&&
904 CpuState
!= CpuStateSleeping
) {
905 return EFI_NOT_READY
;
908 SetApState (CpuData
, CpuStateReady
);
910 SetApProcedure (CpuData
, Procedure
, ProcedureArgument
);
912 // If this AP previous state is Sleeping, we should
913 // wake up this AP by sent a SIPI. and avoid
914 // re-involve the sleeping state. we must call
915 // SetApProcedure() first.
917 if (CpuState
== CpuStateSleeping
) {
918 ResetProcessorToIdleState (CpuData
);
921 CpuData
->Timeout
= TimeoutInMicroseconds
;
922 CpuData
->WaitEvent
= WaitEvent
;
923 CpuData
->TimeoutActive
= (BOOLEAN
) (TimeoutInMicroseconds
!= 0);
924 CpuData
->Finished
= Finished
;
926 mStopCheckAllAPsStatus
= FALSE
;
928 if (WaitEvent
!= NULL
) {
939 if (GetApState (CpuData
) == CpuStateFinished
) {
940 SetApState (CpuData
, CpuStateIdle
);
944 if (CpuData
->TimeoutActive
&& CpuData
->Timeout
< 0) {
945 ResetProcessorToIdleState (CpuData
);
949 gBS
->Stall (gPollInterval
);
950 CpuData
->Timeout
-= gPollInterval
;
957 This service switches the requested AP to be the BSP from that point onward.
958 This service changes the BSP for all purposes. This call can only be performed
961 This service switches the requested AP to be the BSP from that point onward.
962 This service changes the BSP for all purposes. The new BSP can take over the
963 execution of the old BSP and continue seamlessly from where the old one left
964 off. This service may not be supported after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
967 If the BSP cannot be switched prior to the return from this service, then
968 EFI_UNSUPPORTED must be returned.
970 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
971 @param[in] ProcessorNumber The handle number of AP that is to become the new
972 BSP. The range is from 0 to the total number of
973 logical processors minus 1. The total number of
974 logical processors can be retrieved by
975 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
976 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
977 enabled AP. Otherwise, it will be disabled.
979 @retval EFI_SUCCESS BSP successfully switched.
980 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
981 this service returning.
982 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
983 @retval EFI_SUCCESS The calling processor is an AP.
984 @retval EFI_NOT_FOUND The processor with the handle specified by
985 ProcessorNumber does not exist.
986 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
988 @retval EFI_NOT_READY The specified AP is busy.
994 IN EFI_MP_SERVICES_PROTOCOL
*This
,
995 IN UINTN ProcessorNumber
,
996 IN BOOLEAN EnableOldBSP
1000 // Current always return unsupported.
1002 return EFI_UNSUPPORTED
;
1006 This service lets the caller enable or disable an AP from this point onward.
1007 This service may only be called from the BSP.
1009 This service allows the caller enable or disable an AP from this point onward.
1010 The caller can optionally specify the health status of the AP by Health. If
1011 an AP is being disabled, then the state of the disabled AP is implementation
1012 dependent. If an AP is enabled, then the implementation must guarantee that a
1013 complete initialization sequence is performed on the AP, so the AP is in a state
1014 that is compatible with an MP operating system. This service may not be supported
1015 after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled.
1017 If the enable or disable AP operation cannot be completed prior to the return
1018 from this service, then EFI_UNSUPPORTED must be returned.
1020 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
1021 @param[in] ProcessorNumber The handle number of AP that is to become the new
1022 BSP. The range is from 0 to the total number of
1023 logical processors minus 1. The total number of
1024 logical processors can be retrieved by
1025 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
1026 @param[in] EnableAP Specifies the new state for the processor for
1027 enabled, FALSE for disabled.
1028 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
1029 the new health status of the AP. This flag
1030 corresponds to StatusFlag defined in
1031 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
1032 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
1033 bits are ignored. If it is NULL, this parameter
1036 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
1037 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
1038 prior to this service returning.
1039 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
1040 @retval EFI_DEVICE_ERROR The calling processor is an AP.
1041 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
1043 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
1049 IN EFI_MP_SERVICES_PROTOCOL
*This
,
1050 IN UINTN ProcessorNumber
,
1051 IN BOOLEAN EnableAP
,
1052 IN UINT32
*HealthFlag OPTIONAL
1055 CPU_DATA_BLOCK
*CpuData
;
1056 BOOLEAN TempStopCheckState
;
1060 TempStopCheckState
= FALSE
;
1063 return EFI_DEVICE_ERROR
;
1066 if (ProcessorNumber
>= mMpSystemData
.NumberOfProcessors
) {
1067 return EFI_NOT_FOUND
;
1071 // temporarily stop checkAllAPsStatus for initialize parameters.
1073 if (!mStopCheckAllAPsStatus
) {
1074 mStopCheckAllAPsStatus
= TRUE
;
1075 TempStopCheckState
= TRUE
;
1078 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
1079 if (TestCpuStatusFlag (CpuData
, PROCESSOR_AS_BSP_BIT
)) {
1080 return EFI_INVALID_PARAMETER
;
1083 CpuState
= GetApState (CpuData
);
1084 if (CpuState
!= CpuStateIdle
&&
1085 CpuState
!= CpuStateSleeping
) {
1086 return EFI_UNSUPPORTED
;
1090 if (!(TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
))) {
1091 mMpSystemData
.NumberOfEnabledProcessors
++;
1093 CpuStatusFlagOr (CpuData
, PROCESSOR_ENABLED_BIT
);
1095 if (TestCpuStatusFlag (CpuData
, PROCESSOR_ENABLED_BIT
)) {
1096 mMpSystemData
.NumberOfEnabledProcessors
--;
1098 CpuStatusFlagAndNot (CpuData
, PROCESSOR_ENABLED_BIT
);
1101 if (HealthFlag
!= NULL
) {
1102 CpuStatusFlagAndNot (CpuData
, (UINT32
)~PROCESSOR_HEALTH_STATUS_BIT
);
1103 CpuStatusFlagOr (CpuData
, (*HealthFlag
& PROCESSOR_HEALTH_STATUS_BIT
));
1106 if (TempStopCheckState
) {
1107 mStopCheckAllAPsStatus
= FALSE
;
1114 This return the handle number for the calling processor. This service may be
1115 called from the BSP and APs.
1117 This service returns the processor handle number for the calling processor.
1118 The returned value is in the range from 0 to the total number of logical
1119 processors minus 1. The total number of logical processors can be retrieved
1120 with EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be
1121 called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
1122 is returned. Otherwise, the current processors handle number is returned in
1123 ProcessorNumber, and EFI_SUCCESS is returned.
1125 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
1126 @param[out] ProcessorNumber The handle number of AP that is to become the new
1127 BSP. The range is from 0 to the total number of
1128 logical processors minus 1. The total number of
1129 logical processors can be retrieved by
1130 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
1132 @retval EFI_SUCCESS The current processor handle number was returned
1134 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
1140 IN EFI_MP_SERVICES_PROTOCOL
*This
,
1141 OUT UINTN
*ProcessorNumber
1147 if (ProcessorNumber
== NULL
) {
1148 return EFI_INVALID_PARAMETER
;
1151 ProcessorId
= GetApicId ();
1152 for (Index
= 0; Index
< mMpSystemData
.NumberOfProcessors
; Index
++) {
1153 if (mMpSystemData
.CpuDatas
[Index
].Info
.ProcessorId
== ProcessorId
) {
1158 *ProcessorNumber
= Index
;
1163 Terminate AP's task and set it to idle state.
1165 This function terminates AP's task due to timeout by sending INIT-SIPI,
1166 and sends it to idle state.
1168 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
1172 ResetProcessorToIdleState (
1173 IN CPU_DATA_BLOCK
*CpuData
1176 ResetApStackless ((UINT32
)CpuData
->Info
.ProcessorId
);
1180 Application Processors do loop routine
1181 after switch to its own stack.
1183 @param Context1 A pointer to the context to pass into the function.
1184 @param Context2 A pointer to the context to pass into the function.
1188 ProcessorToIdleState (
1189 IN VOID
*Context1
, OPTIONAL
1190 IN VOID
*Context2 OPTIONAL
1193 UINTN ProcessorNumber
;
1194 CPU_DATA_BLOCK
*CpuData
;
1195 EFI_AP_PROCEDURE Procedure
;
1196 volatile VOID
*ProcedureArgument
;
1198 AsmApDoneWithCommonStack ();
1200 while (!mAPsAlreadyInitFinished
) {
1204 WhoAmI (&mMpServicesTemplate
, &ProcessorNumber
);
1205 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
1208 // Avoid forcibly reset AP caused the AP got lock not release.
1210 if (CpuData
->LockSelf
== (INTN
) GetApicId ()) {
1211 ReleaseSpinLock (&CpuData
->CpuDataLock
);
1215 // Avoid forcibly reset AP caused the timeout AP State is not
1218 GetMpSpinLock (CpuData
);
1219 if (CpuData
->State
== CpuStateBusy
) {
1220 CpuData
->Procedure
= NULL
;
1222 CpuData
->State
= CpuStateIdle
;
1223 ReleaseMpSpinLock (CpuData
);
1226 GetMpSpinLock (CpuData
);
1227 ProcedureArgument
= CpuData
->Parameter
;
1228 Procedure
= CpuData
->Procedure
;
1229 ReleaseMpSpinLock (CpuData
);
1231 if (Procedure
!= NULL
) {
1232 SetApState (CpuData
, CpuStateBusy
);
1234 Procedure ((VOID
*) ProcedureArgument
);
1236 GetMpSpinLock (CpuData
);
1237 CpuData
->Procedure
= NULL
;
1238 CpuData
->State
= CpuStateFinished
;
1239 ReleaseMpSpinLock (CpuData
);
1242 // if no procedure to execution, we simply put AP
1243 // into sleeping state, and waiting BSP sent SIPI.
1245 GetMpSpinLock (CpuData
);
1246 if (CpuData
->State
== CpuStateIdle
) {
1247 CpuData
->State
= CpuStateSleeping
;
1249 ReleaseMpSpinLock (CpuData
);
1252 if (GetApState (CpuData
) == CpuStateSleeping
) {
1264 Checks AP' status periodically.
1266 This function is triggerred by timer perodically to check the
1267 state of AP forStartupThisAP() executed in non-blocking mode.
1269 @param Event Event triggered.
1270 @param Context Parameter passed with the event.
1280 CPU_DATA_BLOCK
*CpuData
;
1283 CpuData
= (CPU_DATA_BLOCK
*) Context
;
1284 if (CpuData
->TimeoutActive
) {
1285 CpuData
->Timeout
-= gPollInterval
;
1288 CpuState
= GetApState (CpuData
);
1290 if (CpuState
== CpuStateFinished
) {
1291 if (CpuData
->Finished
) {
1292 *CpuData
->Finished
= TRUE
;
1294 SetApState (CpuData
, CpuStateIdle
);
1298 if (CpuData
->TimeoutActive
&& CpuData
->Timeout
< 0) {
1299 if (CpuState
!= CpuStateIdle
&&
1300 CpuData
->Finished
) {
1301 *CpuData
->Finished
= FALSE
;
1303 ResetProcessorToIdleState (CpuData
);
1310 CpuData
->TimeoutActive
= FALSE
;
1311 gBS
->SignalEvent (CpuData
->WaitEvent
);
1312 CpuData
->WaitEvent
= NULL
;
1316 Checks APs' status periodically.
1318 This function is triggerred by timer perodically to check the
1319 state of APs for StartupAllAPs() executed in non-blocking mode.
1321 @param Event Event triggered.
1322 @param Context Parameter passed with the event.
1332 CPU_DATA_BLOCK
*CpuData
;
1336 if (mMpSystemData
.TimeoutActive
) {
1337 mMpSystemData
.Timeout
-= gPollInterval
;
1340 if (mStopCheckAllAPsStatus
) {
1345 // avoid next timer enter.
1347 Status
= gBS
->SetTimer (
1348 mMpSystemData
.CheckAllAPsEvent
,
1352 ASSERT_EFI_ERROR (Status
);
1354 if (mMpSystemData
.WaitEvent
!= NULL
) {
1355 CheckAndUpdateAllAPsToIdleState ();
1359 if (mMpSystemData
.TimeoutActive
&& mMpSystemData
.Timeout
< 0) {
1360 ResetAllFailedAPs();
1364 mMpSystemData
.FinishCount
= mMpSystemData
.StartCount
;
1367 if (mMpSystemData
.FinishCount
!= mMpSystemData
.StartCount
) {
1371 mMpSystemData
.TimeoutActive
= FALSE
;
1372 gBS
->SignalEvent (mMpSystemData
.WaitEvent
);
1373 mMpSystemData
.WaitEvent
= NULL
;
1374 mStopCheckAllAPsStatus
= TRUE
;
1380 // check each AP status for StartupThisAP
1382 for (Number
= 0; Number
< mMpSystemData
.NumberOfProcessors
; Number
++) {
1383 CpuData
= &mMpSystemData
.CpuDatas
[Number
];
1384 if (CpuData
->WaitEvent
) {
1385 CheckThisAPStatus (NULL
, (VOID
*)CpuData
);
1390 Status
= gBS
->SetTimer (
1391 mMpSystemData
.CheckAllAPsEvent
,
1393 EFI_TIMER_PERIOD_MICROSECONDS (100)
1395 ASSERT_EFI_ERROR (Status
);
1399 Application Processor C code entry point.
1409 UINTN ProcessorNumber
;
1411 if (!mAPsAlreadyInitFinished
) {
1412 FillInProcessorInformation (FALSE
, mMpSystemData
.NumberOfProcessors
);
1413 TopOfApStack
= (UINT8
*)mApStackStart
+ gApStackSize
;
1414 mApStackStart
= TopOfApStack
;
1417 // Store the Stack address, when reset the AP, We can found the original address.
1419 mMpSystemData
.CpuDatas
[mMpSystemData
.NumberOfProcessors
].TopOfStack
= TopOfApStack
;
1420 mMpSystemData
.NumberOfProcessors
++;
1421 mMpSystemData
.NumberOfEnabledProcessors
++;
1423 WhoAmI (&mMpServicesTemplate
, &ProcessorNumber
);
1425 // Get the original stack address.
1427 TopOfApStack
= mMpSystemData
.CpuDatas
[ProcessorNumber
].TopOfStack
;
1431 (SWITCH_STACK_ENTRY_POINT
)(UINTN
)ProcessorToIdleState
,
1438 This function is called by all processors (both BSP and AP) once and collects MP related data.
1440 @param Bsp TRUE if the CPU is BSP
1441 @param ProcessorNumber The specific processor number
1443 @retval EFI_SUCCESS Data for the processor collected and filled in
1447 FillInProcessorInformation (
1449 IN UINTN ProcessorNumber
1452 CPU_DATA_BLOCK
*CpuData
;
1455 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
1456 ProcessorId
= GetApicId ();
1457 CpuData
->Info
.ProcessorId
= ProcessorId
;
1458 CpuData
->Info
.StatusFlag
= PROCESSOR_ENABLED_BIT
| PROCESSOR_HEALTH_STATUS_BIT
;
1460 CpuData
->Info
.StatusFlag
|= PROCESSOR_AS_BSP_BIT
;
1462 CpuData
->Info
.Location
.Package
= ProcessorId
;
1463 CpuData
->Info
.Location
.Core
= 0;
1464 CpuData
->Info
.Location
.Thread
= 0;
1465 CpuData
->State
= Bsp
? CpuStateBusy
: CpuStateIdle
;
1467 CpuData
->Procedure
= NULL
;
1468 CpuData
->Parameter
= NULL
;
1469 InitializeSpinLock (&CpuData
->CpuDataLock
);
1470 CpuData
->LockSelf
= -1;
1476 Prepare the System Data.
1478 @retval EFI_SUCCESS the System Data finished initilization.
1488 ZeroMem (&mMpSystemData
, sizeof (MP_SYSTEM_DATA
));
1490 mMpSystemData
.NumberOfProcessors
= 1;
1491 mMpSystemData
.NumberOfEnabledProcessors
= 1;
1493 mMpSystemData
.CpuDatas
= AllocateZeroPool (sizeof (CPU_DATA_BLOCK
) * gMaxLogicalProcessorNumber
);
1494 ASSERT(mMpSystemData
.CpuDatas
!= NULL
);
1496 Status
= gBS
->CreateEvent (
1497 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1501 &mMpSystemData
.CheckAllAPsEvent
1503 ASSERT_EFI_ERROR (Status
);
1506 // Set timer to check all APs status.
1508 Status
= gBS
->SetTimer (
1509 mMpSystemData
.CheckAllAPsEvent
,
1511 EFI_TIMER_PERIOD_MICROSECONDS (100)
1513 ASSERT_EFI_ERROR (Status
);
1518 FillInProcessorInformation (TRUE
, 0);
1524 Collects BIST data from HOB.
1526 This function collects BIST data from HOB built from Sec Platform Information
1527 PPI or SEC Platform Information2 PPI.
1531 CollectBistDataFromHob (
1535 EFI_HOB_GUID_TYPE
*GuidHob
;
1536 EFI_SEC_PLATFORM_INFORMATION_RECORD2
*SecPlatformInformation2
;
1537 EFI_SEC_PLATFORM_INFORMATION_RECORD
*SecPlatformInformation
;
1539 EFI_SEC_PLATFORM_INFORMATION_CPU
*CpuInstance
;
1540 EFI_SEC_PLATFORM_INFORMATION_CPU BspCpuInstance
;
1541 UINTN ProcessorNumber
;
1542 UINT32 InitialLocalApicId
;
1543 CPU_DATA_BLOCK
*CpuData
;
1545 SecPlatformInformation2
= NULL
;
1546 SecPlatformInformation
= NULL
;
1549 // Get gEfiSecPlatformInformation2PpiGuid Guided HOB firstly
1551 GuidHob
= GetFirstGuidHob (&gEfiSecPlatformInformation2PpiGuid
);
1552 if (GuidHob
!= NULL
) {
1554 // Sec Platform Information2 PPI includes BSP/APs' BIST information
1556 SecPlatformInformation2
= GET_GUID_HOB_DATA (GuidHob
);
1557 NumberOfData
= SecPlatformInformation2
->NumberOfCpus
;
1558 CpuInstance
= SecPlatformInformation2
->CpuInstance
;
1561 // Otherwise, get gEfiSecPlatformInformationPpiGuid Guided HOB
1563 GuidHob
= GetFirstGuidHob (&gEfiSecPlatformInformationPpiGuid
);
1564 if (GuidHob
!= NULL
) {
1565 SecPlatformInformation
= GET_GUID_HOB_DATA (GuidHob
);
1568 // SEC Platform Information only includes BSP's BIST information
1569 // does not have BSP's APIC ID
1571 BspCpuInstance
.CpuLocation
= GetApicId ();
1572 BspCpuInstance
.InfoRecord
.IA32HealthFlags
.Uint32
= SecPlatformInformation
->IA32HealthFlags
.Uint32
;
1573 CpuInstance
= &BspCpuInstance
;
1575 DEBUG ((EFI_D_INFO
, "Does not find any HOB stored CPU BIST information!\n"));
1577 // Does not find any HOB stored BIST information
1583 while ((NumberOfData
--) > 0) {
1584 for (ProcessorNumber
= 0; ProcessorNumber
< mMpSystemData
.NumberOfProcessors
; ProcessorNumber
++) {
1585 CpuData
= &mMpSystemData
.CpuDatas
[ProcessorNumber
];
1586 InitialLocalApicId
= (UINT32
) CpuData
->Info
.ProcessorId
;
1587 if (InitialLocalApicId
== CpuInstance
[NumberOfData
].CpuLocation
) {
1589 // Update CPU health status for MP Services Protocol according to BIST data.
1591 if (CpuInstance
[NumberOfData
].InfoRecord
.IA32HealthFlags
.Uint32
!= 0) {
1592 CpuData
->Info
.StatusFlag
&= ~PROCESSOR_HEALTH_STATUS_BIT
;
1594 // Report Status Code that self test is failed
1596 REPORT_STATUS_CODE (
1597 EFI_ERROR_CODE
| EFI_ERROR_MAJOR
,
1598 (EFI_COMPUTING_UNIT_HOST_PROCESSOR
| EFI_CU_HP_EC_SELF_TEST
)
1607 Callback function for ExitBootServices.
1609 @param Event Event whose notification function is being invoked.
1610 @param Context The pointer to the notification function's context,
1611 which is implementation-dependent.
1616 ExitBootServicesCallback (
1622 // Avoid APs access invalid buff datas which allocated by BootServices,
1623 // so we send INIT IPI to APs to let them wait for SIPI state.
1625 SendInitIpiAllExcludingSelf ();
1629 Initialize Multi-processor support.
1633 InitializeMpSupport (
1639 gMaxLogicalProcessorNumber
= (UINTN
) PcdGet32 (PcdCpuMaxLogicalProcessorNumber
);
1640 if (gMaxLogicalProcessorNumber
< 1) {
1641 DEBUG ((DEBUG_ERROR
, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n"));
1645 if (gMaxLogicalProcessorNumber
== 1) {
1649 gApStackSize
= (UINTN
) PcdGet32 (PcdCpuApStackSize
);
1650 ASSERT ((gApStackSize
& (SIZE_4KB
- 1)) == 0);
1652 mApStackStart
= AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber
* gApStackSize
));
1653 ASSERT (mApStackStart
!= NULL
);
1656 // the first buffer of stack size used for common stack, when the amount of AP
1657 // more than 1, we should never free the common stack which maybe used for AP reset.
1659 mCommonStack
= mApStackStart
;
1660 mTopOfApCommonStack
= (UINT8
*) mApStackStart
+ gApStackSize
;
1661 mApStackStart
= mTopOfApCommonStack
;
1663 InitMpSystemData ();
1665 PrepareAPStartupCode ();
1667 StartApsStackless ();
1669 DEBUG ((DEBUG_INFO
, "Detect CPU count: %d\n", mMpSystemData
.NumberOfProcessors
));
1670 if (mMpSystemData
.NumberOfProcessors
== 1) {
1671 FreeApStartupCode ();
1672 FreePages (mCommonStack
, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber
* gApStackSize
));
1676 mMpSystemData
.CpuDatas
= ReallocatePool (
1677 sizeof (CPU_DATA_BLOCK
) * gMaxLogicalProcessorNumber
,
1678 sizeof (CPU_DATA_BLOCK
) * mMpSystemData
.NumberOfProcessors
,
1679 mMpSystemData
.CpuDatas
);
1681 mAPsAlreadyInitFinished
= TRUE
;
1684 // Update CPU healthy information from Guided HOB
1686 CollectBistDataFromHob ();
1688 Status
= gBS
->InstallMultipleProtocolInterfaces (
1690 &gEfiMpServiceProtocolGuid
, &mMpServicesTemplate
,
1693 ASSERT_EFI_ERROR (Status
);
1695 if (mMpSystemData
.NumberOfProcessors
< gMaxLogicalProcessorNumber
) {
1696 FreePages (mApStackStart
, EFI_SIZE_TO_PAGES (
1697 (gMaxLogicalProcessorNumber
- mMpSystemData
.NumberOfProcessors
) *
1701 Status
= gBS
->CreateEvent (
1702 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
1704 ExitBootServicesCallback
,
1706 &mExitBootServicesEvent
1708 ASSERT_EFI_ERROR (Status
);