UefiCpuPkg/MpInitLib: Add ApWakeupFunction() executed by assembly code
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / MpLib.c
CommitLineData
3e8ad6bd
JF
1/** @file\r
2 CPU MP Initialize Library common functions.\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
16\r
93ca4c0f
JF
17EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;\r
18\r
03a1a925
JF
19/**\r
20 Get the Application Processors state.\r
21\r
22 @param[in] CpuData The pointer to CPU_AP_DATA of specified AP\r
23\r
24 @return The AP status\r
25**/\r
26CPU_STATE\r
27GetApState (\r
28 IN CPU_AP_DATA *CpuData\r
29 )\r
30{\r
31 return CpuData->State;\r
32}\r
33\r
34/**\r
35 Set the Application Processors state.\r
36\r
37 @param[in] CpuData The pointer to CPU_AP_DATA of specified AP\r
38 @param[in] State The AP status\r
39**/\r
40VOID\r
41SetApState (\r
42 IN CPU_AP_DATA *CpuData,\r
43 IN CPU_STATE State\r
44 )\r
45{\r
46 AcquireSpinLock (&CpuData->ApLock);\r
47 CpuData->State = State;\r
48 ReleaseSpinLock (&CpuData->ApLock);\r
49}\r
3e8ad6bd 50\r
68cb9330
JF
51/**\r
52 Save the volatile registers required to be restored following INIT IPI.\r
53\r
54 @param[out] VolatileRegisters Returns buffer saved the volatile resisters\r
55**/\r
56VOID\r
57SaveVolatileRegisters (\r
58 OUT CPU_VOLATILE_REGISTERS *VolatileRegisters\r
59 )\r
60{\r
61 CPUID_VERSION_INFO_EDX VersionInfoEdx;\r
62\r
63 VolatileRegisters->Cr0 = AsmReadCr0 ();\r
64 VolatileRegisters->Cr3 = AsmReadCr3 ();\r
65 VolatileRegisters->Cr4 = AsmReadCr4 ();\r
66\r
67 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);\r
68 if (VersionInfoEdx.Bits.DE != 0) {\r
69 //\r
70 // If processor supports Debugging Extensions feature\r
71 // by CPUID.[EAX=01H]:EDX.BIT2\r
72 //\r
73 VolatileRegisters->Dr0 = AsmReadDr0 ();\r
74 VolatileRegisters->Dr1 = AsmReadDr1 ();\r
75 VolatileRegisters->Dr2 = AsmReadDr2 ();\r
76 VolatileRegisters->Dr3 = AsmReadDr3 ();\r
77 VolatileRegisters->Dr6 = AsmReadDr6 ();\r
78 VolatileRegisters->Dr7 = AsmReadDr7 ();\r
79 }\r
80}\r
81\r
82/**\r
83 Restore the volatile registers following INIT IPI.\r
84\r
85 @param[in] VolatileRegisters Pointer to volatile resisters\r
86 @param[in] IsRestoreDr TRUE: Restore DRx if supported\r
87 FALSE: Do not restore DRx\r
88**/\r
89VOID\r
90RestoreVolatileRegisters (\r
91 IN CPU_VOLATILE_REGISTERS *VolatileRegisters,\r
92 IN BOOLEAN IsRestoreDr\r
93 )\r
94{\r
95 CPUID_VERSION_INFO_EDX VersionInfoEdx;\r
96\r
97 AsmWriteCr0 (VolatileRegisters->Cr0);\r
98 AsmWriteCr3 (VolatileRegisters->Cr3);\r
99 AsmWriteCr4 (VolatileRegisters->Cr4);\r
100\r
101 if (IsRestoreDr) {\r
102 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);\r
103 if (VersionInfoEdx.Bits.DE != 0) {\r
104 //\r
105 // If processor supports Debugging Extensions feature\r
106 // by CPUID.[EAX=01H]:EDX.BIT2\r
107 //\r
108 AsmWriteDr0 (VolatileRegisters->Dr0);\r
109 AsmWriteDr1 (VolatileRegisters->Dr1);\r
110 AsmWriteDr2 (VolatileRegisters->Dr2);\r
111 AsmWriteDr3 (VolatileRegisters->Dr3);\r
112 AsmWriteDr6 (VolatileRegisters->Dr6);\r
113 AsmWriteDr7 (VolatileRegisters->Dr7);\r
114 }\r
115 }\r
116}\r
117\r
9ebcf0f4
JF
118/**\r
119 Detect whether Mwait-monitor feature is supported.\r
120\r
121 @retval TRUE Mwait-monitor feature is supported.\r
122 @retval FALSE Mwait-monitor feature is not supported.\r
123**/\r
124BOOLEAN\r
125IsMwaitSupport (\r
126 VOID\r
127 )\r
128{\r
129 CPUID_VERSION_INFO_ECX VersionInfoEcx;\r
130\r
131 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &VersionInfoEcx.Uint32, NULL);\r
132 return (VersionInfoEcx.Bits.MONITOR == 1) ? TRUE : FALSE;\r
133}\r
134\r
135/**\r
136 Get AP loop mode.\r
137\r
138 @param[out] MonitorFilterSize Returns the largest monitor-line size in bytes.\r
139\r
140 @return The AP loop mode.\r
141**/\r
142UINT8\r
143GetApLoopMode (\r
144 OUT UINT32 *MonitorFilterSize\r
145 )\r
146{\r
147 UINT8 ApLoopMode;\r
148 CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx;\r
149\r
150 ASSERT (MonitorFilterSize != NULL);\r
151\r
152 ApLoopMode = PcdGet8 (PcdCpuApLoopMode);\r
153 ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop);\r
154 if (ApLoopMode == ApInMwaitLoop) {\r
155 if (!IsMwaitSupport ()) {\r
156 //\r
157 // If processor does not support MONITOR/MWAIT feature,\r
158 // force AP in Hlt-loop mode\r
159 //\r
160 ApLoopMode = ApInHltLoop;\r
161 }\r
162 }\r
163\r
164 if (ApLoopMode != ApInMwaitLoop) {\r
165 *MonitorFilterSize = sizeof (UINT32);\r
166 } else {\r
167 //\r
168 // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes\r
169 // CPUID.[EAX=05H].EDX: C-states supported using MWAIT\r
170 //\r
171 AsmCpuid (CPUID_MONITOR_MWAIT, NULL, &MonitorMwaitEbx.Uint32, NULL, NULL);\r
172 *MonitorFilterSize = MonitorMwaitEbx.Bits.LargestMonitorLineSize;\r
173 }\r
174\r
175 return ApLoopMode;\r
176}\r
b8b04307
JF
177\r
178/**\r
179 Do sync on APs.\r
180\r
181 @param[in, out] Buffer Pointer to private data buffer.\r
182**/\r
183VOID\r
184EFIAPI\r
185ApInitializeSync (\r
186 IN OUT VOID *Buffer\r
187 )\r
188{\r
189 CPU_MP_DATA *CpuMpData;\r
190\r
191 CpuMpData = (CPU_MP_DATA *) Buffer;\r
192 //\r
193 // Sync BSP's MTRR table to AP\r
194 //\r
195 MtrrSetAllMtrrs (&CpuMpData->MtrrTable);\r
196 //\r
197 // Load microcode on AP\r
198 //\r
199 MicrocodeDetect (CpuMpData);\r
200}\r
201\r
202/**\r
203 Find the current Processor number by APIC ID.\r
204\r
205 @param[in] CpuMpData Pointer to PEI CPU MP Data\r
206 @param[in] ProcessorNumber Return the pocessor number found\r
207\r
208 @retval EFI_SUCCESS ProcessorNumber is found and returned.\r
209 @retval EFI_NOT_FOUND ProcessorNumber is not found.\r
210**/\r
211EFI_STATUS\r
212GetProcessorNumber (\r
213 IN CPU_MP_DATA *CpuMpData,\r
214 OUT UINTN *ProcessorNumber\r
215 )\r
216{\r
217 UINTN TotalProcessorNumber;\r
218 UINTN Index;\r
219\r
220 TotalProcessorNumber = CpuMpData->CpuCount;\r
221 for (Index = 0; Index < TotalProcessorNumber; Index ++) {\r
222 if (CpuMpData->CpuData[Index].ApicId == GetApicId ()) {\r
223 *ProcessorNumber = Index;\r
224 return EFI_SUCCESS;\r
225 }\r
226 }\r
227 return EFI_NOT_FOUND;\r
228}\r
229\r
03a1a925
JF
230/*\r
231 Initialize CPU AP Data when AP is wakeup at the first time.\r
232\r
233 @param[in, out] CpuMpData Pointer to PEI CPU MP Data\r
234 @param[in] ProcessorNumber The handle number of processor\r
235 @param[in] BistData Processor BIST data\r
236\r
237**/\r
238VOID\r
239InitializeApData (\r
240 IN OUT CPU_MP_DATA *CpuMpData,\r
241 IN UINTN ProcessorNumber,\r
242 IN UINT32 BistData\r
243 )\r
244{\r
245 CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;\r
246 CpuMpData->CpuData[ProcessorNumber].Health = BistData;\r
247 CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;\r
248 CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId ();\r
249 CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
250 if (CpuMpData->CpuData[ProcessorNumber].InitialApicId >= 0xFF) {\r
251 //\r
252 // Set x2APIC mode if there are any logical processor reporting\r
253 // an Initial APIC ID of 255 or greater.\r
254 //\r
255 AcquireSpinLock(&CpuMpData->MpLock);\r
256 CpuMpData->X2ApicEnable = TRUE;\r
257 ReleaseSpinLock(&CpuMpData->MpLock);\r
258 }\r
259\r
260 InitializeSpinLock(&CpuMpData->CpuData[ProcessorNumber].ApLock);\r
261 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);\r
262}\r
263\r
b8b04307
JF
264/**\r
265 This function will be called from AP reset code if BSP uses WakeUpAP.\r
266\r
267 @param[in] ExchangeInfo Pointer to the MP exchange info buffer\r
268 @param[in] NumApsExecuting Number of current executing AP\r
269**/\r
270VOID\r
271EFIAPI\r
272ApWakeupFunction (\r
273 IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,\r
274 IN UINTN NumApsExecuting\r
275 )\r
276{\r
277 CPU_MP_DATA *CpuMpData;\r
278 UINTN ProcessorNumber;\r
279 EFI_AP_PROCEDURE Procedure;\r
280 VOID *Parameter;\r
281 UINT32 BistData;\r
282 volatile UINT32 *ApStartupSignalBuffer;\r
283\r
284 //\r
285 // AP finished assembly code and begin to execute C code\r
286 //\r
287 CpuMpData = ExchangeInfo->CpuMpData;\r
288\r
289 ProgramVirtualWireMode (); \r
290\r
291 while (TRUE) {\r
292 if (CpuMpData->InitFlag == ApInitConfig) {\r
293 //\r
294 // Add CPU number\r
295 //\r
296 InterlockedIncrement ((UINT32 *) &CpuMpData->CpuCount);\r
297 ProcessorNumber = NumApsExecuting;\r
298 //\r
299 // This is first time AP wakeup, get BIST information from AP stack\r
300 //\r
301 BistData = *(UINT32 *) (CpuMpData->Buffer + ProcessorNumber * CpuMpData->CpuApStackSize - sizeof (UINTN));\r
302 //\r
303 // Do some AP initialize sync\r
304 //\r
305 ApInitializeSync (CpuMpData);\r
306 //\r
307 // Sync BSP's Control registers to APs\r
308 //\r
309 RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);\r
310 InitializeApData (CpuMpData, ProcessorNumber, BistData);\r
311 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;\r
312 } else {\r
313 //\r
314 // Execute AP function if AP is ready\r
315 //\r
316 GetProcessorNumber (CpuMpData, &ProcessorNumber);\r
317 //\r
318 // Clear AP start-up signal when AP waken up\r
319 //\r
320 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;\r
321 InterlockedCompareExchange32 (\r
322 (UINT32 *) ApStartupSignalBuffer,\r
323 WAKEUP_AP_SIGNAL,\r
324 0\r
325 );\r
326 if (CpuMpData->ApLoopMode == ApInHltLoop) {\r
327 //\r
328 // Restore AP's volatile registers saved\r
329 //\r
330 RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);\r
331 }\r
332\r
333 if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) {\r
334 Procedure = (EFI_AP_PROCEDURE)CpuMpData->CpuData[ProcessorNumber].ApFunction;\r
335 Parameter = (VOID *) CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument;\r
336 if (Procedure != NULL) {\r
337 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateBusy);\r
338 //\r
339 // Invoke AP function here\r
340 //\r
341 Procedure (Parameter);\r
342 //\r
343 // Re-get the CPU APICID and Initial APICID\r
344 //\r
345 CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId ();\r
346 CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
347 }\r
348 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished);\r
349 }\r
350 }\r
351\r
352 //\r
353 // AP finished executing C code\r
354 //\r
355 InterlockedIncrement ((UINT32 *) &CpuMpData->FinishedCount);\r
356\r
357 //\r
358 // Place AP is specified loop mode\r
359 //\r
360 if (CpuMpData->ApLoopMode == ApInHltLoop) {\r
361 //\r
362 // Save AP volatile registers\r
363 //\r
364 SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);\r
365 //\r
366 // Place AP in HLT-loop\r
367 //\r
368 while (TRUE) {\r
369 DisableInterrupts ();\r
370 CpuSleep ();\r
371 CpuPause ();\r
372 }\r
373 }\r
374 while (TRUE) {\r
375 DisableInterrupts ();\r
376 if (CpuMpData->ApLoopMode == ApInMwaitLoop) {\r
377 //\r
378 // Place AP in MWAIT-loop\r
379 //\r
380 AsmMonitor ((UINTN) ApStartupSignalBuffer, 0, 0);\r
381 if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) {\r
382 //\r
383 // Check AP start-up signal again.\r
384 // If AP start-up signal is not set, place AP into\r
385 // the specified C-state\r
386 //\r
387 AsmMwait (CpuMpData->ApTargetCState << 4, 0);\r
388 }\r
389 } else if (CpuMpData->ApLoopMode == ApInRunLoop) {\r
390 //\r
391 // Place AP in Run-loop\r
392 //\r
393 CpuPause ();\r
394 } else {\r
395 ASSERT (FALSE);\r
396 }\r
397\r
398 //\r
399 // If AP start-up signal is written, AP is waken up\r
400 // otherwise place AP in loop again\r
401 //\r
402 if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {\r
403 break;\r
404 }\r
405 }\r
406 }\r
407}\r
408\r
3e8ad6bd
JF
409/**\r
410 MP Initialize Library initialization.\r
411\r
412 This service will allocate AP reset vector and wakeup all APs to do APs\r
413 initialization.\r
414\r
415 This service must be invoked before all other MP Initialize Library\r
416 service are invoked.\r
417\r
418 @retval EFI_SUCCESS MP initialization succeeds.\r
419 @retval Others MP initialization fails.\r
420\r
421**/\r
422EFI_STATUS\r
423EFIAPI\r
424MpInitLibInitialize (\r
425 VOID\r
426 )\r
427{\r
e59f8f6b
JF
428 UINT32 MaxLogicalProcessorNumber;\r
429 UINT32 ApStackSize;\r
f7f85d83 430 MP_ASSEMBLY_ADDRESS_MAP AddressMap;\r
e59f8f6b 431 UINTN BufferSize;\r
9ebcf0f4 432 UINT32 MonitorFilterSize;\r
e59f8f6b
JF
433 VOID *MpBuffer;\r
434 UINTN Buffer;\r
435 CPU_MP_DATA *CpuMpData;\r
9ebcf0f4 436 UINT8 ApLoopMode;\r
e59f8f6b 437 UINT8 *MonitorBuffer;\r
03a1a925 438 UINTN Index;\r
f7f85d83 439 UINTN ApResetVectorSize;\r
e59f8f6b
JF
440 UINTN BackupBufferAddr;\r
441 MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber);\r
f7f85d83
JF
442\r
443 AsmGetAddressMap (&AddressMap);\r
444 ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);\r
e59f8f6b 445 ApStackSize = PcdGet32(PcdCpuApStackSize);\r
9ebcf0f4
JF
446 ApLoopMode = GetApLoopMode (&MonitorFilterSize);\r
447\r
e59f8f6b
JF
448 BufferSize = ApStackSize * MaxLogicalProcessorNumber;\r
449 BufferSize += MonitorFilterSize * MaxLogicalProcessorNumber;\r
450 BufferSize += sizeof (CPU_MP_DATA);\r
451 BufferSize += ApResetVectorSize;\r
452 BufferSize += (sizeof (CPU_AP_DATA) + sizeof (CPU_INFO_IN_HOB))* MaxLogicalProcessorNumber;\r
453 MpBuffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));\r
454 ASSERT (MpBuffer != NULL);\r
455 ZeroMem (MpBuffer, BufferSize);\r
456 Buffer = (UINTN) MpBuffer;\r
457\r
458 MonitorBuffer = (UINT8 *) (Buffer + ApStackSize * MaxLogicalProcessorNumber);\r
459 BackupBufferAddr = (UINTN) MonitorBuffer + MonitorFilterSize * MaxLogicalProcessorNumber;\r
460 CpuMpData = (CPU_MP_DATA *) (BackupBufferAddr + ApResetVectorSize);\r
461 CpuMpData->Buffer = Buffer;\r
462 CpuMpData->CpuApStackSize = ApStackSize;\r
463 CpuMpData->BackupBuffer = BackupBufferAddr;\r
464 CpuMpData->BackupBufferSize = ApResetVectorSize;\r
465 CpuMpData->EndOfPeiFlag = FALSE;\r
466 CpuMpData->WakeupBuffer = (UINTN) -1;\r
467 CpuMpData->CpuCount = 1;\r
468 CpuMpData->BspNumber = 0;\r
469 CpuMpData->WaitEvent = NULL;\r
470 CpuMpData->CpuData = (CPU_AP_DATA *) (CpuMpData + 1);\r
471 CpuMpData->CpuInfoInHob = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);\r
472 InitializeSpinLock(&CpuMpData->MpLock);\r
473 //\r
68cb9330
JF
474 // Save BSP's Control registers to APs\r
475 //\r
476 SaveVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters);\r
477 //\r
03a1a925
JF
478 // Set BSP basic information\r
479 //\r
480 InitializeApData (CpuMpData, 0, 0);\r
481 //\r
e59f8f6b
JF
482 // Save assembly code information\r
483 //\r
484 CopyMem (&CpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));\r
485 //\r
486 // Finally set AP loop mode\r
487 //\r
488 CpuMpData->ApLoopMode = ApLoopMode;\r
489 DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode));\r
490 //\r
03a1a925
JF
491 // Set up APs wakeup signal buffer\r
492 //\r
493 for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {\r
494 CpuMpData->CpuData[Index].StartupApSignal =\r
495 (UINT32 *)(MonitorBuffer + MonitorFilterSize * Index);\r
496 }\r
94f63c76
JF
497 //\r
498 // Load Microcode on BSP\r
499 //\r
500 MicrocodeDetect (CpuMpData);\r
501 //\r
e59f8f6b
JF
502 // Store BSP's MTRR setting\r
503 //\r
504 MtrrGetAllMtrrs (&CpuMpData->MtrrTable);\r
505\r
93ca4c0f
JF
506\r
507 //\r
508 // Initialize global data for MP support\r
509 //\r
510 InitMpGlobalData (CpuMpData);\r
511\r
f7f85d83 512 return EFI_SUCCESS;\r
3e8ad6bd
JF
513}\r
514\r
515/**\r
516 Gets detailed MP-related information on the requested processor at the\r
517 instant this call is made. This service may only be called from the BSP.\r
518\r
519 @param[in] ProcessorNumber The handle number of processor.\r
520 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for\r
521 the requested processor is deposited.\r
522 @param[out] HealthData Return processor health data.\r
523\r
524 @retval EFI_SUCCESS Processor information was returned.\r
525 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
526 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.\r
527 @retval EFI_NOT_FOUND The processor with the handle specified by\r
528 ProcessorNumber does not exist in the platform.\r
529 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
530\r
531**/\r
532EFI_STATUS\r
533EFIAPI\r
534MpInitLibGetProcessorInfo (\r
535 IN UINTN ProcessorNumber,\r
536 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer,\r
537 OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL\r
538 )\r
539{\r
540 return EFI_UNSUPPORTED;\r
541}\r
542/**\r
543 This return the handle number for the calling processor. This service may be\r
544 called from the BSP and APs.\r
545\r
546 @param[out] ProcessorNumber Pointer to the handle number of AP.\r
547 The range is from 0 to the total number of\r
548 logical processors minus 1. The total number of\r
549 logical processors can be retrieved by\r
550 MpInitLibGetNumberOfProcessors().\r
551\r
552 @retval EFI_SUCCESS The current processor handle number was returned\r
553 in ProcessorNumber.\r
554 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.\r
555 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
556\r
557**/\r
558EFI_STATUS\r
559EFIAPI\r
560MpInitLibWhoAmI (\r
561 OUT UINTN *ProcessorNumber\r
562 )\r
563{\r
564 return EFI_UNSUPPORTED;\r
565}\r
566/**\r
567 Retrieves the number of logical processor in the platform and the number of\r
568 those logical processors that are enabled on this boot. This service may only\r
569 be called from the BSP.\r
570\r
571 @param[out] NumberOfProcessors Pointer to the total number of logical\r
572 processors in the system, including the BSP\r
573 and disabled APs.\r
574 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical\r
575 processors that exist in system, including\r
576 the BSP.\r
577\r
578 @retval EFI_SUCCESS The number of logical processors and enabled\r
579 logical processors was retrieved.\r
580 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
581 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors\r
582 is NULL.\r
583 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
584\r
585**/\r
586EFI_STATUS\r
587EFIAPI\r
588MpInitLibGetNumberOfProcessors (\r
589 OUT UINTN *NumberOfProcessors, OPTIONAL\r
590 OUT UINTN *NumberOfEnabledProcessors OPTIONAL\r
591 )\r
592{\r
593 return EFI_UNSUPPORTED;\r
594}\r
93ca4c0f
JF
595/**\r
596 Get pointer to CPU MP Data structure from GUIDed HOB.\r
597\r
598 @return The pointer to CPU MP Data structure.\r
599**/\r
600CPU_MP_DATA *\r
601GetCpuMpDataFromGuidedHob (\r
602 VOID\r
603 )\r
604{\r
605 EFI_HOB_GUID_TYPE *GuidHob;\r
606 VOID *DataInHob;\r
607 CPU_MP_DATA *CpuMpData;\r
608\r
609 CpuMpData = NULL;\r
610 GuidHob = GetFirstGuidHob (&mCpuInitMpLibHobGuid);\r
611 if (GuidHob != NULL) {\r
612 DataInHob = GET_GUID_HOB_DATA (GuidHob);\r
613 CpuMpData = (CPU_MP_DATA *) (*(UINTN *) DataInHob);\r
614 }\r
615 return CpuMpData;\r
616}\r