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

Reply via email to