CpuMp.c revision cd8c700b03e38e9389a8f13e193a431072802593
16022e28cf744a885c278dad256d50670741ea123Jordan Justen/** @file
26022e28cf744a885c278dad256d50670741ea123Jordan Justen  CPU DXE Module.
36022e28cf744a885c278dad256d50670741ea123Jordan Justen
46022e28cf744a885c278dad256d50670741ea123Jordan Justen  Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
56022e28cf744a885c278dad256d50670741ea123Jordan Justen  This program and the accompanying materials
66022e28cf744a885c278dad256d50670741ea123Jordan Justen  are licensed and made available under the terms and conditions of the BSD License
76022e28cf744a885c278dad256d50670741ea123Jordan Justen  which accompanies this distribution.  The full text of the license may be found at
86022e28cf744a885c278dad256d50670741ea123Jordan Justen  http://opensource.org/licenses/bsd-license.php
96022e28cf744a885c278dad256d50670741ea123Jordan Justen
106022e28cf744a885c278dad256d50670741ea123Jordan Justen  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
116022e28cf744a885c278dad256d50670741ea123Jordan Justen  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
126022e28cf744a885c278dad256d50670741ea123Jordan Justen
136022e28cf744a885c278dad256d50670741ea123Jordan Justen**/
146022e28cf744a885c278dad256d50670741ea123Jordan Justen
156022e28cf744a885c278dad256d50670741ea123Jordan Justen#include "CpuDxe.h"
166022e28cf744a885c278dad256d50670741ea123Jordan Justen#include "CpuMp.h"
176022e28cf744a885c278dad256d50670741ea123Jordan Justen
186a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen FanUINTN gMaxLogicalProcessorNumber;
196a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen FanUINTN gApStackSize;
203f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanUINTN gPollInterval = 100; // 100 microseconds
216a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
2203673ae11e255b9467e8f317175495b1ff79f965Chen FanMP_SYSTEM_DATA mMpSystemData;
2303673ae11e255b9467e8f317175495b1ff79f965Chen Fan
24fab82c1873b792bce33fb22c32db71324fc0ac3bJordan JustenVOID *mCommonStack = 0;
25fab82c1873b792bce33fb22c32db71324fc0ac3bJordan JustenVOID *mTopOfApCommonStack = 0;
266a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen FanVOID *mApStackStart = 0;
27fab82c1873b792bce33fb22c32db71324fc0ac3bJordan Justen
28232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fanvolatile BOOLEAN mAPsAlreadyInitFinished = FALSE;
29acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fanvolatile BOOLEAN mStopCheckAllAPsStatus = TRUE;
30acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan
31003973d98cf1ef84ab810cb4f3870acd3a7f40a6Chen FanEFI_MP_SERVICES_PROTOCOL  mMpServicesTemplate = {
32d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  GetNumberOfProcessors,
33e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  GetProcessorInfo,
345fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  StartupAllAPs,
353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  StartupThisAP,
36b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  SwitchBSP,
37fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  EnableDisableAP,
38cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  WhoAmI
39003973d98cf1ef84ab810cb4f3870acd3a7f40a6Chen Fan};
40003973d98cf1ef84ab810cb4f3870acd3a7f40a6Chen Fan
416022e28cf744a885c278dad256d50670741ea123Jordan Justen/**
42d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan   Get Mp Service Lock.
43d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
44d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  @param   CpuData    the pointer to CPU_DATA_BLOCK of specified processor
45d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
46d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan**/
47d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen FanVOID
48d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen FanGetMpSpinLock (
49d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  IN  CPU_DATA_BLOCK  *CpuData
50d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  )
51d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan{
52d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) {
53d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan    CpuPause ();
54d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  }
550e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  CpuData->LockSelf = GetApicId ();
56d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan}
57d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
58d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan/**
59d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan   Release Mp Service Lock.
60d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
61d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  @param   CpuData    the pointer to CPU_DATA_BLOCK of specified processor
62d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
63d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan**/
64d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen FanVOID
65d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen FanReleaseMpSpinLock (
66d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  IN  CPU_DATA_BLOCK  *CpuData
67d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  )
68d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan{
69d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseSpinLock (&CpuData->CpuDataLock);
70d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan}
71d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
72d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan/**
73d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  Check whether caller processor is BSP.
74d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
75d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval  TRUE       the caller is BSP
76d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval  FALSE      the caller is AP
77d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
78d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan**/
79d894d8b704324da8ed902677703ed9d4f7c85076Chen FanBOOLEAN
80d894d8b704324da8ed902677703ed9d4f7c85076Chen FanIsBSP (
81d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  VOID
82d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  )
83d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan{
84d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  UINTN           CpuIndex;
85d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  CPU_DATA_BLOCK  *CpuData;
86d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
87d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  CpuData = NULL;
88d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
89d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  WhoAmI (&mMpServicesTemplate, &CpuIndex);
90d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  CpuData = &mMpSystemData.CpuDatas[CpuIndex];
91d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
92d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  return CpuData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT ? TRUE : FALSE;
93d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan}
94d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
95d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan/**
96fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  Get the Application Processors state.
97fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
98fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param   CpuData    the pointer to CPU_DATA_BLOCK of specified AP
99fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
100fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval  CPU_STATE  the AP status
101fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
102fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan**/
103fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanCPU_STATE
104fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanGetApState (
105fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  CPU_DATA_BLOCK  *CpuData
106fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  )
107fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan{
108fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  CPU_STATE State;
109fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
110d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
111fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  State = CpuData->State;
112d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
113fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
114fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  return State;
115fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan}
116fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
117fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan/**
1183f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Set the Application Processors state.
1193f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1203f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param   CpuData    The pointer to CPU_DATA_BLOCK of specified AP
1213f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param   State      The AP status
1223f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1233f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
1243f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanVOID
1253f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanSetApState (
1263f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  CPU_DATA_BLOCK   *CpuData,
1273f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  CPU_STATE        State
1283f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
1293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
130d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
1313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->State = State;
132d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
1333f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
1343f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
1363f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Set the Application Processor prepare to run a function specified
1373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  by Params.
1383f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1393f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param CpuData           the pointer to CPU_DATA_BLOCK of specified AP
1403f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param Procedure         A pointer to the function to be run on enabled APs of the system
1413f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param ProcedureArgument Pointer to the optional parameter of the assigned function
1423f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1433f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
1443f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanVOID
1453f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanSetApProcedure (
1463f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN   CPU_DATA_BLOCK        *CpuData,
1473f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN   EFI_AP_PROCEDURE      Procedure,
1483f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN   VOID                  *ProcedureArgument
1493f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
1503f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
151d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
1523f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->Parameter  = ProcedureArgument;
1533f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->Procedure  = Procedure;
154d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
1553f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
1563f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1573f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
158fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  Check the Application Processors Status whether contains the Flags.
159fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
160fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     CpuData  the pointer to CPU_DATA_BLOCK of specified AP
161fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     Flags    the StatusFlag describing in EFI_PROCESSOR_INFORMATION
162fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
163fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval    TRUE     the AP status includes the StatusFlag
164fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval    FALSE    the AP status excludes the StatusFlag
165fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
166fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan**/
167fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanBOOLEAN
168fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanTestCpuStatusFlag (
169fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  CPU_DATA_BLOCK  *CpuData,
170fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  UINT32          Flags
171fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  )
172fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan{
173fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  UINT32 Ret;
174fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
175d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
176fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  Ret = CpuData->Info.StatusFlag & Flags;
177d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
178fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
179fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  return !!(Ret);
180fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan}
181fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
182fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan/**
183fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  Bitwise-Or of the Application Processors Status with the Flags.
184fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
185fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     CpuData  the pointer to CPU_DATA_BLOCK of specified AP
186fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     Flags    the StatusFlag describing in EFI_PROCESSOR_INFORMATION
187fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
188fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan**/
189fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanVOID
190fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanCpuStatusFlagOr (
191fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  CPU_DATA_BLOCK  *CpuData,
192fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  UINT32          Flags
193fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  )
194fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan{
195d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
196fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  CpuData->Info.StatusFlag |= Flags;
197d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
198fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan}
199fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
200fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan/**
201fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  Bitwise-AndNot of the Application Processors Status with the Flags.
202fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
203fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     CpuData  the pointer to CPU_DATA_BLOCK of specified AP
204fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     Flags    the StatusFlag describing in EFI_PROCESSOR_INFORMATION
205fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
206fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan**/
207fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanVOID
208fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanCpuStatusFlagAndNot (
209fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  CPU_DATA_BLOCK  *CpuData,
210fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  UINT32          Flags
211fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  )
212fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan{
213d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
214fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  CpuData->Info.StatusFlag &= ~Flags;
215d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
216fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan}
217fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
218fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan/**
2193f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Searches for the next blocking AP.
2203f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2213f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Search for the next AP that is put in blocking state by single-threaded StartupAllAPs().
2223f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2233f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param  NextNumber           Pointer to the processor number of the next blocking AP.
2243f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2253f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_SUCCESS          The next blocking AP has been found.
2263f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_NOT_FOUND        No blocking AP exists.
2273f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2283f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
2293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanEFI_STATUS
2303f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanGetNextBlockedNumber (
2313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  OUT UINTN  *NextNumber
2323f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
2333f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
2343f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  UINTN                 Number;
2353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CPU_STATE             CpuState;
2363f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CPU_DATA_BLOCK        *CpuData;
2373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2383f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
2393f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    CpuData = &mMpSystemData.CpuDatas[Number];
2403f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
2413f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      //
2423f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      // Skip BSP
2433f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      //
2443f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      continue;
2453f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
2463f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2473f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    CpuState = GetApState (CpuData);
2483f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (CpuState == CpuStateBlocked) {
2493f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      *NextNumber = Number;
2503f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      return EFI_SUCCESS;
2513f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
2523f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
2533f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2543f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  return EFI_NOT_FOUND;
2553f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
2563f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2573f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
2585fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  Check if the APs state are finished, and update them to idle state
2595fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  by StartupAllAPs().
2605fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
2615fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan**/
2625fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanVOID
2635fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanCheckAndUpdateAllAPsToIdleState (
2645fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  VOID
2655fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  )
2665fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan{
2675fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  UINTN                 ProcessorNumber;
2685fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  UINTN                 NextNumber;
2695fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_DATA_BLOCK        *CpuData;
2705fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  EFI_STATUS            Status;
2715fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_STATE             CpuState;
2725fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
2735fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {
2745fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
2755fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
2765fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
2775fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip BSP
2785fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
2795fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
2805fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
2815fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
2825fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
2835fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
2845fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip Disabled processors
2855fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
2865fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
2875fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
2885fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
2895fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuState = GetApState (CpuData);
2905fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (CpuState == CpuStateFinished) {
2915fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      mMpSystemData.FinishCount++;
2925fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      if (mMpSystemData.SingleThread) {
2935fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        Status = GetNextBlockedNumber (&NextNumber);
2945fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        if (!EFI_ERROR (Status)) {
2955fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan          SetApState (&mMpSystemData.CpuDatas[NextNumber], CpuStateReady);
2965fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan          SetApProcedure (&mMpSystemData.CpuDatas[NextNumber],
2975fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                          mMpSystemData.Procedure,
2985fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                          mMpSystemData.ProcedureArgument);
2995fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        }
3005fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      }
3015fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3025fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      SetApState (CpuData, CpuStateIdle);
3035fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
3045fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
3055fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan}
3065fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3075fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan/**
3085fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  If the timeout expires before all APs returns from Procedure,
3095fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  we should forcibly terminate the executing AP and fill FailedList back
3105fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  by StartupAllAPs().
3115fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3125fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan**/
3135fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanVOID
3145fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanResetAllFailedAPs (
3155fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  VOID
3165fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  )
3175fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan{
3185fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_DATA_BLOCK        *CpuData;
3195fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  UINTN                 Number;
3205fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_STATE             CpuState;
3215fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3225fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (mMpSystemData.FailedList != NULL) {
3235fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan     *mMpSystemData.FailedList = AllocatePool ((mMpSystemData.StartCount - mMpSystemData.FinishCount + 1) * sizeof(UINTN));
3245fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan     ASSERT (*mMpSystemData.FailedList != NULL);
3255fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
3265fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3275fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
3285fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuData = &mMpSystemData.CpuDatas[Number];
3295fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (TestCpuStatusFlag (CpuData,  PROCESSOR_AS_BSP_BIT)) {
3305fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
3315fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip BSP
3325fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
3335fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
3345fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
3355fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3365fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
3375fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
3385fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip Disabled processors
3395fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
3405fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
3415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
3425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuState = GetApState (CpuData);
3445fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (CpuState != CpuStateIdle) {
3455fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      if (mMpSystemData.FailedList != NULL) {
3465fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex++] = Number;
3475fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      }
3485fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      ResetProcessorToIdleState (CpuData);
3495fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
3505fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
3515fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3525fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (mMpSystemData.FailedList != NULL) {
3535fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex] = END_OF_CPU_LIST;
3545fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
3555fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan}
3565fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3575fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan/**
358d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  This service retrieves the number of logical processor in the platform
359d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  and the number of those logical processors that are enabled on this boot.
360d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  This service may only be called from the BSP.
361d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
362d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  This function is used to retrieve the following information:
363d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan    - The number of logical processors that are present in the system.
364d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan    - The number of enabled logical processors in the system at the instant
365d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan      this call is made.
366d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
367d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  Because MP Service Protocol provides services to enable and disable processors
368d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  dynamically, the number of enabled logical processors may vary during the
369d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  course of a boot session.
370d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
371d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
372d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
373d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
374d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  is returned in NumberOfProcessors, the number of currently enabled processor
375d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
376d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
377d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @param[in]  This                        A pointer to the EFI_MP_SERVICES_PROTOCOL
378d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                          instance.
379d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @param[out] NumberOfProcessors          Pointer to the total number of logical
380d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                          processors in the system, including the BSP
381d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                          and disabled APs.
382d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @param[out] NumberOfEnabledProcessors   Pointer to the number of enabled logical
383d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                          processors that exist in system, including
384d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                          the BSP.
385d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
386d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval EFI_SUCCESS             The number of logical processors and enabled
387d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                  logical processors was retrieved.
388d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
389d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval EFI_INVALID_PARAMETER   NumberOfProcessors is NULL.
390d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval EFI_INVALID_PARAMETER   NumberOfEnabledProcessors is NULL.
391d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
392d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan**/
393d894d8b704324da8ed902677703ed9d4f7c85076Chen FanEFI_STATUS
394d894d8b704324da8ed902677703ed9d4f7c85076Chen FanEFIAPI
395d894d8b704324da8ed902677703ed9d4f7c85076Chen FanGetNumberOfProcessors (
396d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  IN  EFI_MP_SERVICES_PROTOCOL  *This,
397d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  OUT UINTN                     *NumberOfProcessors,
398d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  OUT UINTN                     *NumberOfEnabledProcessors
399d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  )
400d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan{
401d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  if ((NumberOfProcessors == NULL) || (NumberOfEnabledProcessors == NULL)) {
402d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan    return EFI_INVALID_PARAMETER;
403d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  }
404d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
405d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  if (!IsBSP ()) {
406d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan    return EFI_DEVICE_ERROR;
407d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  }
408d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
409d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  *NumberOfProcessors        = mMpSystemData.NumberOfProcessors;
410d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  *NumberOfEnabledProcessors = mMpSystemData.NumberOfEnabledProcessors;
411d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  return EFI_SUCCESS;
412d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan}
413d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
414d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan/**
415e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  Gets detailed MP-related information on the requested processor at the
416e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  instant this call is made. This service may only be called from the BSP.
417e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
418e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  This service retrieves detailed MP-related information about any processor
419e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  on the platform. Note the following:
420e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan    - The processor information may change during the course of a boot session.
421e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan    - The information presented here is entirely MP related.
422e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
423e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  Information regarding the number of caches and their sizes, frequency of operation,
424e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  slot numbers is all considered platform-related information and is not provided
425e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  by this service.
426e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
427e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @param[in]  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL
428e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan                                    instance.
429e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @param[in]  ProcessorNumber       The handle number of processor.
430e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @param[out] ProcessorInfoBuffer   A pointer to the buffer where information for
431e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan                                    the requested processor is deposited.
432e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
433e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @retval EFI_SUCCESS             Processor information was returned.
434e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
435e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @retval EFI_INVALID_PARAMETER   ProcessorInfoBuffer is NULL.
436e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @retval EFI_NOT_FOUND           The processor with the handle specified by
437e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan                                  ProcessorNumber does not exist in the platform.
438e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
439e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan**/
440e7938b5a869fc42df7f026752f39ea85090eb3f9Chen FanEFI_STATUS
441e7938b5a869fc42df7f026752f39ea85090eb3f9Chen FanEFIAPI
442e7938b5a869fc42df7f026752f39ea85090eb3f9Chen FanGetProcessorInfo (
443e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  IN  EFI_MP_SERVICES_PROTOCOL   *This,
444e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  IN  UINTN                      ProcessorNumber,
445e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  OUT EFI_PROCESSOR_INFORMATION  *ProcessorInfoBuffer
446e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  )
447e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan{
448e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  if (ProcessorInfoBuffer == NULL) {
449e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan    return EFI_INVALID_PARAMETER;
450e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  }
451e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
452e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  if (!IsBSP ()) {
453e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan    return EFI_DEVICE_ERROR;
454e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  }
455e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
456e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
457e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan    return EFI_NOT_FOUND;
458e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  }
459e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
460e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  CopyMem (ProcessorInfoBuffer, &mMpSystemData.CpuDatas[ProcessorNumber], sizeof (EFI_PROCESSOR_INFORMATION));
461e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  return EFI_SUCCESS;
462e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan}
463e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
464e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan/**
4655fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  This service executes a caller provided function on all enabled APs. APs can
4665fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  run either simultaneously or one at a time in sequence. This service supports
4675fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  both blocking and non-blocking requests. The non-blocking requests use EFI
4685fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  events so the BSP can detect when the APs have finished. This service may only
4695fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  be called from the BSP.
4705fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
4715fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  This function is used to dispatch all the enabled APs to the function specified
4725fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  by Procedure.  If any enabled AP is busy, then EFI_NOT_READY is returned
4735fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  immediately and Procedure is not started on any AP.
4745fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
4755fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  If SingleThread is TRUE, all the enabled APs execute the function specified by
4765fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  Procedure one by one, in ascending order of processor handle number. Otherwise,
4775fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  all the enabled APs execute the function specified by Procedure simultaneously.
4785fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
4795fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  If WaitEvent is NULL, execution is in blocking mode. The BSP waits until all
4805fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  APs finish or TimeoutInMicroseconds expires. Otherwise, execution is in non-blocking
4815fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mode, and the BSP returns from this service without waiting for APs. If a
4825fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  non-blocking mode is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
4835fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  is signaled, then EFI_UNSUPPORTED must be returned.
4845fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
4855fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  If the timeout specified by TimeoutInMicroseconds expires before all APs return
4865fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  from Procedure, then Procedure on the failed APs is terminated. All enabled APs
4875fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  are always available for further calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
4885fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  and EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). If FailedCpuList is not NULL, its
4895fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  content points to the list of processor handle numbers in which Procedure was
4905fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  terminated.
4915fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
4925fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  Note: It is the responsibility of the consumer of the EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
4935fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  to make sure that the nature of the code that is executed on the BSP and the
4945fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  dispatched APs is well controlled. The MP Services Protocol does not guarantee
4955fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  that the Procedure function is MP-safe. Hence, the tasks that can be run in
4965fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  parallel are limited to certain independent tasks and well-controlled exclusive
4975fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  code. EFI services and protocols may not be called by APs unless otherwise
4985fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  specified.
4995fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5005fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  In blocking execution mode, BSP waits until all APs finish or
5015fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  TimeoutInMicroseconds expires.
5025fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5035fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  In non-blocking execution mode, BSP is freed to return to the caller and then
5045fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  proceed to the next task without having to wait for APs. The following
5055fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  sequence needs to occur in a non-blocking execution mode:
5065fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5075fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    -# The caller that intends to use this MP Services Protocol in non-blocking
5085fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       mode creates WaitEvent by calling the EFI CreateEvent() service.  The caller
5095fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       invokes EFI_MP_SERVICES_PROTOCOL.StartupAllAPs(). If the parameter WaitEvent
5105fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       is not NULL, then StartupAllAPs() executes in non-blocking mode. It requests
5115fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       the function specified by Procedure to be started on all the enabled APs,
5125fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       and releases the BSP to continue with other tasks.
5135fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    -# The caller can use the CheckEvent() and WaitForEvent() services to check
5145fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       the state of the WaitEvent created in step 1.
5155fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    -# When the APs complete their task or TimeoutInMicroSecondss expires, the MP
5165fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       Service signals WaitEvent by calling the EFI SignalEvent() function. If
5175fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       FailedCpuList is not NULL, its content is available when WaitEvent is
5185fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       signaled. If all APs returned from Procedure prior to the timeout, then
5195fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       FailedCpuList is set to NULL. If not all APs return from Procedure before
5205fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       the timeout, then FailedCpuList is filled in with the list of the failed
5215fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       APs. The buffer is allocated by MP Service Protocol using AllocatePool().
5225fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       It is the caller's responsibility to free the buffer with FreePool() service.
5235fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    -# This invocation of SignalEvent() function informs the caller that invoked
5245fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() that either all the APs completed
5255fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       the specified task or a timeout occurred. The contents of FailedCpuList
5265fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       can be examined to determine which APs did not complete the specified task
5275fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       prior to the timeout.
5285fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5295fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  This                    A pointer to the EFI_MP_SERVICES_PROTOCOL
5305fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      instance.
5315fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  Procedure               A pointer to the function to be run on
5325fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      enabled APs of the system. See type
5335fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      EFI_AP_PROCEDURE.
5345fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  SingleThread            If TRUE, then all the enabled APs execute
5355fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      the function specified by Procedure one by
5365fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      one, in ascending order of processor handle
5375fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      number.  If FALSE, then all the enabled APs
5385fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      execute the function specified by Procedure
5395fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      simultaneously.
5405fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  WaitEvent               The event created by the caller with CreateEvent()
5415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      service.  If it is NULL, then execute in
5425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      blocking mode. BSP waits until all APs finish
5435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      or TimeoutInMicroseconds expires.  If it's
5445fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      not NULL, then execute in non-blocking mode.
5455fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      BSP requests the function specified by
5465fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      Procedure to be started on all the enabled
5475fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      APs, and go on executing immediately. If
5485fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      all return from Procedure, or TimeoutInMicroseconds
5495fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      expires, this event is signaled. The BSP
5505fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      can use the CheckEvent() or WaitForEvent()
5515fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      services to check the state of event.  Type
5525fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      EFI_EVENT is defined in CreateEvent() in
5535fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      the Unified Extensible Firmware Interface
5545fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      Specification.
5555fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
5565fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      APs to return from Procedure, either for
5575fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      blocking or non-blocking mode. Zero means
5585fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      infinity.  If the timeout expires before
5595fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      all APs return from Procedure, then Procedure
5605fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      on the failed APs is terminated. All enabled
5615fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      APs are available for next function assigned
5625fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
5635fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
5645fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      If the timeout expires in blocking mode,
5655fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      BSP returns EFI_TIMEOUT.  If the timeout
5665fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      expires in non-blocking mode, WaitEvent
5675fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      is signaled with SignalEvent().
5685fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  ProcedureArgument       The parameter passed into Procedure for
5695fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      all APs.
5705fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[out] FailedCpuList           If NULL, this parameter is ignored. Otherwise,
5715fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      if all APs finish successfully, then its
5725fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      content is set to NULL. If not all APs
5735fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      finish before timeout expires, then its
5745fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      content is set to address of the buffer
5755fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      holding handle numbers of the failed APs.
5765fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      The buffer is allocated by MP Service Protocol,
5775fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      and it's the caller's responsibility to
5785fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      free the buffer with FreePool() service.
5795fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      In blocking mode, it is ready for consumption
5805fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      when the call returns. In non-blocking mode,
5815fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      it is ready when WaitEvent is signaled.  The
5825fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      list of failed CPU is terminated by
5835fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      END_OF_CPU_LIST.
5845fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5855fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_SUCCESS             In blocking mode, all APs have finished before
5865fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                  the timeout expired.
5875fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_SUCCESS             In non-blocking mode, function has been dispatched
5885fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                  to all enabled APs.
5895fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_UNSUPPORTED         A non-blocking mode request was made after the
5905fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                  UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
5915fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                  signaled.
5925fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_DEVICE_ERROR        Caller processor is AP.
5935fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_NOT_STARTED         No enabled APs exist in the system.
5945fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_NOT_READY           Any enabled APs are busy.
5955fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_TIMEOUT             In blocking mode, the timeout expired before
5965fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                  all enabled APs have finished.
5975fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_INVALID_PARAMETER   Procedure is NULL.
5985fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5995fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan**/
6005fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanEFI_STATUS
6015fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanEFIAPI
6025fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanStartupAllAPs (
6035fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  EFI_MP_SERVICES_PROTOCOL  *This,
6045fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  EFI_AP_PROCEDURE          Procedure,
6055fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  BOOLEAN                   SingleThread,
6065fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  EFI_EVENT                 WaitEvent               OPTIONAL,
6075fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  UINTN                     TimeoutInMicroseconds,
6085fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  VOID                      *ProcedureArgument      OPTIONAL,
6095fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  OUT UINTN                     **FailedCpuList         OPTIONAL
6105fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  )
6115fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan{
6125fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  EFI_STATUS            Status;
6135fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_DATA_BLOCK        *CpuData;
6145fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  UINTN                 Number;
6155fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_STATE             APInitialState;
6165fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6175fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CpuData = NULL;
6185fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6195fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (FailedCpuList != NULL) {
6205fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    *FailedCpuList = NULL;
6215fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
6225fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6235fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (!IsBSP ()) {
6245fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    return EFI_DEVICE_ERROR;
6255fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
6265fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6275fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (mMpSystemData.NumberOfProcessors == 1) {
6285fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    return EFI_NOT_STARTED;
6295fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
6305fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6315fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (Procedure == NULL) {
6325fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    return EFI_INVALID_PARAMETER;
6335fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
6345fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
635cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
636cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  // temporarily stop checkAllAPsStatus for avoid resource dead-lock.
637cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
638cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  mStopCheckAllAPsStatus = TRUE;
639cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
6405fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
6415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuData = &mMpSystemData.CpuDatas[Number];
6425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
6435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6445fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip BSP
6455fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6465fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
6475fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
6485fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6495fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
6505fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6515fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip Disabled processors
6525fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6535fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
6545fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
6555fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6565fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (GetApState (CpuData) != CpuStateIdle) {
6575fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      return EFI_NOT_READY;
6585fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
6595fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
6605fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6615fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.Procedure         = Procedure;
6625fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.ProcedureArgument = ProcedureArgument;
6635fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.WaitEvent         = WaitEvent;
6645fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.Timeout           = TimeoutInMicroseconds;
6655fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.TimeoutActive     = !!(TimeoutInMicroseconds);
6665fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.FinishCount       = 0;
6675fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.StartCount        = 0;
6685fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.SingleThread      = SingleThread;
6695fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.FailedList        = FailedCpuList;
6705fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.FailedListIndex   = 0;
6715fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  APInitialState                  = CpuStateReady;
6725fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6735fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
6745fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuData = &mMpSystemData.CpuDatas[Number];
6755fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
6765fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6775fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip BSP
6785fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6795fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
6805fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
6815fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6825fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
6835fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6845fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip Disabled processors
6855fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6865fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
6875fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
6885fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6895fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
6905fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    // Get APs prepared, and put failing APs into FailedCpuList
6915fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    // if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready
6925fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    // state 1 by 1, until the previous 1 finished its task
6935fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    // if not "SingleThread", all APs are put to ready state from the beginning
6945fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
6955fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (GetApState (CpuData) == CpuStateIdle) {
6965fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      mMpSystemData.StartCount++;
6975fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6985fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      SetApState (CpuData, APInitialState);
6995fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7005fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      if (APInitialState == CpuStateReady) {
7015fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        SetApProcedure (CpuData, Procedure, ProcedureArgument);
7025fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      }
7035fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7045fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      if (SingleThread) {
7055fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        APInitialState = CpuStateBlocked;
7065fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      }
7075fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
7085fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
7095fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
710acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  mStopCheckAllAPsStatus = FALSE;
711acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan
7125fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (WaitEvent != NULL) {
713acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    //
714acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    // non blocking
715acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    //
716acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    return EFI_SUCCESS;
7175fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
7185fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
719cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
720cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  // Blocking temporarily stop CheckAllAPsStatus()
721cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
722cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  mStopCheckAllAPsStatus = TRUE;
723cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
7245fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  while (TRUE) {
7255fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CheckAndUpdateAllAPsToIdleState ();
7265fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (mMpSystemData.FinishCount == mMpSystemData.StartCount) {
7275fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      Status = EFI_SUCCESS;
7285fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      goto Done;
7295fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
7305fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7315fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
7325fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    // task timeout
7335fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
7345fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) {
7355fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      ResetAllFailedAPs();
7365fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      Status = EFI_TIMEOUT;
7375fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      goto Done;
7385fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
7395fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7405fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    gBS->Stall (gPollInterval);
7415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    mMpSystemData.Timeout -= gPollInterval;
7425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
7435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7445fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanDone:
7455fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7465fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  return Status;
7475fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan}
7485fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7495fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan/**
7503f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  This service lets the caller get one enabled AP to execute a caller-provided
7513f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  function. The caller can request the BSP to either wait for the completion
7523f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  of the AP or just proceed with the next task by using the EFI event mechanism.
7533f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  See EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() for more details on non-blocking
7543f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  execution support.  This service may only be called from the BSP.
7553f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
7563f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  This function is used to dispatch one enabled AP to the function specified by
7573f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Procedure passing in the argument specified by ProcedureArgument.  If WaitEvent
7583f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  is NULL, execution is in blocking mode. The BSP waits until the AP finishes or
7593f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  TimeoutInMicroSecondss expires. Otherwise, execution is in non-blocking mode.
7603f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  BSP proceeds to the next task without waiting for the AP. If a non-blocking mode
7613f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled,
7623f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  then EFI_UNSUPPORTED must be returned.
7633f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
7643f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  If the timeout specified by TimeoutInMicroseconds expires before the AP returns
7653f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  from Procedure, then execution of Procedure by the AP is terminated. The AP is
7663f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  available for subsequent calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() and
7673f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
7683f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
7693f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  This                    A pointer to the EFI_MP_SERVICES_PROTOCOL
7703f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      instance.
7713f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  Procedure               A pointer to the function to be run on
7723f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      enabled APs of the system. See type
7733f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      EFI_AP_PROCEDURE.
7743f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  ProcessorNumber         The handle number of the AP. The range is
7753f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      from 0 to the total number of logical
7763f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      processors minus 1. The total number of
7773f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      logical processors can be retrieved by
7783f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
7793f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  WaitEvent               The event created by the caller with CreateEvent()
7803f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      service.  If it is NULL, then execute in
7813f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      blocking mode. BSP waits until all APs finish
7823f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      or TimeoutInMicroseconds expires.  If it's
7833f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      not NULL, then execute in non-blocking mode.
7843f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      BSP requests the function specified by
7853f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      Procedure to be started on all the enabled
7863f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      APs, and go on executing immediately. If
7873f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      all return from Procedure or TimeoutInMicroseconds
7883f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      expires, this event is signaled. The BSP
7893f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      can use the CheckEvent() or WaitForEvent()
7903f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      services to check the state of event.  Type
7913f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      EFI_EVENT is defined in CreateEvent() in
7923f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      the Unified Extensible Firmware Interface
7933f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      Specification.
7943f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
7953f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      APs to return from Procedure, either for
7963f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      blocking or non-blocking mode. Zero means
7973f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      infinity.  If the timeout expires before
7983f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      all APs return from Procedure, then Procedure
7993f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      on the failed APs is terminated. All enabled
8003f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      APs are available for next function assigned
8013f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
8023f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
8033f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      If the timeout expires in blocking mode,
8043f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      BSP returns EFI_TIMEOUT.  If the timeout
8053f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      expires in non-blocking mode, WaitEvent
8063f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      is signaled with SignalEvent().
8073f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  ProcedureArgument       The parameter passed into Procedure for
8083f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      all APs.
8093f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[out] Finished                If NULL, this parameter is ignored.  In
8103f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      blocking mode, this parameter is ignored.
8113f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      In non-blocking mode, if AP returns from
8123f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      Procedure before the timeout expires, its
8133f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      content is set to TRUE. Otherwise, the
8143f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      value is set to FALSE. The caller can
8153f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      determine if the AP returned from Procedure
8163f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      by evaluating this value.
8173f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8183f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_SUCCESS             In blocking mode, specified AP finished before
8193f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  the timeout expires.
8203f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_SUCCESS             In non-blocking mode, the function has been
8213f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  dispatched to specified AP.
8223f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_UNSUPPORTED         A non-blocking mode request was made after the
8233f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
8243f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  signaled.
8253f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
8263f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_TIMEOUT             In blocking mode, the timeout expired before
8273f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  the specified AP has finished.
8283f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_NOT_READY           The specified AP is busy.
8293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_NOT_FOUND           The processor with the handle specified by
8303f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  ProcessorNumber does not exist.
8313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP or disabled AP.
8323f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_INVALID_PARAMETER   Procedure is NULL.
8333f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8343f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
8353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanEFI_STATUS
8363f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanEFIAPI
8373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanStartupThisAP (
8383f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  EFI_MP_SERVICES_PROTOCOL  *This,
8393f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  EFI_AP_PROCEDURE          Procedure,
8403f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  UINTN                     ProcessorNumber,
8413f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  EFI_EVENT                 WaitEvent               OPTIONAL,
8423f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  UINTN                     TimeoutInMicroseconds,
8433f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  VOID                      *ProcedureArgument      OPTIONAL,
8443f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  OUT BOOLEAN                   *Finished               OPTIONAL
8453f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
8463f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
8473f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CPU_DATA_BLOCK        *CpuData;
8483f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8493f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData = NULL;
8503f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8513f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (Finished != NULL) {
8523f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    *Finished = FALSE;
8533f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8543f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8553f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (!IsBSP ()) {
8563f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    return EFI_DEVICE_ERROR;
8573f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8583f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8593f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (Procedure == NULL) {
8603f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    return EFI_INVALID_PARAMETER;
8613f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8623f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8633f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
8643f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    return EFI_NOT_FOUND;
8653f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8663f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
867cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
868cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  // temporarily stop checkAllAPsStatus for avoid resource dead-lock.
869cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
870cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  mStopCheckAllAPsStatus = TRUE;
871cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
8723f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
8733f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT) ||
8743f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      !TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
8753f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    return EFI_INVALID_PARAMETER;
8763f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8773f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8783f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (GetApState (CpuData) != CpuStateIdle) {
8793f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    return EFI_NOT_READY;
8803f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8813f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8823f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  SetApState (CpuData, CpuStateReady);
8833f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8843f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  SetApProcedure (CpuData, Procedure, ProcedureArgument);
8853f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8863f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->Timeout = TimeoutInMicroseconds;
8873f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->WaitEvent = WaitEvent;
8883f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->TimeoutActive = !!(TimeoutInMicroseconds);
8893f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->Finished = Finished;
8903f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
891acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  mStopCheckAllAPsStatus = FALSE;
892acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan
8933f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (WaitEvent != NULL) {
8943f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    //
8953f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    // Non Blocking
8963f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    //
897acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    return EFI_SUCCESS;
8983f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8993f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
9003f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  //
9013f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  // Blocking
9023f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  //
9033f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  while (TRUE) {
9043f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (GetApState (CpuData) == CpuStateFinished) {
9053f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      SetApState (CpuData, CpuStateIdle);
9063f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      break;
9073f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
9083f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
9093f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (CpuData->TimeoutActive && CpuData->Timeout < 0) {
9103f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      ResetProcessorToIdleState (CpuData);
9113f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      return EFI_TIMEOUT;
9123f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
9133f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
9143f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    gBS->Stall (gPollInterval);
9153f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    CpuData->Timeout -= gPollInterval;
9163f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
9173f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
9183f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  return EFI_SUCCESS;
9193f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
9203f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
9213f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
922b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  This service switches the requested AP to be the BSP from that point onward.
923b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  This service changes the BSP for all purposes.   This call can only be performed
924b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  by the current BSP.
925b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
926b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  This service switches the requested AP to be the BSP from that point onward.
927b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  This service changes the BSP for all purposes. The new BSP can take over the
928b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  execution of the old BSP and continue seamlessly from where the old one left
929b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  off. This service may not be supported after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
930b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  is signaled.
931b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
932b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  If the BSP cannot be switched prior to the return from this service, then
933b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  EFI_UNSUPPORTED must be returned.
934b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
935b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @param[in] This              A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
936b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @param[in] ProcessorNumber   The handle number of AP that is to become the new
937b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                               BSP. The range is from 0 to the total number of
938b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                               logical processors minus 1. The total number of
939b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                               logical processors can be retrieved by
940b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                               EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
941b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @param[in] EnableOldBSP      If TRUE, then the old BSP will be listed as an
942b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                               enabled AP. Otherwise, it will be disabled.
943b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
944b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_SUCCESS             BSP successfully switched.
945b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_UNSUPPORTED         Switching the BSP cannot be completed prior to
946b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                                  this service returning.
947b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_UNSUPPORTED         Switching the BSP is not supported.
948b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_SUCCESS             The calling processor is an AP.
949b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_NOT_FOUND           The processor with the handle specified by
950b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                                  ProcessorNumber does not exist.
951b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the current BSP or
952b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                                  a disabled AP.
953b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_NOT_READY           The specified AP is busy.
954b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
955b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan**/
956b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen FanEFI_STATUS
957b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen FanEFIAPI
958b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen FanSwitchBSP (
959b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  IN EFI_MP_SERVICES_PROTOCOL  *This,
960b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  IN  UINTN                    ProcessorNumber,
961b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  IN  BOOLEAN                  EnableOldBSP
962b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  )
963b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan{
964b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan   //
965b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan   // Current always return unsupported.
966b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan   //
967b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan   return EFI_UNSUPPORTED;
968b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan}
969b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
970b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan/**
971fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  This service lets the caller enable or disable an AP from this point onward.
972fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  This service may only be called from the BSP.
973fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
974fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  This service allows the caller enable or disable an AP from this point onward.
975fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  The caller can optionally specify the health status of the AP by Health. If
976fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  an AP is being disabled, then the state of the disabled AP is implementation
977fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  dependent. If an AP is enabled, then the implementation must guarantee that a
978fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  complete initialization sequence is performed on the AP, so the AP is in a state
979fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  that is compatible with an MP operating system. This service may not be supported
980fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled.
981fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
982fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  If the enable or disable AP operation cannot be completed prior to the return
983fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  from this service, then EFI_UNSUPPORTED must be returned.
984fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
985fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param[in] This              A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
986fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param[in] ProcessorNumber   The handle number of AP that is to become the new
987fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               BSP. The range is from 0 to the total number of
988fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               logical processors minus 1. The total number of
989fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               logical processors can be retrieved by
990fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
991fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param[in] EnableAP          Specifies the new state for the processor for
992fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               enabled, FALSE for disabled.
993fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param[in] HealthFlag        If not NULL, a pointer to a value that specifies
994fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               the new health status of the AP. This flag
995fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               corresponds to StatusFlag defined in
996fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
997fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               the PROCESSOR_HEALTH_STATUS_BIT is used. All other
998fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               bits are ignored.  If it is NULL, this parameter
999fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               is ignored.
1000fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1001fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_SUCCESS             The specified AP was enabled or disabled successfully.
1002fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_UNSUPPORTED         Enabling or disabling an AP cannot be completed
1003fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                                  prior to this service returning.
1004fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_UNSUPPORTED         Enabling or disabling an AP is not supported.
1005fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
1006fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_NOT_FOUND           Processor with the handle specified by ProcessorNumber
1007fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                                  does not exist.
1008fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP.
1009fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1010fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan**/
1011fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanEFI_STATUS
1012fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanEFIAPI
1013fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanEnableDisableAP (
1014fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  EFI_MP_SERVICES_PROTOCOL  *This,
1015fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  UINTN                     ProcessorNumber,
1016fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  BOOLEAN                   EnableAP,
1017fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  UINT32                    *HealthFlag OPTIONAL
1018fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  )
1019fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan{
1020fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  CPU_DATA_BLOCK *CpuData;
1021cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  BOOLEAN        TempStopCheckState;
1022cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
1023cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  CpuData = NULL;
1024cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  TempStopCheckState = FALSE;
1025fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1026fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (!IsBSP ()) {
1027fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    return EFI_DEVICE_ERROR;
1028fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1029fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1030fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
1031fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    return EFI_NOT_FOUND;
1032fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1033fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1034cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
1035cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  // temporarily stop checkAllAPsStatus for initialize parameters.
1036cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
1037cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  if (!mStopCheckAllAPsStatus) {
1038cd8c700b03e38e9389a8f13e193a431072802593Chen Fan    mStopCheckAllAPsStatus = TRUE;
1039cd8c700b03e38e9389a8f13e193a431072802593Chen Fan    TempStopCheckState = TRUE;
1040cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  }
1041cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
1042fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
1043fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
1044fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    return EFI_INVALID_PARAMETER;
1045fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1046fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1047fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (GetApState (CpuData) != CpuStateIdle) {
1048fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    return EFI_UNSUPPORTED;
1049fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1050fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1051fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (EnableAP) {
1052fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    if (!(TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT))) {
1053fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan      mMpSystemData.NumberOfEnabledProcessors++;
1054fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    }
1055fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    CpuStatusFlagOr (CpuData, PROCESSOR_ENABLED_BIT);
1056fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  } else {
1057fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    if (TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
1058fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan      mMpSystemData.NumberOfEnabledProcessors--;
1059fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    }
1060fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    CpuStatusFlagAndNot (CpuData, PROCESSOR_ENABLED_BIT);
1061fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1062fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1063fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (HealthFlag != NULL) {
1064fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    CpuStatusFlagAndNot (CpuData, (UINT32)~PROCESSOR_HEALTH_STATUS_BIT);
1065fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    CpuStatusFlagOr (CpuData, (*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT));
1066fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1067fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1068cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  if (TempStopCheckState) {
1069cd8c700b03e38e9389a8f13e193a431072802593Chen Fan    mStopCheckAllAPsStatus = FALSE;
1070cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  }
1071cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
1072fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  return EFI_SUCCESS;
1073fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan}
1074fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1075fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan/**
1076cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  This return the handle number for the calling processor.  This service may be
1077cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  called from the BSP and APs.
1078cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1079cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  This service returns the processor handle number for the calling processor.
1080cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  The returned value is in the range from 0 to the total number of logical
1081cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  processors minus 1. The total number of logical processors can be retrieved
1082cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  with EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be
1083cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
1084cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  is returned. Otherwise, the current processors handle number is returned in
1085cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  ProcessorNumber, and EFI_SUCCESS is returned.
1086cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1087cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  @param[in]  This             A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
1088cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  @param[out] ProcessorNumber  The handle number of AP that is to become the new
1089cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan                               BSP. The range is from 0 to the total number of
1090cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan                               logical processors minus 1. The total number of
1091cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan                               logical processors can be retrieved by
1092cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan                               EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
1093cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1094cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  @retval EFI_SUCCESS             The current processor handle number was returned
1095cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan                                  in ProcessorNumber.
1096cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  @retval EFI_INVALID_PARAMETER   ProcessorNumber is NULL.
1097cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1098cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan**/
1099cfa2fac1f667b227a29a2219321b651c7a143071Chen FanEFI_STATUS
1100cfa2fac1f667b227a29a2219321b651c7a143071Chen FanEFIAPI
1101cfa2fac1f667b227a29a2219321b651c7a143071Chen FanWhoAmI (
1102cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  IN EFI_MP_SERVICES_PROTOCOL  *This,
1103cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  OUT UINTN                    *ProcessorNumber
1104cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  )
1105cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan{
1106cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  UINTN   Index;
1107cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  UINT32  ProcessorId;
1108cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1109cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  if (ProcessorNumber == NULL) {
1110cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan    return EFI_INVALID_PARAMETER;
1111cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  }
1112cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1113cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  ProcessorId = GetApicId ();
1114cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  for (Index = 0; Index < mMpSystemData.NumberOfProcessors; Index++) {
1115cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan    if (mMpSystemData.CpuDatas[Index].Info.ProcessorId == ProcessorId) {
1116cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan      break;
1117cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan    }
1118cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  }
1119cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1120cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  *ProcessorNumber = Index;
1121cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  return EFI_SUCCESS;
1122cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan}
1123cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1124cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan/**
11253f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Terminate AP's task and set it to idle state.
11263f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
11273f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  This function terminates AP's task due to timeout by sending INIT-SIPI,
11283f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  and sends it to idle state.
11293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
11303f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param CpuData           the pointer to CPU_DATA_BLOCK of specified AP
11313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
11323f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
11333f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanVOID
11343f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanResetProcessorToIdleState (
11353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN CPU_DATA_BLOCK  *CpuData
11363f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
11373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
1138ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  ResetApStackless ((UINT32)CpuData->Info.ProcessorId);
11393f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
11403f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
11413f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
1142e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  Application Processors do loop routine
1143e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  after switch to its own stack.
1144e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan
1145e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  @param  Context1    A pointer to the context to pass into the function.
1146e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  @param  Context2    A pointer to the context to pass into the function.
1147e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan
1148e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan**/
1149e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen FanVOID
1150e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen FanProcessorToIdleState (
1151e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  IN      VOID                      *Context1,  OPTIONAL
1152e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  IN      VOID                      *Context2   OPTIONAL
1153e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  )
1154e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan{
11559908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  UINTN                 ProcessorNumber;
11569908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  CPU_DATA_BLOCK        *CpuData;
11579908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  EFI_AP_PROCEDURE      Procedure;
11589908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  VOID                  *ProcedureArgument;
11599908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan
1160232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan  AsmApDoneWithCommonStack ();
1161232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan
1162232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan  while (!mAPsAlreadyInitFinished) {
1163232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan    CpuPause ();
1164232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan  }
1165232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan
11669908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  WhoAmI (&mMpServicesTemplate, &ProcessorNumber);
11679908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
1168e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan
1169ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  //
11700e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  // Avoid forcibly reset AP caused the AP got lock not release.
11710e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  //
11720e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  if (CpuData->LockSelf == (INTN) GetApicId ()) {
11730e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan    ReleaseSpinLock (&CpuData->CpuDataLock);
11740e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  }
11750e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan
11760e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  //
1177ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  // Avoid forcibly reset AP caused the AP State is not updated.
1178ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  //
1179ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  GetMpSpinLock (CpuData);
1180ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  CpuData->State = CpuStateIdle;
1181ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  CpuData->Procedure = NULL;
1182ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  ReleaseMpSpinLock (CpuData);
1183ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan
11849908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  while (TRUE) {
1185d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan    GetMpSpinLock (CpuData);
11869908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan    ProcedureArgument = CpuData->Parameter;
11879908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan    Procedure = CpuData->Procedure;
1188d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan    ReleaseMpSpinLock (CpuData);
11899908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan
11909908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan    if (Procedure != NULL) {
11919908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan      Procedure (ProcedureArgument);
11929908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan
1193d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan      GetMpSpinLock (CpuData);
11949908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan      CpuData->Procedure = NULL;
1195d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan      CpuData->State = CpuStateFinished;
1196d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan      ReleaseMpSpinLock (CpuData);
11979908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan    }
11989908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan
11999908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan    CpuPause ();
12009908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  }
12019908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan
1202e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  CpuSleep ();
1203e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  CpuDeadLoop ();
1204e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan}
1205e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan
1206e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan/**
12073f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Checks AP' status periodically.
12083f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12093f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  This function is triggerred by timer perodically to check the
12103f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  state of AP forStartupThisAP() executed in non-blocking mode.
12113f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12123f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param  Event    Event triggered.
12133f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param  Context  Parameter passed with the event.
12143f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12153f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
12163f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanVOID
12173f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanEFIAPI
12183f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanCheckThisAPStatus (
12193f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  EFI_EVENT        Event,
12203f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  VOID             *Context
12213f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
12223f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
12233f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CPU_DATA_BLOCK  *CpuData;
12243f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CPU_STATE       CpuState;
12253f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12263f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData = (CPU_DATA_BLOCK *) Context;
12273f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (CpuData->TimeoutActive) {
12283f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    CpuData->Timeout -= gPollInterval;
12293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
12303f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuState = GetApState (CpuData);
12323f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12333f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (CpuState == CpuStateFinished) {
12343f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (CpuData->Finished) {
12353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      *CpuData->Finished = TRUE;
12363f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
12373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    SetApState (CpuData, CpuStateIdle);
12383f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    goto out;
12393f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
12403f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12413f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (CpuData->TimeoutActive && CpuData->Timeout < 0) {
12423f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (CpuState != CpuStateIdle &&
12433f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan        CpuData->Finished) {
12443f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      *CpuData->Finished = FALSE;
12453f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
12463f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    ResetProcessorToIdleState (CpuData);
12473f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    goto out;
12483f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
12493f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12503f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  return;
12513f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12523f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fanout:
1253acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  CpuData->TimeoutActive = FALSE;
1254acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  gBS->SignalEvent (CpuData->WaitEvent);
1255acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  CpuData->WaitEvent = NULL;
12563f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
12573f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12583f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
12595fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  Checks APs' status periodically.
12605fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
12615fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  This function is triggerred by timer perodically to check the
12625fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  state of APs for StartupAllAPs() executed in non-blocking mode.
12635fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
12645fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param  Event    Event triggered.
12655fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param  Context  Parameter passed with the event.
12665fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
12675fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan**/
12685fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanVOID
12695fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanEFIAPI
12705fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanCheckAllAPsStatus (
12715fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  EFI_EVENT        Event,
12725fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  VOID             *Context
12735fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  )
12745fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan{
1275acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  CPU_DATA_BLOCK *CpuData;
1276acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  UINTN          Number;
1277e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  EFI_STATUS     Status;
1278acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan
12795fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (mMpSystemData.TimeoutActive) {
12805fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    mMpSystemData.Timeout -= gPollInterval;
12815fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
12825fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
1283acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  if (mStopCheckAllAPsStatus) {
1284acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    return;
1285acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  }
12865fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
1287e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  //
1288e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  // avoid next timer enter.
1289e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  //
1290e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  Status = gBS->SetTimer (
1291e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  mMpSystemData.CheckAllAPsEvent,
1292e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  TimerCancel,
1293e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  0
1294e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  );
1295e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  ASSERT_EFI_ERROR (Status);
1296e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan
1297acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  if (mMpSystemData.WaitEvent != NULL) {
1298acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    CheckAndUpdateAllAPsToIdleState ();
12995fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
1300acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    // task timeout
13015fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
1302acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) {
1303acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      ResetAllFailedAPs();
1304acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      //
1305acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      // force exit
1306acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      //
1307acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      mMpSystemData.FinishCount = mMpSystemData.StartCount;
1308acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    }
13095fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
1310acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    if (mMpSystemData.FinishCount != mMpSystemData.StartCount) {
1311e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan      goto EXIT;
1312acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    }
13135fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
1314acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    mMpSystemData.TimeoutActive = FALSE;
13155fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    gBS->SignalEvent (mMpSystemData.WaitEvent);
13165fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    mMpSystemData.WaitEvent = NULL;
1317acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    mStopCheckAllAPsStatus = TRUE;
1318e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan
1319e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan    goto EXIT;
1320acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  }
1321acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan
1322acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  //
1323acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  // check each AP status for StartupThisAP
1324acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  //
1325acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
1326acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    CpuData = &mMpSystemData.CpuDatas[Number];
1327acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    if (CpuData->WaitEvent) {
1328acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      CheckThisAPStatus (NULL, (VOID *)CpuData);
1329acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    }
13305fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
1331e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan
1332e4aaf764281d12cb8bfe605393a5520e00715838Chen FanEXIT:
1333e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  Status = gBS->SetTimer (
1334e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  mMpSystemData.CheckAllAPsEvent,
1335e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  TimerPeriodic,
1336e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  EFI_TIMER_PERIOD_MICROSECONDS (100)
1337e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  );
1338e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  ASSERT_EFI_ERROR (Status);
13395fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan}
13405fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
13415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan/**
13421535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen  Application Processor C code entry point.
13431535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen
13441535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen**/
13451535c888c6f06bb35881e83cd7ee49fb8554942bJordan JustenVOID
13461535c888c6f06bb35881e83cd7ee49fb8554942bJordan JustenEFIAPI
13471535c888c6f06bb35881e83cd7ee49fb8554942bJordan JustenApEntryPointInC (
13481535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen  VOID
13491535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen  )
13501535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen{
1351ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  VOID*           TopOfApStack;
1352ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  UINTN           ProcessorNumber;
135303673ae11e255b9467e8f317175495b1ff79f965Chen Fan
1354ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  if (!mAPsAlreadyInitFinished) {
1355ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    FillInProcessorInformation (FALSE, mMpSystemData.NumberOfProcessors);
1356ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    TopOfApStack  = (UINT8*)mApStackStart + gApStackSize;
1357ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    mApStackStart = TopOfApStack;
135803673ae11e255b9467e8f317175495b1ff79f965Chen Fan
1359ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    //
1360ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    // Store the Stack address, when reset the AP, We can found the original address.
1361ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    //
1362ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    mMpSystemData.CpuDatas[mMpSystemData.NumberOfProcessors].TopOfStack = TopOfApStack;
1363ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    mMpSystemData.NumberOfProcessors++;
1364ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    mMpSystemData.NumberOfEnabledProcessors++;
1365ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  } else {
1366ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    WhoAmI (&mMpServicesTemplate, &ProcessorNumber);
1367ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    //
1368ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    // Get the original stack address.
1369ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    //
1370ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    TopOfApStack = mMpSystemData.CpuDatas[ProcessorNumber].TopOfStack;
1371ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  }
1372e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan
1373e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  SwitchStack (
1374e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan    (SWITCH_STACK_ENTRY_POINT)(UINTN)ProcessorToIdleState,
1375e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan    NULL,
1376e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan    NULL,
137703673ae11e255b9467e8f317175495b1ff79f965Chen Fan    TopOfApStack);
137803673ae11e255b9467e8f317175495b1ff79f965Chen Fan}
137903673ae11e255b9467e8f317175495b1ff79f965Chen Fan
138003673ae11e255b9467e8f317175495b1ff79f965Chen Fan/**
138103673ae11e255b9467e8f317175495b1ff79f965Chen Fan  This function is called by all processors (both BSP and AP) once and collects MP related data.
138203673ae11e255b9467e8f317175495b1ff79f965Chen Fan
138303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  @param Bsp             TRUE if the CPU is BSP
138403673ae11e255b9467e8f317175495b1ff79f965Chen Fan  @param ProcessorNumber The specific processor number
138503673ae11e255b9467e8f317175495b1ff79f965Chen Fan
138603673ae11e255b9467e8f317175495b1ff79f965Chen Fan  @retval EFI_SUCCESS    Data for the processor collected and filled in
138703673ae11e255b9467e8f317175495b1ff79f965Chen Fan
138803673ae11e255b9467e8f317175495b1ff79f965Chen Fan**/
138903673ae11e255b9467e8f317175495b1ff79f965Chen FanEFI_STATUS
139003673ae11e255b9467e8f317175495b1ff79f965Chen FanFillInProcessorInformation (
139103673ae11e255b9467e8f317175495b1ff79f965Chen Fan  IN     BOOLEAN              Bsp,
139203673ae11e255b9467e8f317175495b1ff79f965Chen Fan  IN     UINTN                ProcessorNumber
139303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  )
139403673ae11e255b9467e8f317175495b1ff79f965Chen Fan{
139503673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CPU_DATA_BLOCK  *CpuData;
139603673ae11e255b9467e8f317175495b1ff79f965Chen Fan  UINT32          ProcessorId;
139703673ae11e255b9467e8f317175495b1ff79f965Chen Fan
139803673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
139903673ae11e255b9467e8f317175495b1ff79f965Chen Fan  ProcessorId  = GetApicId ();
140003673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Info.ProcessorId  = ProcessorId;
140103673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Info.StatusFlag   = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;
140203673ae11e255b9467e8f317175495b1ff79f965Chen Fan  if (Bsp) {
140303673ae11e255b9467e8f317175495b1ff79f965Chen Fan    CpuData->Info.StatusFlag |= PROCESSOR_AS_BSP_BIT;
140403673ae11e255b9467e8f317175495b1ff79f965Chen Fan  }
140503673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Info.Location.Package = ProcessorId;
140603673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Info.Location.Core    = 0;
140703673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Info.Location.Thread  = 0;
140803673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->State = Bsp ? CpuStateBuzy : CpuStateIdle;
140903673ae11e255b9467e8f317175495b1ff79f965Chen Fan
141003673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Procedure        = NULL;
141103673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Parameter        = NULL;
141203673ae11e255b9467e8f317175495b1ff79f965Chen Fan  InitializeSpinLock (&CpuData->CpuDataLock);
14130e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  CpuData->LockSelf         = -1;
141403673ae11e255b9467e8f317175495b1ff79f965Chen Fan
141503673ae11e255b9467e8f317175495b1ff79f965Chen Fan  return EFI_SUCCESS;
14161535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen}
14171535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen
141803673ae11e255b9467e8f317175495b1ff79f965Chen Fan/**
141903673ae11e255b9467e8f317175495b1ff79f965Chen Fan  Prepare the System Data.
142003673ae11e255b9467e8f317175495b1ff79f965Chen Fan
142103673ae11e255b9467e8f317175495b1ff79f965Chen Fan  @retval EFI_SUCCESS     the System Data finished initilization.
142203673ae11e255b9467e8f317175495b1ff79f965Chen Fan
142303673ae11e255b9467e8f317175495b1ff79f965Chen Fan**/
142403673ae11e255b9467e8f317175495b1ff79f965Chen FanEFI_STATUS
142503673ae11e255b9467e8f317175495b1ff79f965Chen FanInitMpSystemData (
142603673ae11e255b9467e8f317175495b1ff79f965Chen Fan  VOID
142703673ae11e255b9467e8f317175495b1ff79f965Chen Fan  )
142803673ae11e255b9467e8f317175495b1ff79f965Chen Fan{
14293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  EFI_STATUS     Status;
14303f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
143103673ae11e255b9467e8f317175495b1ff79f965Chen Fan  ZeroMem (&mMpSystemData, sizeof (MP_SYSTEM_DATA));
143203673ae11e255b9467e8f317175495b1ff79f965Chen Fan
143303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  mMpSystemData.NumberOfProcessors = 1;
143403673ae11e255b9467e8f317175495b1ff79f965Chen Fan  mMpSystemData.NumberOfEnabledProcessors = 1;
143503673ae11e255b9467e8f317175495b1ff79f965Chen Fan
143603673ae11e255b9467e8f317175495b1ff79f965Chen Fan  mMpSystemData.CpuDatas = AllocateZeroPool (sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber);
143703673ae11e255b9467e8f317175495b1ff79f965Chen Fan  ASSERT(mMpSystemData.CpuDatas != NULL);
143803673ae11e255b9467e8f317175495b1ff79f965Chen Fan
14395fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  Status = gBS->CreateEvent (
14405fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
14415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  TPL_CALLBACK,
14425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  CheckAllAPsStatus,
14435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  NULL,
14445fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  &mMpSystemData.CheckAllAPsEvent
14455fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  );
14465fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  ASSERT_EFI_ERROR (Status);
14475fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
1448acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  //
1449acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  // Set timer to check all APs status.
1450acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  //
1451acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  Status = gBS->SetTimer (
1452acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan                  mMpSystemData.CheckAllAPsEvent,
1453acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan                  TimerPeriodic,
1454acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan                  EFI_TIMER_PERIOD_MICROSECONDS (100)
1455acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan                  );
1456acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  ASSERT_EFI_ERROR (Status);
14573f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
145803673ae11e255b9467e8f317175495b1ff79f965Chen Fan  //
145903673ae11e255b9467e8f317175495b1ff79f965Chen Fan  // BSP
146003673ae11e255b9467e8f317175495b1ff79f965Chen Fan  //
146103673ae11e255b9467e8f317175495b1ff79f965Chen Fan  FillInProcessorInformation (TRUE, 0);
146203673ae11e255b9467e8f317175495b1ff79f965Chen Fan
146303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  return EFI_SUCCESS;
146403673ae11e255b9467e8f317175495b1ff79f965Chen Fan}
14651535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen
14661535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen/**
14676022e28cf744a885c278dad256d50670741ea123Jordan Justen  Initialize Multi-processor support.
14686022e28cf744a885c278dad256d50670741ea123Jordan Justen
14696022e28cf744a885c278dad256d50670741ea123Jordan Justen**/
14706022e28cf744a885c278dad256d50670741ea123Jordan JustenVOID
14716022e28cf744a885c278dad256d50670741ea123Jordan JustenInitializeMpSupport (
14726022e28cf744a885c278dad256d50670741ea123Jordan Justen  VOID
14736022e28cf744a885c278dad256d50670741ea123Jordan Justen  )
14746022e28cf744a885c278dad256d50670741ea123Jordan Justen{
14756a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  gMaxLogicalProcessorNumber = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
14766a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  if (gMaxLogicalProcessorNumber < 1) {
14776a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan    DEBUG ((DEBUG_ERROR, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n"));
14786a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan    return;
14796a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  }
14806a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
14816a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  if (gMaxLogicalProcessorNumber == 1) {
14826a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan    return;
14836a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  }
14846a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
14856a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  gApStackSize = (UINTN) PcdGet32 (PcdCpuApStackSize);
14866a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  ASSERT ((gApStackSize & (SIZE_4KB - 1)) == 0);
14876a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
14886a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  mApStackStart = AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));
14896a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  ASSERT (mApStackStart != NULL);
14906022e28cf744a885c278dad256d50670741ea123Jordan Justen
14916a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  //
14926a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  // the first buffer of stack size used for common stack, when the amount of AP
14936a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  // more than 1, we should never free the common stack which maybe used for AP reset.
14946a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  //
14956a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  mCommonStack = mApStackStart;
14966a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  mTopOfApCommonStack = (UINT8*) mApStackStart + gApStackSize;
14976a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  mApStackStart = mTopOfApCommonStack;
14986a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
149903673ae11e255b9467e8f317175495b1ff79f965Chen Fan  InitMpSystemData ();
15006a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
1501fe078dd57f5e935c28eac7348b758ca6fb5e696fChen Fan  PrepareAPStartupCode ();
1502fe078dd57f5e935c28eac7348b758ca6fb5e696fChen Fan
150303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  if (mMpSystemData.NumberOfProcessors == 1) {
1504fe078dd57f5e935c28eac7348b758ca6fb5e696fChen Fan    FreeApStartupCode ();
15056a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan    FreePages (mCommonStack, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));
15066a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan    return;
15076a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  }
15086a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
1509232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan  mMpSystemData.CpuDatas = ReallocatePool (
1510232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan                             sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber,
1511232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan                             sizeof (CPU_DATA_BLOCK) * mMpSystemData.NumberOfProcessors,
1512232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan                             mMpSystemData.CpuDatas);
1513232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan
1514ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  mAPsAlreadyInitFinished = TRUE;
1515ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan
151603673ae11e255b9467e8f317175495b1ff79f965Chen Fan  if (mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) {
151703673ae11e255b9467e8f317175495b1ff79f965Chen Fan    FreePages (mApStackStart, EFI_SIZE_TO_PAGES (
151803673ae11e255b9467e8f317175495b1ff79f965Chen Fan                                (gMaxLogicalProcessorNumber - mMpSystemData.NumberOfProcessors) *
151903673ae11e255b9467e8f317175495b1ff79f965Chen Fan                                gApStackSize));
15206a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  }
15216a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan}
1522