]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuMpPei/CpuMpPei.c
UefiCpuPkg/CpuMpPei: Set X2APIC flag if one x2APIC ID larger than 254
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / CpuMpPei.c
CommitLineData
ea0f431c
JF
1/** @file\r
2 CPU PEI Module installs CPU Multiple Processor PPI.\r
3\r
4 Copyright (c) 2015, 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 "CpuMpPei.h"\r
16\r
17//\r
18// Global Descriptor Table (GDT)\r
19//\r
20GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {\r
21/* selector { Global Segment Descriptor } */\r
22/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //null descriptor\r
23/* 0x08 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear data segment descriptor\r
24/* 0x10 */ {{0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear code segment descriptor\r
25/* 0x18 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor\r
26/* 0x20 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system code segment descriptor\r
27/* 0x28 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor\r
28/* 0x30 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor\r
29/* 0x38 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 1, 0, 1, 0}}, //system code segment descriptor\r
30/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor\r
31};\r
32\r
33//\r
34// IA32 Gdt register\r
35//\r
36GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = {\r
37 sizeof (mGdtEntries) - 1,\r
38 (UINTN) mGdtEntries\r
39 };\r
40\r
41GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = {\r
42 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
43 &gEfiEndOfPeiSignalPpiGuid,\r
44 CpuMpEndOfPeiCallback\r
45};\r
46\r
47/**\r
48 Sort the APIC ID of all processors.\r
49\r
50 This function sorts the APIC ID of all processors so that processor number is\r
51 assigned in the ascending order of APIC ID which eases MP debugging.\r
52\r
53 @param PeiCpuMpData Pointer to PEI CPU MP Data\r
54**/\r
55VOID\r
56SortApicId (\r
57 IN PEI_CPU_MP_DATA *PeiCpuMpData\r
58 )\r
59{\r
60 UINTN Index1;\r
61 UINTN Index2;\r
62 UINTN Index3;\r
63 UINT32 ApicId;\r
64 EFI_HEALTH_FLAGS Health;\r
65 UINT32 ApCount;\r
66\r
67 ApCount = PeiCpuMpData->CpuCount - 1;\r
68\r
69 if (ApCount != 0) {\r
70 for (Index1 = 0; Index1 < ApCount; Index1++) {\r
71 Index3 = Index1;\r
72 //\r
73 // Sort key is the hardware default APIC ID\r
74 //\r
75 ApicId = PeiCpuMpData->CpuData[Index1].ApicId;\r
76 for (Index2 = Index1 + 1; Index2 <= ApCount; Index2++) {\r
77 if (ApicId > PeiCpuMpData->CpuData[Index2].ApicId) {\r
78 Index3 = Index2;\r
79 ApicId = PeiCpuMpData->CpuData[Index2].ApicId;\r
80 }\r
81 }\r
82 if (Index3 != Index1) {\r
83 PeiCpuMpData->CpuData[Index3].ApicId = PeiCpuMpData->CpuData[Index1].ApicId;\r
84 PeiCpuMpData->CpuData[Index1].ApicId = ApicId;\r
85 Health = PeiCpuMpData->CpuData[Index3].Health;\r
86 PeiCpuMpData->CpuData[Index3].Health = PeiCpuMpData->CpuData[Index1].Health;\r
87 PeiCpuMpData->CpuData[Index1].Health = Health;\r
88 }\r
89 }\r
90\r
91 //\r
92 // Get the processor number for the BSP\r
93 //\r
94 ApicId = GetInitialApicId ();\r
95 for (Index1 = 0; Index1 < PeiCpuMpData->CpuCount; Index1++) {\r
96 if (PeiCpuMpData->CpuData[Index1].ApicId == ApicId) {\r
97 PeiCpuMpData->BspNumber = (UINT32) Index1;\r
98 break;\r
99 }\r
100 }\r
101 }\r
102}\r
103\r
104/**\r
105 Get CPU MP Data pointer from the Guided HOB.\r
106\r
107 @return Pointer to Pointer to PEI CPU MP Data\r
108**/\r
109PEI_CPU_MP_DATA *\r
110GetMpHobData (\r
111 VOID\r
112 )\r
113{\r
114 EFI_HOB_GUID_TYPE *GuidHob;\r
115 VOID *DataInHob;\r
116 PEI_CPU_MP_DATA *CpuMpData;\r
117\r
118 CpuMpData = NULL;\r
119 GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);\r
120 if (GuidHob != NULL) {\r
121 DataInHob = GET_GUID_HOB_DATA (GuidHob);\r
122 CpuMpData = (PEI_CPU_MP_DATA *)(*(UINTN *)DataInHob);\r
123 }\r
124 ASSERT (CpuMpData != NULL);\r
125 return CpuMpData;\r
126}\r
127\r
128/**\r
129 This function will be called from AP reset code if BSP uses WakeUpAP.\r
130\r
131 @param ExchangeInfo Pointer to the MP exchange info buffer\r
132 @param NumApsExecuting Number of curret executing AP\r
133**/\r
134VOID\r
135EFIAPI\r
136ApCFunction (\r
137 IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,\r
138 IN UINTN NumApsExecuting\r
139 )\r
140{\r
141 PEI_CPU_MP_DATA *PeiCpuMpData;\r
142 UINTN ProcessorNumber;\r
143 EFI_AP_PROCEDURE Procedure;\r
144 UINTN BistData;\r
145\r
146 PeiCpuMpData = ExchangeInfo->PeiCpuMpData;\r
147 if (PeiCpuMpData->InitFlag) {\r
148 //\r
2f0261b7 149 // This is first time AP wakeup, get BIST information from AP stack\r
ea0f431c
JF
150 //\r
151 BistData = *(UINTN *) (PeiCpuMpData->Buffer + NumApsExecuting * PeiCpuMpData->CpuApStackSize - sizeof (UINTN));\r
ea0f431c 152 PeiCpuMpData->CpuData[NumApsExecuting].Health.Uint32 = (UINT32) BistData;\r
2f0261b7
JF
153 PeiCpuMpData->CpuData[NumApsExecuting].ApicId = GetInitialApicId ();\r
154 if (PeiCpuMpData->CpuData[NumApsExecuting].ApicId >= 0xFF) {\r
155 //\r
156 // Set x2APIC mode if there are any logical processor reporting\r
157 // an APIC ID of 255 or greater.\r
158 //\r
159 AcquireSpinLock(&PeiCpuMpData->MpLock);\r
160 PeiCpuMpData->X2ApicEnable = TRUE;\r
161 ReleaseSpinLock(&PeiCpuMpData->MpLock);\r
162 }\r
ea0f431c
JF
163 //\r
164 // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.\r
165 //\r
166 MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);\r
167 MicrocodeDetect ();\r
168 } else {\r
169 //\r
170 // Execute AP function if AP is not disabled\r
171 //\r
172 GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);\r
173 if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&\r
174 (PeiCpuMpData->ApFunction != 0)) {\r
175 PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;\r
176 Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;\r
177 Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);\r
178 PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;\r
179 }\r
180 }\r
181\r
182 //\r
183 // AP finished executing C code\r
184 //\r
185 InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);\r
186\r
187 AsmCliHltLoop ();\r
188}\r
189\r
190/**\r
191 This function will be called by BSP to wakeup AP.\r
192\r
193 @param PeiCpuMpData Pointer to PEI CPU MP Data\r
194 @param Broadcast TRUE: Send broadcast IPI to all APs\r
195 FALSE: Send IPI to AP by ApicId\r
196 @param ApicId Apic ID for the processor to be waked\r
197 @param Procedure The function to be invoked by AP\r
198 @param ProcedureArgument The argument to be passed into AP function\r
199**/\r
200VOID\r
201WakeUpAP (\r
202 IN PEI_CPU_MP_DATA *PeiCpuMpData,\r
203 IN BOOLEAN Broadcast,\r
204 IN UINT32 ApicId,\r
205 IN EFI_AP_PROCEDURE Procedure, OPTIONAL\r
206 IN VOID *ProcedureArgument OPTIONAL\r
207 )\r
208{\r
209 volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;\r
210\r
211 PeiCpuMpData->ApFunction = (UINTN) Procedure;\r
212 PeiCpuMpData->ApFunctionArgument = (UINTN) ProcedureArgument;\r
213 PeiCpuMpData->FinishedCount = 0;\r
214\r
215 ExchangeInfo = PeiCpuMpData->MpCpuExchangeInfo;\r
216 ExchangeInfo->Lock = 0;\r
217 ExchangeInfo->StackStart = PeiCpuMpData->Buffer;\r
218 ExchangeInfo->StackSize = PeiCpuMpData->CpuApStackSize;\r
219 ExchangeInfo->BufferStart = PeiCpuMpData->WakeupBuffer;\r
220 ExchangeInfo->PmodeOffset = PeiCpuMpData->AddressMap.PModeEntryOffset;\r
221 ExchangeInfo->LmodeOffset = PeiCpuMpData->AddressMap.LModeEntryOffset;\r
222 ExchangeInfo->Cr3 = AsmReadCr3 ();\r
223 ExchangeInfo->CFunction = (UINTN) ApCFunction;\r
224 ExchangeInfo->NumApsExecuting = 0;\r
225 ExchangeInfo->PeiCpuMpData = PeiCpuMpData;\r
226\r
227 //\r
228 // Get the BSP's data of GDT and IDT\r
229 //\r
230 CopyMem ((VOID *)&ExchangeInfo->GdtrProfile, &mGdt, sizeof(mGdt));\r
231 AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile);\r
232\r
233 if (Broadcast) {\r
234 SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart);\r
235 } else {\r
236 SendInitSipiSipi (ApicId, (UINT32) ExchangeInfo->BufferStart);\r
237 }\r
238\r
239 return ;\r
240}\r
241\r
242/**\r
243 Get available system memory below 1MB by specified size.\r
244\r
245 @param WakeupBufferSize Wakeup buffer size required\r
246\r
247 @retval other Return wakeup buffer address below 1MB.\r
248 @retval -1 Cannot find free memory below 1MB.\r
249**/\r
250UINTN\r
251GetWakeupBuffer (\r
252 IN UINTN WakeupBufferSize\r
253 )\r
254{\r
255 EFI_PEI_HOB_POINTERS Hob;\r
256 UINTN WakeupBufferStart;\r
257 UINTN WakeupBufferEnd;\r
258\r
259 //\r
260 // Get the HOB list for processing\r
261 //\r
262 Hob.Raw = GetHobList ();\r
263\r
264 //\r
265 // Collect memory ranges\r
266 //\r
267 while (!END_OF_HOB_LIST (Hob)) {\r
268 if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
269 if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&\r
270 (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&\r
271 ((Hob.ResourceDescriptor->ResourceAttribute &\r
272 (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |\r
273 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |\r
274 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED\r
275 )) == 0)\r
276 ) {\r
277 //\r
278 // Need memory under 1MB to be collected here\r
279 //\r
280 WakeupBufferEnd = (UINTN) (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength);\r
281 if (WakeupBufferEnd > BASE_1MB) {\r
282 //\r
283 // Wakeup buffer should be under 1MB\r
284 //\r
285 WakeupBufferEnd = BASE_1MB;\r
286 }\r
287 //\r
288 // Wakeup buffer should be aligned on 4KB\r
289 //\r
290 WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);\r
291 if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {\r
292 continue;\r
293 }\r
294 //\r
295 // Create a memory allocation HOB.\r
296 //\r
297 BuildMemoryAllocationHob (\r
298 WakeupBufferStart,\r
299 WakeupBufferSize,\r
300 EfiBootServicesData\r
301 );\r
302 return WakeupBufferStart;\r
303 }\r
304 }\r
305 //\r
306 // Find the next HOB\r
307 //\r
308 Hob.Raw = GET_NEXT_HOB (Hob);\r
309 }\r
310\r
311 return (UINTN) -1;\r
312}\r
313\r
314/**\r
315 Get available system memory below 1MB by specified size.\r
316\r
317 @param PeiCpuMpData Pointer to PEI CPU MP Data\r
318**/\r
319VOID\r
320BackupAndPrepareWakeupBuffer(\r
321 IN PEI_CPU_MP_DATA *PeiCpuMpData\r
322 )\r
323{\r
324 CopyMem (\r
325 (VOID *) PeiCpuMpData->BackupBuffer,\r
326 (VOID *) PeiCpuMpData->WakeupBuffer,\r
327 PeiCpuMpData->BackupBufferSize\r
328 );\r
329 CopyMem (\r
330 (VOID *) PeiCpuMpData->WakeupBuffer,\r
331 (VOID *) PeiCpuMpData->AddressMap.RendezvousFunnelAddress,\r
332 PeiCpuMpData->AddressMap.RendezvousFunnelSize\r
333 );\r
334}\r
335\r
336/**\r
337 Restore wakeup buffer data.\r
338\r
339 @param PeiCpuMpData Pointer to PEI CPU MP Data\r
340**/\r
341VOID\r
342RestoreWakeupBuffer(\r
343 IN PEI_CPU_MP_DATA *PeiCpuMpData\r
344 )\r
345{\r
346 CopyMem ((VOID *) PeiCpuMpData->WakeupBuffer, (VOID *) PeiCpuMpData->BackupBuffer, PeiCpuMpData->BackupBufferSize);\r
347}\r
348\r
349/**\r
350 This function will get CPU count in the system.\r
351\r
352 @param PeiCpuMpData Pointer to PEI CPU MP Data\r
353\r
354 @return AP processor count\r
355**/\r
356UINT32\r
357CountProcessorNumber (\r
358 IN PEI_CPU_MP_DATA *PeiCpuMpData\r
359 )\r
360{\r
361 //\r
362 // Load Microcode on BSP\r
363 //\r
364 MicrocodeDetect ();\r
365 //\r
366 // Store BSP's MTRR setting\r
367 //\r
368 MtrrGetAllMtrrs (&PeiCpuMpData->MtrrTable);\r
944f45ae 369\r
ea0f431c 370 //\r
944f45ae 371 // Only perform AP detection if PcdCpuMaxLogicalProcessorNumber is greater than 1\r
ea0f431c 372 //\r
944f45ae
MK
373 if (PcdGet32 (PcdCpuMaxLogicalProcessorNumber) > 1) {\r
374 //\r
2f0261b7 375 // Send 1st broadcast IPI to APs to wakeup APs\r
944f45ae 376 //\r
2f0261b7
JF
377 PeiCpuMpData->InitFlag = TRUE;\r
378 PeiCpuMpData->X2ApicEnable = FALSE;\r
944f45ae
MK
379 WakeUpAP (PeiCpuMpData, TRUE, 0, NULL, NULL);\r
380 //\r
381 // Wait for AP task to complete and then exit.\r
382 //\r
383 MicroSecondDelay (PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));\r
2f0261b7 384 PeiCpuMpData->InitFlag = FALSE;\r
944f45ae
MK
385 PeiCpuMpData->CpuCount += (UINT32)PeiCpuMpData->MpCpuExchangeInfo->NumApsExecuting;\r
386 ASSERT (PeiCpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));\r
387 //\r
388 // Sort BSP/Aps by CPU APIC ID in ascending order\r
389 //\r
390 SortApicId (PeiCpuMpData);\r
391 }\r
ea0f431c
JF
392\r
393 DEBUG ((EFI_D_INFO, "CpuMpPei: Find %d processors in system.\n", PeiCpuMpData->CpuCount));\r
394 return PeiCpuMpData->CpuCount;\r
395}\r
396\r
397/**\r
398 Prepare for AP wakeup buffer and copy AP reset code into it.\r
399\r
400 Get wakeup buffer below 1MB. Allocate memory for CPU MP Data and APs Stack.\r
401\r
402 @return Pointer to PEI CPU MP Data\r
403**/\r
404PEI_CPU_MP_DATA *\r
405PrepareAPStartupVector (\r
406 VOID\r
407 )\r
408{\r
409 EFI_STATUS Status;\r
410 UINT32 MaxCpuCount;\r
411 PEI_CPU_MP_DATA *PeiCpuMpData;\r
412 EFI_PHYSICAL_ADDRESS Buffer;\r
413 UINTN BufferSize;\r
414 UINTN WakeupBuffer;\r
415 UINTN WakeupBufferSize;\r
416 MP_ASSEMBLY_ADDRESS_MAP AddressMap;\r
417\r
418 AsmGetAddressMap (&AddressMap);\r
419 WakeupBufferSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);\r
420 WakeupBuffer = GetWakeupBuffer ((WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1));\r
421 ASSERT (WakeupBuffer != (UINTN) -1);\r
422 DEBUG ((EFI_D_INFO, "CpuMpPei: WakeupBuffer = 0x%x\n", WakeupBuffer));\r
423\r
424 //\r
425 // Allocate Pages for APs stack, CPU MP Data and backup buffer for wakeup buffer\r
426 //\r
427 MaxCpuCount = PcdGet32(PcdCpuMaxLogicalProcessorNumber);\r
428 BufferSize = PcdGet32 (PcdCpuApStackSize) * MaxCpuCount + sizeof (PEI_CPU_MP_DATA)\r
429 + WakeupBufferSize + sizeof (PEI_CPU_DATA) * MaxCpuCount;\r
430 Status = PeiServicesAllocatePages (\r
431 EfiBootServicesData,\r
432 EFI_SIZE_TO_PAGES (BufferSize),\r
433 &Buffer\r
434 );\r
435 ASSERT_EFI_ERROR (Status);\r
436\r
437 PeiCpuMpData = (PEI_CPU_MP_DATA *) (UINTN) (Buffer + PcdGet32 (PcdCpuApStackSize) * MaxCpuCount);\r
438 PeiCpuMpData->Buffer = (UINTN) Buffer;\r
439 PeiCpuMpData->CpuApStackSize = PcdGet32 (PcdCpuApStackSize);\r
440 PeiCpuMpData->WakeupBuffer = WakeupBuffer;\r
441 PeiCpuMpData->BackupBuffer = (UINTN)PeiCpuMpData + sizeof (PEI_CPU_MP_DATA);\r
442 PeiCpuMpData->BackupBufferSize = WakeupBufferSize;\r
443 PeiCpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeupBuffer + AddressMap.RendezvousFunnelSize);\r
444\r
445 PeiCpuMpData->CpuCount = 1;\r
446 PeiCpuMpData->BspNumber = 0;\r
28f27af6
JF
447 PeiCpuMpData->CpuData = (PEI_CPU_DATA *) (PeiCpuMpData->BackupBuffer +\r
448 PeiCpuMpData->BackupBufferSize);\r
ea0f431c
JF
449 PeiCpuMpData->CpuData[0].ApicId = GetInitialApicId ();\r
450 PeiCpuMpData->CpuData[0].Health.Uint32 = 0;\r
451 PeiCpuMpData->EndOfPeiFlag = FALSE;\r
2f0261b7 452 InitializeSpinLock(&PeiCpuMpData->MpLock);\r
ea0f431c
JF
453 CopyMem (&PeiCpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));\r
454\r
455 //\r
456 // Backup original data and copy AP reset code in it\r
457 //\r
458 BackupAndPrepareWakeupBuffer(PeiCpuMpData);\r
459\r
460 return PeiCpuMpData;\r
461}\r
462\r
463/**\r
464 Notify function on End Of Pei PPI.\r
465\r
466 On S3 boot, this function will restore wakeup buffer data.\r
467 On normal boot, this function will flag wakeup buffer to be un-used type.\r
468\r
469 @param PeiServices The pointer to the PEI Services Table.\r
470 @param NotifyDescriptor Address of the notification descriptor data structure.\r
471 @param Ppi Address of the PPI that was installed.\r
472\r
473 @retval EFI_SUCCESS When everything is OK.\r
474\r
475**/\r
476EFI_STATUS\r
477EFIAPI\r
478CpuMpEndOfPeiCallback (\r
479 IN EFI_PEI_SERVICES **PeiServices,\r
480 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
481 IN VOID *Ppi\r
482 )\r
483{\r
484 EFI_STATUS Status;\r
485 EFI_BOOT_MODE BootMode;\r
486 PEI_CPU_MP_DATA *PeiCpuMpData;\r
487 EFI_PEI_HOB_POINTERS Hob;\r
488 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
489\r
490 DEBUG ((EFI_D_INFO, "CpuMpPei: CpuMpEndOfPeiCallback () invokded\n"));\r
491\r
492 Status = PeiServicesGetBootMode (&BootMode);\r
493 ASSERT_EFI_ERROR (Status);\r
494\r
495 PeiCpuMpData = GetMpHobData ();\r
496 ASSERT (PeiCpuMpData != NULL);\r
497\r
498 if (BootMode != BOOT_ON_S3_RESUME) {\r
499 //\r
500 // Get the HOB list for processing\r
501 //\r
502 Hob.Raw = GetHobList ();\r
503 //\r
504 // Collect memory ranges\r
505 //\r
506 while (!END_OF_HOB_LIST (Hob)) {\r
507 if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
508 MemoryHob = Hob.MemoryAllocation;\r
509 if(MemoryHob->AllocDescriptor.MemoryBaseAddress == PeiCpuMpData->WakeupBuffer) {\r
510 //\r
511 // Flag this HOB type to un-used\r
512 //\r
513 GET_HOB_TYPE (Hob) = EFI_HOB_TYPE_UNUSED;\r
514 break;\r
515 }\r
516 }\r
517 Hob.Raw = GET_NEXT_HOB (Hob);\r
518 }\r
519 } else {\r
520 RestoreWakeupBuffer (PeiCpuMpData);\r
521 PeiCpuMpData->EndOfPeiFlag = TRUE;\r
522 }\r
523 return EFI_SUCCESS;\r
524}\r
525\r
526/**\r
527 The Entry point of the MP CPU PEIM.\r
528\r
529 This function will wakeup APs and collect CPU AP count and install the\r
530 Mp Service Ppi.\r
531\r
532 @param FileHandle Handle of the file being invoked.\r
533 @param PeiServices Describes the list of possible PEI Services.\r
534\r
535 @retval EFI_SUCCESS MpServicePpi is installed successfully.\r
536\r
537**/\r
538EFI_STATUS\r
539EFIAPI\r
540CpuMpPeimInit (\r
541 IN EFI_PEI_FILE_HANDLE FileHandle,\r
542 IN CONST EFI_PEI_SERVICES **PeiServices\r
543 )\r
544{\r
545 EFI_STATUS Status;\r
546 PEI_CPU_MP_DATA *PeiCpuMpData;\r
547 UINT32 ProcessorCount;\r
548\r
549 //\r
550 // Load new GDT table on BSP\r
551 //\r
552 AsmInitializeGdt (&mGdt);\r
553 //\r
554 // Get wakeup buffer and copy AP reset code in it\r
555 //\r
556 PeiCpuMpData = PrepareAPStartupVector ();\r
557 //\r
558 // Count processor number and collect processor information\r
559 //\r
560 ProcessorCount = CountProcessorNumber (PeiCpuMpData);\r
561 //\r
562 // Build location of PEI CPU MP DATA buffer in HOB\r
563 //\r
564 BuildGuidDataHob (\r
565 &gEfiCallerIdGuid,\r
566 (VOID *)&PeiCpuMpData,\r
567 sizeof(UINT64)\r
568 );\r
569 //\r
570 // Update and publish CPU BIST information\r
571 //\r
572 CollectBistDataFromPpi (PeiServices, PeiCpuMpData);\r
573 //\r
574 // register an event for EndOfPei\r
575 //\r
576 Status = PeiServicesNotifyPpi (&mNotifyList);\r
577 ASSERT_EFI_ERROR (Status);\r
578 //\r
579 // Install CPU MP PPI\r
580 //\r
581 Status = PeiServicesInstallPpi(&mPeiCpuMpPpiDesc);\r
582 ASSERT_EFI_ERROR (Status);\r
583\r
584 return Status;\r
585}\r