]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/PlatformPei/MemDetect.c
UefiCpuPkg/MpInitLib: wait no longer than necessary for initial AP startup
[mirror_edk2.git] / OvmfPkg / PlatformPei / MemDetect.c
CommitLineData
49ba9447 1/**@file\r
2 Memory Detection for Virtual Machines.\r
3\r
035ce3b3 4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
56d7640a 5 This program and the accompanying materials\r
49ba9447 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
13Module Name:\r
14\r
15 MemDetect.c\r
16\r
17**/\r
18\r
19//\r
20// The package level header files this module uses\r
21//\r
22#include <PiPei.h>\r
23\r
24//\r
25// The Library classes this module consumes\r
26//\r
6a7cba79 27#include <Library/BaseMemoryLib.h>\r
49ba9447 28#include <Library/DebugLib.h>\r
29#include <Library/HobLib.h>\r
30#include <Library/IoLib.h>\r
c1c2669c 31#include <Library/PcdLib.h>\r
49ba9447 32#include <Library/PeimEntryPoint.h>\r
33#include <Library/ResourcePublicationLib.h>\r
e8e5cd4a 34#include <Library/MtrrLib.h>\r
7e5b1b67 35#include <Library/QemuFwCfgLib.h>\r
49ba9447 36\r
37#include "Platform.h"\r
38#include "Cmos.h"\r
39\r
bc89fe48
LE
40UINT8 mPhysMemAddressWidth;\r
41\r
45d87081
LE
42STATIC UINT32 mS3AcpiReservedMemoryBase;\r
43STATIC UINT32 mS3AcpiReservedMemorySize;\r
44\r
4b455f7b 45UINT32\r
c0e10976 46GetSystemMemorySizeBelow4gb (\r
4b455f7b 47 VOID\r
49ba9447 48 )\r
49{\r
50 UINT8 Cmos0x34;\r
51 UINT8 Cmos0x35;\r
52\r
53 //\r
54 // CMOS 0x34/0x35 specifies the system memory above 16 MB.\r
55 // * CMOS(0x35) is the high byte\r
56 // * CMOS(0x34) is the low byte\r
57 // * The size is specified in 64kb chunks\r
58 // * Since this is memory above 16MB, the 16MB must be added\r
59 // into the calculation to get the total memory size.\r
60 //\r
61\r
62 Cmos0x34 = (UINT8) CmosRead8 (0x34);\r
63 Cmos0x35 = (UINT8) CmosRead8 (0x35);\r
64\r
c4046161 65 return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);\r
49ba9447 66}\r
67\r
68\r
c0e10976 69STATIC\r
70UINT64\r
71GetSystemMemorySizeAbove4gb (\r
72 )\r
73{\r
74 UINT32 Size;\r
75 UINTN CmosIndex;\r
76\r
77 //\r
78 // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.\r
79 // * CMOS(0x5d) is the most significant size byte\r
80 // * CMOS(0x5c) is the middle size byte\r
81 // * CMOS(0x5b) is the least significant size byte\r
82 // * The size is specified in 64kb chunks\r
83 //\r
84\r
85 Size = 0;\r
86 for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {\r
87 Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex);\r
88 }\r
89\r
90 return LShiftU64 (Size, 16);\r
91}\r
92\r
bc89fe48 93\r
d5371680
LE
94/**\r
95 Return the highest address that DXE could possibly use, plus one.\r
96**/\r
97STATIC\r
98UINT64\r
99GetFirstNonAddress (\r
100 VOID\r
101 )\r
102{\r
103 UINT64 FirstNonAddress;\r
7e5b1b67
LE
104 UINT64 Pci64Base, Pci64Size;\r
105 CHAR8 MbString[7 + 1];\r
106 EFI_STATUS Status;\r
107 FIRMWARE_CONFIG_ITEM FwCfgItem;\r
108 UINTN FwCfgSize;\r
109 UINT64 HotPlugMemoryEnd;\r
32e083c7 110 RETURN_STATUS PcdStatus;\r
d5371680
LE
111\r
112 FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb ();\r
7e5b1b67
LE
113\r
114 //\r
115 // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO\r
116 // resources to 32-bit anyway. See DegradeResource() in\r
117 // "PciResourceSupport.c".\r
118 //\r
119#ifdef MDE_CPU_IA32\r
120 if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
121 return FirstNonAddress;\r
122 }\r
123#endif\r
124\r
125 //\r
126 // Otherwise, in order to calculate the highest address plus one, we must\r
127 // consider the 64-bit PCI host aperture too. Fetch the default size.\r
128 //\r
129 Pci64Size = PcdGet64 (PcdPciMmio64Size);\r
130\r
131 //\r
132 // See if the user specified the number of megabytes for the 64-bit PCI host\r
133 // aperture. The number of non-NUL characters in MbString allows for\r
134 // 9,999,999 MB, which is approximately 10 TB.\r
135 //\r
136 // As signaled by the "X-" prefix, this knob is experimental, and might go\r
137 // away at any time.\r
138 //\r
139 Status = QemuFwCfgFindFile ("opt/ovmf/X-PciMmio64Mb", &FwCfgItem,\r
140 &FwCfgSize);\r
141 if (!EFI_ERROR (Status)) {\r
142 if (FwCfgSize >= sizeof MbString) {\r
143 DEBUG ((EFI_D_WARN,\r
144 "%a: ignoring malformed 64-bit PCI host aperture size from fw_cfg\n",\r
145 __FUNCTION__));\r
146 } else {\r
147 QemuFwCfgSelectItem (FwCfgItem);\r
148 QemuFwCfgReadBytes (FwCfgSize, MbString);\r
149 MbString[FwCfgSize] = '\0';\r
150 Pci64Size = LShiftU64 (AsciiStrDecimalToUint64 (MbString), 20);\r
151 }\r
152 }\r
153\r
154 if (Pci64Size == 0) {\r
155 if (mBootMode != BOOT_ON_S3_RESUME) {\r
156 DEBUG ((EFI_D_INFO, "%a: disabling 64-bit PCI host aperture\n",\r
157 __FUNCTION__));\r
32e083c7
LE
158 PcdStatus = PcdSet64S (PcdPciMmio64Size, 0);\r
159 ASSERT_RETURN_ERROR (PcdStatus);\r
7e5b1b67
LE
160 }\r
161\r
162 //\r
163 // There's nothing more to do; the amount of memory above 4GB fully\r
164 // determines the highest address plus one. The memory hotplug area (see\r
165 // below) plays no role for the firmware in this case.\r
166 //\r
167 return FirstNonAddress;\r
168 }\r
169\r
170 //\r
171 // The "etc/reserved-memory-end" fw_cfg file, when present, contains an\r
172 // absolute, exclusive end address for the memory hotplug area. This area\r
173 // starts right at the end of the memory above 4GB. The 64-bit PCI host\r
174 // aperture must be placed above it.\r
175 //\r
176 Status = QemuFwCfgFindFile ("etc/reserved-memory-end", &FwCfgItem,\r
177 &FwCfgSize);\r
178 if (!EFI_ERROR (Status) && FwCfgSize == sizeof HotPlugMemoryEnd) {\r
179 QemuFwCfgSelectItem (FwCfgItem);\r
180 QemuFwCfgReadBytes (FwCfgSize, &HotPlugMemoryEnd);\r
181\r
182 ASSERT (HotPlugMemoryEnd >= FirstNonAddress);\r
183 FirstNonAddress = HotPlugMemoryEnd;\r
184 }\r
185\r
186 //\r
187 // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so\r
188 // that the host can map it with 1GB hugepages. Follow suit.\r
189 //\r
190 Pci64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);\r
191 Pci64Size = ALIGN_VALUE (Pci64Size, (UINT64)SIZE_1GB);\r
192\r
193 //\r
194 // The 64-bit PCI host aperture should also be "naturally" aligned. The\r
195 // alignment is determined by rounding the size of the aperture down to the\r
196 // next smaller or equal power of two. That is, align the aperture by the\r
197 // largest BAR size that can fit into it.\r
198 //\r
199 Pci64Base = ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size));\r
200\r
201 if (mBootMode != BOOT_ON_S3_RESUME) {\r
202 //\r
203 // The core PciHostBridgeDxe driver will automatically add this range to\r
204 // the GCD memory space map through our PciHostBridgeLib instance; here we\r
205 // only need to set the PCDs.\r
206 //\r
32e083c7
LE
207 PcdStatus = PcdSet64S (PcdPciMmio64Base, Pci64Base);\r
208 ASSERT_RETURN_ERROR (PcdStatus);\r
209 PcdStatus = PcdSet64S (PcdPciMmio64Size, Pci64Size);\r
210 ASSERT_RETURN_ERROR (PcdStatus);\r
211\r
7e5b1b67
LE
212 DEBUG ((EFI_D_INFO, "%a: Pci64Base=0x%Lx Pci64Size=0x%Lx\n",\r
213 __FUNCTION__, Pci64Base, Pci64Size));\r
214 }\r
215\r
216 //\r
217 // The useful address space ends with the 64-bit PCI host aperture.\r
218 //\r
219 FirstNonAddress = Pci64Base + Pci64Size;\r
d5371680
LE
220 return FirstNonAddress;\r
221}\r
222\r
223\r
bc89fe48
LE
224/**\r
225 Initialize the mPhysMemAddressWidth variable, based on guest RAM size.\r
226**/\r
227VOID\r
228AddressWidthInitialization (\r
229 VOID\r
230 )\r
231{\r
232 UINT64 FirstNonAddress;\r
233\r
234 //\r
235 // As guest-physical memory size grows, the permanent PEI RAM requirements\r
236 // are dominated by the identity-mapping page tables built by the DXE IPL.\r
237 // The DXL IPL keys off of the physical address bits advertized in the CPU\r
238 // HOB. To conserve memory, we calculate the minimum address width here.\r
239 //\r
d5371680 240 FirstNonAddress = GetFirstNonAddress ();\r
bc89fe48
LE
241 mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);\r
242\r
243 //\r
244 // If FirstNonAddress is not an integral power of two, then we need an\r
245 // additional bit.\r
246 //\r
247 if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {\r
248 ++mPhysMemAddressWidth;\r
249 }\r
250\r
251 //\r
252 // The minimum address width is 36 (covers up to and excluding 64 GB, which\r
253 // is the maximum for Ia32 + PAE). The theoretical architecture maximum for\r
254 // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We\r
255 // can simply assert that here, since 48 bits are good enough for 256 TB.\r
256 //\r
257 if (mPhysMemAddressWidth <= 36) {\r
258 mPhysMemAddressWidth = 36;\r
259 }\r
260 ASSERT (mPhysMemAddressWidth <= 48);\r
261}\r
262\r
263\r
264/**\r
265 Calculate the cap for the permanent PEI memory.\r
266**/\r
267STATIC\r
268UINT32\r
269GetPeiMemoryCap (\r
270 VOID\r
271 )\r
272{\r
273 BOOLEAN Page1GSupport;\r
274 UINT32 RegEax;\r
275 UINT32 RegEdx;\r
276 UINT32 Pml4Entries;\r
277 UINT32 PdpEntries;\r
278 UINTN TotalPages;\r
279\r
280 //\r
281 // If DXE is 32-bit, then just return the traditional 64 MB cap.\r
282 //\r
283#ifdef MDE_CPU_IA32\r
284 if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
285 return SIZE_64MB;\r
286 }\r
287#endif\r
288\r
289 //\r
290 // Dependent on physical address width, PEI memory allocations can be\r
291 // dominated by the page tables built for 64-bit DXE. So we key the cap off\r
292 // of those. The code below is based on CreateIdentityMappingPageTables() in\r
293 // "MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c".\r
294 //\r
295 Page1GSupport = FALSE;\r
296 if (PcdGetBool (PcdUse1GPageTable)) {\r
297 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
298 if (RegEax >= 0x80000001) {\r
299 AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
300 if ((RegEdx & BIT26) != 0) {\r
301 Page1GSupport = TRUE;\r
302 }\r
303 }\r
304 }\r
305\r
306 if (mPhysMemAddressWidth <= 39) {\r
307 Pml4Entries = 1;\r
308 PdpEntries = 1 << (mPhysMemAddressWidth - 30);\r
309 ASSERT (PdpEntries <= 0x200);\r
310 } else {\r
311 Pml4Entries = 1 << (mPhysMemAddressWidth - 39);\r
312 ASSERT (Pml4Entries <= 0x200);\r
313 PdpEntries = 512;\r
314 }\r
315\r
316 TotalPages = Page1GSupport ? Pml4Entries + 1 :\r
317 (PdpEntries + 1) * Pml4Entries + 1;\r
318 ASSERT (TotalPages <= 0x40201);\r
319\r
320 //\r
321 // Add 64 MB for miscellaneous allocations. Note that for\r
322 // mPhysMemAddressWidth values close to 36, the cap will actually be\r
323 // dominated by this increment.\r
324 //\r
325 return (UINT32)(EFI_PAGES_TO_SIZE (TotalPages) + SIZE_64MB);\r
326}\r
327\r
328\r
36658fff
WL
329/**\r
330 Publish PEI core memory\r
331\r
332 @return EFI_SUCCESS The PEIM initialized successfully.\r
333\r
334**/\r
335EFI_STATUS\r
336PublishPeiMemory (\r
337 VOID\r
338 )\r
339{\r
340 EFI_STATUS Status;\r
341 EFI_PHYSICAL_ADDRESS MemoryBase;\r
342 UINT64 MemorySize;\r
fc3f005a 343 UINT32 LowerMemorySize;\r
bc89fe48 344 UINT32 PeiMemoryCap;\r
36658fff 345\r
45d87081
LE
346 LowerMemorySize = GetSystemMemorySizeBelow4gb ();\r
347 if (FeaturePcdGet (PcdSmmSmramRequire)) {\r
348 //\r
349 // TSEG is chipped from the end of low RAM\r
350 //\r
351 LowerMemorySize -= FixedPcdGet8 (PcdQ35TsegMbytes) * SIZE_1MB;\r
352 }\r
353\r
354 //\r
355 // If S3 is supported, then the S3 permanent PEI memory is placed next,\r
356 // downwards. Its size is primarily dictated by CpuMpPei. The formula below\r
357 // is an approximation.\r
358 //\r
359 if (mS3Supported) {\r
360 mS3AcpiReservedMemorySize = SIZE_512KB +\r
361 PcdGet32 (PcdCpuMaxLogicalProcessorNumber) *\r
362 PcdGet32 (PcdCpuApStackSize);\r
363 mS3AcpiReservedMemoryBase = LowerMemorySize - mS3AcpiReservedMemorySize;\r
364 LowerMemorySize = mS3AcpiReservedMemoryBase;\r
365 }\r
366\r
8e54500f 367 if (mBootMode == BOOT_ON_S3_RESUME) {\r
45d87081
LE
368 MemoryBase = mS3AcpiReservedMemoryBase;\r
369 MemorySize = mS3AcpiReservedMemorySize;\r
8e54500f 370 } else {\r
bc89fe48
LE
371 PeiMemoryCap = GetPeiMemoryCap ();\r
372 DEBUG ((EFI_D_INFO, "%a: mPhysMemAddressWidth=%d PeiMemoryCap=%u KB\n",\r
373 __FUNCTION__, mPhysMemAddressWidth, PeiMemoryCap >> 10));\r
374\r
8e54500f
JJ
375 //\r
376 // Determine the range of memory to use during PEI\r
377 //\r
efb0f16e
LE
378 // Technically we could lay the permanent PEI RAM over SEC's temporary\r
379 // decompression and scratch buffer even if "secure S3" is needed, since\r
380 // their lifetimes don't overlap. However, PeiFvInitialization() will cover\r
381 // RAM up to PcdOvmfDecompressionScratchEnd with an EfiACPIMemoryNVS memory\r
382 // allocation HOB, and other allocations served from the permanent PEI RAM\r
383 // shouldn't overlap with that HOB.\r
384 //\r
385 MemoryBase = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire) ?\r
386 PcdGet32 (PcdOvmfDecompressionScratchEnd) :\r
387 PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 (PcdOvmfDxeMemFvSize);\r
8e54500f 388 MemorySize = LowerMemorySize - MemoryBase;\r
bc89fe48
LE
389 if (MemorySize > PeiMemoryCap) {\r
390 MemoryBase = LowerMemorySize - PeiMemoryCap;\r
391 MemorySize = PeiMemoryCap;\r
8e54500f 392 }\r
36658fff
WL
393 }\r
394\r
395 //\r
396 // Publish this memory to the PEI Core\r
397 //\r
398 Status = PublishSystemMemory(MemoryBase, MemorySize);\r
399 ASSERT_EFI_ERROR (Status);\r
400\r
401 return Status;\r
402}\r
403\r
c0e10976 404\r
49ba9447 405/**\r
c034906e 406 Peform Memory Detection for QEMU / KVM\r
49ba9447 407\r
408**/\r
c034906e
JJ
409STATIC\r
410VOID\r
411QemuInitializeRam (\r
412 VOID\r
49ba9447 413 )\r
414{\r
c0e10976 415 UINT64 LowerMemorySize;\r
416 UINT64 UpperMemorySize;\r
79d274b8
LE
417 MTRR_SETTINGS MtrrSettings;\r
418 EFI_STATUS Status;\r
49ba9447 419\r
c034906e 420 DEBUG ((EFI_D_INFO, "%a called\n", __FUNCTION__));\r
49ba9447 421\r
422 //\r
423 // Determine total memory size available\r
424 //\r
c0e10976 425 LowerMemorySize = GetSystemMemorySizeBelow4gb ();\r
426 UpperMemorySize = GetSystemMemorySizeAbove4gb ();\r
49ba9447 427\r
e3e3090a
LE
428 if (mBootMode == BOOT_ON_S3_RESUME) {\r
429 //\r
430 // Create the following memory HOB as an exception on the S3 boot path.\r
431 //\r
432 // Normally we'd create memory HOBs only on the normal boot path. However,\r
433 // CpuMpPei specifically needs such a low-memory HOB on the S3 path as\r
434 // well, for "borrowing" a subset of it temporarily, for the AP startup\r
435 // vector.\r
436 //\r
437 // CpuMpPei saves the original contents of the borrowed area in permanent\r
438 // PEI RAM, in a backup buffer allocated with the normal PEI services.\r
439 // CpuMpPei restores the original contents ("returns" the borrowed area) at\r
440 // End-of-PEI. End-of-PEI in turn is emitted by S3Resume2Pei before\r
8c0b0b34 441 // transferring control to the OS's wakeup vector in the FACS.\r
e3e3090a
LE
442 //\r
443 // We expect any other PEIMs that "borrow" memory similarly to CpuMpPei to\r
444 // restore the original contents. Furthermore, we expect all such PEIMs\r
445 // (CpuMpPei included) to claim the borrowed areas by producing memory\r
446 // allocation HOBs, and to honor preexistent memory allocation HOBs when\r
447 // looking for an area to borrow.\r
448 //\r
449 AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);\r
450 } else {\r
bd386eaf
JJ
451 //\r
452 // Create memory HOBs\r
453 //\r
bd386eaf 454 AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);\r
b09c1c6f
LE
455\r
456 if (FeaturePcdGet (PcdSmmSmramRequire)) {\r
457 UINT32 TsegSize;\r
458\r
459 TsegSize = FixedPcdGet8 (PcdQ35TsegMbytes) * SIZE_1MB;\r
460 AddMemoryRangeHob (BASE_1MB, LowerMemorySize - TsegSize);\r
461 AddReservedMemoryBaseSizeHob (LowerMemorySize - TsegSize, TsegSize,\r
462 TRUE);\r
463 } else {\r
464 AddMemoryRangeHob (BASE_1MB, LowerMemorySize);\r
465 }\r
466\r
cfc80e2e 467 if (UpperMemorySize != 0) {\r
035ce3b3 468 AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);\r
cfc80e2e 469 }\r
bd386eaf 470 }\r
49ba9447 471\r
79d274b8
LE
472 //\r
473 // We'd like to keep the following ranges uncached:\r
474 // - [640 KB, 1 MB)\r
475 // - [LowerMemorySize, 4 GB)\r
476 //\r
477 // Everything else should be WB. Unfortunately, programming the inverse (ie.\r
478 // keeping the default UC, and configuring the complement set of the above as\r
479 // WB) is not reliable in general, because the end of the upper RAM can have\r
480 // practically any alignment, and we may not have enough variable MTRRs to\r
481 // cover it exactly.\r
482 //\r
483 if (IsMtrrSupported ()) {\r
484 MtrrGetAllMtrrs (&MtrrSettings);\r
485\r
486 //\r
487 // MTRRs disabled, fixed MTRRs disabled, default type is uncached\r
488 //\r
489 ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);\r
490 ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);\r
491 ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);\r
492\r
493 //\r
494 // flip default type to writeback\r
495 //\r
496 SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);\r
497 ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);\r
498 MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;\r
499 MtrrSetAllMtrrs (&MtrrSettings);\r
e8e5cd4a 500\r
79d274b8
LE
501 //\r
502 // Set memory range from 640KB to 1MB to uncacheable\r
503 //\r
504 Status = MtrrSetMemoryAttribute (BASE_512KB + BASE_128KB,\r
505 BASE_1MB - (BASE_512KB + BASE_128KB), CacheUncacheable);\r
506 ASSERT_EFI_ERROR (Status);\r
e8e5cd4a 507\r
79d274b8
LE
508 //\r
509 // Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB as\r
510 // uncacheable\r
511 //\r
512 Status = MtrrSetMemoryAttribute (LowerMemorySize,\r
513 SIZE_4GB - LowerMemorySize, CacheUncacheable);\r
514 ASSERT_EFI_ERROR (Status);\r
c0e10976 515 }\r
49ba9447 516}\r
517\r
c034906e
JJ
518/**\r
519 Publish system RAM and reserve memory regions\r
520\r
521**/\r
522VOID\r
523InitializeRamRegions (\r
524 VOID\r
525 )\r
526{\r
2818c158
JJ
527 if (!mXen) {\r
528 QemuInitializeRam ();\r
529 } else {\r
2818c158
JJ
530 XenPublishRamRegions ();\r
531 }\r
8e54500f
JJ
532\r
533 if (mS3Supported && mBootMode != BOOT_ON_S3_RESUME) {\r
534 //\r
535 // This is the memory range that will be used for PEI on S3 resume\r
536 //\r
537 BuildMemoryAllocationHob (\r
45d87081
LE
538 mS3AcpiReservedMemoryBase,\r
539 mS3AcpiReservedMemorySize,\r
8e54500f
JJ
540 EfiACPIMemoryNVS\r
541 );\r
e249f906
LE
542\r
543 //\r
544 // Cover the initial RAM area used as stack and temporary PEI heap.\r
545 //\r
546 // This is reserved as ACPI NVS so it can be used on S3 resume.\r
547 //\r
548 BuildMemoryAllocationHob (\r
549 PcdGet32 (PcdOvmfSecPeiTempRamBase),\r
550 PcdGet32 (PcdOvmfSecPeiTempRamSize),\r
551 EfiACPIMemoryNVS\r
552 );\r
78a38b73 553\r
ad43bc6b
LE
554 //\r
555 // SEC stores its table of GUIDed section handlers here.\r
556 //\r
557 BuildMemoryAllocationHob (\r
558 PcdGet64 (PcdGuidedExtractHandlerTableAddress),\r
559 PcdGet32 (PcdGuidedExtractHandlerTableSize),\r
560 EfiACPIMemoryNVS\r
561 );\r
562\r
78a38b73
LE
563#ifdef MDE_CPU_X64\r
564 //\r
565 // Reserve the initial page tables built by the reset vector code.\r
566 //\r
567 // Since this memory range will be used by the Reset Vector on S3\r
568 // resume, it must be reserved as ACPI NVS.\r
569 //\r
570 BuildMemoryAllocationHob (\r
571 (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSecPageTablesBase),\r
572 (UINT64)(UINTN) PcdGet32 (PcdOvmfSecPageTablesSize),\r
573 EfiACPIMemoryNVS\r
574 );\r
575#endif\r
0e8a31f5 576 }\r
6a7cba79 577\r
0e8a31f5 578 if (mBootMode != BOOT_ON_S3_RESUME) {\r
1a7edbbc
LE
579 if (!FeaturePcdGet (PcdSmmSmramRequire)) {\r
580 //\r
581 // Reserve the lock box storage area\r
582 //\r
583 // Since this memory range will be used on S3 resume, it must be\r
584 // reserved as ACPI NVS.\r
585 //\r
586 // If S3 is unsupported, then various drivers might still write to the\r
587 // LockBox area. We ought to prevent DXE from serving allocation requests\r
588 // such that they would overlap the LockBox storage.\r
589 //\r
590 ZeroMem (\r
591 (VOID*)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase),\r
592 (UINTN) PcdGet32 (PcdOvmfLockBoxStorageSize)\r
593 );\r
594 BuildMemoryAllocationHob (\r
595 (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase),\r
596 (UINT64)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageSize),\r
597 mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData\r
598 );\r
599 }\r
b09c1c6f
LE
600\r
601 if (FeaturePcdGet (PcdSmmSmramRequire)) {\r
602 UINT32 TsegSize;\r
603\r
604 //\r
605 // Make sure the TSEG area that we reported as a reserved memory resource\r
606 // cannot be used for reserved memory allocations.\r
607 //\r
608 TsegSize = FixedPcdGet8 (PcdQ35TsegMbytes) * SIZE_1MB;\r
609 BuildMemoryAllocationHob (\r
610 GetSystemMemorySizeBelow4gb() - TsegSize,\r
611 TsegSize,\r
612 EfiReservedMemoryType\r
613 );\r
614 }\r
8e54500f 615 }\r
c034906e 616}\r