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

Reply via email to