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