]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
UefiCpuPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / CpuS3.c
CommitLineData
529a5a86
MK
1/** @file\r
2Code for Processor S3 restoration\r
3\r
e21e355e 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
0acd8697 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
529a5a86
MK
6\r
7**/\r
8\r
9#include "PiSmmCpuDxeSmm.h"\r
10\r
e21e355e 11#pragma pack(1)\r
529a5a86
MK
12typedef struct {\r
13 UINTN Lock;\r
14 VOID *StackStart;\r
15 UINTN StackSize;\r
16 VOID *ApFunction;\r
17 IA32_DESCRIPTOR GdtrProfile;\r
18 IA32_DESCRIPTOR IdtrProfile;\r
19 UINT32 BufferStart;\r
20 UINT32 Cr3;\r
e21e355e 21 UINTN InitializeFloatingPointUnitsAddress;\r
529a5a86 22} MP_CPU_EXCHANGE_INFO;\r
e21e355e 23#pragma pack()\r
529a5a86
MK
24\r
25typedef struct {\r
26 UINT8 *RendezvousFunnelAddress;\r
27 UINTN PModeEntryOffset;\r
28 UINTN FlatJumpOffset;\r
29 UINTN Size;\r
30 UINTN LModeEntryOffset;\r
31 UINTN LongJumpOffset;\r
32} MP_ASSEMBLY_ADDRESS_MAP;\r
33\r
6c4c15fa 34//\r
93324390 35// Flags used when program the register.\r
6c4c15fa 36//\r
93324390 37typedef struct {\r
9bae7811
ED
38 volatile UINTN ConsoleLogLock; // Spinlock used to control console.\r
39 volatile UINTN MemoryMappedLock; // Spinlock used to program mmio\r
40 volatile UINT32 *CoreSemaphoreCount; // Semaphore container used to program\r
41 // core level semaphore.\r
42 volatile UINT32 *PackageSemaphoreCount; // Semaphore container used to program\r
43 // package level semaphore.\r
93324390 44} PROGRAM_CPU_REGISTER_FLAGS;\r
6c4c15fa 45\r
7677b4db
ED
46//\r
47// Signal that SMM BASE relocation is complete.\r
48//\r
49volatile BOOLEAN mInitApsAfterSmmBaseReloc;\r
50\r
529a5a86
MK
51/**\r
52 Get starting address and size of the rendezvous entry for APs.\r
53 Information for fixing a jump instruction in the code is also returned.\r
54\r
55 @param AddressMap Output buffer for address map information.\r
56**/\r
57VOID *\r
58EFIAPI\r
59AsmGetAddressMap (\r
60 MP_ASSEMBLY_ADDRESS_MAP *AddressMap\r
61 );\r
62\r
63#define LEGACY_REGION_SIZE (2 * 0x1000)\r
64#define LEGACY_REGION_BASE (0xA0000 - LEGACY_REGION_SIZE)\r
529a5a86 65\r
93324390 66PROGRAM_CPU_REGISTER_FLAGS mCpuFlags;\r
529a5a86 67ACPI_CPU_DATA mAcpiCpuData;\r
c773514d 68volatile UINT32 mNumberToFinish;\r
529a5a86
MK
69MP_CPU_EXCHANGE_INFO *mExchangeInfo;\r
70BOOLEAN mRestoreSmmConfigurationInS3 = FALSE;\r
529a5a86 71\r
0bdc9e75
SZ
72//\r
73// S3 boot flag\r
74//\r
75BOOLEAN mSmmS3Flag = FALSE;\r
76\r
77//\r
78// Pointer to structure used during S3 Resume\r
79//\r
80SMM_S3_RESUME_STATE *mSmmS3ResumeState = NULL;\r
81\r
b10d5ddc
SZ
82BOOLEAN mAcpiS3Enable = TRUE;\r
83\r
4a0f88dd
JF
84UINT8 *mApHltLoopCode = NULL;\r
85UINT8 mApHltLoopCodeTemplate[] = {\r
ec8a3877
JF
86 0x8B, 0x44, 0x24, 0x04, // mov eax, dword ptr [esp+4]\r
87 0xF0, 0xFF, 0x08, // lock dec dword ptr [eax]\r
88 0xFA, // cli\r
89 0xF4, // hlt\r
90 0xEB, 0xFC // jmp $-2\r
4a0f88dd
JF
91 };\r
92\r
93324390 93CHAR16 *mRegisterTypeStr[] = {L"MSR", L"CR", L"MMIO", L"CACHE", L"SEMAP", L"INVALID" };\r
529a5a86
MK
94\r
95/**\r
96 Sync up the MTRR values for all processors.\r
97\r
98 @param MtrrTable Table holding fixed/variable MTRR values to be loaded.\r
99**/\r
100VOID\r
101EFIAPI\r
102LoadMtrrData (\r
103 EFI_PHYSICAL_ADDRESS MtrrTable\r
104 )\r
105/*++\r
106\r
107Routine Description:\r
108\r
109 Sync up the MTRR values for all processors.\r
110\r
111Arguments:\r
112\r
113Returns:\r
114 None\r
115\r
116--*/\r
117{\r
118 MTRR_SETTINGS *MtrrSettings;\r
119\r
120 MtrrSettings = (MTRR_SETTINGS *) (UINTN) MtrrTable;\r
121 MtrrSetAllMtrrs (MtrrSettings);\r
122}\r
123\r
124/**\r
93324390 125 Increment semaphore by 1.\r
529a5a86 126\r
93324390 127 @param Sem IN: 32-bit unsigned integer\r
529a5a86 128\r
93324390
ED
129**/\r
130VOID\r
131S3ReleaseSemaphore (\r
132 IN OUT volatile UINT32 *Sem\r
133 )\r
134{\r
135 InterlockedIncrement (Sem);\r
136}\r
137\r
138/**\r
139 Decrement the semaphore by 1 if it is not zero.\r
529a5a86 140\r
93324390
ED
141 Performs an atomic decrement operation for semaphore.\r
142 The compare exchange operation must be performed using\r
143 MP safe mechanisms.\r
144\r
145 @param Sem IN: 32-bit unsigned integer\r
146\r
147**/\r
148VOID\r
149S3WaitForSemaphore (\r
150 IN OUT volatile UINT32 *Sem\r
151 )\r
152{\r
153 UINT32 Value;\r
154\r
155 do {\r
156 Value = *Sem;\r
157 } while (Value == 0 ||\r
158 InterlockedCompareExchange32 (\r
159 Sem,\r
160 Value,\r
161 Value - 1\r
162 ) != Value);\r
163}\r
164\r
165/**\r
166 Initialize the CPU registers from a register table.\r
167\r
168 @param[in] RegisterTable The register table for this AP.\r
169 @param[in] ApLocation AP location info for this ap.\r
170 @param[in] CpuStatus CPU status info for this CPU.\r
171 @param[in] CpuFlags Flags data structure used when program the register.\r
172\r
173 @note This service could be called by BSP/APs.\r
529a5a86
MK
174**/\r
175VOID\r
93324390
ED
176ProgramProcessorRegister (\r
177 IN CPU_REGISTER_TABLE *RegisterTable,\r
178 IN EFI_CPU_PHYSICAL_LOCATION *ApLocation,\r
179 IN CPU_STATUS_INFORMATION *CpuStatus,\r
180 IN PROGRAM_CPU_REGISTER_FLAGS *CpuFlags\r
529a5a86
MK
181 )\r
182{\r
183 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
184 UINTN Index;\r
185 UINTN Value;\r
93324390
ED
186 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;\r
187 volatile UINT32 *SemaphorePtr;\r
188 UINT32 FirstThread;\r
189 UINT32 PackageThreadsCount;\r
190 UINT32 CurrentThread;\r
191 UINTN ProcessorIndex;\r
192 UINTN ThreadIndex;\r
193 UINTN ValidThreadCount;\r
194 UINT32 *ValidCoreCountPerPackage;\r
529a5a86
MK
195\r
196 //\r
197 // Traverse Register Table of this logical processor\r
198 //\r
93324390
ED
199 RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;\r
200\r
201 for (Index = 0; Index < RegisterTable->TableLength; Index++) {\r
202\r
203 RegisterTableEntry = &RegisterTableEntryHead[Index];\r
204\r
205 DEBUG_CODE_BEGIN ();\r
206 if (ApLocation != NULL) {\r
207 AcquireSpinLock (&CpuFlags->ConsoleLogLock);\r
208 ThreadIndex = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount +\r
209 ApLocation->Core * CpuStatus->MaxThreadCount +\r
210 ApLocation->Thread;\r
211 DEBUG ((\r
212 DEBUG_INFO,\r
213 "Processor = %lu, Entry Index %lu, Type = %s!\n",\r
214 (UINT64)ThreadIndex,\r
215 (UINT64)Index,\r
216 mRegisterTypeStr[MIN ((REGISTER_TYPE)RegisterTableEntry->RegisterType, InvalidReg)]\r
217 ));\r
218 ReleaseSpinLock (&CpuFlags->ConsoleLogLock);\r
219 }\r
220 DEBUG_CODE_END ();\r
221\r
529a5a86
MK
222 //\r
223 // Check the type of specified register\r
224 //\r
225 switch (RegisterTableEntry->RegisterType) {\r
226 //\r
227 // The specified register is Control Register\r
228 //\r
229 case ControlRegister:\r
230 switch (RegisterTableEntry->Index) {\r
231 case 0:\r
232 Value = AsmReadCr0 ();\r
233 Value = (UINTN) BitFieldWrite64 (\r
234 Value,\r
235 RegisterTableEntry->ValidBitStart,\r
236 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
237 (UINTN) RegisterTableEntry->Value\r
238 );\r
239 AsmWriteCr0 (Value);\r
240 break;\r
241 case 2:\r
242 Value = AsmReadCr2 ();\r
243 Value = (UINTN) BitFieldWrite64 (\r
244 Value,\r
245 RegisterTableEntry->ValidBitStart,\r
246 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
247 (UINTN) RegisterTableEntry->Value\r
248 );\r
249 AsmWriteCr2 (Value);\r
250 break;\r
251 case 3:\r
252 Value = AsmReadCr3 ();\r
253 Value = (UINTN) BitFieldWrite64 (\r
254 Value,\r
255 RegisterTableEntry->ValidBitStart,\r
256 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
257 (UINTN) RegisterTableEntry->Value\r
258 );\r
259 AsmWriteCr3 (Value);\r
260 break;\r
261 case 4:\r
262 Value = AsmReadCr4 ();\r
263 Value = (UINTN) BitFieldWrite64 (\r
264 Value,\r
265 RegisterTableEntry->ValidBitStart,\r
266 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
267 (UINTN) RegisterTableEntry->Value\r
268 );\r
269 AsmWriteCr4 (Value);\r
270 break;\r
271 default:\r
272 break;\r
273 }\r
274 break;\r
275 //\r
276 // The specified register is Model Specific Register\r
277 //\r
278 case Msr:\r
279 //\r
280 // If this function is called to restore register setting after INIT signal,\r
281 // there is no need to restore MSRs in register table.\r
282 //\r
283 if (RegisterTableEntry->ValidBitLength >= 64) {\r
284 //\r
285 // If length is not less than 64 bits, then directly write without reading\r
286 //\r
287 AsmWriteMsr64 (\r
288 RegisterTableEntry->Index,\r
289 RegisterTableEntry->Value\r
290 );\r
291 } else {\r
529a5a86
MK
292 //\r
293 // Set the bit section according to bit start and length\r
294 //\r
295 AsmMsrBitFieldWrite64 (\r
296 RegisterTableEntry->Index,\r
297 RegisterTableEntry->ValidBitStart,\r
298 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
299 RegisterTableEntry->Value\r
300 );\r
529a5a86
MK
301 }\r
302 break;\r
303 //\r
6c4c15fa
JF
304 // MemoryMapped operations\r
305 //\r
306 case MemoryMapped:\r
93324390 307 AcquireSpinLock (&CpuFlags->MemoryMappedLock);\r
6c4c15fa 308 MmioBitFieldWrite32 (\r
30b7a50b 309 (UINTN)(RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32)),\r
6c4c15fa
JF
310 RegisterTableEntry->ValidBitStart,\r
311 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
312 (UINT32)RegisterTableEntry->Value\r
313 );\r
93324390 314 ReleaseSpinLock (&CpuFlags->MemoryMappedLock);\r
6c4c15fa
JF
315 break;\r
316 //\r
529a5a86
MK
317 // Enable or disable cache\r
318 //\r
319 case CacheControl:\r
320 //\r
321 // If value of the entry is 0, then disable cache. Otherwise, enable cache.\r
322 //\r
323 if (RegisterTableEntry->Value == 0) {\r
324 AsmDisableCache ();\r
325 } else {\r
326 AsmEnableCache ();\r
327 }\r
328 break;\r
329\r
93324390
ED
330 case Semaphore:\r
331 // Semaphore works logic like below:\r
332 //\r
333 // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);\r
334 // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);\r
335 //\r
336 // All threads (T0...Tn) waits in P() line and continues running\r
337 // together.\r
338 //\r
339 //\r
340 // T0 T1 ... Tn\r
341 //\r
342 // V(0...n) V(0...n) ... V(0...n)\r
343 // n * P(0) n * P(1) ... n * P(n)\r
344 //\r
345 ASSERT (\r
e07e3ceb 346 (ApLocation != NULL) &&\r
93324390 347 (CpuStatus->ValidCoreCountPerPackage != 0) &&\r
9bae7811
ED
348 (CpuFlags->CoreSemaphoreCount != NULL) &&\r
349 (CpuFlags->PackageSemaphoreCount != NULL)\r
93324390 350 );\r
93324390
ED
351 switch (RegisterTableEntry->Value) {\r
352 case CoreDepType:\r
9bae7811 353 SemaphorePtr = CpuFlags->CoreSemaphoreCount;\r
93324390
ED
354 //\r
355 // Get Offset info for the first thread in the core which current thread belongs to.\r
356 //\r
357 FirstThread = (ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core) * CpuStatus->MaxThreadCount;\r
358 CurrentThread = FirstThread + ApLocation->Thread;\r
359 //\r
360 // First Notify all threads in current Core that this thread has ready.\r
361 //\r
362 for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
363 S3ReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);\r
364 }\r
365 //\r
366 // Second, check whether all valid threads in current core have ready.\r
367 //\r
368 for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
369 S3WaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
370 }\r
371 break;\r
372\r
373 case PackageDepType:\r
9bae7811 374 SemaphorePtr = CpuFlags->PackageSemaphoreCount;\r
93324390
ED
375 ValidCoreCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ValidCoreCountPerPackage;\r
376 //\r
377 // Get Offset info for the first thread in the package which current thread belongs to.\r
378 //\r
379 FirstThread = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount;\r
380 //\r
381 // Get the possible threads count for current package.\r
382 //\r
383 PackageThreadsCount = CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount;\r
384 CurrentThread = FirstThread + CpuStatus->MaxThreadCount * ApLocation->Core + ApLocation->Thread;\r
385 //\r
386 // Get the valid thread count for current package.\r
387 //\r
388 ValidThreadCount = CpuStatus->MaxThreadCount * ValidCoreCountPerPackage[ApLocation->Package];\r
389\r
390 //\r
391 // Different packages may have different valid cores in them. If driver maintail clearly\r
392 // cores number in different packages, the logic will be much complicated.\r
393 // Here driver just simply records the max core number in all packages and use it as expect\r
394 // core number for all packages.\r
395 // In below two steps logic, first current thread will Release semaphore for each thread\r
396 // in current package. Maybe some threads are not valid in this package, but driver don't\r
397 // care. Second, driver will let current thread wait semaphore for all valid threads in\r
398 // current package. Because only the valid threads will do release semaphore for this\r
399 // thread, driver here only need to wait the valid thread count.\r
400 //\r
401\r
402 //\r
403 // First Notify all threads in current package that this thread has ready.\r
404 //\r
405 for (ProcessorIndex = 0; ProcessorIndex < PackageThreadsCount ; ProcessorIndex ++) {\r
406 S3ReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);\r
407 }\r
408 //\r
409 // Second, check whether all valid threads in current package have ready.\r
410 //\r
411 for (ProcessorIndex = 0; ProcessorIndex < ValidThreadCount; ProcessorIndex ++) {\r
412 S3WaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
413 }\r
414 break;\r
415\r
416 default:\r
417 break;\r
418 }\r
419 break;\r
420\r
529a5a86
MK
421 default:\r
422 break;\r
423 }\r
424 }\r
425}\r
426\r
93324390
ED
427/**\r
428\r
429 Set Processor register for one AP.\r
e07e3ceb 430\r
93324390
ED
431 @param PreSmmRegisterTable Use pre Smm register table or register table.\r
432\r
433**/\r
434VOID\r
435SetRegister (\r
436 IN BOOLEAN PreSmmRegisterTable\r
437 )\r
438{\r
439 CPU_REGISTER_TABLE *RegisterTable;\r
440 CPU_REGISTER_TABLE *RegisterTables;\r
441 UINT32 InitApicId;\r
442 UINTN ProcIndex;\r
443 UINTN Index;\r
444\r
445 if (PreSmmRegisterTable) {\r
446 RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.PreSmmInitRegisterTable;\r
447 } else {\r
448 RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable;\r
449 }\r
450\r
451 InitApicId = GetInitialApicId ();\r
452 RegisterTable = NULL;\r
7db4034f 453 ProcIndex = (UINTN)-1;\r
93324390
ED
454 for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {\r
455 if (RegisterTables[Index].InitialApicId == InitApicId) {\r
456 RegisterTable = &RegisterTables[Index];\r
457 ProcIndex = Index;\r
458 break;\r
459 }\r
460 }\r
461 ASSERT (RegisterTable != NULL);\r
462\r
463 if (mAcpiCpuData.ApLocation != 0) {\r
464 ProgramProcessorRegister (\r
465 RegisterTable,\r
466 (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)mAcpiCpuData.ApLocation + ProcIndex,\r
467 &mAcpiCpuData.CpuStatus,\r
468 &mCpuFlags\r
469 );\r
470 } else {\r
471 ProgramProcessorRegister (\r
472 RegisterTable,\r
473 NULL,\r
474 &mAcpiCpuData.CpuStatus,\r
475 &mCpuFlags\r
476 );\r
477 }\r
478}\r
479\r
529a5a86 480/**\r
7677b4db 481 AP initialization before then after SMBASE relocation in the S3 boot path.\r
529a5a86
MK
482**/\r
483VOID\r
94744aa2 484InitializeAp (\r
529a5a86
MK
485 VOID\r
486 )\r
487{\r
7677b4db
ED
488 UINTN TopOfStack;\r
489 UINT8 Stack[128];\r
529a5a86
MK
490\r
491 LoadMtrrData (mAcpiCpuData.MtrrTable);\r
492\r
93324390 493 SetRegister (TRUE);\r
7677b4db 494\r
529a5a86
MK
495 //\r
496 // Count down the number with lock mechanism.\r
497 //\r
498 InterlockedDecrement (&mNumberToFinish);\r
529a5a86 499\r
7677b4db
ED
500 //\r
501 // Wait for BSP to signal SMM Base relocation done.\r
502 //\r
503 while (!mInitApsAfterSmmBaseReloc) {\r
504 CpuPause ();\r
505 }\r
529a5a86
MK
506\r
507 ProgramVirtualWireMode ();\r
508 DisableLvtInterrupts ();\r
509\r
93324390 510 SetRegister (FALSE);\r
529a5a86
MK
511\r
512 //\r
ec8a3877 513 // Place AP into the safe code, count down the number with lock mechanism in the safe code.\r
4a0f88dd 514 //\r
672b80c8
MK
515 TopOfStack = (UINTN) Stack + sizeof (Stack);\r
516 TopOfStack &= ~(UINTN) (CPU_STACK_ALIGNMENT - 1);\r
4a0f88dd 517 CopyMem ((VOID *) (UINTN) mApHltLoopCode, mApHltLoopCodeTemplate, sizeof (mApHltLoopCodeTemplate));\r
672b80c8 518 TransferApToSafeState ((UINTN)mApHltLoopCode, TopOfStack, (UINTN)&mNumberToFinish);\r
529a5a86
MK
519}\r
520\r
521/**\r
522 Prepares startup vector for APs.\r
523\r
524 This function prepares startup vector for APs.\r
525\r
526 @param WorkingBuffer The address of the work buffer.\r
527**/\r
528VOID\r
529PrepareApStartupVector (\r
530 EFI_PHYSICAL_ADDRESS WorkingBuffer\r
531 )\r
532{\r
533 EFI_PHYSICAL_ADDRESS StartupVector;\r
534 MP_ASSEMBLY_ADDRESS_MAP AddressMap;\r
535\r
536 //\r
537 // Get the address map of startup code for AP,\r
538 // including code size, and offset of long jump instructions to redirect.\r
539 //\r
540 ZeroMem (&AddressMap, sizeof (AddressMap));\r
541 AsmGetAddressMap (&AddressMap);\r
542\r
543 StartupVector = WorkingBuffer;\r
544\r
545 //\r
546 // Copy AP startup code to startup vector, and then redirect the long jump\r
547 // instructions for mode switching.\r
548 //\r
549 CopyMem ((VOID *) (UINTN) StartupVector, AddressMap.RendezvousFunnelAddress, AddressMap.Size);\r
550 *(UINT32 *) (UINTN) (StartupVector + AddressMap.FlatJumpOffset + 3) = (UINT32) (StartupVector + AddressMap.PModeEntryOffset);\r
551 if (AddressMap.LongJumpOffset != 0) {\r
552 *(UINT32 *) (UINTN) (StartupVector + AddressMap.LongJumpOffset + 2) = (UINT32) (StartupVector + AddressMap.LModeEntryOffset);\r
553 }\r
554\r
555 //\r
556 // Get the start address of exchange data between BSP and AP.\r
557 //\r
558 mExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (StartupVector + AddressMap.Size);\r
559 ZeroMem ((VOID *) mExchangeInfo, sizeof (MP_CPU_EXCHANGE_INFO));\r
560\r
561 CopyMem ((VOID *) (UINTN) &mExchangeInfo->GdtrProfile, (VOID *) (UINTN) mAcpiCpuData.GdtrProfile, sizeof (IA32_DESCRIPTOR));\r
562 CopyMem ((VOID *) (UINTN) &mExchangeInfo->IdtrProfile, (VOID *) (UINTN) mAcpiCpuData.IdtrProfile, sizeof (IA32_DESCRIPTOR));\r
563\r
529a5a86
MK
564 mExchangeInfo->StackStart = (VOID *) (UINTN) mAcpiCpuData.StackAddress;\r
565 mExchangeInfo->StackSize = mAcpiCpuData.StackSize;\r
566 mExchangeInfo->BufferStart = (UINT32) StartupVector;\r
567 mExchangeInfo->Cr3 = (UINT32) (AsmReadCr3 ());\r
e21e355e 568 mExchangeInfo->InitializeFloatingPointUnitsAddress = (UINTN)InitializeFloatingPointUnits;\r
529a5a86
MK
569}\r
570\r
571/**\r
572 The function is invoked before SMBASE relocation in S3 path to restores CPU status.\r
573\r
574 The function is invoked before SMBASE relocation in S3 path. It does first time microcode load\r
575 and restores MTRRs for both BSP and APs.\r
576\r
577**/\r
578VOID\r
94744aa2 579InitializeCpuBeforeRebase (\r
529a5a86
MK
580 VOID\r
581 )\r
582{\r
529a5a86
MK
583 LoadMtrrData (mAcpiCpuData.MtrrTable);\r
584\r
93324390 585 SetRegister (TRUE);\r
529a5a86
MK
586\r
587 ProgramVirtualWireMode ();\r
588\r
589 PrepareApStartupVector (mAcpiCpuData.StartupVector);\r
590\r
591 mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1;\r
94744aa2 592 mExchangeInfo->ApFunction = (VOID *) (UINTN) InitializeAp;\r
7677b4db
ED
593\r
594 //\r
595 // Execute code for before SmmBaseReloc. Note: This flag is maintained across S3 boots.\r
596 //\r
597 mInitApsAfterSmmBaseReloc = FALSE;\r
529a5a86
MK
598\r
599 //\r
600 // Send INIT IPI - SIPI to all APs\r
601 //\r
602 SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector);\r
603\r
604 while (mNumberToFinish > 0) {\r
605 CpuPause ();\r
606 }\r
607}\r
608\r
609/**\r
610 The function is invoked after SMBASE relocation in S3 path to restores CPU status.\r
611\r
612 The function is invoked after SMBASE relocation in S3 path. It restores configuration according to\r
613 data saved by normal boot path for both BSP and APs.\r
614\r
615**/\r
616VOID\r
94744aa2 617InitializeCpuAfterRebase (\r
529a5a86
MK
618 VOID\r
619 )\r
620{\r
529a5a86 621 mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1;\r
529a5a86
MK
622\r
623 //\r
93324390 624 // Signal that SMM base relocation is complete and to continue initialization for all APs.\r
529a5a86 625 //\r
7677b4db 626 mInitApsAfterSmmBaseReloc = TRUE;\r
529a5a86 627\r
93324390
ED
628 //\r
629 // Must begin set register after all APs have continue their initialization.\r
630 // This is a requirement to support semaphore mechanism in register table.\r
631 // Because if semaphore's dependence type is package type, semaphore will wait\r
632 // for all Aps in one package finishing their tasks before set next register\r
633 // for all APs. If the Aps not begin its task during BSP doing its task, the\r
634 // BSP thread will hang because it is waiting for other Aps in the same\r
635 // package finishing their task.\r
636 //\r
637 SetRegister (FALSE);\r
638\r
529a5a86
MK
639 while (mNumberToFinish > 0) {\r
640 CpuPause ();\r
641 }\r
642}\r
0bdc9e75
SZ
643\r
644/**\r
645 Restore SMM Configuration in S3 boot path.\r
646\r
647**/\r
648VOID\r
649RestoreSmmConfigurationInS3 (\r
650 VOID\r
651 )\r
652{\r
b10d5ddc
SZ
653 if (!mAcpiS3Enable) {\r
654 return;\r
655 }\r
656\r
0bdc9e75
SZ
657 //\r
658 // Restore SMM Configuration in S3 boot path.\r
659 //\r
660 if (mRestoreSmmConfigurationInS3) {\r
661 //\r
662 // Need make sure gSmst is correct because below function may use them.\r
663 //\r
664 gSmst->SmmStartupThisAp = gSmmCpuPrivate->SmmCoreEntryContext.SmmStartupThisAp;\r
665 gSmst->CurrentlyExecutingCpu = gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu;\r
666 gSmst->NumberOfCpus = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
667 gSmst->CpuSaveStateSize = gSmmCpuPrivate->SmmCoreEntryContext.CpuSaveStateSize;\r
668 gSmst->CpuSaveState = gSmmCpuPrivate->SmmCoreEntryContext.CpuSaveState;\r
669\r
670 //\r
671 // Configure SMM Code Access Check feature if available.\r
672 //\r
673 ConfigSmmCodeAccessCheck ();\r
674\r
675 SmmCpuFeaturesCompleteSmmReadyToLock ();\r
676\r
677 mRestoreSmmConfigurationInS3 = FALSE;\r
678 }\r
679}\r
680\r
681/**\r
682 Perform SMM initialization for all processors in the S3 boot path.\r
683\r
684 For a native platform, MP initialization in the S3 boot path is also performed in this function.\r
685**/\r
686VOID\r
687EFIAPI\r
688SmmRestoreCpu (\r
689 VOID\r
690 )\r
691{\r
692 SMM_S3_RESUME_STATE *SmmS3ResumeState;\r
693 IA32_DESCRIPTOR Ia32Idtr;\r
694 IA32_DESCRIPTOR X64Idtr;\r
695 IA32_IDT_GATE_DESCRIPTOR IdtEntryTable[EXCEPTION_VECTOR_NUMBER];\r
696 EFI_STATUS Status;\r
697\r
698 DEBUG ((EFI_D_INFO, "SmmRestoreCpu()\n"));\r
699\r
700 mSmmS3Flag = TRUE;\r
701\r
0bdc9e75
SZ
702 //\r
703 // See if there is enough context to resume PEI Phase\r
704 //\r
705 if (mSmmS3ResumeState == NULL) {\r
706 DEBUG ((EFI_D_ERROR, "No context to return to PEI Phase\n"));\r
707 CpuDeadLoop ();\r
708 }\r
709\r
710 SmmS3ResumeState = mSmmS3ResumeState;\r
711 ASSERT (SmmS3ResumeState != NULL);\r
712\r
713 if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {\r
714 //\r
715 // Save the IA32 IDT Descriptor\r
716 //\r
717 AsmReadIdtr ((IA32_DESCRIPTOR *) &Ia32Idtr);\r
718\r
719 //\r
720 // Setup X64 IDT table\r
721 //\r
722 ZeroMem (IdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32);\r
723 X64Idtr.Base = (UINTN) IdtEntryTable;\r
724 X64Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32 - 1);\r
725 AsmWriteIdtr ((IA32_DESCRIPTOR *) &X64Idtr);\r
726\r
727 //\r
728 // Setup the default exception handler\r
729 //\r
730 Status = InitializeCpuExceptionHandlers (NULL);\r
731 ASSERT_EFI_ERROR (Status);\r
732\r
733 //\r
734 // Initialize Debug Agent to support source level debug\r
735 //\r
736 InitializeDebugAgent (DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64, (VOID *)&Ia32Idtr, NULL);\r
737 }\r
738\r
739 //\r
740 // Skip initialization if mAcpiCpuData is not valid\r
741 //\r
742 if (mAcpiCpuData.NumberOfCpus > 0) {\r
743 //\r
744 // First time microcode load and restore MTRRs\r
745 //\r
94744aa2 746 InitializeCpuBeforeRebase ();\r
0bdc9e75
SZ
747 }\r
748\r
749 //\r
750 // Restore SMBASE for BSP and all APs\r
751 //\r
752 SmmRelocateBases ();\r
753\r
754 //\r
755 // Skip initialization if mAcpiCpuData is not valid\r
756 //\r
757 if (mAcpiCpuData.NumberOfCpus > 0) {\r
758 //\r
759 // Restore MSRs for BSP and all APs\r
760 //\r
94744aa2 761 InitializeCpuAfterRebase ();\r
0bdc9e75
SZ
762 }\r
763\r
764 //\r
765 // Set a flag to restore SMM configuration in S3 path.\r
766 //\r
767 mRestoreSmmConfigurationInS3 = TRUE;\r
768\r
769 DEBUG (( EFI_D_INFO, "SMM S3 Return CS = %x\n", SmmS3ResumeState->ReturnCs));\r
770 DEBUG (( EFI_D_INFO, "SMM S3 Return Entry Point = %x\n", SmmS3ResumeState->ReturnEntryPoint));\r
771 DEBUG (( EFI_D_INFO, "SMM S3 Return Context1 = %x\n", SmmS3ResumeState->ReturnContext1));\r
772 DEBUG (( EFI_D_INFO, "SMM S3 Return Context2 = %x\n", SmmS3ResumeState->ReturnContext2));\r
773 DEBUG (( EFI_D_INFO, "SMM S3 Return Stack Pointer = %x\n", SmmS3ResumeState->ReturnStackPointer));\r
774\r
775 //\r
776 // If SMM is in 32-bit mode, then use SwitchStack() to resume PEI Phase\r
777 //\r
778 if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) {\r
779 DEBUG ((EFI_D_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));\r
780\r
781 SwitchStack (\r
782 (SWITCH_STACK_ENTRY_POINT)(UINTN)SmmS3ResumeState->ReturnEntryPoint,\r
783 (VOID *)(UINTN)SmmS3ResumeState->ReturnContext1,\r
784 (VOID *)(UINTN)SmmS3ResumeState->ReturnContext2,\r
785 (VOID *)(UINTN)SmmS3ResumeState->ReturnStackPointer\r
786 );\r
787 }\r
788\r
789 //\r
790 // If SMM is in 64-bit mode, then use AsmDisablePaging64() to resume PEI Phase\r
791 //\r
792 if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {\r
793 DEBUG ((EFI_D_INFO, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n"));\r
794 //\r
795 // Disable interrupt of Debug timer, since new IDT table is for IA32 and will not work in long mode.\r
796 //\r
797 SaveAndSetDebugTimerInterrupt (FALSE);\r
798 //\r
799 // Restore IA32 IDT table\r
800 //\r
801 AsmWriteIdtr ((IA32_DESCRIPTOR *) &Ia32Idtr);\r
802 AsmDisablePaging64 (\r
803 SmmS3ResumeState->ReturnCs,\r
804 (UINT32)SmmS3ResumeState->ReturnEntryPoint,\r
805 (UINT32)SmmS3ResumeState->ReturnContext1,\r
806 (UINT32)SmmS3ResumeState->ReturnContext2,\r
807 (UINT32)SmmS3ResumeState->ReturnStackPointer\r
808 );\r
809 }\r
810\r
811 //\r
812 // Can not resume PEI Phase\r
813 //\r
814 DEBUG ((EFI_D_ERROR, "No context to return to PEI Phase\n"));\r
815 CpuDeadLoop ();\r
816}\r
817\r
818/**\r
819 Initialize SMM S3 resume state structure used during S3 Resume.\r
820\r
821 @param[in] Cr3 The base address of the page tables to use in SMM.\r
822\r
823**/\r
824VOID\r
825InitSmmS3ResumeState (\r
826 IN UINT32 Cr3\r
827 )\r
828{\r
829 VOID *GuidHob;\r
830 EFI_SMRAM_DESCRIPTOR *SmramDescriptor;\r
831 SMM_S3_RESUME_STATE *SmmS3ResumeState;\r
4a0f88dd
JF
832 EFI_PHYSICAL_ADDRESS Address;\r
833 EFI_STATUS Status;\r
0bdc9e75 834\r
b10d5ddc
SZ
835 if (!mAcpiS3Enable) {\r
836 return;\r
837 }\r
838\r
0bdc9e75 839 GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);\r
a95c9cfd
JW
840 if (GuidHob == NULL) {\r
841 DEBUG ((\r
842 DEBUG_ERROR,\r
843 "ERROR:%a(): HOB(gEfiAcpiVariableGuid=%g) needed by S3 resume doesn't exist!\n",\r
844 __FUNCTION__,\r
845 &gEfiAcpiVariableGuid\r
846 ));\r
847 CpuDeadLoop ();\r
848 } else {\r
0bdc9e75
SZ
849 SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);\r
850\r
851 DEBUG ((EFI_D_INFO, "SMM S3 SMRAM Structure = %x\n", SmramDescriptor));\r
852 DEBUG ((EFI_D_INFO, "SMM S3 Structure = %x\n", SmramDescriptor->CpuStart));\r
853\r
854 SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;\r
855 ZeroMem (SmmS3ResumeState, sizeof (SMM_S3_RESUME_STATE));\r
856\r
857 mSmmS3ResumeState = SmmS3ResumeState;\r
858 SmmS3ResumeState->Smst = (EFI_PHYSICAL_ADDRESS)(UINTN)gSmst;\r
859\r
860 SmmS3ResumeState->SmmS3ResumeEntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)SmmRestoreCpu;\r
861\r
862 SmmS3ResumeState->SmmS3StackSize = SIZE_32KB;\r
863 SmmS3ResumeState->SmmS3StackBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES ((UINTN)SmmS3ResumeState->SmmS3StackSize));\r
864 if (SmmS3ResumeState->SmmS3StackBase == 0) {\r
865 SmmS3ResumeState->SmmS3StackSize = 0;\r
866 }\r
867\r
f0053e83 868 SmmS3ResumeState->SmmS3Cr0 = mSmmCr0;\r
0bdc9e75 869 SmmS3ResumeState->SmmS3Cr3 = Cr3;\r
351b49c1 870 SmmS3ResumeState->SmmS3Cr4 = mSmmCr4;\r
0bdc9e75
SZ
871\r
872 if (sizeof (UINTN) == sizeof (UINT64)) {\r
873 SmmS3ResumeState->Signature = SMM_S3_RESUME_SMM_64;\r
874 }\r
875 if (sizeof (UINTN) == sizeof (UINT32)) {\r
876 SmmS3ResumeState->Signature = SMM_S3_RESUME_SMM_32;\r
877 }\r
0bdc9e75 878\r
16d84657
JW
879 //\r
880 // Patch SmmS3ResumeState->SmmS3Cr3\r
881 //\r
882 InitSmmS3Cr3 ();\r
883 }\r
4a0f88dd
JF
884\r
885 //\r
886 // Allocate safe memory in ACPI NVS for AP to execute hlt loop in\r
887 // protected mode on S3 path\r
888 //\r
889 Address = BASE_4GB - 1;\r
890 Status = gBS->AllocatePages (\r
891 AllocateMaxAddress,\r
892 EfiACPIMemoryNVS,\r
893 EFI_SIZE_TO_PAGES (sizeof (mApHltLoopCodeTemplate)),\r
894 &Address\r
895 );\r
896 ASSERT_EFI_ERROR (Status);\r
897 mApHltLoopCode = (UINT8 *) (UINTN) Address;\r
0bdc9e75
SZ
898}\r
899\r
900/**\r
901 Copy register table from ACPI NVS memory into SMRAM.\r
902\r
903 @param[in] DestinationRegisterTableList Points to destination register table.\r
904 @param[in] SourceRegisterTableList Points to source register table.\r
905 @param[in] NumberOfCpus Number of CPUs.\r
906\r
907**/\r
908VOID\r
909CopyRegisterTable (\r
910 IN CPU_REGISTER_TABLE *DestinationRegisterTableList,\r
911 IN CPU_REGISTER_TABLE *SourceRegisterTableList,\r
912 IN UINT32 NumberOfCpus\r
913 )\r
914{\r
915 UINTN Index;\r
0bdc9e75
SZ
916 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
917\r
918 CopyMem (DestinationRegisterTableList, SourceRegisterTableList, NumberOfCpus * sizeof (CPU_REGISTER_TABLE));\r
919 for (Index = 0; Index < NumberOfCpus; Index++) {\r
30d995ee
JF
920 if (DestinationRegisterTableList[Index].AllocatedSize != 0) {\r
921 RegisterTableEntry = AllocateCopyPool (\r
922 DestinationRegisterTableList[Index].AllocatedSize,\r
923 (VOID *)(UINTN)SourceRegisterTableList[Index].RegisterTableEntry\r
924 );\r
925 ASSERT (RegisterTableEntry != NULL);\r
926 DestinationRegisterTableList[Index].RegisterTableEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTableEntry;\r
0bdc9e75
SZ
927 }\r
928 }\r
929}\r
930\r
931/**\r
932 Get ACPI CPU data.\r
933\r
934**/\r
935VOID\r
936GetAcpiCpuData (\r
937 VOID\r
938 )\r
939{\r
940 ACPI_CPU_DATA *AcpiCpuData;\r
941 IA32_DESCRIPTOR *Gdtr;\r
942 IA32_DESCRIPTOR *Idtr;\r
293f8766
ED
943 VOID *GdtForAp;\r
944 VOID *IdtForAp;\r
945 VOID *MachineCheckHandlerForAp;\r
93324390 946 CPU_STATUS_INFORMATION *CpuStatus;\r
0bdc9e75 947\r
b10d5ddc
SZ
948 if (!mAcpiS3Enable) {\r
949 return;\r
950 }\r
951\r
0bdc9e75
SZ
952 //\r
953 // Prevent use of mAcpiCpuData by initialize NumberOfCpus to 0\r
954 //\r
955 mAcpiCpuData.NumberOfCpus = 0;\r
956\r
957 //\r
958 // If PcdCpuS3DataAddress was never set, then do not copy CPU S3 Data into SMRAM\r
959 //\r
960 AcpiCpuData = (ACPI_CPU_DATA *)(UINTN)PcdGet64 (PcdCpuS3DataAddress);\r
961 if (AcpiCpuData == 0) {\r
962 return;\r
963 }\r
964\r
965 //\r
966 // For a native platform, copy the CPU S3 data into SMRAM for use on CPU S3 Resume.\r
967 //\r
968 CopyMem (&mAcpiCpuData, AcpiCpuData, sizeof (mAcpiCpuData));\r
969\r
970 mAcpiCpuData.MtrrTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (sizeof (MTRR_SETTINGS));\r
971 ASSERT (mAcpiCpuData.MtrrTable != 0);\r
972\r
973 CopyMem ((VOID *)(UINTN)mAcpiCpuData.MtrrTable, (VOID *)(UINTN)AcpiCpuData->MtrrTable, sizeof (MTRR_SETTINGS));\r
974\r
975 mAcpiCpuData.GdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (sizeof (IA32_DESCRIPTOR));\r
976 ASSERT (mAcpiCpuData.GdtrProfile != 0);\r
977\r
978 CopyMem ((VOID *)(UINTN)mAcpiCpuData.GdtrProfile, (VOID *)(UINTN)AcpiCpuData->GdtrProfile, sizeof (IA32_DESCRIPTOR));\r
979\r
980 mAcpiCpuData.IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (sizeof (IA32_DESCRIPTOR));\r
981 ASSERT (mAcpiCpuData.IdtrProfile != 0);\r
982\r
983 CopyMem ((VOID *)(UINTN)mAcpiCpuData.IdtrProfile, (VOID *)(UINTN)AcpiCpuData->IdtrProfile, sizeof (IA32_DESCRIPTOR));\r
984\r
985 mAcpiCpuData.PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));\r
986 ASSERT (mAcpiCpuData.PreSmmInitRegisterTable != 0);\r
987\r
988 CopyRegisterTable (\r
989 (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.PreSmmInitRegisterTable,\r
990 (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->PreSmmInitRegisterTable,\r
991 mAcpiCpuData.NumberOfCpus\r
992 );\r
993\r
994 mAcpiCpuData.RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));\r
995 ASSERT (mAcpiCpuData.RegisterTable != 0);\r
996\r
997 CopyRegisterTable (\r
998 (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable,\r
999 (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable,\r
1000 mAcpiCpuData.NumberOfCpus\r
1001 );\r
1002\r
1003 //\r
1004 // Copy AP's GDT, IDT and Machine Check handler into SMRAM.\r
1005 //\r
1006 Gdtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.GdtrProfile;\r
1007 Idtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.IdtrProfile;\r
1008\r
293f8766
ED
1009 GdtForAp = AllocatePool ((Gdtr->Limit + 1) + (Idtr->Limit + 1) + mAcpiCpuData.ApMachineCheckHandlerSize);\r
1010 ASSERT (GdtForAp != NULL);\r
1011 IdtForAp = (VOID *) ((UINTN)GdtForAp + (Gdtr->Limit + 1));\r
1012 MachineCheckHandlerForAp = (VOID *) ((UINTN)IdtForAp + (Idtr->Limit + 1));\r
1013\r
1014 CopyMem (GdtForAp, (VOID *)Gdtr->Base, Gdtr->Limit + 1);\r
1015 CopyMem (IdtForAp, (VOID *)Idtr->Base, Idtr->Limit + 1);\r
1016 CopyMem (MachineCheckHandlerForAp, (VOID *)(UINTN)mAcpiCpuData.ApMachineCheckHandlerBase, mAcpiCpuData.ApMachineCheckHandlerSize);\r
0bdc9e75 1017\r
293f8766
ED
1018 Gdtr->Base = (UINTN)GdtForAp;\r
1019 Idtr->Base = (UINTN)IdtForAp;\r
1020 mAcpiCpuData.ApMachineCheckHandlerBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MachineCheckHandlerForAp;\r
93324390
ED
1021\r
1022 CpuStatus = &mAcpiCpuData.CpuStatus;\r
1023 CopyMem (CpuStatus, &AcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMATION));\r
1024 if (AcpiCpuData->CpuStatus.ValidCoreCountPerPackage != 0) {\r
1025 CpuStatus->ValidCoreCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (\r
1026 sizeof (UINT32) * CpuStatus->PackageCount,\r
1027 (UINT32 *)(UINTN)AcpiCpuData->CpuStatus.ValidCoreCountPerPackage\r
1028 );\r
1029 ASSERT (CpuStatus->ValidCoreCountPerPackage != 0);\r
1030 }\r
1031 if (AcpiCpuData->ApLocation != 0) {\r
1032 mAcpiCpuData.ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (\r
1033 mAcpiCpuData.NumberOfCpus * sizeof (EFI_CPU_PHYSICAL_LOCATION),\r
1034 (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->ApLocation\r
1035 );\r
1036 ASSERT (mAcpiCpuData.ApLocation != 0);\r
1037 }\r
1038 if (CpuStatus->PackageCount != 0) {\r
9bae7811
ED
1039 mCpuFlags.CoreSemaphoreCount = AllocateZeroPool (\r
1040 sizeof (UINT32) * CpuStatus->PackageCount *\r
1041 CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount\r
1042 );\r
1043 ASSERT (mCpuFlags.CoreSemaphoreCount != NULL);\r
1044 mCpuFlags.PackageSemaphoreCount = AllocateZeroPool (\r
1045 sizeof (UINT32) * CpuStatus->PackageCount *\r
1046 CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount\r
1047 );\r
1048 ASSERT (mCpuFlags.PackageSemaphoreCount != NULL);\r
93324390
ED
1049 }\r
1050 InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.MemoryMappedLock);\r
1051 InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.ConsoleLogLock);\r
0bdc9e75 1052}\r
b10d5ddc
SZ
1053\r
1054/**\r
1055 Get ACPI S3 enable flag.\r
1056\r
1057**/\r
1058VOID\r
1059GetAcpiS3EnableFlag (\r
1060 VOID\r
1061 )\r
1062{\r
1063 mAcpiS3Enable = PcdGetBool (PcdAcpiS3Enable);\r
1064}\r