UefiCpuPkg MpInitLib: Save/restore original WakeupBuffer for DxeMpLib
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / DxeMpLib.c
1 /** @file
2 MP initialize support functions for DXE phase.
3
4 Copyright (c) 2016, 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
9
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.
12
13 **/
14
15 #include "MpLib.h"
16
17 #include <Library/UefiLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/DebugAgentLib.h>
20
21 #include <Protocol/Timer.h>
22
23 #define AP_CHECK_INTERVAL (EFI_TIMER_PERIOD_MILLISECONDS (100))
24 #define AP_SAFE_STACK_SIZE 128
25
26 CPU_MP_DATA *mCpuMpData = NULL;
27 EFI_EVENT mCheckAllApsEvent = NULL;
28 EFI_EVENT mMpInitExitBootServicesEvent = NULL;
29 EFI_EVENT mLegacyBootEvent = NULL;
30 volatile BOOLEAN mStopCheckAllApsStatus = TRUE;
31 VOID *mReservedApLoopFunc = NULL;
32 UINTN mReservedTopOfApStack;
33 volatile UINT32 mNumberToFinish = 0;
34
35 /**
36 Enable Debug Agent to support source debugging on AP function.
37
38 **/
39 VOID
40 EnableDebugAgent (
41 VOID
42 )
43 {
44 //
45 // Initialize Debug Agent to support source level debug in DXE phase
46 //
47 InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP, NULL, NULL);
48 }
49
50 /**
51 Get the pointer to CPU MP Data structure.
52
53 @return The pointer to CPU MP Data structure.
54 **/
55 CPU_MP_DATA *
56 GetCpuMpData (
57 VOID
58 )
59 {
60 ASSERT (mCpuMpData != NULL);
61 return mCpuMpData;
62 }
63
64 /**
65 Save the pointer to CPU MP Data structure.
66
67 @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
68 **/
69 VOID
70 SaveCpuMpData (
71 IN CPU_MP_DATA *CpuMpData
72 )
73 {
74 mCpuMpData = CpuMpData;
75 }
76
77 /**
78 Get available system memory below 1MB by specified size.
79
80 @param[in] WakeupBufferSize Wakeup buffer size required
81
82 @retval other Return wakeup buffer address below 1MB.
83 @retval -1 Cannot find free memory below 1MB.
84 **/
85 UINTN
86 GetWakeupBuffer (
87 IN UINTN WakeupBufferSize
88 )
89 {
90 EFI_STATUS Status;
91 EFI_PHYSICAL_ADDRESS StartAddress;
92
93 StartAddress = BASE_1MB;
94 Status = gBS->AllocatePages (
95 AllocateMaxAddress,
96 EfiBootServicesData,
97 EFI_SIZE_TO_PAGES (WakeupBufferSize),
98 &StartAddress
99 );
100 ASSERT_EFI_ERROR (Status);
101 if (!EFI_ERROR (Status)) {
102 Status = gBS->FreePages(
103 StartAddress,
104 EFI_SIZE_TO_PAGES (WakeupBufferSize)
105 );
106 ASSERT_EFI_ERROR (Status);
107 DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
108 (UINTN) StartAddress, WakeupBufferSize));
109 } else {
110 StartAddress = (EFI_PHYSICAL_ADDRESS) -1;
111 }
112 return (UINTN) StartAddress;
113 }
114
115 /**
116 Checks APs status and updates APs status if needed.
117
118 **/
119 VOID
120 CheckAndUpdateApsStatus (
121 VOID
122 )
123 {
124 UINTN ProcessorNumber;
125 EFI_STATUS Status;
126 CPU_MP_DATA *CpuMpData;
127
128 CpuMpData = GetCpuMpData ();
129
130 //
131 // First, check whether pending StartupAllAPs() exists.
132 //
133 if (CpuMpData->WaitEvent != NULL) {
134
135 Status = CheckAllAPs ();
136 //
137 // If all APs finish for StartupAllAPs(), signal the WaitEvent for it.
138 //
139 if (Status != EFI_NOT_READY) {
140 Status = gBS->SignalEvent (CpuMpData->WaitEvent);
141 CpuMpData->WaitEvent = NULL;
142 }
143 }
144
145 //
146 // Second, check whether pending StartupThisAPs() callings exist.
147 //
148 for (ProcessorNumber = 0; ProcessorNumber < CpuMpData->CpuCount; ProcessorNumber++) {
149
150 if (CpuMpData->CpuData[ProcessorNumber].WaitEvent == NULL) {
151 continue;
152 }
153
154 Status = CheckThisAP (ProcessorNumber);
155
156 if (Status != EFI_NOT_READY) {
157 gBS->SignalEvent (CpuMpData->CpuData[ProcessorNumber].WaitEvent);
158 CpuMpData->CpuData[ProcessorNumber].WaitEvent = NULL;
159 }
160 }
161 }
162
163 /**
164 Checks APs' status periodically.
165
166 This function is triggered by timer periodically to check the
167 state of APs for StartupAllAPs() and StartupThisAP() executed
168 in non-blocking mode.
169
170 @param[in] Event Event triggered.
171 @param[in] Context Parameter passed with the event.
172
173 **/
174 VOID
175 EFIAPI
176 CheckApsStatus (
177 IN EFI_EVENT Event,
178 IN VOID *Context
179 )
180 {
181 //
182 // If CheckApsStatus() is not stopped, otherwise return immediately.
183 //
184 if (!mStopCheckAllApsStatus) {
185 CheckAndUpdateApsStatus ();
186 }
187 }
188
189 /**
190 Get Protected mode code segment from current GDT table.
191
192 @return Protected mode code segment value.
193 **/
194 UINT16
195 GetProtectedModeCS (
196 VOID
197 )
198 {
199 IA32_DESCRIPTOR GdtrDesc;
200 IA32_SEGMENT_DESCRIPTOR *GdtEntry;
201 UINTN GdtEntryCount;
202 UINT16 Index;
203
204 Index = (UINT16) -1;
205 AsmReadGdtr (&GdtrDesc);
206 GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);
207 GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
208 for (Index = 0; Index < GdtEntryCount; Index++) {
209 if (GdtEntry->Bits.L == 0) {
210 if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) {
211 break;
212 }
213 }
214 GdtEntry++;
215 }
216 ASSERT (Index != -1);
217 return Index * 8;
218 }
219
220 /**
221 Do sync on APs.
222
223 @param[in, out] Buffer Pointer to private data buffer.
224 **/
225 VOID
226 EFIAPI
227 RelocateApLoop (
228 IN OUT VOID *Buffer
229 )
230 {
231 CPU_MP_DATA *CpuMpData;
232 BOOLEAN MwaitSupport;
233 ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc;
234 UINTN ProcessorNumber;
235
236 MpInitLibWhoAmI (&ProcessorNumber);
237 CpuMpData = GetCpuMpData ();
238 MwaitSupport = IsMwaitSupport ();
239 AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP) (UINTN) mReservedApLoopFunc;
240 AsmRelocateApLoopFunc (
241 MwaitSupport,
242 CpuMpData->ApTargetCState,
243 CpuMpData->PmCodeSegment,
244 mReservedTopOfApStack - ProcessorNumber * AP_SAFE_STACK_SIZE,
245 (UINTN) &mNumberToFinish
246 );
247 //
248 // It should never reach here
249 //
250 ASSERT (FALSE);
251 }
252
253 /**
254 Callback function for ExitBootServices.
255
256 @param[in] Event Event whose notification function is being invoked.
257 @param[in] Context The pointer to the notification function's context,
258 which is implementation-dependent.
259
260 **/
261 VOID
262 EFIAPI
263 MpInitChangeApLoopCallback (
264 IN EFI_EVENT Event,
265 IN VOID *Context
266 )
267 {
268 CPU_MP_DATA *CpuMpData;
269
270 CpuMpData = GetCpuMpData ();
271 CpuMpData->PmCodeSegment = GetProtectedModeCS ();
272 CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode);
273 mNumberToFinish = CpuMpData->CpuCount - 1;
274 WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL);
275 while (mNumberToFinish > 0) {
276 CpuPause ();
277 }
278 DEBUG ((DEBUG_INFO, "%a() done!\n", __FUNCTION__));
279 }
280
281 /**
282 Initialize global data for MP support.
283
284 @param[in] CpuMpData The pointer to CPU MP Data structure.
285 **/
286 VOID
287 InitMpGlobalData (
288 IN CPU_MP_DATA *CpuMpData
289 )
290 {
291 EFI_STATUS Status;
292 EFI_PHYSICAL_ADDRESS Address;
293 UINTN ApSafeBufferSize;
294
295 SaveCpuMpData (CpuMpData);
296
297 if (CpuMpData->CpuCount == 1) {
298 //
299 // If only BSP exists, return
300 //
301 return;
302 }
303
304 //
305 // Avoid APs access invalid buffer data which allocated by BootServices,
306 // so we will allocate reserved data for AP loop code. We also need to
307 // allocate this buffer below 4GB due to APs may be transferred to 32bit
308 // protected mode on long mode DXE.
309 // Allocating it in advance since memory services are not available in
310 // Exit Boot Services callback function.
311 //
312 ApSafeBufferSize = CpuMpData->AddressMap.RelocateApLoopFuncSize;
313 ApSafeBufferSize += CpuMpData->CpuCount * AP_SAFE_STACK_SIZE;
314
315 Address = BASE_4GB - 1;
316 Status = gBS->AllocatePages (
317 AllocateMaxAddress,
318 EfiReservedMemoryType,
319 EFI_SIZE_TO_PAGES (ApSafeBufferSize),
320 &Address
321 );
322 ASSERT_EFI_ERROR (Status);
323 mReservedApLoopFunc = (VOID *) (UINTN) Address;
324 ASSERT (mReservedApLoopFunc != NULL);
325 mReservedTopOfApStack = (UINTN) Address + EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (ApSafeBufferSize));
326 ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);
327 CopyMem (
328 mReservedApLoopFunc,
329 CpuMpData->AddressMap.RelocateApLoopFuncAddress,
330 CpuMpData->AddressMap.RelocateApLoopFuncSize
331 );
332
333 Status = gBS->CreateEvent (
334 EVT_TIMER | EVT_NOTIFY_SIGNAL,
335 TPL_NOTIFY,
336 CheckApsStatus,
337 NULL,
338 &mCheckAllApsEvent
339 );
340 ASSERT_EFI_ERROR (Status);
341
342 //
343 // Set timer to check all APs status.
344 //
345 Status = gBS->SetTimer (
346 mCheckAllApsEvent,
347 TimerPeriodic,
348 AP_CHECK_INTERVAL
349 );
350 ASSERT_EFI_ERROR (Status);
351
352 Status = gBS->CreateEvent (
353 EVT_SIGNAL_EXIT_BOOT_SERVICES,
354 TPL_CALLBACK,
355 MpInitChangeApLoopCallback,
356 NULL,
357 &mMpInitExitBootServicesEvent
358 );
359 ASSERT_EFI_ERROR (Status);
360
361 Status = gBS->CreateEventEx (
362 EVT_NOTIFY_SIGNAL,
363 TPL_CALLBACK,
364 MpInitChangeApLoopCallback,
365 NULL,
366 &gEfiEventLegacyBootGuid,
367 &mLegacyBootEvent
368 );
369 ASSERT_EFI_ERROR (Status);
370 }
371
372 /**
373 This service executes a caller provided function on all enabled APs.
374
375 @param[in] Procedure A pointer to the function to be run on
376 enabled APs of the system. See type
377 EFI_AP_PROCEDURE.
378 @param[in] SingleThread If TRUE, then all the enabled APs execute
379 the function specified by Procedure one by
380 one, in ascending order of processor handle
381 number. If FALSE, then all the enabled APs
382 execute the function specified by Procedure
383 simultaneously.
384 @param[in] WaitEvent The event created by the caller with CreateEvent()
385 service. If it is NULL, then execute in
386 blocking mode. BSP waits until all APs finish
387 or TimeoutInMicroSeconds expires. If it's
388 not NULL, then execute in non-blocking mode.
389 BSP requests the function specified by
390 Procedure to be started on all the enabled
391 APs, and go on executing immediately. If
392 all return from Procedure, or TimeoutInMicroSeconds
393 expires, this event is signaled. The BSP
394 can use the CheckEvent() or WaitForEvent()
395 services to check the state of event. Type
396 EFI_EVENT is defined in CreateEvent() in
397 the Unified Extensible Firmware Interface
398 Specification.
399 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
400 APs to return from Procedure, either for
401 blocking or non-blocking mode. Zero means
402 infinity. If the timeout expires before
403 all APs return from Procedure, then Procedure
404 on the failed APs is terminated. All enabled
405 APs are available for next function assigned
406 by MpInitLibStartupAllAPs() or
407 MPInitLibStartupThisAP().
408 If the timeout expires in blocking mode,
409 BSP returns EFI_TIMEOUT. If the timeout
410 expires in non-blocking mode, WaitEvent
411 is signaled with SignalEvent().
412 @param[in] ProcedureArgument The parameter passed into Procedure for
413 all APs.
414 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
415 if all APs finish successfully, then its
416 content is set to NULL. If not all APs
417 finish before timeout expires, then its
418 content is set to address of the buffer
419 holding handle numbers of the failed APs.
420 The buffer is allocated by MP Initialization
421 library, and it's the caller's responsibility to
422 free the buffer with FreePool() service.
423 In blocking mode, it is ready for consumption
424 when the call returns. In non-blocking mode,
425 it is ready when WaitEvent is signaled. The
426 list of failed CPU is terminated by
427 END_OF_CPU_LIST.
428
429 @retval EFI_SUCCESS In blocking mode, all APs have finished before
430 the timeout expired.
431 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
432 to all enabled APs.
433 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
434 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
435 signaled.
436 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
437 supported.
438 @retval EFI_DEVICE_ERROR Caller processor is AP.
439 @retval EFI_NOT_STARTED No enabled APs exist in the system.
440 @retval EFI_NOT_READY Any enabled APs are busy.
441 @retval EFI_NOT_READY MP Initialize Library is not initialized.
442 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
443 all enabled APs have finished.
444 @retval EFI_INVALID_PARAMETER Procedure is NULL.
445
446 **/
447 EFI_STATUS
448 EFIAPI
449 MpInitLibStartupAllAPs (
450 IN EFI_AP_PROCEDURE Procedure,
451 IN BOOLEAN SingleThread,
452 IN EFI_EVENT WaitEvent OPTIONAL,
453 IN UINTN TimeoutInMicroseconds,
454 IN VOID *ProcedureArgument OPTIONAL,
455 OUT UINTN **FailedCpuList OPTIONAL
456 )
457 {
458 EFI_STATUS Status;
459
460 //
461 // Temporarily stop checkAllApsStatus for avoid resource dead-lock.
462 //
463 mStopCheckAllApsStatus = TRUE;
464
465 Status = StartupAllAPsWorker (
466 Procedure,
467 SingleThread,
468 WaitEvent,
469 TimeoutInMicroseconds,
470 ProcedureArgument,
471 FailedCpuList
472 );
473
474 //
475 // Start checkAllApsStatus
476 //
477 mStopCheckAllApsStatus = FALSE;
478
479 return Status;
480 }
481
482 /**
483 This service lets the caller get one enabled AP to execute a caller-provided
484 function.
485
486 @param[in] Procedure A pointer to the function to be run on the
487 designated AP of the system. See type
488 EFI_AP_PROCEDURE.
489 @param[in] ProcessorNumber The handle number of the AP. The range is
490 from 0 to the total number of logical
491 processors minus 1. The total number of
492 logical processors can be retrieved by
493 MpInitLibGetNumberOfProcessors().
494 @param[in] WaitEvent The event created by the caller with CreateEvent()
495 service. If it is NULL, then execute in
496 blocking mode. BSP waits until this AP finish
497 or TimeoutInMicroSeconds expires. If it's
498 not NULL, then execute in non-blocking mode.
499 BSP requests the function specified by
500 Procedure to be started on this AP,
501 and go on executing immediately. If this AP
502 return from Procedure or TimeoutInMicroSeconds
503 expires, this event is signaled. The BSP
504 can use the CheckEvent() or WaitForEvent()
505 services to check the state of event. Type
506 EFI_EVENT is defined in CreateEvent() in
507 the Unified Extensible Firmware Interface
508 Specification.
509 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
510 this AP to finish this Procedure, either for
511 blocking or non-blocking mode. Zero means
512 infinity. If the timeout expires before
513 this AP returns from Procedure, then Procedure
514 on the AP is terminated. The
515 AP is available for next function assigned
516 by MpInitLibStartupAllAPs() or
517 MpInitLibStartupThisAP().
518 If the timeout expires in blocking mode,
519 BSP returns EFI_TIMEOUT. If the timeout
520 expires in non-blocking mode, WaitEvent
521 is signaled with SignalEvent().
522 @param[in] ProcedureArgument The parameter passed into Procedure on the
523 specified AP.
524 @param[out] Finished If NULL, this parameter is ignored. In
525 blocking mode, this parameter is ignored.
526 In non-blocking mode, if AP returns from
527 Procedure before the timeout expires, its
528 content is set to TRUE. Otherwise, the
529 value is set to FALSE. The caller can
530 determine if the AP returned from Procedure
531 by evaluating this value.
532
533 @retval EFI_SUCCESS In blocking mode, specified AP finished before
534 the timeout expires.
535 @retval EFI_SUCCESS In non-blocking mode, the function has been
536 dispatched to specified AP.
537 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
538 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
539 signaled.
540 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
541 supported.
542 @retval EFI_DEVICE_ERROR The calling processor is an AP.
543 @retval EFI_TIMEOUT In blocking mode, the timeout expired before
544 the specified AP has finished.
545 @retval EFI_NOT_READY The specified AP is busy.
546 @retval EFI_NOT_READY MP Initialize Library is not initialized.
547 @retval EFI_NOT_FOUND The processor with the handle specified by
548 ProcessorNumber does not exist.
549 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
550 @retval EFI_INVALID_PARAMETER Procedure is NULL.
551
552 **/
553 EFI_STATUS
554 EFIAPI
555 MpInitLibStartupThisAP (
556 IN EFI_AP_PROCEDURE Procedure,
557 IN UINTN ProcessorNumber,
558 IN EFI_EVENT WaitEvent OPTIONAL,
559 IN UINTN TimeoutInMicroseconds,
560 IN VOID *ProcedureArgument OPTIONAL,
561 OUT BOOLEAN *Finished OPTIONAL
562 )
563 {
564 EFI_STATUS Status;
565
566 //
567 // temporarily stop checkAllApsStatus for avoid resource dead-lock.
568 //
569 mStopCheckAllApsStatus = TRUE;
570
571 Status = StartupThisAPWorker (
572 Procedure,
573 ProcessorNumber,
574 WaitEvent,
575 TimeoutInMicroseconds,
576 ProcedureArgument,
577 Finished
578 );
579
580 mStopCheckAllApsStatus = FALSE;
581
582 return Status;
583 }
584
585 /**
586 This service switches the requested AP to be the BSP from that point onward.
587 This service changes the BSP for all purposes. This call can only be performed
588 by the current BSP.
589
590 @param[in] ProcessorNumber The handle number of AP that is to become the new
591 BSP. The range is from 0 to the total number of
592 logical processors minus 1. The total number of
593 logical processors can be retrieved by
594 MpInitLibGetNumberOfProcessors().
595 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
596 enabled AP. Otherwise, it will be disabled.
597
598 @retval EFI_SUCCESS BSP successfully switched.
599 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
600 this service returning.
601 @retval EFI_UNSUPPORTED Switching the BSP is not supported.
602 @retval EFI_DEVICE_ERROR The calling processor is an AP.
603 @retval EFI_NOT_FOUND The processor with the handle specified by
604 ProcessorNumber does not exist.
605 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
606 a disabled AP.
607 @retval EFI_NOT_READY The specified AP is busy.
608 @retval EFI_NOT_READY MP Initialize Library is not initialized.
609
610 **/
611 EFI_STATUS
612 EFIAPI
613 MpInitLibSwitchBSP (
614 IN UINTN ProcessorNumber,
615 IN BOOLEAN EnableOldBSP
616 )
617 {
618 EFI_STATUS Status;
619 EFI_TIMER_ARCH_PROTOCOL *Timer;
620 UINT64 TimerPeriod;
621
622 TimerPeriod = 0;
623 //
624 // Locate Timer Arch Protocol
625 //
626 Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **) &Timer);
627 if (EFI_ERROR (Status)) {
628 Timer = NULL;
629 }
630
631 if (Timer != NULL) {
632 //
633 // Save current rate of DXE Timer
634 //
635 Timer->GetTimerPeriod (Timer, &TimerPeriod);
636 //
637 // Disable DXE Timer and drain pending interrupts
638 //
639 Timer->SetTimerPeriod (Timer, 0);
640 }
641
642 Status = SwitchBSPWorker (ProcessorNumber, EnableOldBSP);
643
644 if (Timer != NULL) {
645 //
646 // Enable and restore rate of DXE Timer
647 //
648 Timer->SetTimerPeriod (Timer, TimerPeriod);
649 }
650
651 return Status;
652 }
653
654 /**
655 This service lets the caller enable or disable an AP from this point onward.
656 This service may only be called from the BSP.
657
658 @param[in] ProcessorNumber The handle number of AP.
659 The range is from 0 to the total number of
660 logical processors minus 1. The total number of
661 logical processors can be retrieved by
662 MpInitLibGetNumberOfProcessors().
663 @param[in] EnableAP Specifies the new state for the processor for
664 enabled, FALSE for disabled.
665 @param[in] HealthFlag If not NULL, a pointer to a value that specifies
666 the new health status of the AP. This flag
667 corresponds to StatusFlag defined in
668 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
669 the PROCESSOR_HEALTH_STATUS_BIT is used. All other
670 bits are ignored. If it is NULL, this parameter
671 is ignored.
672
673 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
674 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
675 prior to this service returning.
676 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
677 @retval EFI_DEVICE_ERROR The calling processor is an AP.
678 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
679 does not exist.
680 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
681 @retval EFI_NOT_READY MP Initialize Library is not initialized.
682
683 **/
684 EFI_STATUS
685 EFIAPI
686 MpInitLibEnableDisableAP (
687 IN UINTN ProcessorNumber,
688 IN BOOLEAN EnableAP,
689 IN UINT32 *HealthFlag OPTIONAL
690 )
691 {
692 EFI_STATUS Status;
693 BOOLEAN TempStopCheckState;
694
695 TempStopCheckState = FALSE;
696 //
697 // temporarily stop checkAllAPsStatus for initialize parameters.
698 //
699 if (!mStopCheckAllApsStatus) {
700 mStopCheckAllApsStatus = TRUE;
701 TempStopCheckState = TRUE;
702 }
703
704 Status = EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);
705
706 if (TempStopCheckState) {
707 mStopCheckAllApsStatus = FALSE;
708 }
709
710 return Status;
711 }