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