Thanks for working to increase the supported guest-physical RAM size. Reviewed-by: Brian J. Johnson <bjohn...@sgi.com>
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 (); > > -- Brian J. Johnson -------------------------------------------------------------------- My statements are my own, are not authorized by SGI, and do not necessarily represent SGI’s positions. ------------------------------------------------------------------------------ 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