]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuDxe/CpuMp.c
UefiCpuPkg/CpuDxe: Consume MpInitLib to produce CPU MP Protocol services
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuMp.c
CommitLineData
6022e28c 1/** @file\r
7fadaacd 2 CPU DXE Module to produce CPU MP Protocol.\r
6022e28c 3\r
7fadaacd 4 Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>\r
6022e28c
JJ
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "CpuDxe.h"\r
16#include "CpuMp.h"\r
17\r
6a26a597
CF
18UINTN gMaxLogicalProcessorNumber;\r
19UINTN gApStackSize;\r
3f4f0af8 20UINTN gPollInterval = 100; // 100 microseconds\r
6a26a597 21\r
03673ae1 22MP_SYSTEM_DATA mMpSystemData;\r
9840b129 23EFI_HANDLE mMpServiceHandle = NULL;\r
7fadaacd 24UINTN mNumberOfProcessors = 1;\r
9840b129 25EFI_EVENT mExitBootServicesEvent = (EFI_EVENT)NULL;\r
03673ae1 26\r
fab82c18
JJ
27VOID *mCommonStack = 0;\r
28VOID *mTopOfApCommonStack = 0;\r
6a26a597 29VOID *mApStackStart = 0;\r
fab82c18 30\r
232eb4c8 31volatile BOOLEAN mAPsAlreadyInitFinished = FALSE;\r
acb2172d 32\r
003973d9 33EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = {\r
d894d8b7 34 GetNumberOfProcessors,\r
e7938b5a 35 GetProcessorInfo,\r
5fee172f 36 StartupAllAPs,\r
3f4f0af8 37 StartupThisAP,\r
b7c05ba5 38 SwitchBSP,\r
fa7ce675 39 EnableDisableAP,\r
cfa2fac1 40 WhoAmI\r
003973d9
CF
41};\r
42\r
d16cf36d
CF
43/**\r
44 Get Mp Service Lock.\r
45\r
46 @param CpuData the pointer to CPU_DATA_BLOCK of specified processor\r
47\r
48**/\r
49VOID\r
50GetMpSpinLock (\r
51 IN CPU_DATA_BLOCK *CpuData\r
52 )\r
53{\r
54 while (!AcquireSpinLockOrFail (&CpuData->CpuDataLock)) {\r
55 CpuPause ();\r
56 }\r
0e724fc1 57 CpuData->LockSelf = GetApicId ();\r
d16cf36d
CF
58}\r
59\r
60/**\r
61 Release Mp Service Lock.\r
62\r
63 @param CpuData the pointer to CPU_DATA_BLOCK of specified processor\r
64\r
65**/\r
66VOID\r
67ReleaseMpSpinLock (\r
68 IN CPU_DATA_BLOCK *CpuData\r
69 )\r
70{\r
71 ReleaseSpinLock (&CpuData->CpuDataLock);\r
72}\r
73\r
d894d8b7
CF
74/**\r
75 Check whether caller processor is BSP.\r
76\r
77 @retval TRUE the caller is BSP\r
78 @retval FALSE the caller is AP\r
79\r
80**/\r
81BOOLEAN\r
82IsBSP (\r
83 VOID\r
84 )\r
85{\r
86 UINTN CpuIndex;\r
87 CPU_DATA_BLOCK *CpuData;\r
88\r
89 CpuData = NULL;\r
90\r
91 WhoAmI (&mMpServicesTemplate, &CpuIndex);\r
92 CpuData = &mMpSystemData.CpuDatas[CpuIndex];\r
93\r
94 return CpuData->Info.StatusFlag & PROCESSOR_AS_BSP_BIT ? TRUE : FALSE;\r
95}\r
96\r
fa7ce675
CF
97/**\r
98 Get the Application Processors state.\r
99\r
100 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
101\r
102 @retval CPU_STATE the AP status\r
103\r
104**/\r
7fadaacd 105STATIC\r
fa7ce675
CF
106CPU_STATE\r
107GetApState (\r
108 IN CPU_DATA_BLOCK *CpuData\r
109 )\r
110{\r
111 CPU_STATE State;\r
112\r
d16cf36d 113 GetMpSpinLock (CpuData);\r
fa7ce675 114 State = CpuData->State;\r
d16cf36d 115 ReleaseMpSpinLock (CpuData);\r
fa7ce675
CF
116\r
117 return State;\r
118}\r
119\r
3f4f0af8
CF
120/**\r
121 Set the Application Processors state.\r
122\r
123 @param CpuData The pointer to CPU_DATA_BLOCK of specified AP\r
124 @param State The AP status\r
125\r
126**/\r
7fadaacd 127STATIC\r
3f4f0af8
CF
128VOID\r
129SetApState (\r
130 IN CPU_DATA_BLOCK *CpuData,\r
131 IN CPU_STATE State\r
132 )\r
133{\r
d16cf36d 134 GetMpSpinLock (CpuData);\r
3f4f0af8 135 CpuData->State = State;\r
d16cf36d 136 ReleaseMpSpinLock (CpuData);\r
3f4f0af8
CF
137}\r
138\r
139/**\r
140 Set the Application Processor prepare to run a function specified\r
141 by Params.\r
142\r
143 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
144 @param Procedure A pointer to the function to be run on enabled APs of the system\r
145 @param ProcedureArgument Pointer to the optional parameter of the assigned function\r
146\r
147**/\r
148VOID\r
149SetApProcedure (\r
150 IN CPU_DATA_BLOCK *CpuData,\r
151 IN EFI_AP_PROCEDURE Procedure,\r
152 IN VOID *ProcedureArgument\r
153 )\r
154{\r
d16cf36d 155 GetMpSpinLock (CpuData);\r
3f4f0af8
CF
156 CpuData->Parameter = ProcedureArgument;\r
157 CpuData->Procedure = Procedure;\r
d16cf36d 158 ReleaseMpSpinLock (CpuData);\r
3f4f0af8
CF
159}\r
160\r
fa7ce675
CF
161/**\r
162 Check the Application Processors Status whether contains the Flags.\r
163\r
164 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
165 @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION\r
166\r
167 @retval TRUE the AP status includes the StatusFlag\r
168 @retval FALSE the AP status excludes the StatusFlag\r
169\r
170**/\r
171BOOLEAN\r
172TestCpuStatusFlag (\r
173 IN CPU_DATA_BLOCK *CpuData,\r
174 IN UINT32 Flags\r
175 )\r
176{\r
177 UINT32 Ret;\r
178\r
d16cf36d 179 GetMpSpinLock (CpuData);\r
fa7ce675 180 Ret = CpuData->Info.StatusFlag & Flags;\r
d16cf36d 181 ReleaseMpSpinLock (CpuData);\r
fa7ce675 182\r
7475d138 183 return (BOOLEAN) (Ret != 0);\r
fa7ce675
CF
184}\r
185\r
186/**\r
187 Bitwise-Or of the Application Processors Status with the Flags.\r
188\r
189 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
190 @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION\r
191\r
192**/\r
193VOID\r
194CpuStatusFlagOr (\r
195 IN CPU_DATA_BLOCK *CpuData,\r
196 IN UINT32 Flags\r
197 )\r
198{\r
d16cf36d 199 GetMpSpinLock (CpuData);\r
fa7ce675 200 CpuData->Info.StatusFlag |= Flags;\r
d16cf36d 201 ReleaseMpSpinLock (CpuData);\r
fa7ce675
CF
202}\r
203\r
204/**\r
205 Bitwise-AndNot of the Application Processors Status with the Flags.\r
206\r
207 @param CpuData the pointer to CPU_DATA_BLOCK of specified AP\r
208 @param Flags the StatusFlag describing in EFI_PROCESSOR_INFORMATION\r
209\r
210**/\r
211VOID\r
212CpuStatusFlagAndNot (\r
213 IN CPU_DATA_BLOCK *CpuData,\r
214 IN UINT32 Flags\r
215 )\r
216{\r
d16cf36d 217 GetMpSpinLock (CpuData);\r
fa7ce675 218 CpuData->Info.StatusFlag &= ~Flags;\r
d16cf36d 219 ReleaseMpSpinLock (CpuData);\r
fa7ce675
CF
220}\r
221\r
3f4f0af8
CF
222/**\r
223 Searches for the next blocking AP.\r
224\r
225 Search for the next AP that is put in blocking state by single-threaded StartupAllAPs().\r
226\r
227 @param NextNumber Pointer to the processor number of the next blocking AP.\r
228\r
229 @retval EFI_SUCCESS The next blocking AP has been found.\r
230 @retval EFI_NOT_FOUND No blocking AP exists.\r
231\r
232**/\r
233EFI_STATUS\r
234GetNextBlockedNumber (\r
235 OUT UINTN *NextNumber\r
236 )\r
237{\r
238 UINTN Number;\r
239 CPU_STATE CpuState;\r
240 CPU_DATA_BLOCK *CpuData;\r
241\r
242 for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {\r
243 CpuData = &mMpSystemData.CpuDatas[Number];\r
244 if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
245 //\r
246 // Skip BSP\r
247 //\r
248 continue;\r
249 }\r
250\r
251 CpuState = GetApState (CpuData);\r
252 if (CpuState == CpuStateBlocked) {\r
253 *NextNumber = Number;\r
254 return EFI_SUCCESS;\r
255 }\r
256 }\r
257\r
258 return EFI_NOT_FOUND;\r
259}\r
260\r
5fee172f
CF
261/**\r
262 Check if the APs state are finished, and update them to idle state\r
263 by StartupAllAPs().\r
264\r
265**/\r
266VOID\r
267CheckAndUpdateAllAPsToIdleState (\r
268 VOID\r
269 )\r
270{\r
271 UINTN ProcessorNumber;\r
272 UINTN NextNumber;\r
273 CPU_DATA_BLOCK *CpuData;\r
274 EFI_STATUS Status;\r
275 CPU_STATE CpuState;\r
276\r
277 for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {\r
278 CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
279 if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
280 //\r
281 // Skip BSP\r
282 //\r
283 continue;\r
284 }\r
285\r
286 if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {\r
287 //\r
288 // Skip Disabled processors\r
289 //\r
290 continue;\r
291 }\r
292\r
293 CpuState = GetApState (CpuData);\r
294 if (CpuState == CpuStateFinished) {\r
295 mMpSystemData.FinishCount++;\r
296 if (mMpSystemData.SingleThread) {\r
297 Status = GetNextBlockedNumber (&NextNumber);\r
298 if (!EFI_ERROR (Status)) {\r
299 SetApState (&mMpSystemData.CpuDatas[NextNumber], CpuStateReady);\r
300 SetApProcedure (&mMpSystemData.CpuDatas[NextNumber],\r
301 mMpSystemData.Procedure,\r
302 mMpSystemData.ProcedureArgument);\r
68f06742
CF
303 //\r
304 // If this AP previous state is blocked, we should\r
305 // wake up this AP by sent a SIPI. and avoid\r
306 // re-involve the sleeping state. we must call\r
307 // SetApProcedure() first.\r
308 //\r
309 ResetProcessorToIdleState (&mMpSystemData.CpuDatas[NextNumber]);\r
5fee172f
CF
310 }\r
311 }\r
5fee172f
CF
312 SetApState (CpuData, CpuStateIdle);\r
313 }\r
314 }\r
315}\r
316\r
1aa6bf52
MK
317/**\r
318 Check if all APs are in state CpuStateSleeping.\r
319\r
320 Return TRUE if all APs are in the CpuStateSleeping state. Do not\r
321 check the state of the BSP or any disabled APs.\r
322\r
323 @retval TRUE All APs are in CpuStateSleeping state.\r
324 @retval FALSE One or more APs are not in CpuStateSleeping state.\r
325\r
326**/\r
327BOOLEAN\r
328CheckAllAPsSleeping (\r
329 VOID\r
330 )\r
331{\r
332 UINTN ProcessorNumber;\r
333 CPU_DATA_BLOCK *CpuData;\r
334\r
335 for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {\r
336 CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];\r
337 if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
338 //\r
339 // Skip BSP\r
340 //\r
341 continue;\r
342 }\r
343\r
344 if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {\r
345 //\r
346 // Skip Disabled processors\r
347 //\r
348 continue;\r
349 }\r
350\r
351 if (GetApState (CpuData) != CpuStateSleeping) {\r
352 return FALSE;\r
353 }\r
354 }\r
355 return TRUE;\r
356}\r
357\r
5fee172f
CF
358/**\r
359 If the timeout expires before all APs returns from Procedure,\r
360 we should forcibly terminate the executing AP and fill FailedList back\r
361 by StartupAllAPs().\r
362\r
363**/\r
364VOID\r
365ResetAllFailedAPs (\r
366 VOID\r
367 )\r
368{\r
369 CPU_DATA_BLOCK *CpuData;\r
370 UINTN Number;\r
371 CPU_STATE CpuState;\r
372\r
373 if (mMpSystemData.FailedList != NULL) {\r
374 *mMpSystemData.FailedList = AllocatePool ((mMpSystemData.StartCount - mMpSystemData.FinishCount + 1) * sizeof(UINTN));\r
375 ASSERT (*mMpSystemData.FailedList != NULL);\r
376 }\r
377\r
378 for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {\r
379 CpuData = &mMpSystemData.CpuDatas[Number];\r
380 if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {\r
381 //\r
382 // Skip BSP\r
383 //\r
384 continue;\r
385 }\r
386\r
387 if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {\r
388 //\r
389 // Skip Disabled processors\r
390 //\r
391 continue;\r
392 }\r
393\r
394 CpuState = GetApState (CpuData);\r
68f06742
CF
395 if (CpuState != CpuStateIdle &&\r
396 CpuState != CpuStateSleeping) {\r
5fee172f
CF
397 if (mMpSystemData.FailedList != NULL) {\r
398 (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex++] = Number;\r
399 }\r
400 ResetProcessorToIdleState (CpuData);\r
401 }\r
402 }\r
403\r
404 if (mMpSystemData.FailedList != NULL) {\r
405 (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex] = END_OF_CPU_LIST;\r
406 }\r
407}\r
408\r
d894d8b7
CF
409/**\r
410 This service retrieves the number of logical processor in the platform\r
411 and the number of those logical processors that are enabled on this boot.\r
412 This service may only be called from the BSP.\r
413\r
414 This function is used to retrieve the following information:\r
415 - The number of logical processors that are present in the system.\r
416 - The number of enabled logical processors in the system at the instant\r
417 this call is made.\r
418\r
419 Because MP Service Protocol provides services to enable and disable processors\r
420 dynamically, the number of enabled logical processors may vary during the\r
421 course of a boot session.\r
422\r
423 If this service is called from an AP, then EFI_DEVICE_ERROR is returned.\r
424 If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then\r
425 EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors\r
426 is returned in NumberOfProcessors, the number of currently enabled processor\r
427 is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.\r
428\r
429 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL\r
430 instance.\r
431 @param[out] NumberOfProcessors Pointer to the total number of logical\r
432 processors in the system, including the BSP\r
433 and disabled APs.\r
434 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical\r
435 processors that exist in system, including\r
436 the BSP.\r
437\r
438 @retval EFI_SUCCESS The number of logical processors and enabled\r
439 logical processors was retrieved.\r
440 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
441 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.\r
442 @retval EFI_INVALID_PARAMETER NumberOfEnabledProcessors is NULL.\r
443\r
444**/\r
445EFI_STATUS\r
446EFIAPI\r
447GetNumberOfProcessors (\r
448 IN EFI_MP_SERVICES_PROTOCOL *This,\r
449 OUT UINTN *NumberOfProcessors,\r
450 OUT UINTN *NumberOfEnabledProcessors\r
451 )\r
452{\r
453 if ((NumberOfProcessors == NULL) || (NumberOfEnabledProcessors == NULL)) {\r
454 return EFI_INVALID_PARAMETER;\r
455 }\r
456\r
7fadaacd
JF
457 return MpInitLibGetNumberOfProcessors (\r
458 NumberOfProcessors,\r
459 NumberOfEnabledProcessors\r
460 );\r
d894d8b7
CF
461}\r
462\r
e7938b5a
CF
463/**\r
464 Gets detailed MP-related information on the requested processor at the\r
465 instant this call is made. This service may only be called from the BSP.\r
466\r
467 This service retrieves detailed MP-related information about any processor\r
468 on the platform. Note the following:\r
469 - The processor information may change during the course of a boot session.\r
470 - The information presented here is entirely MP related.\r
471\r
472 Information regarding the number of caches and their sizes, frequency of operation,\r
473 slot numbers is all considered platform-related information and is not provided\r
474 by this service.\r
475\r
476 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL\r
477 instance.\r
478 @param[in] ProcessorNumber The handle number of processor.\r
479 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for\r
480 the requested processor is deposited.\r
481\r
482 @retval EFI_SUCCESS Processor information was returned.\r
483 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
484 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.\r
485 @retval EFI_NOT_FOUND The processor with the handle specified by\r
486 ProcessorNumber does not exist in the platform.\r
487\r
488**/\r
489EFI_STATUS\r
490EFIAPI\r
491GetProcessorInfo (\r
492 IN EFI_MP_SERVICES_PROTOCOL *This,\r
493 IN UINTN ProcessorNumber,\r
494 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer\r
495 )\r
496{\r
7fadaacd 497 return MpInitLibGetProcessorInfo (ProcessorNumber, ProcessorInfoBuffer, NULL);\r
e7938b5a
CF
498}\r
499\r
5fee172f
CF
500/**\r
501 This service executes a caller provided function on all enabled APs. APs can\r
502 run either simultaneously or one at a time in sequence. This service supports\r
503 both blocking and non-blocking requests. The non-blocking requests use EFI\r
504 events so the BSP can detect when the APs have finished. This service may only\r
505 be called from the BSP.\r
506\r
507 This function is used to dispatch all the enabled APs to the function specified\r
508 by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned\r
509 immediately and Procedure is not started on any AP.\r
510\r
511 If SingleThread is TRUE, all the enabled APs execute the function specified by\r
512 Procedure one by one, in ascending order of processor handle number. Otherwise,\r
513 all the enabled APs execute the function specified by Procedure simultaneously.\r
514\r
515 If WaitEvent is NULL, execution is in blocking mode. The BSP waits until all\r
516 APs finish or TimeoutInMicroseconds expires. Otherwise, execution is in non-blocking\r
517 mode, and the BSP returns from this service without waiting for APs. If a\r
518 non-blocking mode is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT\r
519 is signaled, then EFI_UNSUPPORTED must be returned.\r
520\r
521 If the timeout specified by TimeoutInMicroseconds expires before all APs return\r
522 from Procedure, then Procedure on the failed APs is terminated. All enabled APs\r
523 are always available for further calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()\r
524 and EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). If FailedCpuList is not NULL, its\r
525 content points to the list of processor handle numbers in which Procedure was\r
526 terminated.\r
527\r
528 Note: It is the responsibility of the consumer of the EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()\r
529 to make sure that the nature of the code that is executed on the BSP and the\r
530 dispatched APs is well controlled. The MP Services Protocol does not guarantee\r
531 that the Procedure function is MP-safe. Hence, the tasks that can be run in\r
532 parallel are limited to certain independent tasks and well-controlled exclusive\r
533 code. EFI services and protocols may not be called by APs unless otherwise\r
534 specified.\r
535\r
536 In blocking execution mode, BSP waits until all APs finish or\r
537 TimeoutInMicroseconds expires.\r
538\r
539 In non-blocking execution mode, BSP is freed to return to the caller and then\r
540 proceed to the next task without having to wait for APs. The following\r
541 sequence needs to occur in a non-blocking execution mode:\r
542\r
543 -# The caller that intends to use this MP Services Protocol in non-blocking\r
544 mode creates WaitEvent by calling the EFI CreateEvent() service. The caller\r
545 invokes EFI_MP_SERVICES_PROTOCOL.StartupAllAPs(). If the parameter WaitEvent\r
546 is not NULL, then StartupAllAPs() executes in non-blocking mode. It requests\r
547 the function specified by Procedure to be started on all the enabled APs,\r
548 and releases the BSP to continue with other tasks.\r
549 -# The caller can use the CheckEvent() and WaitForEvent() services to check\r
550 the state of the WaitEvent created in step 1.\r
551 -# When the APs complete their task or TimeoutInMicroSecondss expires, the MP\r
552 Service signals WaitEvent by calling the EFI SignalEvent() function. If\r
553 FailedCpuList is not NULL, its content is available when WaitEvent is\r
554 signaled. If all APs returned from Procedure prior to the timeout, then\r
555 FailedCpuList is set to NULL. If not all APs return from Procedure before\r
556 the timeout, then FailedCpuList is filled in with the list of the failed\r
557 APs. The buffer is allocated by MP Service Protocol using AllocatePool().\r
558 It is the caller's responsibility to free the buffer with FreePool() service.\r
559 -# This invocation of SignalEvent() function informs the caller that invoked\r
560 EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() that either all the APs completed\r
561 the specified task or a timeout occurred. The contents of FailedCpuList\r
562 can be examined to determine which APs did not complete the specified task\r
563 prior to the timeout.\r
564\r
565 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL\r
566 instance.\r
567 @param[in] Procedure A pointer to the function to be run on\r
568 enabled APs of the system. See type\r
569 EFI_AP_PROCEDURE.\r
570 @param[in] SingleThread If TRUE, then all the enabled APs execute\r
571 the function specified by Procedure one by\r
572 one, in ascending order of processor handle\r
573 number. If FALSE, then all the enabled APs\r
574 execute the function specified by Procedure\r
575 simultaneously.\r
576 @param[in] WaitEvent The event created by the caller with CreateEvent()\r
577 service. If it is NULL, then execute in\r
578 blocking mode. BSP waits until all APs finish\r
579 or TimeoutInMicroseconds expires. If it's\r
580 not NULL, then execute in non-blocking mode.\r
581 BSP requests the function specified by\r
582 Procedure to be started on all the enabled\r
583 APs, and go on executing immediately. If\r
584 all return from Procedure, or TimeoutInMicroseconds\r
585 expires, this event is signaled. The BSP\r
586 can use the CheckEvent() or WaitForEvent()\r
587 services to check the state of event. Type\r
588 EFI_EVENT is defined in CreateEvent() in\r
589 the Unified Extensible Firmware Interface\r
590 Specification.\r
591 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
592 APs to return from Procedure, either for\r
593 blocking or non-blocking mode. Zero means\r
594 infinity. If the timeout expires before\r
595 all APs return from Procedure, then Procedure\r
596 on the failed APs is terminated. All enabled\r
597 APs are available for next function assigned\r
598 by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()\r
599 or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().\r
600 If the timeout expires in blocking mode,\r
601 BSP returns EFI_TIMEOUT. If the timeout\r
602 expires in non-blocking mode, WaitEvent\r
603 is signaled with SignalEvent().\r
604 @param[in] ProcedureArgument The parameter passed into Procedure for\r
605 all APs.\r
606 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,\r
607 if all APs finish successfully, then its\r
608 content is set to NULL. If not all APs\r
609 finish before timeout expires, then its\r
610 content is set to address of the buffer\r
611 holding handle numbers of the failed APs.\r
612 The buffer is allocated by MP Service Protocol,\r
613 and it's the caller's responsibility to\r
614 free the buffer with FreePool() service.\r
615 In blocking mode, it is ready for consumption\r
616 when the call returns. In non-blocking mode,\r
617 it is ready when WaitEvent is signaled. The\r
618 list of failed CPU is terminated by\r
619 END_OF_CPU_LIST.\r
620\r
621 @retval EFI_SUCCESS In blocking mode, all APs have finished before\r
622 the timeout expired.\r
623 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched\r
624 to all enabled APs.\r
625 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the\r
626 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was\r
627 signaled.\r
628 @retval EFI_DEVICE_ERROR Caller processor is AP.\r
629 @retval EFI_NOT_STARTED No enabled APs exist in the system.\r
630 @retval EFI_NOT_READY Any enabled APs are busy.\r
631 @retval EFI_TIMEOUT In blocking mode, the timeout expired before\r
632 all enabled APs have finished.\r
633 @retval EFI_INVALID_PARAMETER Procedure is NULL.\r
634\r
635**/\r
636EFI_STATUS\r
637EFIAPI\r
638StartupAllAPs (\r
639 IN EFI_MP_SERVICES_PROTOCOL *This,\r
640 IN EFI_AP_PROCEDURE Procedure,\r
641 IN BOOLEAN SingleThread,\r
642 IN EFI_EVENT WaitEvent OPTIONAL,\r
643 IN UINTN TimeoutInMicroseconds,\r
644 IN VOID *ProcedureArgument OPTIONAL,\r
645 OUT UINTN **FailedCpuList OPTIONAL\r
646 )\r
647{\r
7fadaacd
JF
648 return MpInitLibStartupAllAPs (\r
649 Procedure,\r
650 SingleThread,\r
651 WaitEvent,\r
652 TimeoutInMicroseconds,\r
653 ProcedureArgument,\r
654 FailedCpuList\r
655 );\r
5fee172f
CF
656}\r
657\r
3f4f0af8
CF
658/**\r
659 This service lets the caller get one enabled AP to execute a caller-provided\r
660 function. The caller can request the BSP to either wait for the completion\r
661 of the AP or just proceed with the next task by using the EFI event mechanism.\r
662 See EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() for more details on non-blocking\r
663 execution support. This service may only be called from the BSP.\r
664\r
665 This function is used to dispatch one enabled AP to the function specified by\r
666 Procedure passing in the argument specified by ProcedureArgument. If WaitEvent\r
667 is NULL, execution is in blocking mode. The BSP waits until the AP finishes or\r
668 TimeoutInMicroSecondss expires. Otherwise, execution is in non-blocking mode.\r
669 BSP proceeds to the next task without waiting for the AP. If a non-blocking mode\r
670 is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled,\r
671 then EFI_UNSUPPORTED must be returned.\r
672\r
673 If the timeout specified by TimeoutInMicroseconds expires before the AP returns\r
674 from Procedure, then execution of Procedure by the AP is terminated. The AP is\r
675 available for subsequent calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() and\r
676 EFI_MP_SERVICES_PROTOCOL.StartupThisAP().\r
677\r
678 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL\r
679 instance.\r
680 @param[in] Procedure A pointer to the function to be run on\r
681 enabled APs of the system. See type\r
682 EFI_AP_PROCEDURE.\r
683 @param[in] ProcessorNumber The handle number of the AP. The range is\r
684 from 0 to the total number of logical\r
685 processors minus 1. The total number of\r
686 logical processors can be retrieved by\r
687 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().\r
688 @param[in] WaitEvent The event created by the caller with CreateEvent()\r
689 service. If it is NULL, then execute in\r
690 blocking mode. BSP waits until all APs finish\r
691 or TimeoutInMicroseconds expires. If it's\r
692 not NULL, then execute in non-blocking mode.\r
693 BSP requests the function specified by\r
694 Procedure to be started on all the enabled\r
695 APs, and go on executing immediately. If\r
696 all return from Procedure or TimeoutInMicroseconds\r
697 expires, this event is signaled. The BSP\r
698 can use the CheckEvent() or WaitForEvent()\r
699 services to check the state of event. Type\r
700 EFI_EVENT is defined in CreateEvent() in\r
701 the Unified Extensible Firmware Interface\r
702 Specification.\r
703 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
704 APs to return from Procedure, either for\r
705 blocking or non-blocking mode. Zero means\r
706 infinity. If the timeout expires before\r
707 all APs return from Procedure, then Procedure\r
708 on the failed APs is terminated. All enabled\r
709 APs are available for next function assigned\r
710 by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()\r
711 or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().\r
712 If the timeout expires in blocking mode,\r
713 BSP returns EFI_TIMEOUT. If the timeout\r
714 expires in non-blocking mode, WaitEvent\r
715 is signaled with SignalEvent().\r
716 @param[in] ProcedureArgument The parameter passed into Procedure for\r
717 all APs.\r
718 @param[out] Finished If NULL, this parameter is ignored. In\r
719 blocking mode, this parameter is ignored.\r
720 In non-blocking mode, if AP returns from\r
721 Procedure before the timeout expires, its\r
722 content is set to TRUE. Otherwise, the\r
723 value is set to FALSE. The caller can\r
724 determine if the AP returned from Procedure\r
725 by evaluating this value.\r
726\r
727 @retval EFI_SUCCESS In blocking mode, specified AP finished before\r
728 the timeout expires.\r
729 @retval EFI_SUCCESS In non-blocking mode, the function has been\r
730 dispatched to specified AP.\r
731 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the\r
732 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was\r
733 signaled.\r
734 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
735 @retval EFI_TIMEOUT In blocking mode, the timeout expired before\r
736 the specified AP has finished.\r
737 @retval EFI_NOT_READY The specified AP is busy.\r
738 @retval EFI_NOT_FOUND The processor with the handle specified by\r
739 ProcessorNumber does not exist.\r
740 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.\r
741 @retval EFI_INVALID_PARAMETER Procedure is NULL.\r
742\r
743**/\r
744EFI_STATUS\r
745EFIAPI\r
746StartupThisAP (\r
747 IN EFI_MP_SERVICES_PROTOCOL *This,\r
748 IN EFI_AP_PROCEDURE Procedure,\r
749 IN UINTN ProcessorNumber,\r
750 IN EFI_EVENT WaitEvent OPTIONAL,\r
751 IN UINTN TimeoutInMicroseconds,\r
752 IN VOID *ProcedureArgument OPTIONAL,\r
753 OUT BOOLEAN *Finished OPTIONAL\r
754 )\r
755{\r
7fadaacd
JF
756 return MpInitLibStartupThisAP (\r
757 Procedure,\r
758 ProcessorNumber,\r
759 WaitEvent,\r
760 TimeoutInMicroseconds,\r
761 ProcedureArgument,\r
762 Finished\r
763 );\r
3f4f0af8
CF
764}\r
765\r
b7c05ba5
CF
766/**\r
767 This service switches the requested AP to be the BSP from that point onward.\r
768 This service changes the BSP for all purposes. This call can only be performed\r
769 by the current BSP.\r
770\r
771 This service switches the requested AP to be the BSP from that point onward.\r
772 This service changes the BSP for all purposes. The new BSP can take over the\r
773 execution of the old BSP and continue seamlessly from where the old one left\r
774 off. This service may not be supported after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT\r
775 is signaled.\r
776\r
777 If the BSP cannot be switched prior to the return from this service, then\r
778 EFI_UNSUPPORTED must be returned.\r
779\r
780 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
781 @param[in] ProcessorNumber The handle number of AP that is to become the new\r
782 BSP. The range is from 0 to the total number of\r
783 logical processors minus 1. The total number of\r
784 logical processors can be retrieved by\r
785 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().\r
786 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an\r
787 enabled AP. Otherwise, it will be disabled.\r
788\r
789 @retval EFI_SUCCESS BSP successfully switched.\r
790 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to\r
791 this service returning.\r
792 @retval EFI_UNSUPPORTED Switching the BSP is not supported.\r
793 @retval EFI_SUCCESS The calling processor is an AP.\r
794 @retval EFI_NOT_FOUND The processor with the handle specified by\r
795 ProcessorNumber does not exist.\r
796 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or\r
797 a disabled AP.\r
798 @retval EFI_NOT_READY The specified AP is busy.\r
799\r
800**/\r
801EFI_STATUS\r
802EFIAPI\r
803SwitchBSP (\r
804 IN EFI_MP_SERVICES_PROTOCOL *This,\r
805 IN UINTN ProcessorNumber,\r
806 IN BOOLEAN EnableOldBSP\r
807 )\r
808{\r
7fadaacd 809 return MpInitLibSwitchBSP (ProcessorNumber, EnableOldBSP);\r
b7c05ba5
CF
810}\r
811\r
fa7ce675
CF
812/**\r
813 This service lets the caller enable or disable an AP from this point onward.\r
814 This service may only be called from the BSP.\r
815\r
816 This service allows the caller enable or disable an AP from this point onward.\r
817 The caller can optionally specify the health status of the AP by Health. If\r
818 an AP is being disabled, then the state of the disabled AP is implementation\r
819 dependent. If an AP is enabled, then the implementation must guarantee that a\r
820 complete initialization sequence is performed on the AP, so the AP is in a state\r
821 that is compatible with an MP operating system. This service may not be supported\r
822 after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled.\r
823\r
824 If the enable or disable AP operation cannot be completed prior to the return\r
825 from this service, then EFI_UNSUPPORTED must be returned.\r
826\r
827 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
828 @param[in] ProcessorNumber The handle number of AP that is to become the new\r
829 BSP. The range is from 0 to the total number of\r
830 logical processors minus 1. The total number of\r
831 logical processors can be retrieved by\r
832 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().\r
833 @param[in] EnableAP Specifies the new state for the processor for\r
834 enabled, FALSE for disabled.\r
835 @param[in] HealthFlag If not NULL, a pointer to a value that specifies\r
836 the new health status of the AP. This flag\r
837 corresponds to StatusFlag defined in\r
838 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only\r
839 the PROCESSOR_HEALTH_STATUS_BIT is used. All other\r
840 bits are ignored. If it is NULL, this parameter\r
841 is ignored.\r
842\r
843 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.\r
844 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed\r
845 prior to this service returning.\r
846 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.\r
847 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
848 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber\r
849 does not exist.\r
850 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.\r
851\r
852**/\r
853EFI_STATUS\r
854EFIAPI\r
855EnableDisableAP (\r
856 IN EFI_MP_SERVICES_PROTOCOL *This,\r
857 IN UINTN ProcessorNumber,\r
858 IN BOOLEAN EnableAP,\r
859 IN UINT32 *HealthFlag OPTIONAL\r
860 )\r
861{\r
7fadaacd 862 return MpInitLibEnableDisableAP (ProcessorNumber, EnableAP, HealthFlag);\r
fa7ce675
CF
863}\r
864\r
cfa2fac1
CF
865/**\r
866 This return the handle number for the calling processor. This service may be\r
867 called from the BSP and APs.\r
868\r
869 This service returns the processor handle number for the calling processor.\r
870 The returned value is in the range from 0 to the total number of logical\r
871 processors minus 1. The total number of logical processors can be retrieved\r
872 with EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be\r
873 called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER\r
874 is returned. Otherwise, the current processors handle number is returned in\r
875 ProcessorNumber, and EFI_SUCCESS is returned.\r
876\r
877 @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
878 @param[out] ProcessorNumber The handle number of AP that is to become the new\r
879 BSP. The range is from 0 to the total number of\r
880 logical processors minus 1. The total number of\r
881 logical processors can be retrieved by\r
882 EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().\r
883\r
884 @retval EFI_SUCCESS The current processor handle number was returned\r
885 in ProcessorNumber.\r
886 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.\r
887\r
888**/\r
889EFI_STATUS\r
890EFIAPI\r
891WhoAmI (\r
892 IN EFI_MP_SERVICES_PROTOCOL *This,\r
893 OUT UINTN *ProcessorNumber\r
894 )\r
895{\r
7fadaacd 896 return MpInitLibWhoAmI (ProcessorNumber);;\r
03673ae1 897}\r
1535c888 898\r
db61e163
JF
899/**\r
900 Collects BIST data from HOB.\r
901\r
902 This function collects BIST data from HOB built from Sec Platform Information\r
903 PPI or SEC Platform Information2 PPI.\r
904\r
905**/\r
906VOID\r
907CollectBistDataFromHob (\r
908 VOID\r
909 )\r
910{\r
911 EFI_HOB_GUID_TYPE *GuidHob;\r
912 EFI_SEC_PLATFORM_INFORMATION_RECORD2 *SecPlatformInformation2;\r
913 EFI_SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformation;\r
914 UINTN NumberOfData;\r
915 EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance;\r
916 EFI_SEC_PLATFORM_INFORMATION_CPU BspCpuInstance;\r
917 UINTN ProcessorNumber;\r
7fadaacd
JF
918 EFI_PROCESSOR_INFORMATION ProcessorInfo;\r
919 EFI_HEALTH_FLAGS BistData;\r
db61e163
JF
920\r
921 SecPlatformInformation2 = NULL;\r
922 SecPlatformInformation = NULL;\r
923\r
924 //\r
925 // Get gEfiSecPlatformInformation2PpiGuid Guided HOB firstly\r
926 //\r
927 GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformation2PpiGuid);\r
928 if (GuidHob != NULL) {\r
929 //\r
930 // Sec Platform Information2 PPI includes BSP/APs' BIST information\r
931 //\r
932 SecPlatformInformation2 = GET_GUID_HOB_DATA (GuidHob);\r
933 NumberOfData = SecPlatformInformation2->NumberOfCpus;\r
934 CpuInstance = SecPlatformInformation2->CpuInstance;\r
935 } else {\r
936 //\r
937 // Otherwise, get gEfiSecPlatformInformationPpiGuid Guided HOB\r
938 //\r
939 GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformationPpiGuid);\r
940 if (GuidHob != NULL) {\r
941 SecPlatformInformation = GET_GUID_HOB_DATA (GuidHob);\r
942 NumberOfData = 1;\r
943 //\r
944 // SEC Platform Information only includes BSP's BIST information\r
945 // does not have BSP's APIC ID\r
946 //\r
947 BspCpuInstance.CpuLocation = GetApicId ();\r
948 BspCpuInstance.InfoRecord.IA32HealthFlags.Uint32 = SecPlatformInformation->IA32HealthFlags.Uint32;\r
949 CpuInstance = &BspCpuInstance;\r
950 } else {\r
951 DEBUG ((EFI_D_INFO, "Does not find any HOB stored CPU BIST information!\n"));\r
952 //\r
953 // Does not find any HOB stored BIST information\r
954 //\r
955 return;\r
956 }\r
957 }\r
958\r
13181dde 959 while ((NumberOfData--) > 0) {\r
7fadaacd
JF
960 for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {\r
961 MpInitLibGetProcessorInfo (ProcessorNumber, &ProcessorInfo, &BistData);\r
962 if (ProcessorInfo.ProcessorId == CpuInstance[NumberOfData].CpuLocation) {\r
db61e163
JF
963 //\r
964 // Update CPU health status for MP Services Protocol according to BIST data.\r
965 //\r
7fadaacd
JF
966 BistData = CpuInstance[NumberOfData].InfoRecord.IA32HealthFlags;\r
967 }\r
968 if (BistData.Uint32 != 0) {\r
969 //\r
970 // Report Status Code that self test is failed\r
971 //\r
972 REPORT_STATUS_CODE (\r
973 EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
974 (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)\r
975 );\r
db61e163
JF
976 }\r
977 }\r
978 }\r
979}\r
980\r
9840b129
CF
981/**\r
982 Callback function for ExitBootServices.\r
983\r
984 @param Event Event whose notification function is being invoked.\r
985 @param Context The pointer to the notification function's context,\r
986 which is implementation-dependent.\r
987\r
988**/\r
989VOID\r
990EFIAPI\r
991ExitBootServicesCallback (\r
992 IN EFI_EVENT Event,\r
993 IN VOID *Context\r
994 )\r
995{\r
996 //\r
997 // Avoid APs access invalid buff datas which allocated by BootServices,\r
998 // so we send INIT IPI to APs to let them wait for SIPI state.\r
999 //\r
1000 SendInitIpiAllExcludingSelf ();\r
1001}\r
1002\r
94941c88
LE
1003/**\r
1004 A minimal wrapper function that allows MtrrSetAllMtrrs() to be passed to\r
1005 EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() as Procedure.\r
1006\r
1007 @param[in] Buffer Pointer to an MTRR_SETTINGS object, to be passed to\r
1008 MtrrSetAllMtrrs().\r
1009**/\r
1010VOID\r
1011EFIAPI\r
1012SetMtrrsFromBuffer (\r
1013 IN VOID *Buffer\r
1014 )\r
1015{\r
1016 MtrrSetAllMtrrs (Buffer);\r
1017}\r
1018\r
6022e28c
JJ
1019/**\r
1020 Initialize Multi-processor support.\r
1021\r
1022**/\r
1023VOID\r
1024InitializeMpSupport (\r
1025 VOID\r
1026 )\r
1027{\r
1aa6bf52 1028 EFI_STATUS Status;\r
7fadaacd
JF
1029 UINTN NumberOfProcessors;\r
1030 UINTN NumberOfEnabledProcessors;\r
4a50c272 1031\r
7fadaacd
JF
1032 NumberOfProcessors = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);\r
1033 if (NumberOfProcessors < 1) {\r
6a26a597
CF
1034 DEBUG ((DEBUG_ERROR, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n"));\r
1035 return;\r
1036 }\r
1037\r
6a26a597 1038 //\r
944f45ae 1039 // Only perform AP detection if PcdCpuMaxLogicalProcessorNumber is greater than 1\r
6a26a597 1040 //\r
7fadaacd
JF
1041 if (NumberOfProcessors > 1) {\r
1042 Status = MpInitLibInitialize ();\r
1043 ASSERT_EFI_ERROR (Status);\r
fe078dd5 1044\r
7fadaacd
JF
1045 MpInitLibGetNumberOfProcessors (&NumberOfProcessors, &NumberOfEnabledProcessors);\r
1046 mNumberOfProcessors = NumberOfProcessors;\r
6a26a597 1047 }\r
7fadaacd 1048 DEBUG ((EFI_D_ERROR, "Detect CPU count: %d\n", mNumberOfProcessors));\r
1aa6bf52 1049\r
db61e163
JF
1050 //\r
1051 // Update CPU healthy information from Guided HOB\r
1052 //\r
1053 CollectBistDataFromHob ();\r
1054\r
4a50c272
CF
1055 Status = gBS->InstallMultipleProtocolInterfaces (\r
1056 &mMpServiceHandle,\r
1057 &gEfiMpServiceProtocolGuid, &mMpServicesTemplate,\r
1058 NULL\r
1059 );\r
1060 ASSERT_EFI_ERROR (Status);\r
6a26a597 1061}\r
7fadaacd 1062\r