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