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