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