]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/MpInitLib: Add ApWakeupFunction() executed by assembly code
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / MpLib.c
... / ...
CommitLineData
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
17EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;\r
18\r
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
50\r
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
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
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
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
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
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
428 UINT32 MaxLogicalProcessorNumber;\r
429 UINT32 ApStackSize;\r
430 MP_ASSEMBLY_ADDRESS_MAP AddressMap;\r
431 UINTN BufferSize;\r
432 UINT32 MonitorFilterSize;\r
433 VOID *MpBuffer;\r
434 UINTN Buffer;\r
435 CPU_MP_DATA *CpuMpData;\r
436 UINT8 ApLoopMode;\r
437 UINT8 *MonitorBuffer;\r
438 UINTN Index;\r
439 UINTN ApResetVectorSize;\r
440 UINTN BackupBufferAddr;\r
441 MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber);\r
442\r
443 AsmGetAddressMap (&AddressMap);\r
444 ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);\r
445 ApStackSize = PcdGet32(PcdCpuApStackSize);\r
446 ApLoopMode = GetApLoopMode (&MonitorFilterSize);\r
447\r
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
474 // Save BSP's Control registers to APs\r
475 //\r
476 SaveVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters);\r
477 //\r
478 // Set BSP basic information\r
479 //\r
480 InitializeApData (CpuMpData, 0, 0);\r
481 //\r
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
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
497 //\r
498 // Load Microcode on BSP\r
499 //\r
500 MicrocodeDetect (CpuMpData);\r
501 //\r
502 // Store BSP's MTRR setting\r
503 //\r
504 MtrrGetAllMtrrs (&CpuMpData->MtrrTable);\r
505\r
506\r
507 //\r
508 // Initialize global data for MP support\r
509 //\r
510 InitMpGlobalData (CpuMpData);\r
511\r
512 return EFI_SUCCESS;\r
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
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