#include "Platform.h"\r
#include "Cmos.h"\r
\r
+UINT8 mPhysMemAddressWidth;\r
+\r
UINT32\r
GetSystemMemorySizeBelow4gb (\r
VOID\r
return LShiftU64 (Size, 16);\r
}\r
\r
+\r
+/**\r
+ Initialize the mPhysMemAddressWidth variable, based on guest RAM size.\r
+**/\r
+VOID\r
+AddressWidthInitialization (\r
+ VOID\r
+ )\r
+{\r
+ UINT64 FirstNonAddress;\r
+\r
+ //\r
+ // As guest-physical memory size grows, the permanent PEI RAM requirements\r
+ // are dominated by the identity-mapping page tables built by the DXE IPL.\r
+ // The DXL IPL keys off of the physical address bits advertized in the CPU\r
+ // HOB. To conserve memory, we calculate the minimum address width here.\r
+ //\r
+ FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb ();\r
+ mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);\r
+\r
+ //\r
+ // If FirstNonAddress is not an integral power of two, then we need an\r
+ // additional bit.\r
+ //\r
+ if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {\r
+ ++mPhysMemAddressWidth;\r
+ }\r
+\r
+ //\r
+ // The minimum address width is 36 (covers up to and excluding 64 GB, which\r
+ // is the maximum for Ia32 + PAE). The theoretical architecture maximum for\r
+ // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We\r
+ // can simply assert that here, since 48 bits are good enough for 256 TB.\r
+ //\r
+ if (mPhysMemAddressWidth <= 36) {\r
+ mPhysMemAddressWidth = 36;\r
+ }\r
+ ASSERT (mPhysMemAddressWidth <= 48);\r
+}\r
+\r
+\r
+/**\r
+ Calculate the cap for the permanent PEI memory.\r
+**/\r
+STATIC\r
+UINT32\r
+GetPeiMemoryCap (\r
+ VOID\r
+ )\r
+{\r
+ BOOLEAN Page1GSupport;\r
+ UINT32 RegEax;\r
+ UINT32 RegEdx;\r
+ UINT32 Pml4Entries;\r
+ UINT32 PdpEntries;\r
+ UINTN TotalPages;\r
+\r
+ //\r
+ // If DXE is 32-bit, then just return the traditional 64 MB cap.\r
+ //\r
+#ifdef MDE_CPU_IA32\r
+ if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+ return SIZE_64MB;\r
+ }\r
+#endif\r
+\r
+ //\r
+ // Dependent on physical address width, PEI memory allocations can be\r
+ // dominated by the page tables built for 64-bit DXE. So we key the cap off\r
+ // of those. The code below is based on CreateIdentityMappingPageTables() in\r
+ // "MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c".\r
+ //\r
+ Page1GSupport = FALSE;\r
+ if (PcdGetBool (PcdUse1GPageTable)) {\r
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x80000001) {\r
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
+ if ((RegEdx & BIT26) != 0) {\r
+ Page1GSupport = TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (mPhysMemAddressWidth <= 39) {\r
+ Pml4Entries = 1;\r
+ PdpEntries = 1 << (mPhysMemAddressWidth - 30);\r
+ ASSERT (PdpEntries <= 0x200);\r
+ } else {\r
+ Pml4Entries = 1 << (mPhysMemAddressWidth - 39);\r
+ ASSERT (Pml4Entries <= 0x200);\r
+ PdpEntries = 512;\r
+ }\r
+\r
+ TotalPages = Page1GSupport ? Pml4Entries + 1 :\r
+ (PdpEntries + 1) * Pml4Entries + 1;\r
+ ASSERT (TotalPages <= 0x40201);\r
+\r
+ //\r
+ // Add 64 MB for miscellaneous allocations. Note that for\r
+ // mPhysMemAddressWidth values close to 36, the cap will actually be\r
+ // dominated by this increment.\r
+ //\r
+ return (UINT32)(EFI_PAGES_TO_SIZE (TotalPages) + SIZE_64MB);\r
+}\r
+\r
+\r
/**\r
Publish PEI core memory\r
\r
EFI_PHYSICAL_ADDRESS MemoryBase;\r
UINT64 MemorySize;\r
UINT64 LowerMemorySize;\r
+ UINT32 PeiMemoryCap;\r
\r
if (mBootMode == BOOT_ON_S3_RESUME) {\r
MemoryBase = PcdGet32 (PcdS3AcpiReservedMemoryBase);\r
} else {\r
LowerMemorySize = GetSystemMemorySizeBelow4gb ();\r
\r
+ PeiMemoryCap = GetPeiMemoryCap ();\r
+ DEBUG ((EFI_D_INFO, "%a: mPhysMemAddressWidth=%d PeiMemoryCap=%u KB\n",\r
+ __FUNCTION__, mPhysMemAddressWidth, PeiMemoryCap >> 10));\r
+\r
//\r
// Determine the range of memory to use during PEI\r
//\r
MemoryBase = PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 (PcdOvmfDxeMemFvSize);\r
MemorySize = LowerMemorySize - MemoryBase;\r
- if (MemorySize > SIZE_64MB) {\r
- MemoryBase = LowerMemorySize - SIZE_64MB;\r
- MemorySize = SIZE_64MB;\r
+ if (MemorySize > PeiMemoryCap) {\r
+ MemoryBase = LowerMemorySize - PeiMemoryCap;\r
+ MemorySize = PeiMemoryCap;\r
}\r
}\r
\r