On 2015-06-16 10:05:24, 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> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Laszlo Ersek <ler...@redhat.com> > Tested-by: Wei Liu <wei.l...@citrix.com> > Tested-by: Maoming <maoming.maom...@huawei.com> > --- > OvmfPkg/PlatformPei/Platform.h | 7 +++++ > OvmfPkg/PlatformPei/MemDetect.c | 61 > +++++++++++++++++++++++++++++++++++++++-- > OvmfPkg/PlatformPei/Platform.c | 1 + > 3 files changed, 66 insertions(+), 3 deletions(-) > > 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..6b424f7 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,47 @@ 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); > +} > + > + > /** > Publish PEI core memory > > @@ -99,6 +142,7 @@ PublishPeiMemory ( > EFI_PHYSICAL_ADDRESS MemoryBase; > UINT64 MemorySize; > UINT64 LowerMemorySize; > + UINT32 PeiMemoryCap; > > if (mBootMode == BOOT_ON_S3_RESUME) { > MemoryBase = PcdGet32 (PcdS3AcpiReservedMemoryBase); > @@ -107,13 +151,24 @@ PublishPeiMemory ( > LowerMemorySize = GetSystemMemorySizeBelow4gb (); > > // > + // For the minimum address width of 36, installing 64 MB as permanent PEI > + // RAM is sufficient. For the maximum width, the DXE IPL needs a bit more > + // than 1 GB for paging structures. Therefore we establish an exponential > + // formula so that the 48-36+1=13 different widths map to permanent PEI > RAM > + // sizes in [64 MB, 2 GB], that is [1<<26, 1<<31]; 6 different powers. > + // > + PeiMemoryCap = SIZE_64MB << ((mPhysMemAddressWidth - 36) * 5 / 12);
In the python interpreter, I wrote: >>> for p in map(lambda a: (a, 64 << ((a-36) * 5 / 12)), range(36,49)): print >>> '%d bits => %d MB' % p ... 36 bits => 64 MB 37 bits => 64 MB 38 bits => 64 MB 39 bits => 128 MB 40 bits => 128 MB 41 bits => 256 MB 42 bits => 256 MB 43 bits => 256 MB 44 bits => 512 MB 45 bits => 512 MB 46 bits => 1024 MB 47 bits => 1024 MB 48 bits => 2048 MB Interesting, but I still don't quite feel like it makes (intuitive) sense to me. :) What if you make a calculation of how big the tables should be and then add 64 MB to it? -Jordan > + DEBUG ((EFI_D_INFO, "%a: mPhysMemAddressWidth=%d PeiMemoryCap=%uMB\n", > + __FUNCTION__, mPhysMemAddressWidth, PeiMemoryCap >> 20)); > + > + // > // 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 1ad5bfc..54ec822 100644 > --- a/OvmfPkg/PlatformPei/Platform.c > +++ b/OvmfPkg/PlatformPei/Platform.c > @@ -405,6 +405,7 @@ InitializePlatform ( > } > > BootModeInitialization (); > + AddressWidthInitialization (); > > PublishPeiMemory (); > > -- > 1.8.3.1 > > > > ------------------------------------------------------------------------------ > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/edk2-devel ------------------------------------------------------------------------------ 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