On 06/23/15 23:07, Brian J. Johnson wrote: > Thanks for working to increase the supported guest-physical RAM size. > > Reviewed-by: Brian J. Johnson <bjohn...@sgi.com>
Thanks for your help and for taking the time to review this! Laszlo > On 06/23/2015 02:53 PM, Laszlo Ersek wrote: >> We'll soon increase the maximum guest-physical RAM size supported by >> OVMF. >> For more RAM, the DXE IPL is going to build more page tables, and for >> that >> it's going to need a bigger chunk from the permanent PEI RAM. >> >> Otherwise CreateIdentityMappingPageTables() would fail with: >> >>> DXE IPL Entry >>> Loading PEIM at 0x000BFF61000 EntryPoint=0x000BFF61260 DxeCore.efi >>> Loading DXE CORE at 0x000BFF61000 EntryPoint=0x000BFF61260 >>> AllocatePages failed: No 0x40201 Pages is available. >>> There is only left 0x3F1F pages memory resource to be allocated. >>> ASSERT .../MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c(123): >>> BigPageAddress != 0 >> >> (The above example belongs to the artificially high, maximal address >> width >> of 52, clamped by the DXE core to 48. The address width of 48 bits >> corresponds to 256 TB or RAM, and requires a bit more than 1GB for paging >> structures.) >> >> Cc: Maoming <maoming.maom...@huawei.com> >> Cc: Huangpeng (Peter) <peter.huangp...@huawei.com> >> Cc: Wei Liu <wei.l...@citrix.com> >> Cc: Brian J. Johnson <bjohn...@sgi.com> >> Contributed-under: TianoCore Contribution Agreement 1.0 >> Signed-off-by: Laszlo Ersek <ler...@redhat.com> >> --- >> >> Notes: >> v2: >> - imitating CreateIdentityMappingPageTables() [Jordan, Brian] >> >> OvmfPkg/PlatformPei/PlatformPei.inf | 2 + >> OvmfPkg/PlatformPei/Platform.h | 7 ++ >> OvmfPkg/PlatformPei/MemDetect.c | 119 +++++++++++++++++++- >> OvmfPkg/PlatformPei/Platform.c | 1 + >> 4 files changed, 126 insertions(+), 3 deletions(-) >> >> diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf >> b/OvmfPkg/PlatformPei/PlatformPei.inf >> index 721495b..cb7d7dd 100644 >> --- a/OvmfPkg/PlatformPei/PlatformPei.inf >> +++ b/OvmfPkg/PlatformPei/PlatformPei.inf >> @@ -83,6 +83,8 @@ [Pcd] >> gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved >> gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration >> gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion >> + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode >> + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable >> gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress >> >> [Ppis] >> diff --git a/OvmfPkg/PlatformPei/Platform.h >> b/OvmfPkg/PlatformPei/Platform.h >> index 31640e9..8b6a976 100644 >> --- a/OvmfPkg/PlatformPei/Platform.h >> +++ b/OvmfPkg/PlatformPei/Platform.h >> @@ -59,6 +59,11 @@ AddUntestedMemoryRangeHob ( >> EFI_PHYSICAL_ADDRESS MemoryLimit >> ); >> >> +VOID >> +AddressWidthInitialization ( >> + VOID >> + ); >> + >> EFI_STATUS >> PublishPeiMemory ( >> VOID >> @@ -100,4 +105,6 @@ extern EFI_BOOT_MODE mBootMode; >> >> extern BOOLEAN mS3Supported; >> >> +extern UINT8 mPhysMemAddressWidth; >> + >> #endif // _PLATFORM_PEI_H_INCLUDED_ >> diff --git a/OvmfPkg/PlatformPei/MemDetect.c >> b/OvmfPkg/PlatformPei/MemDetect.c >> index bd7bb02..ceff1e2 100644 >> --- a/OvmfPkg/PlatformPei/MemDetect.c >> +++ b/OvmfPkg/PlatformPei/MemDetect.c >> @@ -36,6 +36,8 @@ Module Name: >> #include "Platform.h" >> #include "Cmos.h" >> >> +UINT8 mPhysMemAddressWidth; >> + >> UINT32 >> GetSystemMemorySizeBelow4gb ( >> VOID >> @@ -84,6 +86,112 @@ GetSystemMemorySizeAbove4gb ( >> return LShiftU64 (Size, 16); >> } >> >> + >> +/** >> + Initialize the mPhysMemAddressWidth variable, based on guest RAM size. >> +**/ >> +VOID >> +AddressWidthInitialization ( >> + VOID >> + ) >> +{ >> + UINT64 FirstNonAddress; >> + >> + // >> + // As guest-physical memory size grows, the permanent PEI RAM >> requirements >> + // are dominated by the identity-mapping page tables built by the >> DXE IPL. >> + // The DXL IPL keys off of the physical address bits advertized in >> the CPU >> + // HOB. To conserve memory, we calculate the minimum address width >> here. >> + // >> + FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb (); >> + mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress); >> + >> + // >> + // If FirstNonAddress is not an integral power of two, then we need an >> + // additional bit. >> + // >> + if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) { >> + ++mPhysMemAddressWidth; >> + } >> + >> + // >> + // The minimum address width is 36 (covers up to and excluding 64 >> GB, which >> + // is the maximum for Ia32 + PAE). The theoretical architecture >> maximum for >> + // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 >> bits. We >> + // can simply assert that here, since 48 bits are good enough for >> 256 TB. >> + // >> + if (mPhysMemAddressWidth <= 36) { >> + mPhysMemAddressWidth = 36; >> + } >> + ASSERT (mPhysMemAddressWidth <= 48); >> +} >> + >> + >> +/** >> + Calculate the cap for the permanent PEI memory. >> +**/ >> +STATIC >> +UINT32 >> +GetPeiMemoryCap ( >> + VOID >> + ) >> +{ >> + BOOLEAN Page1GSupport; >> + UINT32 RegEax; >> + UINT32 RegEdx; >> + UINT32 Pml4Entries; >> + UINT32 PdpEntries; >> + UINTN TotalPages; >> + >> + // >> + // If DXE is 32-bit, then just return the traditional 64 MB cap. >> + // >> +#ifdef MDE_CPU_IA32 >> + if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { >> + return SIZE_64MB; >> + } >> +#endif >> + >> + // >> + // Dependent on physical address width, PEI memory allocations can be >> + // dominated by the page tables built for 64-bit DXE. So we key the >> cap off >> + // of those. The code below is based on >> CreateIdentityMappingPageTables() in >> + // "MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c". >> + // >> + Page1GSupport = FALSE; >> + if (PcdGetBool (PcdUse1GPageTable)) { >> + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); >> + if (RegEax >= 0x80000001) { >> + AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx); >> + if ((RegEdx & BIT26) != 0) { >> + Page1GSupport = TRUE; >> + } >> + } >> + } >> + >> + if (mPhysMemAddressWidth <= 39) { >> + Pml4Entries = 1; >> + PdpEntries = 1 << (mPhysMemAddressWidth - 30); >> + ASSERT (PdpEntries <= 0x200); >> + } else { >> + Pml4Entries = 1 << (mPhysMemAddressWidth - 39); >> + ASSERT (Pml4Entries <= 0x200); >> + PdpEntries = 512; >> + } >> + >> + TotalPages = Page1GSupport ? Pml4Entries + 1 : >> + (PdpEntries + 1) * Pml4Entries + 1; >> + ASSERT (TotalPages <= 0x40201); >> + >> + // >> + // Add 64 MB for miscellaneous allocations. Note that for >> + // mPhysMemAddressWidth values close to 36, the cap will actually be >> + // dominated by this increment. >> + // >> + return (UINT32)(EFI_PAGES_TO_SIZE (TotalPages) + SIZE_64MB); >> +} >> + >> + >> /** >> Publish PEI core memory >> >> @@ -99,6 +207,7 @@ PublishPeiMemory ( >> EFI_PHYSICAL_ADDRESS MemoryBase; >> UINT64 MemorySize; >> UINT64 LowerMemorySize; >> + UINT32 PeiMemoryCap; >> >> if (mBootMode == BOOT_ON_S3_RESUME) { >> MemoryBase = PcdGet32 (PcdS3AcpiReservedMemoryBase); >> @@ -106,14 +215,18 @@ PublishPeiMemory ( >> } else { >> LowerMemorySize = GetSystemMemorySizeBelow4gb (); >> >> + PeiMemoryCap = GetPeiMemoryCap (); >> + DEBUG ((EFI_D_INFO, "%a: mPhysMemAddressWidth=%d PeiMemoryCap=%u >> KB\n", >> + __FUNCTION__, mPhysMemAddressWidth, PeiMemoryCap >> 10)); >> + >> // >> // Determine the range of memory to use during PEI >> // >> MemoryBase = PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 >> (PcdOvmfDxeMemFvSize); >> MemorySize = LowerMemorySize - MemoryBase; >> - if (MemorySize > SIZE_64MB) { >> - MemoryBase = LowerMemorySize - SIZE_64MB; >> - MemorySize = SIZE_64MB; >> + if (MemorySize > PeiMemoryCap) { >> + MemoryBase = LowerMemorySize - PeiMemoryCap; >> + MemorySize = PeiMemoryCap; >> } >> } >> >> diff --git a/OvmfPkg/PlatformPei/Platform.c >> b/OvmfPkg/PlatformPei/Platform.c >> index 2105787..6557a33 100644 >> --- a/OvmfPkg/PlatformPei/Platform.c >> +++ b/OvmfPkg/PlatformPei/Platform.c >> @@ -442,6 +442,7 @@ InitializePlatform ( >> } >> >> BootModeInitialization (); >> + AddressWidthInitialization (); >> >> PublishPeiMemory (); >> >> > > ------------------------------------------------------------------------------ Monitor 25 network devices or servers for free with OpManager! OpManager is web-based network management software that monitors network devices and physical & virtual servers, alerts via email & sms for fault. Monitor 25 devices for free with no restriction. Download now http://ad.doubleclick.net/ddm/clk/292181274;119417398;o _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel