]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
UefiCpuPkg/MpInitLib: Use XADD to avoid lock acquire/release
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / PeiMpLib.c
CommitLineData
3e8ad6bd
JF
1/** @file\r
2 MP initialize support functions for PEI phase.\r
3\r
348a34d9 4 Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>\r
0acd8697 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
3e8ad6bd
JF
6\r
7**/\r
8\r
9#include "MpLib.h"\r
58942277
ED
10#include <Library/PeiServicesLib.h>\r
11#include <Guid/S3SmmInitDone.h>\r
c788c2b1 12#include <Ppi/ShadowMicrocode.h>\r
58942277
ED
13\r
14/**\r
15 S3 SMM Init Done notification function.\r
16\r
17 @param PeiServices Indirect reference to the PEI Services Table.\r
18 @param NotifyDesc Address of the notification descriptor data structure.\r
19 @param InvokePpi Address of the PPI that was invoked.\r
20\r
21 @retval EFI_SUCCESS The function completes successfully.\r
22\r
23**/\r
24EFI_STATUS\r
25EFIAPI\r
26NotifyOnS3SmmInitDonePpi (\r
27 IN EFI_PEI_SERVICES **PeiServices,\r
28 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
29 IN VOID *InvokePpi\r
30 );\r
31\r
32\r
33//\r
34// Global function\r
35//\r
36EFI_PEI_NOTIFY_DESCRIPTOR mS3SmmInitDoneNotifyDesc = {\r
37 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
38 &gEdkiiS3SmmInitDoneGuid,\r
39 NotifyOnS3SmmInitDonePpi\r
40};\r
41\r
58942277
ED
42/**\r
43 S3 SMM Init Done notification function.\r
44\r
45 @param PeiServices Indirect reference to the PEI Services Table.\r
46 @param NotifyDesc Address of the notification descriptor data structure.\r
47 @param InvokePpi Address of the PPI that was invoked.\r
48\r
49 @retval EFI_SUCCESS The function completes successfully.\r
50\r
51**/\r
52EFI_STATUS\r
53EFIAPI\r
54NotifyOnS3SmmInitDonePpi (\r
55 IN EFI_PEI_SERVICES **PeiServices,\r
56 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
57 IN VOID *InvokePpi\r
58 )\r
59{\r
60 CPU_MP_DATA *CpuMpData;\r
61\r
62 CpuMpData = GetCpuMpData ();\r
63\r
64 //\r
65 // PiSmmCpuDxeSmm driver hardcode change the loop mode to HLT mode.\r
66 // So in this notify function, code need to check the current loop\r
67 // mode, if it is not HLT mode, code need to change loop mode back\r
68 // to the original mode.\r
69 //\r
70 if (CpuMpData->ApLoopMode != ApInHltLoop) {\r
71 CpuMpData->WakeUpByInitSipiSipi = TRUE;\r
72 }\r
73\r
74 return EFI_SUCCESS;\r
75}\r
76\r
43c9fdcc
JF
77\r
78/**\r
79 Enable Debug Agent to support source debugging on AP function.\r
80\r
81**/\r
82VOID\r
83EnableDebugAgent (\r
84 VOID\r
85 )\r
86{\r
87}\r
88\r
93ca4c0f
JF
89/**\r
90 Get pointer to CPU MP Data structure.\r
c563077a
RN
91 For BSP, the pointer is retrieved from HOB.\r
92 For AP, the structure is just after IDT.\r
93ca4c0f
JF
93\r
94 @return The pointer to CPU MP Data structure.\r
95**/\r
96CPU_MP_DATA *\r
97GetCpuMpData (\r
98 VOID\r
99 )\r
100{\r
c563077a
RN
101 CPU_MP_DATA *CpuMpData;\r
102 MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;\r
103 IA32_DESCRIPTOR Idtr;\r
93ca4c0f 104\r
c563077a
RN
105 ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);\r
106 if (ApicBaseMsr.Bits.BSP == 1) {\r
107 CpuMpData = GetCpuMpDataFromGuidedHob ();\r
108 ASSERT (CpuMpData != NULL);\r
109 } else {\r
110 AsmReadIdtr (&Idtr);\r
111 CpuMpData = (CPU_MP_DATA *) (Idtr.Base + Idtr.Limit + 1);\r
112 }\r
93ca4c0f
JF
113 return CpuMpData;\r
114}\r
115\r
116/**\r
117 Save the pointer to CPU MP Data structure.\r
118\r
119 @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.\r
120**/\r
121VOID\r
122SaveCpuMpData (\r
123 IN CPU_MP_DATA *CpuMpData\r
124 )\r
125{\r
126 UINT64 Data64;\r
127 //\r
128 // Build location of CPU MP DATA buffer in HOB\r
129 //\r
130 Data64 = (UINT64) (UINTN) CpuMpData;\r
131 BuildGuidDataHob (\r
132 &mCpuInitMpLibHobGuid,\r
133 (VOID *) &Data64,\r
134 sizeof (UINT64)\r
135 );\r
136}\r
137\r
ed66e0e3
JF
138/**\r
139 Check if AP wakeup buffer is overlapped with existing allocated buffer.\r
140\r
141 @param[in] WakeupBufferStart AP wakeup buffer start address.\r
142 @param[in] WakeupBufferEnd AP wakeup buffer end address.\r
143\r
144 @retval TRUE There is overlap.\r
145 @retval FALSE There is no overlap.\r
146**/\r
147BOOLEAN\r
148CheckOverlapWithAllocatedBuffer (\r
5986cf38
RN
149 IN UINT64 WakeupBufferStart,\r
150 IN UINT64 WakeupBufferEnd\r
ed66e0e3
JF
151 )\r
152{\r
153 EFI_PEI_HOB_POINTERS Hob;\r
154 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
155 BOOLEAN Overlapped;\r
5986cf38
RN
156 UINT64 MemoryStart;\r
157 UINT64 MemoryEnd;\r
ed66e0e3
JF
158\r
159 Overlapped = FALSE;\r
160 //\r
161 // Get the HOB list for processing\r
162 //\r
163 Hob.Raw = GetHobList ();\r
164 //\r
165 // Collect memory ranges\r
166 //\r
167 while (!END_OF_HOB_LIST (Hob)) {\r
168 if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
169 MemoryHob = Hob.MemoryAllocation;\r
5986cf38
RN
170 MemoryStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
171 MemoryEnd = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength;\r
ed66e0e3
JF
172 if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {\r
173 Overlapped = TRUE;\r
174 break;\r
175 }\r
176 }\r
177 Hob.Raw = GET_NEXT_HOB (Hob);\r
178 }\r
179 return Overlapped;\r
180}\r
181\r
182/**\r
183 Get available system memory below 1MB by specified size.\r
184\r
185 @param[in] WakeupBufferSize Wakeup buffer size required\r
186\r
187 @retval other Return wakeup buffer address below 1MB.\r
188 @retval -1 Cannot find free memory below 1MB.\r
189**/\r
190UINTN\r
191GetWakeupBuffer (\r
192 IN UINTN WakeupBufferSize\r
193 )\r
194{\r
195 EFI_PEI_HOB_POINTERS Hob;\r
5986cf38
RN
196 UINT64 WakeupBufferStart;\r
197 UINT64 WakeupBufferEnd;\r
ed66e0e3
JF
198\r
199 WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);\r
200\r
201 //\r
202 // Get the HOB list for processing\r
203 //\r
204 Hob.Raw = GetHobList ();\r
205\r
206 //\r
207 // Collect memory ranges\r
208 //\r
209 while (!END_OF_HOB_LIST (Hob)) {\r
210 if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
211 if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&\r
212 (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&\r
213 ((Hob.ResourceDescriptor->ResourceAttribute &\r
214 (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |\r
215 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |\r
216 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED\r
217 )) == 0)\r
218 ) {\r
219 //\r
220 // Need memory under 1MB to be collected here\r
221 //\r
5986cf38 222 WakeupBufferEnd = Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength;\r
ed66e0e3
JF
223 if (WakeupBufferEnd > BASE_1MB) {\r
224 //\r
225 // Wakeup buffer should be under 1MB\r
226 //\r
227 WakeupBufferEnd = BASE_1MB;\r
228 }\r
229 while (WakeupBufferEnd > WakeupBufferSize) {\r
230 //\r
231 // Wakeup buffer should be aligned on 4KB\r
232 //\r
233 WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);\r
234 if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {\r
235 break;\r
236 }\r
237 if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {\r
238 //\r
239 // If this range is overlapped with existing allocated buffer, skip it\r
240 // and find the next range\r
241 //\r
242 WakeupBufferEnd -= WakeupBufferSize;\r
243 continue;\r
244 }\r
245 DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",\r
246 WakeupBufferStart, WakeupBufferSize));\r
5986cf38 247 return (UINTN)WakeupBufferStart;\r
ed66e0e3
JF
248 }\r
249 }\r
250 }\r
251 //\r
252 // Find the next HOB\r
253 //\r
254 Hob.Raw = GET_NEXT_HOB (Hob);\r
255 }\r
256\r
257 return (UINTN) -1;\r
258}\r
259\r
f32bfe6d
JW
260/**\r
261 Get available EfiBootServicesCode memory below 4GB by specified size.\r
262\r
263 This buffer is required to safely transfer AP from real address mode to\r
264 protected mode or long mode, due to the fact that the buffer returned by\r
265 GetWakeupBuffer() may be marked as non-executable.\r
266\r
267 @param[in] BufferSize Wakeup transition buffer size.\r
268\r
269 @retval other Return wakeup transition buffer address below 4GB.\r
270 @retval 0 Cannot find free memory below 4GB.\r
271**/\r
272UINTN\r
273GetModeTransitionBuffer (\r
274 IN UINTN BufferSize\r
275 )\r
276{\r
277 //\r
278 // PEI phase doesn't need to do such transition. So simply return 0.\r
279 //\r
280 return 0;\r
281}\r
282\r
7b7508ad
TL
283/**\r
284 Return the address of the SEV-ES AP jump table.\r
285\r
286 This buffer is required in order for an SEV-ES guest to transition from\r
287 UEFI into an OS.\r
288\r
289 @return Return SEV-ES AP jump table buffer\r
290**/\r
291UINTN\r
292GetSevEsAPMemory (\r
293 VOID\r
294 )\r
295{\r
296 //\r
297 // PEI phase doesn't need to do such transition. So simply return 0.\r
298 //\r
299 return 0;\r
300}\r
301\r
08085f08
JF
302/**\r
303 Checks APs status and updates APs status if needed.\r
304\r
305**/\r
306VOID\r
307CheckAndUpdateApsStatus (\r
308 VOID\r
309 )\r
310{\r
311}\r
312\r
e1ed5573
HW
313/**\r
314 Build the microcode patch HOB that contains the base address and size of the\r
315 microcode patch stored in the memory.\r
316\r
317 @param[in] CpuMpData Pointer to the CPU_MP_DATA structure.\r
318\r
319**/\r
320VOID\r
321BuildMicrocodeCacheHob (\r
322 IN CPU_MP_DATA *CpuMpData\r
323 )\r
324{\r
325 EDKII_MICROCODE_PATCH_HOB *MicrocodeHob;\r
326 UINTN HobDataLength;\r
327 UINT32 Index;\r
328\r
329 HobDataLength = sizeof (EDKII_MICROCODE_PATCH_HOB) +\r
330 sizeof (UINT64) * CpuMpData->CpuCount;\r
331\r
332 MicrocodeHob = AllocatePool (HobDataLength);\r
333 if (MicrocodeHob == NULL) {\r
334 ASSERT (FALSE);\r
335 return;\r
336 }\r
337\r
338 //\r
339 // Store the information of the memory region that holds the microcode patches.\r
340 //\r
341 MicrocodeHob->MicrocodePatchAddress = CpuMpData->MicrocodePatchAddress;\r
342 MicrocodeHob->MicrocodePatchRegionSize = CpuMpData->MicrocodePatchRegionSize;\r
343\r
344 //\r
345 // Store the detected microcode patch for each processor as well.\r
346 //\r
347 MicrocodeHob->ProcessorCount = CpuMpData->CpuCount;\r
348 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
349 if (CpuMpData->CpuData[Index].MicrocodeEntryAddr != 0) {\r
350 MicrocodeHob->ProcessorSpecificPatchOffset[Index] =\r
351 CpuMpData->CpuData[Index].MicrocodeEntryAddr - CpuMpData->MicrocodePatchAddress;\r
352 } else {\r
353 MicrocodeHob->ProcessorSpecificPatchOffset[Index] = MAX_UINT64;\r
354 }\r
355 }\r
356\r
357 BuildGuidDataHob (\r
358 &gEdkiiMicrocodePatchHobGuid,\r
359 MicrocodeHob,\r
360 HobDataLength\r
361 );\r
362\r
363 return;\r
364}\r
365\r
93ca4c0f
JF
366/**\r
367 Initialize global data for MP support.\r
368\r
369 @param[in] CpuMpData The pointer to CPU MP Data structure.\r
370**/\r
371VOID\r
372InitMpGlobalData (\r
373 IN CPU_MP_DATA *CpuMpData\r
374 )\r
375{\r
58942277
ED
376 EFI_STATUS Status;\r
377\r
e1ed5573 378 BuildMicrocodeCacheHob (CpuMpData);\r
93ca4c0f 379 SaveCpuMpData (CpuMpData);\r
58942277
ED
380\r
381 ///\r
382 /// Install Notify\r
383 ///\r
384 Status = PeiServicesNotifyPpi (&mS3SmmInitDoneNotifyDesc);\r
385 ASSERT_EFI_ERROR (Status);\r
93ca4c0f
JF
386}\r
387\r
3e8ad6bd
JF
388/**\r
389 This service executes a caller provided function on all enabled APs.\r
390\r
391 @param[in] Procedure A pointer to the function to be run on\r
392 enabled APs of the system. See type\r
393 EFI_AP_PROCEDURE.\r
394 @param[in] SingleThread If TRUE, then all the enabled APs execute\r
395 the function specified by Procedure one by\r
396 one, in ascending order of processor handle\r
397 number. If FALSE, then all the enabled APs\r
398 execute the function specified by Procedure\r
399 simultaneously.\r
400 @param[in] WaitEvent The event created by the caller with CreateEvent()\r
401 service. If it is NULL, then execute in\r
402 blocking mode. BSP waits until all APs finish\r
403 or TimeoutInMicroSeconds expires. If it's\r
404 not NULL, then execute in non-blocking mode.\r
405 BSP requests the function specified by\r
406 Procedure to be started on all the enabled\r
407 APs, and go on executing immediately. If\r
408 all return from Procedure, or TimeoutInMicroSeconds\r
409 expires, this event is signaled. The BSP\r
410 can use the CheckEvent() or WaitForEvent()\r
411 services to check the state of event. Type\r
412 EFI_EVENT is defined in CreateEvent() in\r
413 the Unified Extensible Firmware Interface\r
414 Specification.\r
367284e7 415 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
3e8ad6bd
JF
416 APs to return from Procedure, either for\r
417 blocking or non-blocking mode. Zero means\r
418 infinity. If the timeout expires before\r
419 all APs return from Procedure, then Procedure\r
420 on the failed APs is terminated. All enabled\r
421 APs are available for next function assigned\r
422 by MpInitLibStartupAllAPs() or\r
423 MPInitLibStartupThisAP().\r
424 If the timeout expires in blocking mode,\r
425 BSP returns EFI_TIMEOUT. If the timeout\r
426 expires in non-blocking mode, WaitEvent\r
427 is signaled with SignalEvent().\r
428 @param[in] ProcedureArgument The parameter passed into Procedure for\r
429 all APs.\r
430 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,\r
431 if all APs finish successfully, then its\r
432 content is set to NULL. If not all APs\r
433 finish before timeout expires, then its\r
434 content is set to address of the buffer\r
435 holding handle numbers of the failed APs.\r
436 The buffer is allocated by MP Initialization\r
437 library, and it's the caller's responsibility to\r
438 free the buffer with FreePool() service.\r
439 In blocking mode, it is ready for consumption\r
440 when the call returns. In non-blocking mode,\r
441 it is ready when WaitEvent is signaled. The\r
442 list of failed CPU is terminated by\r
443 END_OF_CPU_LIST.\r
444\r
445 @retval EFI_SUCCESS In blocking mode, all APs have finished before\r
446 the timeout expired.\r
447 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched\r
448 to all enabled APs.\r
449 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the\r
450 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was\r
451 signaled.\r
452 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not\r
453 supported.\r
454 @retval EFI_DEVICE_ERROR Caller processor is AP.\r
455 @retval EFI_NOT_STARTED No enabled APs exist in the system.\r
456 @retval EFI_NOT_READY Any enabled APs are busy.\r
457 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
458 @retval EFI_TIMEOUT In blocking mode, the timeout expired before\r
459 all enabled APs have finished.\r
460 @retval EFI_INVALID_PARAMETER Procedure is NULL.\r
461\r
462**/\r
463EFI_STATUS\r
464EFIAPI\r
465MpInitLibStartupAllAPs (\r
466 IN EFI_AP_PROCEDURE Procedure,\r
467 IN BOOLEAN SingleThread,\r
468 IN EFI_EVENT WaitEvent OPTIONAL,\r
469 IN UINTN TimeoutInMicroseconds,\r
470 IN VOID *ProcedureArgument OPTIONAL,\r
471 OUT UINTN **FailedCpuList OPTIONAL\r
472 )\r
473{\r
86efe976
JF
474 if (WaitEvent != NULL) {\r
475 return EFI_UNSUPPORTED;\r
476 }\r
477\r
ee0c39fa 478 return StartupAllCPUsWorker (\r
86efe976
JF
479 Procedure,\r
480 SingleThread,\r
ee0c39fa 481 TRUE,\r
86efe976
JF
482 NULL,\r
483 TimeoutInMicroseconds,\r
484 ProcedureArgument,\r
485 FailedCpuList\r
486 );\r
3e8ad6bd
JF
487}\r
488\r
489/**\r
490 This service lets the caller get one enabled AP to execute a caller-provided\r
491 function.\r
492\r
493 @param[in] Procedure A pointer to the function to be run on the\r
494 designated AP of the system. See type\r
495 EFI_AP_PROCEDURE.\r
496 @param[in] ProcessorNumber The handle number of the AP. The range is\r
497 from 0 to the total number of logical\r
498 processors minus 1. The total number of\r
499 logical processors can be retrieved by\r
500 MpInitLibGetNumberOfProcessors().\r
501 @param[in] WaitEvent The event created by the caller with CreateEvent()\r
502 service. If it is NULL, then execute in\r
503 blocking mode. BSP waits until this AP finish\r
504 or TimeoutInMicroSeconds expires. If it's\r
505 not NULL, then execute in non-blocking mode.\r
506 BSP requests the function specified by\r
507 Procedure to be started on this AP,\r
508 and go on executing immediately. If this AP\r
509 return from Procedure or TimeoutInMicroSeconds\r
510 expires, this event is signaled. The BSP\r
511 can use the CheckEvent() or WaitForEvent()\r
512 services to check the state of event. Type\r
513 EFI_EVENT is defined in CreateEvent() in\r
514 the Unified Extensible Firmware Interface\r
515 Specification.\r
367284e7 516 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
3e8ad6bd
JF
517 this AP to finish this Procedure, either for\r
518 blocking or non-blocking mode. Zero means\r
519 infinity. If the timeout expires before\r
520 this AP returns from Procedure, then Procedure\r
521 on the AP is terminated. The\r
522 AP is available for next function assigned\r
523 by MpInitLibStartupAllAPs() or\r
524 MpInitLibStartupThisAP().\r
525 If the timeout expires in blocking mode,\r
526 BSP returns EFI_TIMEOUT. If the timeout\r
527 expires in non-blocking mode, WaitEvent\r
528 is signaled with SignalEvent().\r
529 @param[in] ProcedureArgument The parameter passed into Procedure on the\r
530 specified AP.\r
531 @param[out] Finished If NULL, this parameter is ignored. In\r
532 blocking mode, this parameter is ignored.\r
533 In non-blocking mode, if AP returns from\r
534 Procedure before the timeout expires, its\r
535 content is set to TRUE. Otherwise, the\r
536 value is set to FALSE. The caller can\r
537 determine if the AP returned from Procedure\r
538 by evaluating this value.\r
539\r
540 @retval EFI_SUCCESS In blocking mode, specified AP finished before\r
541 the timeout expires.\r
542 @retval EFI_SUCCESS In non-blocking mode, the function has been\r
543 dispatched to specified AP.\r
544 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the\r
545 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was\r
546 signaled.\r
547 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not\r
548 supported.\r
549 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
550 @retval EFI_TIMEOUT In blocking mode, the timeout expired before\r
551 the specified AP has finished.\r
552 @retval EFI_NOT_READY The specified AP is busy.\r
553 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
554 @retval EFI_NOT_FOUND The processor with the handle specified by\r
555 ProcessorNumber does not exist.\r
556 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.\r
557 @retval EFI_INVALID_PARAMETER Procedure is NULL.\r
558\r
559**/\r
560EFI_STATUS\r
561EFIAPI\r
562MpInitLibStartupThisAP (\r
563 IN EFI_AP_PROCEDURE Procedure,\r
564 IN UINTN ProcessorNumber,\r
565 IN EFI_EVENT WaitEvent OPTIONAL,\r
566 IN UINTN TimeoutInMicroseconds,\r
567 IN VOID *ProcedureArgument OPTIONAL,\r
568 OUT BOOLEAN *Finished OPTIONAL\r
569 )\r
570{\r
20ae5774
JF
571 if (WaitEvent != NULL) {\r
572 return EFI_UNSUPPORTED;\r
573 }\r
574\r
575 return StartupThisAPWorker (\r
576 Procedure,\r
577 ProcessorNumber,\r
578 NULL,\r
579 TimeoutInMicroseconds,\r
580 ProcedureArgument,\r
581 Finished\r
582 );\r
3e8ad6bd
JF
583}\r
584\r
585/**\r
586 This service switches the requested AP to be the BSP from that point onward.\r
587 This service changes the BSP for all purposes. This call can only be performed\r
588 by the current BSP.\r
589\r
590 @param[in] ProcessorNumber The handle number of AP that is to become the new\r
591 BSP. The range is from 0 to the total number of\r
592 logical processors minus 1. The total number of\r
593 logical processors can be retrieved by\r
594 MpInitLibGetNumberOfProcessors().\r
595 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an\r
596 enabled AP. Otherwise, it will be disabled.\r
597\r
598 @retval EFI_SUCCESS BSP successfully switched.\r
599 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to\r
600 this service returning.\r
601 @retval EFI_UNSUPPORTED Switching the BSP is not supported.\r
602 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
603 @retval EFI_NOT_FOUND The processor with the handle specified by\r
604 ProcessorNumber does not exist.\r
605 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or\r
606 a disabled AP.\r
607 @retval EFI_NOT_READY The specified AP is busy.\r
608 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
609\r
610**/\r
611EFI_STATUS\r
612EFIAPI\r
613MpInitLibSwitchBSP (\r
614 IN UINTN ProcessorNumber,\r
615 IN BOOLEAN EnableOldBSP\r
616 )\r
617{\r
41be0da5 618 return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);\r
3e8ad6bd
JF
619}\r
620\r
621/**\r
622 This service lets the caller enable or disable an AP from this point onward.\r
623 This service may only be called from the BSP.\r
624\r
625 @param[in] ProcessorNumber The handle number of AP.\r
626 The range is from 0 to the total number of\r
627 logical processors minus 1. The total number of\r
628 logical processors can be retrieved by\r
629 MpInitLibGetNumberOfProcessors().\r
630 @param[in] EnableAP Specifies the new state for the processor for\r
631 enabled, FALSE for disabled.\r
632 @param[in] HealthFlag If not NULL, a pointer to a value that specifies\r
633 the new health status of the AP. This flag\r
634 corresponds to StatusFlag defined in\r
635 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only\r
636 the PROCESSOR_HEALTH_STATUS_BIT is used. All other\r
637 bits are ignored. If it is NULL, this parameter\r
638 is ignored.\r
639\r
640 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.\r
641 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed\r
642 prior to this service returning.\r
643 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.\r
644 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
645 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber\r
646 does not exist.\r
647 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.\r
648 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
649\r
650**/\r
651EFI_STATUS\r
652EFIAPI\r
653MpInitLibEnableDisableAP (\r
654 IN UINTN ProcessorNumber,\r
655 IN BOOLEAN EnableAP,\r
656 IN UINT32 *HealthFlag OPTIONAL\r
657 )\r
658{\r
e37109bc 659 return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);\r
3e8ad6bd
JF
660}\r
661\r
c788c2b1
SF
662/**\r
663 This funtion will try to invoke platform specific microcode shadow logic to\r
664 relocate microcode update patches into memory.\r
665\r
4ac82ea1 666 @param[in, out] CpuMpData The pointer to CPU MP Data structure.\r
3e8ad6bd 667\r
c788c2b1
SF
668 @retval EFI_SUCCESS Shadow microcode success.\r
669 @retval EFI_OUT_OF_RESOURCES No enough resource to complete the operation.\r
670 @retval EFI_UNSUPPORTED Can't find platform specific microcode shadow\r
671 PPI/Protocol.\r
672**/\r
673EFI_STATUS\r
674PlatformShadowMicrocode (\r
675 IN OUT CPU_MP_DATA *CpuMpData\r
676 )\r
677{\r
678 EFI_STATUS Status;\r
679 EDKII_PEI_SHADOW_MICROCODE_PPI *ShadowMicrocodePpi;\r
680 UINTN CpuCount;\r
681 EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuId;\r
682 UINTN Index;\r
683 UINTN BufferSize;\r
684 VOID *Buffer;\r
685\r
686 Status = PeiServicesLocatePpi (\r
687 &gEdkiiPeiShadowMicrocodePpiGuid,\r
688 0,\r
689 NULL,\r
690 (VOID **) &ShadowMicrocodePpi\r
691 );\r
692 if (EFI_ERROR (Status)) {\r
693 return EFI_UNSUPPORTED;\r
694 }\r
695\r
696 CpuCount = CpuMpData->CpuCount;\r
697 MicrocodeCpuId = (EDKII_PEI_MICROCODE_CPU_ID *) AllocateZeroPool (sizeof (EDKII_PEI_MICROCODE_CPU_ID) * CpuCount);\r
698 if (MicrocodeCpuId == NULL) {\r
699 return EFI_OUT_OF_RESOURCES;\r
700 }\r
701\r
702 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
703 MicrocodeCpuId[Index].ProcessorSignature = CpuMpData->CpuData[Index].ProcessorSignature;\r
704 MicrocodeCpuId[Index].PlatformId = CpuMpData->CpuData[Index].PlatformId;\r
705 }\r
706\r
707 Status = ShadowMicrocodePpi->ShadowMicrocode (\r
708 ShadowMicrocodePpi,\r
709 CpuCount,\r
710 MicrocodeCpuId,\r
711 &BufferSize,\r
712 &Buffer\r
713 );\r
714 FreePool (MicrocodeCpuId);\r
715 if (EFI_ERROR (Status)) {\r
716 return EFI_NOT_FOUND;\r
717 }\r
718\r
719 CpuMpData->MicrocodePatchAddress = (UINTN) Buffer;\r
720 CpuMpData->MicrocodePatchRegionSize = BufferSize;\r
721\r
722 DEBUG ((\r
723 DEBUG_INFO,\r
724 "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",\r
725 __FUNCTION__, CpuMpData->MicrocodePatchAddress, CpuMpData->MicrocodePatchRegionSize\r
726 ));\r
727\r
728 return EFI_SUCCESS;\r
729}\r