2 MP initialize support functions for DXE phase.
4 Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Library/UefiLib.h>
12 #include <Library/UefiBootServicesTableLib.h>
13 #include <Library/DebugAgentLib.h>
14 #include <Library/DxeServicesTableLib.h>
15 #include <Register/Amd/Fam17Msr.h>
16 #include <Register/Amd/Ghcb.h>
18 #include <Protocol/Timer.h>
20 #define AP_SAFE_STACK_SIZE 128
22 CPU_MP_DATA
*mCpuMpData
= NULL
;
23 EFI_EVENT mCheckAllApsEvent
= NULL
;
24 EFI_EVENT mMpInitExitBootServicesEvent
= NULL
;
25 EFI_EVENT mLegacyBootEvent
= NULL
;
26 volatile BOOLEAN mStopCheckAllApsStatus
= TRUE
;
27 VOID
*mReservedApLoopFunc
= NULL
;
28 UINTN mReservedTopOfApStack
;
29 volatile UINT32 mNumberToFinish
= 0;
32 Enable Debug Agent to support source debugging on AP function.
41 // Initialize Debug Agent to support source level debug in DXE phase
43 InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP
, NULL
, NULL
);
47 Get the pointer to CPU MP Data structure.
49 @return The pointer to CPU MP Data structure.
56 ASSERT (mCpuMpData
!= NULL
);
61 Save the pointer to CPU MP Data structure.
63 @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
67 IN CPU_MP_DATA
*CpuMpData
70 mCpuMpData
= CpuMpData
;
74 Get available system memory below 0x88000 by specified size.
76 @param[in] WakeupBufferSize Wakeup buffer size required
78 @retval other Return wakeup buffer address below 1MB.
79 @retval -1 Cannot find free memory below 1MB.
83 IN UINTN WakeupBufferSize
87 EFI_PHYSICAL_ADDRESS StartAddress
;
90 // Try to allocate buffer below 1M for waking vector.
91 // LegacyBios driver only reports warning when page allocation in range
92 // [0x60000, 0x88000) fails.
93 // This library is consumed by CpuDxe driver to produce CPU Arch protocol.
94 // LagacyBios driver depends on CPU Arch protocol which guarantees below
95 // allocation runs earlier than LegacyBios driver.
97 StartAddress
= 0x88000;
98 Status
= gBS
->AllocatePages (
101 EFI_SIZE_TO_PAGES (WakeupBufferSize
),
104 ASSERT_EFI_ERROR (Status
);
105 if (EFI_ERROR (Status
)) {
106 StartAddress
= (EFI_PHYSICAL_ADDRESS
) -1;
109 DEBUG ((DEBUG_INFO
, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
110 (UINTN
) StartAddress
, WakeupBufferSize
));
112 return (UINTN
) StartAddress
;
116 Get available EfiBootServicesCode memory below 4GB by specified size.
118 This buffer is required to safely transfer AP from real address mode to
119 protected mode or long mode, due to the fact that the buffer returned by
120 GetWakeupBuffer() may be marked as non-executable.
122 @param[in] BufferSize Wakeup transition buffer size.
124 @retval other Return wakeup transition buffer address below 4GB.
125 @retval 0 Cannot find free memory below 4GB.
128 GetModeTransitionBuffer (
133 EFI_PHYSICAL_ADDRESS StartAddress
;
135 StartAddress
= BASE_4GB
- 1;
136 Status
= gBS
->AllocatePages (
139 EFI_SIZE_TO_PAGES (BufferSize
),
142 if (EFI_ERROR (Status
)) {
146 return (UINTN
)StartAddress
;
150 Return the address of the SEV-ES AP jump table.
152 This buffer is required in order for an SEV-ES guest to transition from
155 @return Return SEV-ES AP jump table buffer
163 EFI_PHYSICAL_ADDRESS StartAddress
;
166 // Allocate 1 page for AP jump table page
168 StartAddress
= BASE_4GB
- 1;
169 Status
= gBS
->AllocatePages (
171 EfiReservedMemoryType
,
175 ASSERT_EFI_ERROR (Status
);
177 DEBUG ((DEBUG_INFO
, "Dxe: SevEsAPMemory = %lx\n", (UINTN
) StartAddress
));
179 return (UINTN
) StartAddress
;
183 Checks APs status and updates APs status if needed.
187 CheckAndUpdateApsStatus (
191 UINTN ProcessorNumber
;
193 CPU_MP_DATA
*CpuMpData
;
195 CpuMpData
= GetCpuMpData ();
198 // First, check whether pending StartupAllAPs() exists.
200 if (CpuMpData
->WaitEvent
!= NULL
) {
202 Status
= CheckAllAPs ();
204 // If all APs finish for StartupAllAPs(), signal the WaitEvent for it.
206 if (Status
!= EFI_NOT_READY
) {
207 Status
= gBS
->SignalEvent (CpuMpData
->WaitEvent
);
208 CpuMpData
->WaitEvent
= NULL
;
213 // Second, check whether pending StartupThisAPs() callings exist.
215 for (ProcessorNumber
= 0; ProcessorNumber
< CpuMpData
->CpuCount
; ProcessorNumber
++) {
217 if (CpuMpData
->CpuData
[ProcessorNumber
].WaitEvent
== NULL
) {
221 Status
= CheckThisAP (ProcessorNumber
);
223 if (Status
!= EFI_NOT_READY
) {
224 gBS
->SignalEvent (CpuMpData
->CpuData
[ProcessorNumber
].WaitEvent
);
225 CpuMpData
->CpuData
[ProcessorNumber
].WaitEvent
= NULL
;
231 Checks APs' status periodically.
233 This function is triggered by timer periodically to check the
234 state of APs for StartupAllAPs() and StartupThisAP() executed
235 in non-blocking mode.
237 @param[in] Event Event triggered.
238 @param[in] Context Parameter passed with the event.
249 // If CheckApsStatus() is not stopped, otherwise return immediately.
251 if (!mStopCheckAllApsStatus
) {
252 CheckAndUpdateApsStatus ();
257 Get Protected mode code segment with 16-bit default addressing
258 from current GDT table.
260 @return Protected mode 16-bit code segment value.
263 GetProtectedMode16CS (
267 IA32_DESCRIPTOR GdtrDesc
;
268 IA32_SEGMENT_DESCRIPTOR
*GdtEntry
;
273 AsmReadGdtr (&GdtrDesc
);
274 GdtEntryCount
= (GdtrDesc
.Limit
+ 1) / sizeof (IA32_SEGMENT_DESCRIPTOR
);
275 GdtEntry
= (IA32_SEGMENT_DESCRIPTOR
*) GdtrDesc
.Base
;
276 for (Index
= 0; Index
< GdtEntryCount
; Index
++) {
277 if (GdtEntry
->Bits
.L
== 0) {
278 if (GdtEntry
->Bits
.Type
> 8 && GdtEntry
->Bits
.DB
== 0) {
284 ASSERT (Index
!= GdtEntryCount
);
289 Get Protected mode code segment from current GDT table.
291 @return Protected mode code segment value.
298 IA32_DESCRIPTOR GdtrDesc
;
299 IA32_SEGMENT_DESCRIPTOR
*GdtEntry
;
303 AsmReadGdtr (&GdtrDesc
);
304 GdtEntryCount
= (GdtrDesc
.Limit
+ 1) / sizeof (IA32_SEGMENT_DESCRIPTOR
);
305 GdtEntry
= (IA32_SEGMENT_DESCRIPTOR
*) GdtrDesc
.Base
;
306 for (Index
= 0; Index
< GdtEntryCount
; Index
++) {
307 if (GdtEntry
->Bits
.L
== 0) {
308 if (GdtEntry
->Bits
.Type
> 8 && GdtEntry
->Bits
.DB
== 1) {
314 ASSERT (Index
!= GdtEntryCount
);
321 @param[in, out] Buffer Pointer to private data buffer.
329 CPU_MP_DATA
*CpuMpData
;
330 BOOLEAN MwaitSupport
;
331 ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc
;
332 UINTN ProcessorNumber
;
334 MpInitLibWhoAmI (&ProcessorNumber
);
335 CpuMpData
= GetCpuMpData ();
336 MwaitSupport
= IsMwaitSupport ();
337 AsmRelocateApLoopFunc
= (ASM_RELOCATE_AP_LOOP
) (UINTN
) mReservedApLoopFunc
;
338 AsmRelocateApLoopFunc (
340 CpuMpData
->ApTargetCState
,
341 CpuMpData
->PmCodeSegment
,
342 mReservedTopOfApStack
- ProcessorNumber
* AP_SAFE_STACK_SIZE
,
343 (UINTN
) &mNumberToFinish
346 // It should never reach here
352 Callback function for ExitBootServices.
354 @param[in] Event Event whose notification function is being invoked.
355 @param[in] Context The pointer to the notification function's context,
356 which is implementation-dependent.
361 MpInitChangeApLoopCallback (
366 CPU_MP_DATA
*CpuMpData
;
368 CpuMpData
= GetCpuMpData ();
369 CpuMpData
->PmCodeSegment
= GetProtectedModeCS ();
370 CpuMpData
->Pm16CodeSegment
= GetProtectedMode16CS ();
371 CpuMpData
->ApLoopMode
= PcdGet8 (PcdCpuApLoopMode
);
372 mNumberToFinish
= CpuMpData
->CpuCount
- 1;
373 WakeUpAP (CpuMpData
, TRUE
, 0, RelocateApLoop
, NULL
, TRUE
);
374 while (mNumberToFinish
> 0) {
377 DEBUG ((DEBUG_INFO
, "%a() done!\n", __FUNCTION__
));
381 Initialize global data for MP support.
383 @param[in] CpuMpData The pointer to CPU MP Data structure.
387 IN CPU_MP_DATA
*CpuMpData
391 EFI_PHYSICAL_ADDRESS Address
;
392 UINTN ApSafeBufferSize
;
394 EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc
;
396 CPU_INFO_IN_HOB
*CpuInfoInHob
;
398 SaveCpuMpData (CpuMpData
);
400 if (CpuMpData
->CpuCount
== 1) {
402 // If only BSP exists, return
407 if (PcdGetBool (PcdCpuStackGuard
)) {
409 // One extra page at the bottom of the stack is needed for Guard page.
411 if (CpuMpData
->CpuApStackSize
<= EFI_PAGE_SIZE
) {
412 DEBUG ((DEBUG_ERROR
, "PcdCpuApStackSize is not big enough for Stack Guard!\n"));
417 // DXE will reuse stack allocated for APs at PEI phase if it's available.
418 // Let's check it here.
420 // Note: BSP's stack guard is set at DxeIpl phase. But for the sake of
421 // BSP/AP exchange, stack guard for ApTopOfStack of cpu 0 will still be
424 CpuInfoInHob
= (CPU_INFO_IN_HOB
*)(UINTN
)CpuMpData
->CpuInfoInHob
;
425 for (Index
= 0; Index
< CpuMpData
->CpuCount
; ++Index
) {
426 if (CpuInfoInHob
!= NULL
&& CpuInfoInHob
[Index
].ApTopOfStack
!= 0) {
427 StackBase
= (UINTN
)CpuInfoInHob
[Index
].ApTopOfStack
- CpuMpData
->CpuApStackSize
;
429 StackBase
= CpuMpData
->Buffer
+ Index
* CpuMpData
->CpuApStackSize
;
432 Status
= gDS
->GetMemorySpaceDescriptor (StackBase
, &MemDesc
);
433 ASSERT_EFI_ERROR (Status
);
435 Status
= gDS
->SetMemorySpaceAttributes (
437 EFI_PAGES_TO_SIZE (1),
438 MemDesc
.Attributes
| EFI_MEMORY_RP
440 ASSERT_EFI_ERROR (Status
);
442 DEBUG ((DEBUG_INFO
, "Stack Guard set at %lx [cpu%lu]!\n",
443 (UINT64
)StackBase
, (UINT64
)Index
));
448 // Avoid APs access invalid buffer data which allocated by BootServices,
449 // so we will allocate reserved data for AP loop code. We also need to
450 // allocate this buffer below 4GB due to APs may be transferred to 32bit
451 // protected mode on long mode DXE.
452 // Allocating it in advance since memory services are not available in
453 // Exit Boot Services callback function.
455 ApSafeBufferSize
= EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (
456 CpuMpData
->AddressMap
.RelocateApLoopFuncSize
458 Address
= BASE_4GB
- 1;
459 Status
= gBS
->AllocatePages (
461 EfiReservedMemoryType
,
462 EFI_SIZE_TO_PAGES (ApSafeBufferSize
),
465 ASSERT_EFI_ERROR (Status
);
467 mReservedApLoopFunc
= (VOID
*) (UINTN
) Address
;
468 ASSERT (mReservedApLoopFunc
!= NULL
);
471 // Make sure that the buffer memory is executable if NX protection is enabled
472 // for EfiReservedMemoryType.
474 // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD
477 Status
= gDS
->GetMemorySpaceDescriptor (Address
, &MemDesc
);
478 if (!EFI_ERROR (Status
)) {
479 gDS
->SetMemorySpaceAttributes (
482 MemDesc
.Attributes
& (~EFI_MEMORY_XP
)
486 ApSafeBufferSize
= EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (
487 CpuMpData
->CpuCount
* AP_SAFE_STACK_SIZE
489 Address
= BASE_4GB
- 1;
490 Status
= gBS
->AllocatePages (
492 EfiReservedMemoryType
,
493 EFI_SIZE_TO_PAGES (ApSafeBufferSize
),
496 ASSERT_EFI_ERROR (Status
);
498 mReservedTopOfApStack
= (UINTN
) Address
+ ApSafeBufferSize
;
499 ASSERT ((mReservedTopOfApStack
& (UINTN
)(CPU_STACK_ALIGNMENT
- 1)) == 0);
502 CpuMpData
->AddressMap
.RelocateApLoopFuncAddress
,
503 CpuMpData
->AddressMap
.RelocateApLoopFuncSize
506 Status
= gBS
->CreateEvent (
507 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
513 ASSERT_EFI_ERROR (Status
);
516 // Set timer to check all APs status.
518 Status
= gBS
->SetTimer (
521 EFI_TIMER_PERIOD_MICROSECONDS (
522 PcdGet32 (PcdCpuApStatusCheckIntervalInMicroSeconds
)
525 ASSERT_EFI_ERROR (Status
);
527 Status
= gBS
->CreateEvent (
528 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
530 MpInitChangeApLoopCallback
,
532 &mMpInitExitBootServicesEvent
534 ASSERT_EFI_ERROR (Status
);
536 Status
= gBS
->CreateEventEx (
539 MpInitChangeApLoopCallback
,
541 &gEfiEventLegacyBootGuid
,
544 ASSERT_EFI_ERROR (Status
);
548 This service executes a caller provided function on all enabled APs.
550 @param[in] Procedure A pointer to the function to be run on
551 enabled APs of the system. See type
553 @param[in] SingleThread If TRUE, then all the enabled APs execute
554 the function specified by Procedure one by
555 one, in ascending order of processor handle
556 number. If FALSE, then all the enabled APs
557 execute the function specified by Procedure
559 @param[in] WaitEvent The event created by the caller with CreateEvent()
560 service. If it is NULL, then execute in
561 blocking mode. BSP waits until all APs finish
562 or TimeoutInMicroSeconds expires. If it's
563 not NULL, then execute in non-blocking mode.
564 BSP requests the function specified by
565 Procedure to be started on all the enabled
566 APs, and go on executing immediately. If
567 all return from Procedure, or TimeoutInMicroSeconds
568 expires, this event is signaled. The BSP
569 can use the CheckEvent() or WaitForEvent()
570 services to check the state of event. Type
571 EFI_EVENT is defined in CreateEvent() in
572 the Unified Extensible Firmware Interface
574 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
575 APs to return from Procedure, either for
576 blocking or non-blocking mode. Zero means
577 infinity. If the timeout expires before
578 all APs return from Procedure, then Procedure
579 on the failed APs is terminated. All enabled
580 APs are available for next function assigned
581 by MpInitLibStartupAllAPs() or
582 MPInitLibStartupThisAP().
583 If the timeout expires in blocking mode,
584 BSP returns EFI_TIMEOUT. If the timeout
585 expires in non-blocking mode, WaitEvent
586 is signaled with SignalEvent().
587 @param[in] ProcedureArgument The parameter passed into Procedure for
589 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
590 if all APs finish successfully, then its
591 content is set to NULL. If not all APs
592 finish before timeout expires, then its
593 content is set to address of the buffer
594 holding handle numbers of the failed APs.
595 The buffer is allocated by MP Initialization
596 library, and it's the caller's responsibility to
597 free the buffer with FreePool() service.
598 In blocking mode, it is ready for consumption
599 when the call returns. In non-blocking mode,
600 it is ready when WaitEvent is signaled. The
601 list of failed CPU is terminated by
604 @retval EFI_SUCCESS In blocking mode, all APs have finished before
606 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
608 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
609 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
611 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
613 @retval EFI_DEVICE_ERROR Caller processor is AP.
614 @retval EFI_NOT_STARTED No enabled APs exist in the system.
615 @retval EFI_NOT_READY Any enabled APs are busy.
616 @retval EFI_NOT_READY MP Initialize Library is not initialized.
617 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
618 all enabled APs have finished.
619 @retval EFI_INVALID_PARAMETER Procedure is NULL.
624 MpInitLibStartupAllAPs (
625 IN EFI_AP_PROCEDURE Procedure
,
626 IN BOOLEAN SingleThread
,
627 IN EFI_EVENT WaitEvent OPTIONAL
,
628 IN UINTN TimeoutInMicroseconds
,
629 IN VOID
*ProcedureArgument OPTIONAL
,
630 OUT UINTN
**FailedCpuList OPTIONAL
636 // Temporarily stop checkAllApsStatus for avoid resource dead-lock.
638 mStopCheckAllApsStatus
= TRUE
;
640 Status
= StartupAllCPUsWorker (
645 TimeoutInMicroseconds
,
651 // Start checkAllApsStatus
653 mStopCheckAllApsStatus
= FALSE
;
659 This service lets the caller get one enabled AP to execute a caller-provided
662 @param[in] Procedure A pointer to the function to be run on the
663 designated AP of the system. See type
665 @param[in] ProcessorNumber The handle number of the AP. The range is
666 from 0 to the total number of logical
667 processors minus 1. The total number of
668 logical processors can be retrieved by
669 MpInitLibGetNumberOfProcessors().
670 @param[in] WaitEvent The event created by the caller with CreateEvent()
671 service. If it is NULL, then execute in
672 blocking mode. BSP waits until this AP finish
673 or TimeoutInMicroSeconds expires. If it's
674 not NULL, then execute in non-blocking mode.
675 BSP requests the function specified by
676 Procedure to be started on this AP,
677 and go on executing immediately. If this AP
678 return from Procedure or TimeoutInMicroSeconds
679 expires, this event is signaled. The BSP
680 can use the CheckEvent() or WaitForEvent()
681 services to check the state of event. Type
682 EFI_EVENT is defined in CreateEvent() in
683 the Unified Extensible Firmware Interface
685 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
686 this AP to finish this Procedure, either for
687 blocking or non-blocking mode. Zero means
688 infinity. If the timeout expires before
689 this AP returns from Procedure, then Procedure
690 on the AP is terminated. The
691 AP is available for next function assigned
692 by MpInitLibStartupAllAPs() or
693 MpInitLibStartupThisAP().
694 If the timeout expires in blocking mode,
695 BSP returns EFI_TIMEOUT. If the timeout
696 expires in non-blocking mode, WaitEvent
697 is signaled with SignalEvent().
698 @param[in] ProcedureArgument The parameter passed into Procedure on the
700 @param[out] Finished If NULL, this parameter is ignored. In
701 blocking mode, this parameter is ignored.
702 In non-blocking mode, if AP returns from
703 Procedure before the timeout expires, its
704 content is set to TRUE. Otherwise, the
705 value is set to FALSE. The caller can
706 determine if the AP returned from Procedure
707 by evaluating this value.
709 @retval EFI_SUCCESS In blocking mode, specified AP finished before
711 @retval EFI_SUCCESS In non-blocking mode, the function has been
712 dispatched to specified AP.
713 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
714 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
716 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
718 @retval EFI_DEVICE_ERROR The calling processor is an AP.
719 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
720 the specified AP has finished.
721 @retval EFI_NOT_READY The specified AP is busy.
722 @retval EFI_NOT_READY MP Initialize Library is not initialized.
723 @retval EFI_NOT_FOUND The processor with the handle specified by
724 ProcessorNumber does not exist.
725 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
726 @retval EFI_INVALID_PARAMETER Procedure is NULL.
731 MpInitLibStartupThisAP (
732 IN EFI_AP_PROCEDURE Procedure
,
733 IN UINTN ProcessorNumber
,
734 IN EFI_EVENT WaitEvent OPTIONAL
,
735 IN UINTN TimeoutInMicroseconds
,
736 IN VOID
*ProcedureArgument OPTIONAL
,
737 OUT BOOLEAN
*Finished OPTIONAL
743 // temporarily stop checkAllApsStatus for avoid resource dead-lock.
745 mStopCheckAllApsStatus
= TRUE
;
747 Status
= StartupThisAPWorker (
751 TimeoutInMicroseconds
,
756 mStopCheckAllApsStatus
= FALSE
;
762 This service switches the requested AP to be the BSP from that point onward.
763 This service changes the BSP for all purposes. This call can only be performed
766 @param[in] ProcessorNumber The handle number of AP that is to become the new
767 BSP. The range is from 0 to the total number of
768 logical processors minus 1. The total number of
769 logical processors can be retrieved by
770 MpInitLibGetNumberOfProcessors().
771 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
772 enabled AP. Otherwise, it will be disabled.
774 @retval EFI_SUCCESS BSP successfully switched.
775 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
776 this service returning.
777 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
778 @retval EFI_DEVICE_ERROR The calling processor is an AP.
779 @retval EFI_NOT_FOUND The processor with the handle specified by
780 ProcessorNumber does not exist.
781 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
783 @retval EFI_NOT_READY The specified AP is busy.
784 @retval EFI_NOT_READY MP Initialize Library is not initialized.
790 IN UINTN ProcessorNumber
,
791 IN BOOLEAN EnableOldBSP
795 EFI_TIMER_ARCH_PROTOCOL
*Timer
;
800 // Locate Timer Arch Protocol
802 Status
= gBS
->LocateProtocol (&gEfiTimerArchProtocolGuid
, NULL
, (VOID
**) &Timer
);
803 if (EFI_ERROR (Status
)) {
809 // Save current rate of DXE Timer
811 Timer
->GetTimerPeriod (Timer
, &TimerPeriod
);
813 // Disable DXE Timer and drain pending interrupts
815 Timer
->SetTimerPeriod (Timer
, 0);
818 Status
= SwitchBSPWorker (ProcessorNumber
, EnableOldBSP
);
822 // Enable and restore rate of DXE Timer
824 Timer
->SetTimerPeriod (Timer
, TimerPeriod
);
831 This service lets the caller enable or disable an AP from this point onward.
832 This service may only be called from the BSP.
834 @param[in] ProcessorNumber The handle number of AP.
835 The range is from 0 to the total number of
836 logical processors minus 1. The total number of
837 logical processors can be retrieved by
838 MpInitLibGetNumberOfProcessors().
839 @param[in] EnableAP Specifies the new state for the processor for
840 enabled, FALSE for disabled.
841 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
842 the new health status of the AP. This flag
843 corresponds to StatusFlag defined in
844 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
845 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
846 bits are ignored. If it is NULL, this parameter
849 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
850 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
851 prior to this service returning.
852 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
853 @retval EFI_DEVICE_ERROR The calling processor is an AP.
854 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
856 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
857 @retval EFI_NOT_READY MP Initialize Library is not initialized.
862 MpInitLibEnableDisableAP (
863 IN UINTN ProcessorNumber
,
865 IN UINT32
*HealthFlag OPTIONAL
869 BOOLEAN TempStopCheckState
;
871 TempStopCheckState
= FALSE
;
873 // temporarily stop checkAllAPsStatus for initialize parameters.
875 if (!mStopCheckAllApsStatus
) {
876 mStopCheckAllApsStatus
= TRUE
;
877 TempStopCheckState
= TRUE
;
880 Status
= EnableDisableApWorker (ProcessorNumber
, EnableAP
, HealthFlag
);
882 if (TempStopCheckState
) {
883 mStopCheckAllApsStatus
= FALSE
;
890 This funtion will try to invoke platform specific microcode shadow logic to
891 relocate microcode update patches into memory.
893 @param[in, out] CpuMpData The pointer to CPU MP Data structure.
895 @retval EFI_SUCCESS Shadow microcode success.
896 @retval EFI_OUT_OF_RESOURCES No enough resource to complete the operation.
897 @retval EFI_UNSUPPORTED Can't find platform specific microcode shadow
901 PlatformShadowMicrocode (
902 IN OUT CPU_MP_DATA
*CpuMpData
906 // There is no DXE version of platform shadow microcode protocol so far.
907 // A platform which only uses DxeMpInitLib instance could only supports
908 // the PCD based microcode shadowing.
910 return EFI_UNSUPPORTED
;