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 <[email protected]>
> Cc: Huangpeng (Peter) <[email protected]>
> Cc: Wei Liu <[email protected]>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Laszlo Ersek <[email protected]>
> Tested-by: Wei Liu <[email protected]>
> Tested-by: Maoming <[email protected]>
> ---
> 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
> [email protected]
> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel