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