2 MP initialize support functions for DXE phase.
4 Copyright (c) 2016 - 2018, 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.
17 #include <Library/UefiLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/DebugAgentLib.h>
20 #include <Library/DxeServicesTableLib.h>
22 #include <Protocol/Timer.h>
24 #define AP_CHECK_INTERVAL (EFI_TIMER_PERIOD_MILLISECONDS (100))
25 #define AP_SAFE_STACK_SIZE 128
27 CPU_MP_DATA
*mCpuMpData
= NULL
;
28 EFI_EVENT mCheckAllApsEvent
= NULL
;
29 EFI_EVENT mMpInitExitBootServicesEvent
= NULL
;
30 EFI_EVENT mLegacyBootEvent
= NULL
;
31 volatile BOOLEAN mStopCheckAllApsStatus
= TRUE
;
32 VOID
*mReservedApLoopFunc
= NULL
;
33 UINTN mReservedTopOfApStack
;
34 volatile UINT32 mNumberToFinish
= 0;
37 Enable Debug Agent to support source debugging on AP function.
46 // Initialize Debug Agent to support source level debug in DXE phase
48 InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP
, NULL
, NULL
);
52 Get the pointer to CPU MP Data structure.
54 @return The pointer to CPU MP Data structure.
61 ASSERT (mCpuMpData
!= NULL
);
66 Save the pointer to CPU MP Data structure.
68 @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
72 IN CPU_MP_DATA
*CpuMpData
75 mCpuMpData
= CpuMpData
;
79 Get available system memory below 0x88000 by specified size.
81 @param[in] WakeupBufferSize Wakeup buffer size required
83 @retval other Return wakeup buffer address below 1MB.
84 @retval -1 Cannot find free memory below 1MB.
88 IN UINTN WakeupBufferSize
92 EFI_PHYSICAL_ADDRESS StartAddress
;
95 // Try to allocate buffer below 1M for waking vector.
96 // LegacyBios driver only reports warning when page allocation in range
97 // [0x60000, 0x88000) fails.
98 // This library is consumed by CpuDxe driver to produce CPU Arch protocol.
99 // LagacyBios driver depends on CPU Arch protocol which guarantees below
100 // allocation runs earlier than LegacyBios driver.
102 StartAddress
= 0x88000;
103 Status
= gBS
->AllocatePages (
106 EFI_SIZE_TO_PAGES (WakeupBufferSize
),
109 ASSERT_EFI_ERROR (Status
);
110 if (EFI_ERROR (Status
)) {
111 StartAddress
= (EFI_PHYSICAL_ADDRESS
) -1;
114 DEBUG ((DEBUG_INFO
, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
115 (UINTN
) StartAddress
, WakeupBufferSize
));
117 return (UINTN
) StartAddress
;
121 Get available EfiBootServicesCode memory below 4GB by specified size.
123 This buffer is required to safely transfer AP from real address mode to
124 protected mode or long mode, due to the fact that the buffer returned by
125 GetWakeupBuffer() may be marked as non-executable.
127 @param[in] BufferSize Wakeup transition buffer size.
129 @retval other Return wakeup transition buffer address below 4GB.
130 @retval 0 Cannot find free memory below 4GB.
133 GetModeTransitionBuffer (
138 EFI_PHYSICAL_ADDRESS StartAddress
;
140 StartAddress
= BASE_4GB
- 1;
141 Status
= gBS
->AllocatePages (
144 EFI_SIZE_TO_PAGES (BufferSize
),
147 if (EFI_ERROR (Status
)) {
151 return (UINTN
)StartAddress
;
155 Checks APs status and updates APs status if needed.
159 CheckAndUpdateApsStatus (
163 UINTN ProcessorNumber
;
165 CPU_MP_DATA
*CpuMpData
;
167 CpuMpData
= GetCpuMpData ();
170 // First, check whether pending StartupAllAPs() exists.
172 if (CpuMpData
->WaitEvent
!= NULL
) {
174 Status
= CheckAllAPs ();
176 // If all APs finish for StartupAllAPs(), signal the WaitEvent for it.
178 if (Status
!= EFI_NOT_READY
) {
179 Status
= gBS
->SignalEvent (CpuMpData
->WaitEvent
);
180 CpuMpData
->WaitEvent
= NULL
;
185 // Second, check whether pending StartupThisAPs() callings exist.
187 for (ProcessorNumber
= 0; ProcessorNumber
< CpuMpData
->CpuCount
; ProcessorNumber
++) {
189 if (CpuMpData
->CpuData
[ProcessorNumber
].WaitEvent
== NULL
) {
193 Status
= CheckThisAP (ProcessorNumber
);
195 if (Status
!= EFI_NOT_READY
) {
196 gBS
->SignalEvent (CpuMpData
->CpuData
[ProcessorNumber
].WaitEvent
);
197 CpuMpData
->CpuData
[ProcessorNumber
].WaitEvent
= NULL
;
203 Checks APs' status periodically.
205 This function is triggered by timer periodically to check the
206 state of APs for StartupAllAPs() and StartupThisAP() executed
207 in non-blocking mode.
209 @param[in] Event Event triggered.
210 @param[in] Context Parameter passed with the event.
221 // If CheckApsStatus() is not stopped, otherwise return immediately.
223 if (!mStopCheckAllApsStatus
) {
224 CheckAndUpdateApsStatus ();
229 Get Protected mode code segment from current GDT table.
231 @return Protected mode code segment value.
238 IA32_DESCRIPTOR GdtrDesc
;
239 IA32_SEGMENT_DESCRIPTOR
*GdtEntry
;
243 AsmReadGdtr (&GdtrDesc
);
244 GdtEntryCount
= (GdtrDesc
.Limit
+ 1) / sizeof (IA32_SEGMENT_DESCRIPTOR
);
245 GdtEntry
= (IA32_SEGMENT_DESCRIPTOR
*) GdtrDesc
.Base
;
246 for (Index
= 0; Index
< GdtEntryCount
; Index
++) {
247 if (GdtEntry
->Bits
.L
== 0) {
248 if (GdtEntry
->Bits
.Type
> 8 && GdtEntry
->Bits
.L
== 0) {
254 ASSERT (Index
!= GdtEntryCount
);
261 @param[in, out] Buffer Pointer to private data buffer.
269 CPU_MP_DATA
*CpuMpData
;
270 BOOLEAN MwaitSupport
;
271 ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc
;
272 UINTN ProcessorNumber
;
274 MpInitLibWhoAmI (&ProcessorNumber
);
275 CpuMpData
= GetCpuMpData ();
276 MwaitSupport
= IsMwaitSupport ();
277 AsmRelocateApLoopFunc
= (ASM_RELOCATE_AP_LOOP
) (UINTN
) mReservedApLoopFunc
;
278 AsmRelocateApLoopFunc (
280 CpuMpData
->ApTargetCState
,
281 CpuMpData
->PmCodeSegment
,
282 mReservedTopOfApStack
- ProcessorNumber
* AP_SAFE_STACK_SIZE
,
283 (UINTN
) &mNumberToFinish
286 // It should never reach here
292 Callback function for ExitBootServices.
294 @param[in] Event Event whose notification function is being invoked.
295 @param[in] Context The pointer to the notification function's context,
296 which is implementation-dependent.
301 MpInitChangeApLoopCallback (
306 CPU_MP_DATA
*CpuMpData
;
308 CpuMpData
= GetCpuMpData ();
309 CpuMpData
->PmCodeSegment
= GetProtectedModeCS ();
310 CpuMpData
->ApLoopMode
= PcdGet8 (PcdCpuApLoopMode
);
311 mNumberToFinish
= CpuMpData
->CpuCount
- 1;
312 WakeUpAP (CpuMpData
, TRUE
, 0, RelocateApLoop
, NULL
, TRUE
);
313 while (mNumberToFinish
> 0) {
316 DEBUG ((DEBUG_INFO
, "%a() done!\n", __FUNCTION__
));
320 Initialize global data for MP support.
322 @param[in] CpuMpData The pointer to CPU MP Data structure.
326 IN CPU_MP_DATA
*CpuMpData
330 EFI_PHYSICAL_ADDRESS Address
;
331 UINTN ApSafeBufferSize
;
333 EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc
;
335 CPU_INFO_IN_HOB
*CpuInfoInHob
;
337 SaveCpuMpData (CpuMpData
);
339 if (CpuMpData
->CpuCount
== 1) {
341 // If only BSP exists, return
346 if (PcdGetBool (PcdCpuStackGuard
)) {
348 // One extra page at the bottom of the stack is needed for Guard page.
350 if (CpuMpData
->CpuApStackSize
<= EFI_PAGE_SIZE
) {
351 DEBUG ((DEBUG_ERROR
, "PcdCpuApStackSize is not big enough for Stack Guard!\n"));
356 // DXE will reuse stack allocated for APs at PEI phase if it's available.
357 // Let's check it here.
359 // Note: BSP's stack guard is set at DxeIpl phase. But for the sake of
360 // BSP/AP exchange, stack guard for ApTopOfStack of cpu 0 will still be
363 CpuInfoInHob
= (CPU_INFO_IN_HOB
*)(UINTN
)CpuMpData
->CpuInfoInHob
;
364 for (Index
= 0; Index
< CpuMpData
->CpuCount
; ++Index
) {
365 if (CpuInfoInHob
!= NULL
&& CpuInfoInHob
[Index
].ApTopOfStack
!= 0) {
366 StackBase
= (UINTN
)CpuInfoInHob
[Index
].ApTopOfStack
- CpuMpData
->CpuApStackSize
;
368 StackBase
= CpuMpData
->Buffer
+ Index
* CpuMpData
->CpuApStackSize
;
371 Status
= gDS
->GetMemorySpaceDescriptor (StackBase
, &MemDesc
);
372 ASSERT_EFI_ERROR (Status
);
374 Status
= gDS
->SetMemorySpaceAttributes (
376 EFI_PAGES_TO_SIZE (1),
377 MemDesc
.Attributes
| EFI_MEMORY_RP
379 ASSERT_EFI_ERROR (Status
);
381 DEBUG ((DEBUG_INFO
, "Stack Guard set at %lx [cpu%lu]!\n",
382 (UINT64
)StackBase
, (UINT64
)Index
));
387 // Avoid APs access invalid buffer data which allocated by BootServices,
388 // so we will allocate reserved data for AP loop code. We also need to
389 // allocate this buffer below 4GB due to APs may be transferred to 32bit
390 // protected mode on long mode DXE.
391 // Allocating it in advance since memory services are not available in
392 // Exit Boot Services callback function.
394 ApSafeBufferSize
= EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (
395 CpuMpData
->AddressMap
.RelocateApLoopFuncSize
397 Address
= BASE_4GB
- 1;
398 Status
= gBS
->AllocatePages (
400 EfiReservedMemoryType
,
401 EFI_SIZE_TO_PAGES (ApSafeBufferSize
),
404 ASSERT_EFI_ERROR (Status
);
406 mReservedApLoopFunc
= (VOID
*) (UINTN
) Address
;
407 ASSERT (mReservedApLoopFunc
!= NULL
);
410 // Make sure that the buffer memory is executable if NX protection is enabled
411 // for EfiReservedMemoryType.
413 // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD
416 Status
= gDS
->GetMemorySpaceDescriptor (Address
, &MemDesc
);
417 if (!EFI_ERROR (Status
)) {
418 gDS
->SetMemorySpaceAttributes (
421 MemDesc
.Attributes
& (~EFI_MEMORY_XP
)
425 ApSafeBufferSize
= EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (
426 CpuMpData
->CpuCount
* AP_SAFE_STACK_SIZE
428 Address
= BASE_4GB
- 1;
429 Status
= gBS
->AllocatePages (
431 EfiReservedMemoryType
,
432 EFI_SIZE_TO_PAGES (ApSafeBufferSize
),
435 ASSERT_EFI_ERROR (Status
);
437 mReservedTopOfApStack
= (UINTN
) Address
+ ApSafeBufferSize
;
438 ASSERT ((mReservedTopOfApStack
& (UINTN
)(CPU_STACK_ALIGNMENT
- 1)) == 0);
441 CpuMpData
->AddressMap
.RelocateApLoopFuncAddress
,
442 CpuMpData
->AddressMap
.RelocateApLoopFuncSize
445 Status
= gBS
->CreateEvent (
446 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
452 ASSERT_EFI_ERROR (Status
);
455 // Set timer to check all APs status.
457 Status
= gBS
->SetTimer (
462 ASSERT_EFI_ERROR (Status
);
464 Status
= gBS
->CreateEvent (
465 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
467 MpInitChangeApLoopCallback
,
469 &mMpInitExitBootServicesEvent
471 ASSERT_EFI_ERROR (Status
);
473 Status
= gBS
->CreateEventEx (
476 MpInitChangeApLoopCallback
,
478 &gEfiEventLegacyBootGuid
,
481 ASSERT_EFI_ERROR (Status
);
485 This service executes a caller provided function on all enabled APs.
487 @param[in] Procedure A pointer to the function to be run on
488 enabled APs of the system. See type
490 @param[in] SingleThread If TRUE, then all the enabled APs execute
491 the function specified by Procedure one by
492 one, in ascending order of processor handle
493 number. If FALSE, then all the enabled APs
494 execute the function specified by Procedure
496 @param[in] WaitEvent The event created by the caller with CreateEvent()
497 service. If it is NULL, then execute in
498 blocking mode. BSP waits until all APs finish
499 or TimeoutInMicroSeconds expires. If it's
500 not NULL, then execute in non-blocking mode.
501 BSP requests the function specified by
502 Procedure to be started on all the enabled
503 APs, and go on executing immediately. If
504 all return from Procedure, or TimeoutInMicroSeconds
505 expires, this event is signaled. The BSP
506 can use the CheckEvent() or WaitForEvent()
507 services to check the state of event. Type
508 EFI_EVENT is defined in CreateEvent() in
509 the Unified Extensible Firmware Interface
511 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
512 APs to return from Procedure, either for
513 blocking or non-blocking mode. Zero means
514 infinity. If the timeout expires before
515 all APs return from Procedure, then Procedure
516 on the failed APs is terminated. All enabled
517 APs are available for next function assigned
518 by MpInitLibStartupAllAPs() or
519 MPInitLibStartupThisAP().
520 If the timeout expires in blocking mode,
521 BSP returns EFI_TIMEOUT. If the timeout
522 expires in non-blocking mode, WaitEvent
523 is signaled with SignalEvent().
524 @param[in] ProcedureArgument The parameter passed into Procedure for
526 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
527 if all APs finish successfully, then its
528 content is set to NULL. If not all APs
529 finish before timeout expires, then its
530 content is set to address of the buffer
531 holding handle numbers of the failed APs.
532 The buffer is allocated by MP Initialization
533 library, and it's the caller's responsibility to
534 free the buffer with FreePool() service.
535 In blocking mode, it is ready for consumption
536 when the call returns. In non-blocking mode,
537 it is ready when WaitEvent is signaled. The
538 list of failed CPU is terminated by
541 @retval EFI_SUCCESS In blocking mode, all APs have finished before
543 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
545 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
546 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
548 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
550 @retval EFI_DEVICE_ERROR Caller processor is AP.
551 @retval EFI_NOT_STARTED No enabled APs exist in the system.
552 @retval EFI_NOT_READY Any enabled APs are busy.
553 @retval EFI_NOT_READY MP Initialize Library is not initialized.
554 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
555 all enabled APs have finished.
556 @retval EFI_INVALID_PARAMETER Procedure is NULL.
561 MpInitLibStartupAllAPs (
562 IN EFI_AP_PROCEDURE Procedure
,
563 IN BOOLEAN SingleThread
,
564 IN EFI_EVENT WaitEvent OPTIONAL
,
565 IN UINTN TimeoutInMicroseconds
,
566 IN VOID
*ProcedureArgument OPTIONAL
,
567 OUT UINTN
**FailedCpuList OPTIONAL
573 // Temporarily stop checkAllApsStatus for avoid resource dead-lock.
575 mStopCheckAllApsStatus
= TRUE
;
577 Status
= StartupAllAPsWorker (
581 TimeoutInMicroseconds
,
587 // Start checkAllApsStatus
589 mStopCheckAllApsStatus
= FALSE
;
595 This service lets the caller get one enabled AP to execute a caller-provided
598 @param[in] Procedure A pointer to the function to be run on the
599 designated AP of the system. See type
601 @param[in] ProcessorNumber The handle number of the AP. The range is
602 from 0 to the total number of logical
603 processors minus 1. The total number of
604 logical processors can be retrieved by
605 MpInitLibGetNumberOfProcessors().
606 @param[in] WaitEvent The event created by the caller with CreateEvent()
607 service. If it is NULL, then execute in
608 blocking mode. BSP waits until this AP finish
609 or TimeoutInMicroSeconds expires. If it's
610 not NULL, then execute in non-blocking mode.
611 BSP requests the function specified by
612 Procedure to be started on this AP,
613 and go on executing immediately. If this AP
614 return from Procedure or TimeoutInMicroSeconds
615 expires, this event is signaled. The BSP
616 can use the CheckEvent() or WaitForEvent()
617 services to check the state of event. Type
618 EFI_EVENT is defined in CreateEvent() in
619 the Unified Extensible Firmware Interface
621 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
622 this AP to finish this Procedure, either for
623 blocking or non-blocking mode. Zero means
624 infinity. If the timeout expires before
625 this AP returns from Procedure, then Procedure
626 on the AP is terminated. The
627 AP is available for next function assigned
628 by MpInitLibStartupAllAPs() or
629 MpInitLibStartupThisAP().
630 If the timeout expires in blocking mode,
631 BSP returns EFI_TIMEOUT. If the timeout
632 expires in non-blocking mode, WaitEvent
633 is signaled with SignalEvent().
634 @param[in] ProcedureArgument The parameter passed into Procedure on the
636 @param[out] Finished If NULL, this parameter is ignored. In
637 blocking mode, this parameter is ignored.
638 In non-blocking mode, if AP returns from
639 Procedure before the timeout expires, its
640 content is set to TRUE. Otherwise, the
641 value is set to FALSE. The caller can
642 determine if the AP returned from Procedure
643 by evaluating this value.
645 @retval EFI_SUCCESS In blocking mode, specified AP finished before
647 @retval EFI_SUCCESS In non-blocking mode, the function has been
648 dispatched to specified AP.
649 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
650 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
652 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
654 @retval EFI_DEVICE_ERROR The calling processor is an AP.
655 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
656 the specified AP has finished.
657 @retval EFI_NOT_READY The specified AP is busy.
658 @retval EFI_NOT_READY MP Initialize Library is not initialized.
659 @retval EFI_NOT_FOUND The processor with the handle specified by
660 ProcessorNumber does not exist.
661 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
662 @retval EFI_INVALID_PARAMETER Procedure is NULL.
667 MpInitLibStartupThisAP (
668 IN EFI_AP_PROCEDURE Procedure
,
669 IN UINTN ProcessorNumber
,
670 IN EFI_EVENT WaitEvent OPTIONAL
,
671 IN UINTN TimeoutInMicroseconds
,
672 IN VOID
*ProcedureArgument OPTIONAL
,
673 OUT BOOLEAN
*Finished OPTIONAL
679 // temporarily stop checkAllApsStatus for avoid resource dead-lock.
681 mStopCheckAllApsStatus
= TRUE
;
683 Status
= StartupThisAPWorker (
687 TimeoutInMicroseconds
,
692 mStopCheckAllApsStatus
= FALSE
;
698 This service switches the requested AP to be the BSP from that point onward.
699 This service changes the BSP for all purposes. This call can only be performed
702 @param[in] ProcessorNumber The handle number of AP that is to become the new
703 BSP. The range is from 0 to the total number of
704 logical processors minus 1. The total number of
705 logical processors can be retrieved by
706 MpInitLibGetNumberOfProcessors().
707 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
708 enabled AP. Otherwise, it will be disabled.
710 @retval EFI_SUCCESS BSP successfully switched.
711 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
712 this service returning.
713 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
714 @retval EFI_DEVICE_ERROR The calling processor is an AP.
715 @retval EFI_NOT_FOUND The processor with the handle specified by
716 ProcessorNumber does not exist.
717 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
719 @retval EFI_NOT_READY The specified AP is busy.
720 @retval EFI_NOT_READY MP Initialize Library is not initialized.
726 IN UINTN ProcessorNumber
,
727 IN BOOLEAN EnableOldBSP
731 EFI_TIMER_ARCH_PROTOCOL
*Timer
;
736 // Locate Timer Arch Protocol
738 Status
= gBS
->LocateProtocol (&gEfiTimerArchProtocolGuid
, NULL
, (VOID
**) &Timer
);
739 if (EFI_ERROR (Status
)) {
745 // Save current rate of DXE Timer
747 Timer
->GetTimerPeriod (Timer
, &TimerPeriod
);
749 // Disable DXE Timer and drain pending interrupts
751 Timer
->SetTimerPeriod (Timer
, 0);
754 Status
= SwitchBSPWorker (ProcessorNumber
, EnableOldBSP
);
758 // Enable and restore rate of DXE Timer
760 Timer
->SetTimerPeriod (Timer
, TimerPeriod
);
767 This service lets the caller enable or disable an AP from this point onward.
768 This service may only be called from the BSP.
770 @param[in] ProcessorNumber The handle number of AP.
771 The range is from 0 to the total number of
772 logical processors minus 1. The total number of
773 logical processors can be retrieved by
774 MpInitLibGetNumberOfProcessors().
775 @param[in] EnableAP Specifies the new state for the processor for
776 enabled, FALSE for disabled.
777 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
778 the new health status of the AP. This flag
779 corresponds to StatusFlag defined in
780 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
781 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
782 bits are ignored. If it is NULL, this parameter
785 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
786 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
787 prior to this service returning.
788 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
789 @retval EFI_DEVICE_ERROR The calling processor is an AP.
790 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
792 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
793 @retval EFI_NOT_READY MP Initialize Library is not initialized.
798 MpInitLibEnableDisableAP (
799 IN UINTN ProcessorNumber
,
801 IN UINT32
*HealthFlag OPTIONAL
805 BOOLEAN TempStopCheckState
;
807 TempStopCheckState
= FALSE
;
809 // temporarily stop checkAllAPsStatus for initialize parameters.
811 if (!mStopCheckAllApsStatus
) {
812 mStopCheckAllApsStatus
= TRUE
;
813 TempStopCheckState
= TRUE
;
816 Status
= EnableDisableApWorker (ProcessorNumber
, EnableAP
, HealthFlag
);
818 if (TempStopCheckState
) {
819 mStopCheckAllApsStatus
= FALSE
;