CpuMp.c revision 9840b1299de78458a42d35b8d1d6cbadd1f6da72
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;
239840b1299de78458a42d35b8d1d6cbadd1f6da72Chen FanEFI_HANDLE     mMpServiceHandle       = NULL;
249840b1299de78458a42d35b8d1d6cbadd1f6da72Chen FanEFI_EVENT      mExitBootServicesEvent = (EFI_EVENT)NULL;
2503673ae11e255b9467e8f317175495b1ff79f965Chen Fan
26fab82c1873b792bce33fb22c32db71324fc0ac3bJordan JustenVOID *mCommonStack = 0;
27fab82c1873b792bce33fb22c32db71324fc0ac3bJordan JustenVOID *mTopOfApCommonStack = 0;
286a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen FanVOID *mApStackStart = 0;
29fab82c1873b792bce33fb22c32db71324fc0ac3bJordan Justen
30232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fanvolatile BOOLEAN mAPsAlreadyInitFinished = FALSE;
31acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fanvolatile BOOLEAN mStopCheckAllAPsStatus = TRUE;
32acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan
33003973d98cf1ef84ab810cb4f3870acd3a7f40a6Chen FanEFI_MP_SERVICES_PROTOCOL  mMpServicesTemplate = {
34d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  GetNumberOfProcessors,
35e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  GetProcessorInfo,
365fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  StartupAllAPs,
373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  StartupThisAP,
38b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  SwitchBSP,
39fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  EnableDisableAP,
40cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  WhoAmI
41003973d98cf1ef84ab810cb4f3870acd3a7f40a6Chen Fan};
42003973d98cf1ef84ab810cb4f3870acd3a7f40a6Chen Fan
436022e28cf744a885c278dad256d50670741ea123Jordan Justen/**
44d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan   Get Mp Service Lock.
45d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
46d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  @param   CpuData    the pointer to CPU_DATA_BLOCK of specified processor
47d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
48d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan**/
49d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen FanVOID
50d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen FanGetMpSpinLock (
51d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  IN  CPU_DATA_BLOCK  *CpuData
52d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  )
53d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan{
54d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) {
55d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan    CpuPause ();
56d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  }
570e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  CpuData->LockSelf = GetApicId ();
58d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan}
59d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
60d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan/**
61d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan   Release Mp Service Lock.
62d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
63d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  @param   CpuData    the pointer to CPU_DATA_BLOCK of specified processor
64d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
65d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan**/
66d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen FanVOID
67d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen FanReleaseMpSpinLock (
68d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  IN  CPU_DATA_BLOCK  *CpuData
69d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  )
70d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan{
71d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseSpinLock (&CpuData->CpuDataLock);
72d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan}
73d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan
74d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan/**
75d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  Check whether caller processor is BSP.
76d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
77d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval  TRUE       the caller is BSP
78d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval  FALSE      the caller is AP
79d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
80d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan**/
81d894d8b704324da8ed902677703ed9d4f7c85076Chen FanBOOLEAN
82d894d8b704324da8ed902677703ed9d4f7c85076Chen FanIsBSP (
83d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  VOID
84d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  )
85d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan{
86d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  UINTN           CpuIndex;
87d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  CPU_DATA_BLOCK  *CpuData;
88d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
89d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  CpuData = NULL;
90d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
91d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  WhoAmI (&mMpServicesTemplate, &CpuIndex);
92d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  CpuData = &mMpSystemData.CpuDatas[CpuIndex];
93d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
94d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  return CpuData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT ? TRUE : FALSE;
95d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan}
96d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
97d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan/**
98fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  Get the Application Processors state.
99fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
100fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param   CpuData    the pointer to CPU_DATA_BLOCK of specified AP
101fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
102fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval  CPU_STATE  the AP status
103fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
104fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan**/
105fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanCPU_STATE
106fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanGetApState (
107fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  CPU_DATA_BLOCK  *CpuData
108fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  )
109fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan{
110fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  CPU_STATE State;
111fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
112d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
113fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  State = CpuData->State;
114d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
115fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
116fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  return State;
117fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan}
118fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
119fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan/**
1203f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Set the Application Processors state.
1213f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1223f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param   CpuData    The pointer to CPU_DATA_BLOCK of specified AP
1233f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param   State      The AP status
1243f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1253f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
1263f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanVOID
1273f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanSetApState (
1283f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  CPU_DATA_BLOCK   *CpuData,
1293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  CPU_STATE        State
1303f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
1313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
132d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
1333f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->State = State;
134d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
1353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
1363f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
1383f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Set the Application Processor prepare to run a function specified
1393f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  by Params.
1403f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1413f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param CpuData           the pointer to CPU_DATA_BLOCK of specified AP
1423f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param Procedure         A pointer to the function to be run on enabled APs of the system
1433f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param ProcedureArgument Pointer to the optional parameter of the assigned function
1443f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1453f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
1463f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanVOID
1473f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanSetApProcedure (
1483f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN   CPU_DATA_BLOCK        *CpuData,
1493f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN   EFI_AP_PROCEDURE      Procedure,
1503f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN   VOID                  *ProcedureArgument
1513f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
1523f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
153d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
1543f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->Parameter  = ProcedureArgument;
1553f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->Procedure  = Procedure;
156d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
1573f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
1583f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
1593f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
160fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  Check the Application Processors Status whether contains the Flags.
161fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
162fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     CpuData  the pointer to CPU_DATA_BLOCK of specified AP
163fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     Flags    the StatusFlag describing in EFI_PROCESSOR_INFORMATION
164fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
165fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval    TRUE     the AP status includes the StatusFlag
166fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval    FALSE    the AP status excludes the StatusFlag
167fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
168fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan**/
169fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanBOOLEAN
170fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanTestCpuStatusFlag (
171fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  CPU_DATA_BLOCK  *CpuData,
172fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  UINT32          Flags
173fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  )
174fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan{
175fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  UINT32 Ret;
176fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
177d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
178fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  Ret = CpuData->Info.StatusFlag & Flags;
179d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
180fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
181fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  return !!(Ret);
182fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan}
183fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
184fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan/**
185fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  Bitwise-Or of the Application Processors Status with the Flags.
186fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
187fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     CpuData  the pointer to CPU_DATA_BLOCK of specified AP
188fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     Flags    the StatusFlag describing in EFI_PROCESSOR_INFORMATION
189fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
190fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan**/
191fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanVOID
192fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanCpuStatusFlagOr (
193fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  CPU_DATA_BLOCK  *CpuData,
194fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  UINT32          Flags
195fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  )
196fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan{
197d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
198fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  CpuData->Info.StatusFlag |= Flags;
199d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
200fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan}
201fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
202fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan/**
203fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  Bitwise-AndNot of the Application Processors Status with the Flags.
204fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
205fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     CpuData  the pointer to CPU_DATA_BLOCK of specified AP
206fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param     Flags    the StatusFlag describing in EFI_PROCESSOR_INFORMATION
207fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
208fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan**/
209fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanVOID
210fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanCpuStatusFlagAndNot (
211fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  CPU_DATA_BLOCK  *CpuData,
212fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  UINT32          Flags
213fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  )
214fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan{
215d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  GetMpSpinLock (CpuData);
216fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  CpuData->Info.StatusFlag &= ~Flags;
217d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan  ReleaseMpSpinLock (CpuData);
218fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan}
219fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
220fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan/**
2213f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Searches for the next blocking AP.
2223f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2233f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Search for the next AP that is put in blocking state by single-threaded StartupAllAPs().
2243f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2253f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param  NextNumber           Pointer to the processor number of the next blocking AP.
2263f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2273f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_SUCCESS          The next blocking AP has been found.
2283f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_NOT_FOUND        No blocking AP exists.
2293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2303f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
2313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanEFI_STATUS
2323f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanGetNextBlockedNumber (
2333f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  OUT UINTN  *NextNumber
2343f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
2353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
2363f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  UINTN                 Number;
2373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CPU_STATE             CpuState;
2383f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CPU_DATA_BLOCK        *CpuData;
2393f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2403f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
2413f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    CpuData = &mMpSystemData.CpuDatas[Number];
2423f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
2433f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      //
2443f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      // Skip BSP
2453f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      //
2463f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      continue;
2473f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
2483f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2493f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    CpuState = GetApState (CpuData);
2503f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (CpuState == CpuStateBlocked) {
2513f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      *NextNumber = Number;
2523f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      return EFI_SUCCESS;
2533f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
2543f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
2553f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2563f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  return EFI_NOT_FOUND;
2573f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
2583f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
2593f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
2605fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  Check if the APs state are finished, and update them to idle state
2615fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  by StartupAllAPs().
2625fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
2635fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan**/
2645fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanVOID
2655fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanCheckAndUpdateAllAPsToIdleState (
2665fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  VOID
2675fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  )
2685fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan{
2695fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  UINTN                 ProcessorNumber;
2705fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  UINTN                 NextNumber;
2715fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_DATA_BLOCK        *CpuData;
2725fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  EFI_STATUS            Status;
2735fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_STATE             CpuState;
2745fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
2755fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {
2765fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
2775fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
2785fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
2795fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip BSP
2805fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
2815fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
2825fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
2835fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
2845fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
2855fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
2865fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip Disabled processors
2875fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
2885fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
2895fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
2905fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
2915fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuState = GetApState (CpuData);
2925fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (CpuState == CpuStateFinished) {
2935fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      mMpSystemData.FinishCount++;
2945fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      if (mMpSystemData.SingleThread) {
2955fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        Status = GetNextBlockedNumber (&NextNumber);
2965fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        if (!EFI_ERROR (Status)) {
2975fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan          SetApState (&mMpSystemData.CpuDatas[NextNumber], CpuStateReady);
2985fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan          SetApProcedure (&mMpSystemData.CpuDatas[NextNumber],
2995fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                          mMpSystemData.Procedure,
3005fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                          mMpSystemData.ProcedureArgument);
3015fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        }
3025fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      }
3035fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3045fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      SetApState (CpuData, CpuStateIdle);
3055fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
3065fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
3075fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan}
3085fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3095fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan/**
3105fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  If the timeout expires before all APs returns from Procedure,
3115fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  we should forcibly terminate the executing AP and fill FailedList back
3125fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  by StartupAllAPs().
3135fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3145fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan**/
3155fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanVOID
3165fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanResetAllFailedAPs (
3175fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  VOID
3185fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  )
3195fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan{
3205fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_DATA_BLOCK        *CpuData;
3215fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  UINTN                 Number;
3225fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_STATE             CpuState;
3235fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3245fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (mMpSystemData.FailedList != NULL) {
3255fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan     *mMpSystemData.FailedList = AllocatePool ((mMpSystemData.StartCount - mMpSystemData.FinishCount + 1) * sizeof(UINTN));
3265fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan     ASSERT (*mMpSystemData.FailedList != NULL);
3275fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
3285fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3295fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
3305fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuData = &mMpSystemData.CpuDatas[Number];
3315fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (TestCpuStatusFlag (CpuData,  PROCESSOR_AS_BSP_BIT)) {
3325fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
3335fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip BSP
3345fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
3355fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
3365fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
3375fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3385fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
3395fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
3405fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip Disabled processors
3415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
3425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
3435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
3445fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3455fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuState = GetApState (CpuData);
3465fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (CpuState != CpuStateIdle) {
3475fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      if (mMpSystemData.FailedList != NULL) {
3485fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex++] = Number;
3495fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      }
3505fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      ResetProcessorToIdleState (CpuData);
3515fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
3525fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
3535fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3545fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (mMpSystemData.FailedList != NULL) {
3555fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex] = END_OF_CPU_LIST;
3565fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
3575fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan}
3585fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
3595fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan/**
360d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  This service retrieves the number of logical processor in the platform
361d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  and the number of those logical processors that are enabled on this boot.
362d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  This service may only be called from the BSP.
363d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
364d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  This function is used to retrieve the following information:
365d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan    - The number of logical processors that are present in the system.
366d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan    - The number of enabled logical processors in the system at the instant
367d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan      this call is made.
368d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
369d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  Because MP Service Protocol provides services to enable and disable processors
370d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  dynamically, the number of enabled logical processors may vary during the
371d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  course of a boot session.
372d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
373d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
374d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
375d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
376d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  is returned in NumberOfProcessors, the number of currently enabled processor
377d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
378d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
379d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @param[in]  This                        A pointer to the EFI_MP_SERVICES_PROTOCOL
380d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                          instance.
381d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @param[out] NumberOfProcessors          Pointer to the total number of logical
382d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                          processors in the system, including the BSP
383d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                          and disabled APs.
384d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @param[out] NumberOfEnabledProcessors   Pointer to the number of enabled logical
385d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                          processors that exist in system, including
386d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                          the BSP.
387d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
388d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval EFI_SUCCESS             The number of logical processors and enabled
389d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan                                  logical processors was retrieved.
390d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
391d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval EFI_INVALID_PARAMETER   NumberOfProcessors is NULL.
392d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  @retval EFI_INVALID_PARAMETER   NumberOfEnabledProcessors is NULL.
393d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
394d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan**/
395d894d8b704324da8ed902677703ed9d4f7c85076Chen FanEFI_STATUS
396d894d8b704324da8ed902677703ed9d4f7c85076Chen FanEFIAPI
397d894d8b704324da8ed902677703ed9d4f7c85076Chen FanGetNumberOfProcessors (
398d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  IN  EFI_MP_SERVICES_PROTOCOL  *This,
399d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  OUT UINTN                     *NumberOfProcessors,
400d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  OUT UINTN                     *NumberOfEnabledProcessors
401d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  )
402d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan{
403d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  if ((NumberOfProcessors == NULL) || (NumberOfEnabledProcessors == NULL)) {
404d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan    return EFI_INVALID_PARAMETER;
405d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  }
406d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
407d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  if (!IsBSP ()) {
408d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan    return EFI_DEVICE_ERROR;
409d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  }
410d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
411d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  *NumberOfProcessors        = mMpSystemData.NumberOfProcessors;
412d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  *NumberOfEnabledProcessors = mMpSystemData.NumberOfEnabledProcessors;
413d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan  return EFI_SUCCESS;
414d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan}
415d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan
416d894d8b704324da8ed902677703ed9d4f7c85076Chen Fan/**
417e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  Gets detailed MP-related information on the requested processor at the
418e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  instant this call is made. This service may only be called from the BSP.
419e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
420e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  This service retrieves detailed MP-related information about any processor
421e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  on the platform. Note the following:
422e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan    - The processor information may change during the course of a boot session.
423e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan    - The information presented here is entirely MP related.
424e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
425e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  Information regarding the number of caches and their sizes, frequency of operation,
426e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  slot numbers is all considered platform-related information and is not provided
427e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  by this service.
428e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
429e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @param[in]  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL
430e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan                                    instance.
431e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @param[in]  ProcessorNumber       The handle number of processor.
432e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @param[out] ProcessorInfoBuffer   A pointer to the buffer where information for
433e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan                                    the requested processor is deposited.
434e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
435e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @retval EFI_SUCCESS             Processor information was returned.
436e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
437e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @retval EFI_INVALID_PARAMETER   ProcessorInfoBuffer is NULL.
438e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  @retval EFI_NOT_FOUND           The processor with the handle specified by
439e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan                                  ProcessorNumber does not exist in the platform.
440e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
441e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan**/
442e7938b5a869fc42df7f026752f39ea85090eb3f9Chen FanEFI_STATUS
443e7938b5a869fc42df7f026752f39ea85090eb3f9Chen FanEFIAPI
444e7938b5a869fc42df7f026752f39ea85090eb3f9Chen FanGetProcessorInfo (
445e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  IN  EFI_MP_SERVICES_PROTOCOL   *This,
446e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  IN  UINTN                      ProcessorNumber,
447e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  OUT EFI_PROCESSOR_INFORMATION  *ProcessorInfoBuffer
448e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  )
449e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan{
450e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  if (ProcessorInfoBuffer == NULL) {
451e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan    return EFI_INVALID_PARAMETER;
452e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  }
453e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
454e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  if (!IsBSP ()) {
455e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan    return EFI_DEVICE_ERROR;
456e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  }
457e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
458e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
459e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan    return EFI_NOT_FOUND;
460e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  }
461e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
462e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  CopyMem (ProcessorInfoBuffer, &mMpSystemData.CpuDatas[ProcessorNumber], sizeof (EFI_PROCESSOR_INFORMATION));
463e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan  return EFI_SUCCESS;
464e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan}
465e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan
466e7938b5a869fc42df7f026752f39ea85090eb3f9Chen Fan/**
4675fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  This service executes a caller provided function on all enabled APs. APs can
4685fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  run either simultaneously or one at a time in sequence. This service supports
4695fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  both blocking and non-blocking requests. The non-blocking requests use EFI
4705fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  events so the BSP can detect when the APs have finished. This service may only
4715fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  be called from the BSP.
4725fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
4735fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  This function is used to dispatch all the enabled APs to the function specified
4745fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  by Procedure.  If any enabled AP is busy, then EFI_NOT_READY is returned
4755fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  immediately and Procedure is not started on any AP.
4765fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
4775fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  If SingleThread is TRUE, all the enabled APs execute the function specified by
4785fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  Procedure one by one, in ascending order of processor handle number. Otherwise,
4795fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  all the enabled APs execute the function specified by Procedure simultaneously.
4805fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
4815fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  If WaitEvent is NULL, execution is in blocking mode. The BSP waits until all
4825fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  APs finish or TimeoutInMicroseconds expires. Otherwise, execution is in non-blocking
4835fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mode, and the BSP returns from this service without waiting for APs. If a
4845fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  non-blocking mode is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
4855fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  is signaled, then EFI_UNSUPPORTED must be returned.
4865fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
4875fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  If the timeout specified by TimeoutInMicroseconds expires before all APs return
4885fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  from Procedure, then Procedure on the failed APs is terminated. All enabled APs
4895fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  are always available for further calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
4905fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  and EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). If FailedCpuList is not NULL, its
4915fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  content points to the list of processor handle numbers in which Procedure was
4925fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  terminated.
4935fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
4945fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  Note: It is the responsibility of the consumer of the EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
4955fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  to make sure that the nature of the code that is executed on the BSP and the
4965fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  dispatched APs is well controlled. The MP Services Protocol does not guarantee
4975fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  that the Procedure function is MP-safe. Hence, the tasks that can be run in
4985fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  parallel are limited to certain independent tasks and well-controlled exclusive
4995fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  code. EFI services and protocols may not be called by APs unless otherwise
5005fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  specified.
5015fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5025fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  In blocking execution mode, BSP waits until all APs finish or
5035fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  TimeoutInMicroseconds expires.
5045fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5055fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  In non-blocking execution mode, BSP is freed to return to the caller and then
5065fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  proceed to the next task without having to wait for APs. The following
5075fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  sequence needs to occur in a non-blocking execution mode:
5085fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5095fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    -# The caller that intends to use this MP Services Protocol in non-blocking
5105fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       mode creates WaitEvent by calling the EFI CreateEvent() service.  The caller
5115fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       invokes EFI_MP_SERVICES_PROTOCOL.StartupAllAPs(). If the parameter WaitEvent
5125fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       is not NULL, then StartupAllAPs() executes in non-blocking mode. It requests
5135fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       the function specified by Procedure to be started on all the enabled APs,
5145fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       and releases the BSP to continue with other tasks.
5155fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    -# The caller can use the CheckEvent() and WaitForEvent() services to check
5165fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       the state of the WaitEvent created in step 1.
5175fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    -# When the APs complete their task or TimeoutInMicroSecondss expires, the MP
5185fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       Service signals WaitEvent by calling the EFI SignalEvent() function. If
5195fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       FailedCpuList is not NULL, its content is available when WaitEvent is
5205fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       signaled. If all APs returned from Procedure prior to the timeout, then
5215fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       FailedCpuList is set to NULL. If not all APs return from Procedure before
5225fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       the timeout, then FailedCpuList is filled in with the list of the failed
5235fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       APs. The buffer is allocated by MP Service Protocol using AllocatePool().
5245fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       It is the caller's responsibility to free the buffer with FreePool() service.
5255fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    -# This invocation of SignalEvent() function informs the caller that invoked
5265fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() that either all the APs completed
5275fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       the specified task or a timeout occurred. The contents of FailedCpuList
5285fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       can be examined to determine which APs did not complete the specified task
5295fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan       prior to the timeout.
5305fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5315fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  This                    A pointer to the EFI_MP_SERVICES_PROTOCOL
5325fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      instance.
5335fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  Procedure               A pointer to the function to be run on
5345fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      enabled APs of the system. See type
5355fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      EFI_AP_PROCEDURE.
5365fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  SingleThread            If TRUE, then all the enabled APs execute
5375fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      the function specified by Procedure one by
5385fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      one, in ascending order of processor handle
5395fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      number.  If FALSE, then all the enabled APs
5405fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      execute the function specified by Procedure
5415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      simultaneously.
5425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  WaitEvent               The event created by the caller with CreateEvent()
5435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      service.  If it is NULL, then execute in
5445fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      blocking mode. BSP waits until all APs finish
5455fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      or TimeoutInMicroseconds expires.  If it's
5465fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      not NULL, then execute in non-blocking mode.
5475fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      BSP requests the function specified by
5485fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      Procedure to be started on all the enabled
5495fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      APs, and go on executing immediately. If
5505fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      all return from Procedure, or TimeoutInMicroseconds
5515fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      expires, this event is signaled. The BSP
5525fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      can use the CheckEvent() or WaitForEvent()
5535fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      services to check the state of event.  Type
5545fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      EFI_EVENT is defined in CreateEvent() in
5555fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      the Unified Extensible Firmware Interface
5565fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      Specification.
5575fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
5585fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      APs to return from Procedure, either for
5595fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      blocking or non-blocking mode. Zero means
5605fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      infinity.  If the timeout expires before
5615fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      all APs return from Procedure, then Procedure
5625fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      on the failed APs is terminated. All enabled
5635fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      APs are available for next function assigned
5645fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
5655fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
5665fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      If the timeout expires in blocking mode,
5675fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      BSP returns EFI_TIMEOUT.  If the timeout
5685fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      expires in non-blocking mode, WaitEvent
5695fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      is signaled with SignalEvent().
5705fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[in]  ProcedureArgument       The parameter passed into Procedure for
5715fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      all APs.
5725fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param[out] FailedCpuList           If NULL, this parameter is ignored. Otherwise,
5735fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      if all APs finish successfully, then its
5745fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      content is set to NULL. If not all APs
5755fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      finish before timeout expires, then its
5765fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      content is set to address of the buffer
5775fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      holding handle numbers of the failed APs.
5785fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      The buffer is allocated by MP Service Protocol,
5795fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      and it's the caller's responsibility to
5805fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      free the buffer with FreePool() service.
5815fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      In blocking mode, it is ready for consumption
5825fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      when the call returns. In non-blocking mode,
5835fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      it is ready when WaitEvent is signaled.  The
5845fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      list of failed CPU is terminated by
5855fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                      END_OF_CPU_LIST.
5865fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
5875fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_SUCCESS             In blocking mode, all APs have finished before
5885fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                  the timeout expired.
5895fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_SUCCESS             In non-blocking mode, function has been dispatched
5905fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                  to all enabled APs.
5915fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_UNSUPPORTED         A non-blocking mode request was made after the
5925fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                  UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
5935fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                  signaled.
5945fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_DEVICE_ERROR        Caller processor is AP.
5955fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_NOT_STARTED         No enabled APs exist in the system.
5965fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_NOT_READY           Any enabled APs are busy.
5975fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_TIMEOUT             In blocking mode, the timeout expired before
5985fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                                  all enabled APs have finished.
5995fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @retval EFI_INVALID_PARAMETER   Procedure is NULL.
6005fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6015fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan**/
6025fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanEFI_STATUS
6035fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanEFIAPI
6045fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanStartupAllAPs (
6055fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  EFI_MP_SERVICES_PROTOCOL  *This,
6065fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  EFI_AP_PROCEDURE          Procedure,
6075fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  BOOLEAN                   SingleThread,
6085fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  EFI_EVENT                 WaitEvent               OPTIONAL,
6095fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  UINTN                     TimeoutInMicroseconds,
6105fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  VOID                      *ProcedureArgument      OPTIONAL,
6115fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  OUT UINTN                     **FailedCpuList         OPTIONAL
6125fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  )
6135fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan{
6145fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  EFI_STATUS            Status;
6155fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_DATA_BLOCK        *CpuData;
6165fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  UINTN                 Number;
6175fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CPU_STATE             APInitialState;
6185fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6195fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  CpuData = NULL;
6205fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6215fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (FailedCpuList != NULL) {
6225fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    *FailedCpuList = NULL;
6235fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
6245fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6255fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (!IsBSP ()) {
6265fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    return EFI_DEVICE_ERROR;
6275fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
6285fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6295fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (mMpSystemData.NumberOfProcessors == 1) {
6305fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    return EFI_NOT_STARTED;
6315fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
6325fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6335fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (Procedure == NULL) {
6345fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    return EFI_INVALID_PARAMETER;
6355fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
6365fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
637cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
638cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  // temporarily stop checkAllAPsStatus for avoid resource dead-lock.
639cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
640cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  mStopCheckAllAPsStatus = TRUE;
641cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
6425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
6435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuData = &mMpSystemData.CpuDatas[Number];
6445fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
6455fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6465fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip BSP
6475fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6485fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
6495fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
6505fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6515fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
6525fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6535fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip Disabled processors
6545fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6555fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
6565fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
6575fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6585fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (GetApState (CpuData) != CpuStateIdle) {
6595fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      return EFI_NOT_READY;
6605fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
6615fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
6625fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6635fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.Procedure         = Procedure;
6645fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.ProcedureArgument = ProcedureArgument;
6655fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.WaitEvent         = WaitEvent;
6665fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.Timeout           = TimeoutInMicroseconds;
6675fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.TimeoutActive     = !!(TimeoutInMicroseconds);
6685fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.FinishCount       = 0;
6695fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.StartCount        = 0;
6705fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.SingleThread      = SingleThread;
6715fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.FailedList        = FailedCpuList;
6725fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  mMpSystemData.FailedListIndex   = 0;
6735fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  APInitialState                  = CpuStateReady;
6745fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6755fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
6765fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CpuData = &mMpSystemData.CpuDatas[Number];
6775fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
6785fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6795fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip BSP
6805fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6815fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
6825fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
6835fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6845fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
6855fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6865fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      // Skip Disabled processors
6875fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      //
6885fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      continue;
6895fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
6905fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
6915fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
6925fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    // Get APs prepared, and put failing APs into FailedCpuList
6935fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    // if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready
6945fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    // state 1 by 1, until the previous 1 finished its task
6955fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    // if not "SingleThread", all APs are put to ready state from the beginning
6965fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
6975fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (GetApState (CpuData) == CpuStateIdle) {
6985fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      mMpSystemData.StartCount++;
6995fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7005fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      SetApState (CpuData, APInitialState);
7015fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7025fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      if (APInitialState == CpuStateReady) {
7035fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        SetApProcedure (CpuData, Procedure, ProcedureArgument);
7045fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      }
7055fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7065fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      if (SingleThread) {
7075fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan        APInitialState = CpuStateBlocked;
7085fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      }
7095fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
7105fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
7115fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
712acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  mStopCheckAllAPsStatus = FALSE;
713acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan
7145fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (WaitEvent != NULL) {
715acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    //
716acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    // non blocking
717acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    //
718acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    return EFI_SUCCESS;
7195fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
7205fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
721cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
722cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  // Blocking temporarily stop CheckAllAPsStatus()
723cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
724cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  mStopCheckAllAPsStatus = TRUE;
725cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
7265fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  while (TRUE) {
7275fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    CheckAndUpdateAllAPsToIdleState ();
7285fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (mMpSystemData.FinishCount == mMpSystemData.StartCount) {
7295fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      Status = EFI_SUCCESS;
7305fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      goto Done;
7315fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
7325fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7335fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
7345fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    // task timeout
7355fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
7365fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) {
7375fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      ResetAllFailedAPs();
7385fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      Status = EFI_TIMEOUT;
7395fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan      goto Done;
7405fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    }
7415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    gBS->Stall (gPollInterval);
7435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    mMpSystemData.Timeout -= gPollInterval;
7445fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
7455fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7465fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanDone:
7475fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7485fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  return Status;
7495fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan}
7505fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
7515fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan/**
7523f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  This service lets the caller get one enabled AP to execute a caller-provided
7533f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  function. The caller can request the BSP to either wait for the completion
7543f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  of the AP or just proceed with the next task by using the EFI event mechanism.
7553f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  See EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() for more details on non-blocking
7563f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  execution support.  This service may only be called from the BSP.
7573f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
7583f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  This function is used to dispatch one enabled AP to the function specified by
7593f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Procedure passing in the argument specified by ProcedureArgument.  If WaitEvent
7603f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  is NULL, execution is in blocking mode. The BSP waits until the AP finishes or
7613f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  TimeoutInMicroSecondss expires. Otherwise, execution is in non-blocking mode.
7623f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  BSP proceeds to the next task without waiting for the AP. If a non-blocking mode
7633f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled,
7643f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  then EFI_UNSUPPORTED must be returned.
7653f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
7663f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  If the timeout specified by TimeoutInMicroseconds expires before the AP returns
7673f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  from Procedure, then execution of Procedure by the AP is terminated. The AP is
7683f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  available for subsequent calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() and
7693f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
7703f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
7713f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  This                    A pointer to the EFI_MP_SERVICES_PROTOCOL
7723f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      instance.
7733f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  Procedure               A pointer to the function to be run on
7743f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      enabled APs of the system. See type
7753f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      EFI_AP_PROCEDURE.
7763f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  ProcessorNumber         The handle number of the AP. The range is
7773f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      from 0 to the total number of logical
7783f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      processors minus 1. The total number of
7793f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      logical processors can be retrieved by
7803f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
7813f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  WaitEvent               The event created by the caller with CreateEvent()
7823f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      service.  If it is NULL, then execute in
7833f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      blocking mode. BSP waits until all APs finish
7843f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      or TimeoutInMicroseconds expires.  If it's
7853f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      not NULL, then execute in non-blocking mode.
7863f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      BSP requests the function specified by
7873f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      Procedure to be started on all the enabled
7883f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      APs, and go on executing immediately. If
7893f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      all return from Procedure or TimeoutInMicroseconds
7903f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      expires, this event is signaled. The BSP
7913f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      can use the CheckEvent() or WaitForEvent()
7923f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      services to check the state of event.  Type
7933f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      EFI_EVENT is defined in CreateEvent() in
7943f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      the Unified Extensible Firmware Interface
7953f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      Specification.
7963f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
7973f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      APs to return from Procedure, either for
7983f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      blocking or non-blocking mode. Zero means
7993f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      infinity.  If the timeout expires before
8003f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      all APs return from Procedure, then Procedure
8013f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      on the failed APs is terminated. All enabled
8023f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      APs are available for next function assigned
8033f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
8043f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
8053f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      If the timeout expires in blocking mode,
8063f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      BSP returns EFI_TIMEOUT.  If the timeout
8073f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      expires in non-blocking mode, WaitEvent
8083f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      is signaled with SignalEvent().
8093f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[in]  ProcedureArgument       The parameter passed into Procedure for
8103f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      all APs.
8113f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param[out] Finished                If NULL, this parameter is ignored.  In
8123f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      blocking mode, this parameter is ignored.
8133f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      In non-blocking mode, if AP returns from
8143f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      Procedure before the timeout expires, its
8153f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      content is set to TRUE. Otherwise, the
8163f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      value is set to FALSE. The caller can
8173f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      determine if the AP returned from Procedure
8183f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                      by evaluating this value.
8193f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8203f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_SUCCESS             In blocking mode, specified AP finished before
8213f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  the timeout expires.
8223f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_SUCCESS             In non-blocking mode, the function has been
8233f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  dispatched to specified AP.
8243f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_UNSUPPORTED         A non-blocking mode request was made after the
8253f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
8263f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  signaled.
8273f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
8283f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_TIMEOUT             In blocking mode, the timeout expired before
8293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  the specified AP has finished.
8303f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_NOT_READY           The specified AP is busy.
8313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_NOT_FOUND           The processor with the handle specified by
8323f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan                                  ProcessorNumber does not exist.
8333f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP or disabled AP.
8343f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @retval EFI_INVALID_PARAMETER   Procedure is NULL.
8353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8363f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
8373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanEFI_STATUS
8383f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanEFIAPI
8393f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanStartupThisAP (
8403f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  EFI_MP_SERVICES_PROTOCOL  *This,
8413f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  EFI_AP_PROCEDURE          Procedure,
8423f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  UINTN                     ProcessorNumber,
8433f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  EFI_EVENT                 WaitEvent               OPTIONAL,
8443f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  UINTN                     TimeoutInMicroseconds,
8453f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  VOID                      *ProcedureArgument      OPTIONAL,
8463f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  OUT BOOLEAN                   *Finished               OPTIONAL
8473f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
8483f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
8493f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CPU_DATA_BLOCK        *CpuData;
8503f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8513f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData = NULL;
8523f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8533f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (Finished != NULL) {
8543f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    *Finished = FALSE;
8553f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8563f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8573f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (!IsBSP ()) {
8583f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    return EFI_DEVICE_ERROR;
8593f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8603f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8613f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (Procedure == NULL) {
8623f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    return EFI_INVALID_PARAMETER;
8633f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8643f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8653f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
8663f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    return EFI_NOT_FOUND;
8673f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8683f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
869cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
870cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  // temporarily stop checkAllAPsStatus for avoid resource dead-lock.
871cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
872cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  mStopCheckAllAPsStatus = TRUE;
873cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
8743f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
8753f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT) ||
8763f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      !TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
8773f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    return EFI_INVALID_PARAMETER;
8783f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8793f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8803f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (GetApState (CpuData) != CpuStateIdle) {
8813f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    return EFI_NOT_READY;
8823f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
8833f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8843f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  SetApState (CpuData, CpuStateReady);
8853f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8863f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  SetApProcedure (CpuData, Procedure, ProcedureArgument);
8873f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
8883f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->Timeout = TimeoutInMicroseconds;
8893f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->WaitEvent = WaitEvent;
8903f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->TimeoutActive = !!(TimeoutInMicroseconds);
8913f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData->Finished = Finished;
8923f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
893acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  mStopCheckAllAPsStatus = FALSE;
894acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan
8953f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (WaitEvent != NULL) {
8963f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    //
8973f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    // Non Blocking
8983f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    //
899acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    return EFI_SUCCESS;
9003f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
9013f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
9023f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  //
9033f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  // Blocking
9043f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  //
9053f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  while (TRUE) {
9063f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (GetApState (CpuData) == CpuStateFinished) {
9073f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      SetApState (CpuData, CpuStateIdle);
9083f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      break;
9093f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
9103f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
9113f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (CpuData->TimeoutActive && CpuData->Timeout < 0) {
9123f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      ResetProcessorToIdleState (CpuData);
9133f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      return EFI_TIMEOUT;
9143f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
9153f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
9163f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    gBS->Stall (gPollInterval);
9173f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    CpuData->Timeout -= gPollInterval;
9183f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
9193f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
9203f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  return EFI_SUCCESS;
9213f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
9223f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
9233f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
924b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  This service switches the requested AP to be the BSP from that point onward.
925b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  This service changes the BSP for all purposes.   This call can only be performed
926b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  by the current BSP.
927b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
928b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  This service switches the requested AP to be the BSP from that point onward.
929b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  This service changes the BSP for all purposes. The new BSP can take over the
930b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  execution of the old BSP and continue seamlessly from where the old one left
931b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  off. This service may not be supported after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
932b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  is signaled.
933b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
934b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  If the BSP cannot be switched prior to the return from this service, then
935b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  EFI_UNSUPPORTED must be returned.
936b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
937b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @param[in] This              A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
938b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @param[in] ProcessorNumber   The handle number of AP that is to become the new
939b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                               BSP. The range is from 0 to the total number of
940b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                               logical processors minus 1. The total number of
941b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                               logical processors can be retrieved by
942b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                               EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
943b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @param[in] EnableOldBSP      If TRUE, then the old BSP will be listed as an
944b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                               enabled AP. Otherwise, it will be disabled.
945b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
946b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_SUCCESS             BSP successfully switched.
947b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_UNSUPPORTED         Switching the BSP cannot be completed prior to
948b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                                  this service returning.
949b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_UNSUPPORTED         Switching the BSP is not supported.
950b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_SUCCESS             The calling processor is an AP.
951b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_NOT_FOUND           The processor with the handle specified by
952b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                                  ProcessorNumber does not exist.
953b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the current BSP or
954b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan                                  a disabled AP.
955b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  @retval EFI_NOT_READY           The specified AP is busy.
956b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
957b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan**/
958b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen FanEFI_STATUS
959b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen FanEFIAPI
960b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen FanSwitchBSP (
961b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  IN EFI_MP_SERVICES_PROTOCOL  *This,
962b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  IN  UINTN                    ProcessorNumber,
963b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  IN  BOOLEAN                  EnableOldBSP
964b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan  )
965b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan{
966b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan   //
967b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan   // Current always return unsupported.
968b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan   //
969b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan   return EFI_UNSUPPORTED;
970b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan}
971b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan
972b7c05ba5173f4ae8ccfc901755aa79dcc97ebde2Chen Fan/**
973fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  This service lets the caller enable or disable an AP from this point onward.
974fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  This service may only be called from the BSP.
975fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
976fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  This service allows the caller enable or disable an AP from this point onward.
977fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  The caller can optionally specify the health status of the AP by Health. If
978fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  an AP is being disabled, then the state of the disabled AP is implementation
979fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  dependent. If an AP is enabled, then the implementation must guarantee that a
980fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  complete initialization sequence is performed on the AP, so the AP is in a state
981fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  that is compatible with an MP operating system. This service may not be supported
982fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled.
983fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
984fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  If the enable or disable AP operation cannot be completed prior to the return
985fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  from this service, then EFI_UNSUPPORTED must be returned.
986fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
987fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param[in] This              A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
988fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param[in] ProcessorNumber   The handle number of AP that is to become the new
989fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               BSP. The range is from 0 to the total number of
990fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               logical processors minus 1. The total number of
991fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               logical processors can be retrieved by
992fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
993fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param[in] EnableAP          Specifies the new state for the processor for
994fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               enabled, FALSE for disabled.
995fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @param[in] HealthFlag        If not NULL, a pointer to a value that specifies
996fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               the new health status of the AP. This flag
997fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               corresponds to StatusFlag defined in
998fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
999fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               the PROCESSOR_HEALTH_STATUS_BIT is used. All other
1000fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               bits are ignored.  If it is NULL, this parameter
1001fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                               is ignored.
1002fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1003fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_SUCCESS             The specified AP was enabled or disabled successfully.
1004fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_UNSUPPORTED         Enabling or disabling an AP cannot be completed
1005fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                                  prior to this service returning.
1006fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_UNSUPPORTED         Enabling or disabling an AP is not supported.
1007fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
1008fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_NOT_FOUND           Processor with the handle specified by ProcessorNumber
1009fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan                                  does not exist.
1010fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP.
1011fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1012fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan**/
1013fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanEFI_STATUS
1014fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanEFIAPI
1015fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen FanEnableDisableAP (
1016fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  EFI_MP_SERVICES_PROTOCOL  *This,
1017fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  UINTN                     ProcessorNumber,
1018fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  BOOLEAN                   EnableAP,
1019fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  IN  UINT32                    *HealthFlag OPTIONAL
1020fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  )
1021fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan{
1022fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  CPU_DATA_BLOCK *CpuData;
1023cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  BOOLEAN        TempStopCheckState;
1024cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
1025cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  CpuData = NULL;
1026cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  TempStopCheckState = FALSE;
1027fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1028fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (!IsBSP ()) {
1029fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    return EFI_DEVICE_ERROR;
1030fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1031fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1032fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
1033fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    return EFI_NOT_FOUND;
1034fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1035fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1036cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
1037cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  // temporarily stop checkAllAPsStatus for initialize parameters.
1038cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  //
1039cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  if (!mStopCheckAllAPsStatus) {
1040cd8c700b03e38e9389a8f13e193a431072802593Chen Fan    mStopCheckAllAPsStatus = TRUE;
1041cd8c700b03e38e9389a8f13e193a431072802593Chen Fan    TempStopCheckState = TRUE;
1042cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  }
1043cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
1044fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
1045fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
1046fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    return EFI_INVALID_PARAMETER;
1047fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1048fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1049fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (GetApState (CpuData) != CpuStateIdle) {
1050fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    return EFI_UNSUPPORTED;
1051fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1052fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1053fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (EnableAP) {
1054fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    if (!(TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT))) {
1055fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan      mMpSystemData.NumberOfEnabledProcessors++;
1056fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    }
1057fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    CpuStatusFlagOr (CpuData, PROCESSOR_ENABLED_BIT);
1058fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  } else {
1059fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    if (TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
1060fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan      mMpSystemData.NumberOfEnabledProcessors--;
1061fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    }
1062fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    CpuStatusFlagAndNot (CpuData, PROCESSOR_ENABLED_BIT);
1063fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1064fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1065fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  if (HealthFlag != NULL) {
1066fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    CpuStatusFlagAndNot (CpuData, (UINT32)~PROCESSOR_HEALTH_STATUS_BIT);
1067fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan    CpuStatusFlagOr (CpuData, (*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT));
1068fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  }
1069fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1070cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  if (TempStopCheckState) {
1071cd8c700b03e38e9389a8f13e193a431072802593Chen Fan    mStopCheckAllAPsStatus = FALSE;
1072cd8c700b03e38e9389a8f13e193a431072802593Chen Fan  }
1073cd8c700b03e38e9389a8f13e193a431072802593Chen Fan
1074fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan  return EFI_SUCCESS;
1075fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan}
1076fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan
1077fa7ce675b991bca6e18fcda8446737717ae3c1f6Chen Fan/**
1078cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  This return the handle number for the calling processor.  This service may be
1079cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  called from the BSP and APs.
1080cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1081cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  This service returns the processor handle number for the calling processor.
1082cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  The returned value is in the range from 0 to the total number of logical
1083cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  processors minus 1. The total number of logical processors can be retrieved
1084cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  with EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be
1085cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
1086cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  is returned. Otherwise, the current processors handle number is returned in
1087cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  ProcessorNumber, and EFI_SUCCESS is returned.
1088cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1089cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  @param[in]  This             A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
1090cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  @param[out] ProcessorNumber  The handle number of AP that is to become the new
1091cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan                               BSP. The range is from 0 to the total number of
1092cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan                               logical processors minus 1. The total number of
1093cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan                               logical processors can be retrieved by
1094cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan                               EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
1095cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1096cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  @retval EFI_SUCCESS             The current processor handle number was returned
1097cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan                                  in ProcessorNumber.
1098cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  @retval EFI_INVALID_PARAMETER   ProcessorNumber is NULL.
1099cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1100cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan**/
1101cfa2fac1f667b227a29a2219321b651c7a143071Chen FanEFI_STATUS
1102cfa2fac1f667b227a29a2219321b651c7a143071Chen FanEFIAPI
1103cfa2fac1f667b227a29a2219321b651c7a143071Chen FanWhoAmI (
1104cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  IN EFI_MP_SERVICES_PROTOCOL  *This,
1105cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  OUT UINTN                    *ProcessorNumber
1106cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  )
1107cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan{
1108cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  UINTN   Index;
1109cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  UINT32  ProcessorId;
1110cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1111cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  if (ProcessorNumber == NULL) {
1112cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan    return EFI_INVALID_PARAMETER;
1113cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  }
1114cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1115cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  ProcessorId = GetApicId ();
1116cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  for (Index = 0; Index < mMpSystemData.NumberOfProcessors; Index++) {
1117cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan    if (mMpSystemData.CpuDatas[Index].Info.ProcessorId == ProcessorId) {
1118cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan      break;
1119cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan    }
1120cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  }
1121cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1122cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  *ProcessorNumber = Index;
1123cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan  return EFI_SUCCESS;
1124cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan}
1125cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan
1126cfa2fac1f667b227a29a2219321b651c7a143071Chen Fan/**
11273f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Terminate AP's task and set it to idle state.
11283f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
11293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  This function terminates AP's task due to timeout by sending INIT-SIPI,
11303f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  and sends it to idle state.
11313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
11323f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param CpuData           the pointer to CPU_DATA_BLOCK of specified AP
11333f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
11343f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
11353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanVOID
11363f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanResetProcessorToIdleState (
11373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN CPU_DATA_BLOCK  *CpuData
11383f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
11393f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
1140ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  ResetApStackless ((UINT32)CpuData->Info.ProcessorId);
11413f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
11423f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
11433f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
1144e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  Application Processors do loop routine
1145e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  after switch to its own stack.
1146e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan
1147e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  @param  Context1    A pointer to the context to pass into the function.
1148e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  @param  Context2    A pointer to the context to pass into the function.
1149e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan
1150e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan**/
1151e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen FanVOID
1152e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen FanProcessorToIdleState (
1153e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  IN      VOID                      *Context1,  OPTIONAL
1154e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  IN      VOID                      *Context2   OPTIONAL
1155e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  )
1156e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan{
11579908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  UINTN                 ProcessorNumber;
11589908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  CPU_DATA_BLOCK        *CpuData;
11599908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  EFI_AP_PROCEDURE      Procedure;
11609908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  VOID                  *ProcedureArgument;
11619908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan
1162232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan  AsmApDoneWithCommonStack ();
1163232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan
1164232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan  while (!mAPsAlreadyInitFinished) {
1165232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan    CpuPause ();
1166232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan  }
1167232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan
11689908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  WhoAmI (&mMpServicesTemplate, &ProcessorNumber);
11699908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
1170e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan
1171ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  //
11720e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  // Avoid forcibly reset AP caused the AP got lock not release.
11730e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  //
11740e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  if (CpuData->LockSelf == (INTN) GetApicId ()) {
11750e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan    ReleaseSpinLock (&CpuData->CpuDataLock);
11760e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  }
11770e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan
11780e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  //
1179ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  // Avoid forcibly reset AP caused the AP State is not updated.
1180ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  //
1181ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  GetMpSpinLock (CpuData);
1182ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  CpuData->State = CpuStateIdle;
1183ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  CpuData->Procedure = NULL;
1184ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  ReleaseMpSpinLock (CpuData);
1185ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan
11869908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  while (TRUE) {
1187d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan    GetMpSpinLock (CpuData);
11889908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan    ProcedureArgument = CpuData->Parameter;
11899908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan    Procedure = CpuData->Procedure;
1190d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan    ReleaseMpSpinLock (CpuData);
11919908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan
11929908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan    if (Procedure != NULL) {
11939908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan      Procedure (ProcedureArgument);
11949908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan
1195d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan      GetMpSpinLock (CpuData);
11969908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan      CpuData->Procedure = NULL;
1197d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan      CpuData->State = CpuStateFinished;
1198d16cf36d2a226cf6a527099407b6b0b70a0f9faaChen Fan      ReleaseMpSpinLock (CpuData);
11999908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan    }
12009908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan
12019908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan    CpuPause ();
12029908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan  }
12039908a829d0c1c92ca9bf462c0d9210f63784c131Chen Fan
1204e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  CpuSleep ();
1205e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  CpuDeadLoop ();
1206e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan}
1207e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan
1208e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan/**
12093f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  Checks AP' status periodically.
12103f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12113f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  This function is triggerred by timer perodically to check the
12123f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  state of AP forStartupThisAP() executed in non-blocking mode.
12133f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12143f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param  Event    Event triggered.
12153f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  @param  Context  Parameter passed with the event.
12163f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12173f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan**/
12183f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanVOID
12193f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanEFIAPI
12203f4f0af8724c56ed6fac052b5086e33511aa9a80Chen FanCheckThisAPStatus (
12213f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  EFI_EVENT        Event,
12223f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  IN  VOID             *Context
12233f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  )
12243f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan{
12253f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CPU_DATA_BLOCK  *CpuData;
12263f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CPU_STATE       CpuState;
12273f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12283f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuData = (CPU_DATA_BLOCK *) Context;
12293f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (CpuData->TimeoutActive) {
12303f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    CpuData->Timeout -= gPollInterval;
12313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
12323f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12333f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  CpuState = GetApState (CpuData);
12343f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12353f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (CpuState == CpuStateFinished) {
12363f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (CpuData->Finished) {
12373f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      *CpuData->Finished = TRUE;
12383f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
12393f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    SetApState (CpuData, CpuStateIdle);
12403f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    goto out;
12413f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
12423f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12433f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  if (CpuData->TimeoutActive && CpuData->Timeout < 0) {
12443f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    if (CpuState != CpuStateIdle &&
12453f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan        CpuData->Finished) {
12463f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan      *CpuData->Finished = FALSE;
12473f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    }
12483f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    ResetProcessorToIdleState (CpuData);
12493f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan    goto out;
12503f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  }
12513f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12523f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  return;
12533f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12543f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fanout:
1255acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  CpuData->TimeoutActive = FALSE;
1256acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  gBS->SignalEvent (CpuData->WaitEvent);
1257acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  CpuData->WaitEvent = NULL;
12583f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan}
12593f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
12603f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan/**
12615fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  Checks APs' status periodically.
12625fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
12635fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  This function is triggerred by timer perodically to check the
12645fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  state of APs for StartupAllAPs() executed in non-blocking mode.
12655fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
12665fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param  Event    Event triggered.
12675fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  @param  Context  Parameter passed with the event.
12685fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
12695fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan**/
12705fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanVOID
12715fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanEFIAPI
12725fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen FanCheckAllAPsStatus (
12735fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  EFI_EVENT        Event,
12745fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  IN  VOID             *Context
12755fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  )
12765fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan{
1277acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  CPU_DATA_BLOCK *CpuData;
1278acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  UINTN          Number;
1279e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  EFI_STATUS     Status;
1280acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan
12815fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  if (mMpSystemData.TimeoutActive) {
12825fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    mMpSystemData.Timeout -= gPollInterval;
12835fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
12845fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
1285acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  if (mStopCheckAllAPsStatus) {
1286acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    return;
1287acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  }
12885fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
1289e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  //
1290e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  // avoid next timer enter.
1291e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  //
1292e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  Status = gBS->SetTimer (
1293e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  mMpSystemData.CheckAllAPsEvent,
1294e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  TimerCancel,
1295e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  0
1296e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  );
1297e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  ASSERT_EFI_ERROR (Status);
1298e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan
1299acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  if (mMpSystemData.WaitEvent != NULL) {
1300acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    CheckAndUpdateAllAPsToIdleState ();
13015fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
1302acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    // task timeout
13035fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    //
1304acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) {
1305acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      ResetAllFailedAPs();
1306acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      //
1307acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      // force exit
1308acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      //
1309acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      mMpSystemData.FinishCount = mMpSystemData.StartCount;
1310acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    }
13115fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
1312acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    if (mMpSystemData.FinishCount != mMpSystemData.StartCount) {
1313e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan      goto EXIT;
1314acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    }
13155fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
1316acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    mMpSystemData.TimeoutActive = FALSE;
13175fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    gBS->SignalEvent (mMpSystemData.WaitEvent);
13185fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan    mMpSystemData.WaitEvent = NULL;
1319acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    mStopCheckAllAPsStatus = TRUE;
1320e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan
1321e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan    goto EXIT;
1322acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  }
1323acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan
1324acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  //
1325acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  // check each AP status for StartupThisAP
1326acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  //
1327acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
1328acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    CpuData = &mMpSystemData.CpuDatas[Number];
1329acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    if (CpuData->WaitEvent) {
1330acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan      CheckThisAPStatus (NULL, (VOID *)CpuData);
1331acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan    }
13325fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  }
1333e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan
1334e4aaf764281d12cb8bfe605393a5520e00715838Chen FanEXIT:
1335e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  Status = gBS->SetTimer (
1336e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  mMpSystemData.CheckAllAPsEvent,
1337e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  TimerPeriodic,
1338e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  EFI_TIMER_PERIOD_MICROSECONDS (100)
1339e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan                  );
1340e4aaf764281d12cb8bfe605393a5520e00715838Chen Fan  ASSERT_EFI_ERROR (Status);
13415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan}
13425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
13435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan/**
13441535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen  Application Processor C code entry point.
13451535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen
13461535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen**/
13471535c888c6f06bb35881e83cd7ee49fb8554942bJordan JustenVOID
13481535c888c6f06bb35881e83cd7ee49fb8554942bJordan JustenEFIAPI
13491535c888c6f06bb35881e83cd7ee49fb8554942bJordan JustenApEntryPointInC (
13501535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen  VOID
13511535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen  )
13521535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen{
1353ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  VOID*           TopOfApStack;
1354ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  UINTN           ProcessorNumber;
135503673ae11e255b9467e8f317175495b1ff79f965Chen Fan
1356ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  if (!mAPsAlreadyInitFinished) {
1357ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    FillInProcessorInformation (FALSE, mMpSystemData.NumberOfProcessors);
1358ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    TopOfApStack  = (UINT8*)mApStackStart + gApStackSize;
1359ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    mApStackStart = TopOfApStack;
136003673ae11e255b9467e8f317175495b1ff79f965Chen Fan
1361ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    //
1362ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    // Store the Stack address, when reset the AP, We can found the original address.
1363ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    //
1364ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    mMpSystemData.CpuDatas[mMpSystemData.NumberOfProcessors].TopOfStack = TopOfApStack;
1365ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    mMpSystemData.NumberOfProcessors++;
1366ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    mMpSystemData.NumberOfEnabledProcessors++;
1367ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  } else {
1368ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    WhoAmI (&mMpServicesTemplate, &ProcessorNumber);
1369ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    //
1370ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    // Get the original stack address.
1371ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    //
1372ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan    TopOfApStack = mMpSystemData.CpuDatas[ProcessorNumber].TopOfStack;
1373ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  }
1374e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan
1375e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan  SwitchStack (
1376e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan    (SWITCH_STACK_ENTRY_POINT)(UINTN)ProcessorToIdleState,
1377e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan    NULL,
1378e343f8f7b35a400bb1d6e0edd7dddc53dd9e436dChen Fan    NULL,
137903673ae11e255b9467e8f317175495b1ff79f965Chen Fan    TopOfApStack);
138003673ae11e255b9467e8f317175495b1ff79f965Chen Fan}
138103673ae11e255b9467e8f317175495b1ff79f965Chen Fan
138203673ae11e255b9467e8f317175495b1ff79f965Chen Fan/**
138303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  This function is called by all processors (both BSP and AP) once and collects MP related data.
138403673ae11e255b9467e8f317175495b1ff79f965Chen Fan
138503673ae11e255b9467e8f317175495b1ff79f965Chen Fan  @param Bsp             TRUE if the CPU is BSP
138603673ae11e255b9467e8f317175495b1ff79f965Chen Fan  @param ProcessorNumber The specific processor number
138703673ae11e255b9467e8f317175495b1ff79f965Chen Fan
138803673ae11e255b9467e8f317175495b1ff79f965Chen Fan  @retval EFI_SUCCESS    Data for the processor collected and filled in
138903673ae11e255b9467e8f317175495b1ff79f965Chen Fan
139003673ae11e255b9467e8f317175495b1ff79f965Chen Fan**/
139103673ae11e255b9467e8f317175495b1ff79f965Chen FanEFI_STATUS
139203673ae11e255b9467e8f317175495b1ff79f965Chen FanFillInProcessorInformation (
139303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  IN     BOOLEAN              Bsp,
139403673ae11e255b9467e8f317175495b1ff79f965Chen Fan  IN     UINTN                ProcessorNumber
139503673ae11e255b9467e8f317175495b1ff79f965Chen Fan  )
139603673ae11e255b9467e8f317175495b1ff79f965Chen Fan{
139703673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CPU_DATA_BLOCK  *CpuData;
139803673ae11e255b9467e8f317175495b1ff79f965Chen Fan  UINT32          ProcessorId;
139903673ae11e255b9467e8f317175495b1ff79f965Chen Fan
140003673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
140103673ae11e255b9467e8f317175495b1ff79f965Chen Fan  ProcessorId  = GetApicId ();
140203673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Info.ProcessorId  = ProcessorId;
140303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Info.StatusFlag   = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;
140403673ae11e255b9467e8f317175495b1ff79f965Chen Fan  if (Bsp) {
140503673ae11e255b9467e8f317175495b1ff79f965Chen Fan    CpuData->Info.StatusFlag |= PROCESSOR_AS_BSP_BIT;
140603673ae11e255b9467e8f317175495b1ff79f965Chen Fan  }
140703673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Info.Location.Package = ProcessorId;
140803673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Info.Location.Core    = 0;
140903673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Info.Location.Thread  = 0;
141003673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->State = Bsp ? CpuStateBuzy : CpuStateIdle;
141103673ae11e255b9467e8f317175495b1ff79f965Chen Fan
141203673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Procedure        = NULL;
141303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  CpuData->Parameter        = NULL;
141403673ae11e255b9467e8f317175495b1ff79f965Chen Fan  InitializeSpinLock (&CpuData->CpuDataLock);
14150e724fc1981b3c47bb16432c4c414a50c9e3a519Chen Fan  CpuData->LockSelf         = -1;
141603673ae11e255b9467e8f317175495b1ff79f965Chen Fan
141703673ae11e255b9467e8f317175495b1ff79f965Chen Fan  return EFI_SUCCESS;
14181535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen}
14191535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen
142003673ae11e255b9467e8f317175495b1ff79f965Chen Fan/**
142103673ae11e255b9467e8f317175495b1ff79f965Chen Fan  Prepare the System Data.
142203673ae11e255b9467e8f317175495b1ff79f965Chen Fan
142303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  @retval EFI_SUCCESS     the System Data finished initilization.
142403673ae11e255b9467e8f317175495b1ff79f965Chen Fan
142503673ae11e255b9467e8f317175495b1ff79f965Chen Fan**/
142603673ae11e255b9467e8f317175495b1ff79f965Chen FanEFI_STATUS
142703673ae11e255b9467e8f317175495b1ff79f965Chen FanInitMpSystemData (
142803673ae11e255b9467e8f317175495b1ff79f965Chen Fan  VOID
142903673ae11e255b9467e8f317175495b1ff79f965Chen Fan  )
143003673ae11e255b9467e8f317175495b1ff79f965Chen Fan{
14313f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan  EFI_STATUS     Status;
14323f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
143303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  ZeroMem (&mMpSystemData, sizeof (MP_SYSTEM_DATA));
143403673ae11e255b9467e8f317175495b1ff79f965Chen Fan
143503673ae11e255b9467e8f317175495b1ff79f965Chen Fan  mMpSystemData.NumberOfProcessors = 1;
143603673ae11e255b9467e8f317175495b1ff79f965Chen Fan  mMpSystemData.NumberOfEnabledProcessors = 1;
143703673ae11e255b9467e8f317175495b1ff79f965Chen Fan
143803673ae11e255b9467e8f317175495b1ff79f965Chen Fan  mMpSystemData.CpuDatas = AllocateZeroPool (sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber);
143903673ae11e255b9467e8f317175495b1ff79f965Chen Fan  ASSERT(mMpSystemData.CpuDatas != NULL);
144003673ae11e255b9467e8f317175495b1ff79f965Chen Fan
14415fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  Status = gBS->CreateEvent (
14425fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
14435fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  TPL_CALLBACK,
14445fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  CheckAllAPsStatus,
14455fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  NULL,
14465fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  &mMpSystemData.CheckAllAPsEvent
14475fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan                  );
14485fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan  ASSERT_EFI_ERROR (Status);
14495fee172fb75ba07df4638abfd0cfc0ce83fc1073Chen Fan
1450acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  //
1451acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  // Set timer to check all APs status.
1452acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  //
1453acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  Status = gBS->SetTimer (
1454acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan                  mMpSystemData.CheckAllAPsEvent,
1455acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan                  TimerPeriodic,
1456acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan                  EFI_TIMER_PERIOD_MICROSECONDS (100)
1457acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan                  );
1458acb2172d15ed793c8ae0484700d42dcc105f2ea1Chen Fan  ASSERT_EFI_ERROR (Status);
14593f4f0af8724c56ed6fac052b5086e33511aa9a80Chen Fan
146003673ae11e255b9467e8f317175495b1ff79f965Chen Fan  //
146103673ae11e255b9467e8f317175495b1ff79f965Chen Fan  // BSP
146203673ae11e255b9467e8f317175495b1ff79f965Chen Fan  //
146303673ae11e255b9467e8f317175495b1ff79f965Chen Fan  FillInProcessorInformation (TRUE, 0);
146403673ae11e255b9467e8f317175495b1ff79f965Chen Fan
146503673ae11e255b9467e8f317175495b1ff79f965Chen Fan  return EFI_SUCCESS;
146603673ae11e255b9467e8f317175495b1ff79f965Chen Fan}
14671535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen
14681535c888c6f06bb35881e83cd7ee49fb8554942bJordan Justen/**
14699840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  Callback function for ExitBootServices.
14709840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan
14719840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  @param  Event                 Event whose notification function is being invoked.
14729840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  @param  Context               The pointer to the notification function's context,
14739840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan                                which is implementation-dependent.
14749840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan
14759840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan**/
14769840b1299de78458a42d35b8d1d6cbadd1f6da72Chen FanVOID
14779840b1299de78458a42d35b8d1d6cbadd1f6da72Chen FanEFIAPI
14789840b1299de78458a42d35b8d1d6cbadd1f6da72Chen FanExitBootServicesCallback (
14799840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  IN EFI_EVENT                Event,
14809840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  IN VOID                     *Context
14819840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  )
14829840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan{
14839840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  //
14849840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  // Avoid APs access invalid buff datas which allocated by BootServices,
14859840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  // so we send INIT IPI to APs to let them wait for SIPI state.
14869840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  //
14879840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  SendInitIpiAllExcludingSelf ();
14889840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan}
14899840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan
14909840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan/**
14916022e28cf744a885c278dad256d50670741ea123Jordan Justen  Initialize Multi-processor support.
14926022e28cf744a885c278dad256d50670741ea123Jordan Justen
14936022e28cf744a885c278dad256d50670741ea123Jordan Justen**/
14946022e28cf744a885c278dad256d50670741ea123Jordan JustenVOID
14956022e28cf744a885c278dad256d50670741ea123Jordan JustenInitializeMpSupport (
14966022e28cf744a885c278dad256d50670741ea123Jordan Justen  VOID
14976022e28cf744a885c278dad256d50670741ea123Jordan Justen  )
14986022e28cf744a885c278dad256d50670741ea123Jordan Justen{
14994a50c2728540b9c487c9eccf19548f5322851212Chen Fan  EFI_STATUS Status;
15004a50c2728540b9c487c9eccf19548f5322851212Chen Fan
15016a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  gMaxLogicalProcessorNumber = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
15026a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  if (gMaxLogicalProcessorNumber < 1) {
15036a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan    DEBUG ((DEBUG_ERROR, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n"));
15046a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan    return;
15056a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  }
15066a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
15076a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  if (gMaxLogicalProcessorNumber == 1) {
15086a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan    return;
15096a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  }
15106a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
15116a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  gApStackSize = (UINTN) PcdGet32 (PcdCpuApStackSize);
15126a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  ASSERT ((gApStackSize & (SIZE_4KB - 1)) == 0);
15136a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
15146a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  mApStackStart = AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));
15156a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  ASSERT (mApStackStart != NULL);
15166022e28cf744a885c278dad256d50670741ea123Jordan Justen
15176a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  //
15186a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  // the first buffer of stack size used for common stack, when the amount of AP
15196a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  // more than 1, we should never free the common stack which maybe used for AP reset.
15206a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  //
15216a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  mCommonStack = mApStackStart;
15226a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  mTopOfApCommonStack = (UINT8*) mApStackStart + gApStackSize;
15236a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  mApStackStart = mTopOfApCommonStack;
15246a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
152503673ae11e255b9467e8f317175495b1ff79f965Chen Fan  InitMpSystemData ();
15266a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
1527fe078dd57f5e935c28eac7348b758ca6fb5e696fChen Fan  PrepareAPStartupCode ();
1528fe078dd57f5e935c28eac7348b758ca6fb5e696fChen Fan
1529dee9376ffc6e5522bb5e50512b521952a5421fa5Jordan Justen  StartApsStackless ();
1530dee9376ffc6e5522bb5e50512b521952a5421fa5Jordan Justen
1531dee9376ffc6e5522bb5e50512b521952a5421fa5Jordan Justen  DEBUG ((DEBUG_INFO, "Detect CPU count: %d\n", mMpSystemData.NumberOfProcessors));
153203673ae11e255b9467e8f317175495b1ff79f965Chen Fan  if (mMpSystemData.NumberOfProcessors == 1) {
1533fe078dd57f5e935c28eac7348b758ca6fb5e696fChen Fan    FreeApStartupCode ();
15346a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan    FreePages (mCommonStack, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));
15356a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan    return;
15366a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  }
15376a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan
1538232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan  mMpSystemData.CpuDatas = ReallocatePool (
1539232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan                             sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber,
1540232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan                             sizeof (CPU_DATA_BLOCK) * mMpSystemData.NumberOfProcessors,
1541232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan                             mMpSystemData.CpuDatas);
1542232eb4c82637e92b65ebbfc89a45e9daa8535171Chen Fan
1543ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan  mAPsAlreadyInitFinished = TRUE;
1544ac9dbb3b03313c7426c5bb15663b20b57ca771ceChen Fan
15454a50c2728540b9c487c9eccf19548f5322851212Chen Fan  Status = gBS->InstallMultipleProtocolInterfaces (
15464a50c2728540b9c487c9eccf19548f5322851212Chen Fan                  &mMpServiceHandle,
15474a50c2728540b9c487c9eccf19548f5322851212Chen Fan                  &gEfiMpServiceProtocolGuid,  &mMpServicesTemplate,
15484a50c2728540b9c487c9eccf19548f5322851212Chen Fan                  NULL
15494a50c2728540b9c487c9eccf19548f5322851212Chen Fan                  );
15504a50c2728540b9c487c9eccf19548f5322851212Chen Fan  ASSERT_EFI_ERROR (Status);
15514a50c2728540b9c487c9eccf19548f5322851212Chen Fan
155203673ae11e255b9467e8f317175495b1ff79f965Chen Fan  if (mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) {
155303673ae11e255b9467e8f317175495b1ff79f965Chen Fan    FreePages (mApStackStart, EFI_SIZE_TO_PAGES (
155403673ae11e255b9467e8f317175495b1ff79f965Chen Fan                                (gMaxLogicalProcessorNumber - mMpSystemData.NumberOfProcessors) *
155503673ae11e255b9467e8f317175495b1ff79f965Chen Fan                                gApStackSize));
15566a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan  }
15579840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan
15589840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  Status = gBS->CreateEvent (
15599840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
15609840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan                  TPL_CALLBACK,
15619840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan                  ExitBootServicesCallback,
15629840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan                  NULL,
15639840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan                  &mExitBootServicesEvent
15649840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan                  );
15659840b1299de78458a42d35b8d1d6cbadd1f6da72Chen Fan  ASSERT_EFI_ERROR (Status);
15666a26a597a38d36c670a5c1ce0bf54c8a413a1868Chen Fan}
1567