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