Discussion:
[edk2] [PATCH v2 0/4] OvmfPkg: enable >= 64 GB guests
Laszlo Ersek
2015-06-23 19:53:45 UTC
Permalink
Updated patches #1 and #4, based on v1 review. Changes are noted on the
individual patches.

Since the v2 1/4 change is significant, I dropped Wei Liu's and
Maoming's Tested-by. Retesting would be appreciated. (I tested a 128 GB
guest on KVM.)

Public branch: <https://github.com/lersek/edk2/commits/bigram_v2>.

Cc: Maoming <***@huawei.com>
Cc: Huangpeng (Peter) <***@huawei.com>
Cc: Wei Liu <***@citrix.com>
Cc: Brian J. Johnson <***@sgi.com>
Cc: Jordan Justen (Intel address) <***@intel.com>

Laszlo Ersek (4):
OvmfPkg: PlatformPei: enable larger permanent PEI RAM
OvmfPkg: PlatformPei: create the CPU HOB with dynamic memory space
width
OvmfPkg: PlatformPei: beautify memory HOB order in QemuInitializeRam()
OvmfPkg: PlatformPei: invert MTRR setup in QemuInitializeRam()

OvmfPkg/PlatformPei/PlatformPei.inf | 2 +
OvmfPkg/PlatformPei/Platform.h | 7 +
OvmfPkg/PlatformPei/MemDetect.c | 176 ++++++++++++++++++--
OvmfPkg/PlatformPei/Platform.c | 7 +-
4 files changed, 177 insertions(+), 15 deletions(-)
--
1.8.3.1
Laszlo Ersek
2015-06-23 19:53:46 UTC
Permalink
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.
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.
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 <***@huawei.com>
Cc: Huangpeng (Peter) <***@huawei.com>
Cc: Wei Liu <***@citrix.com>
Cc: Brian J. Johnson <***@sgi.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@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 ();
--
1.8.3.1
Brian J. Johnson
2015-06-23 21:07:03 UTC
Permalink
Thanks for working to increase the supported guest-physical RAM size.
Post by Laszlo Ersek
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.
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.
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.)
Contributed-under: TianoCore Contribution Agreement 1.0
---
- 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
#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;
+ }
+
+ (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.
Laszlo Ersek
2015-06-23 21:15:47 UTC
Permalink
Post by Brian J. Johnson
Thanks for working to increase the supported guest-physical RAM size.
Thanks for your help and for taking the time to review this!

Laszlo
Post by Brian J. Johnson
Post by Laszlo Ersek
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.
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.
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.)
Contributed-under: TianoCore Contribution Agreement 1.0
---
- 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
#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;
+ }
+
+ (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 ();
Laszlo Ersek
2015-06-23 19:53:47 UTC
Permalink
Maoming reported that guest memory sizes equal to or larger than 64GB
were not correctly handled by OVMF.

Enabling the DEBUG_GCD (0x00100000) bit in PcdDebugPrintErrorLevel, and
starting QEMU with 64GB guest RAM size, I found the following error in the
GCD:AddMemorySpace(Base=0000000100000000,Length=0000000F40000000)
GcdMemoryType = Reserved
Capabilities = 030000000000000F
Status = Unsupported
This message is emitted when the DXE core is initializing the memory space
map, processing the "above 4GB" memory resource descriptor HOB that was
created by OVMF's QemuInitializeRam() function (see "UpperMemorySize").

The DXE core's call chain fails in:

CoreInternalAddMemorySpace() [MdeModulePkg/Core/Dxe/Gcd/Gcd.c]
CoreConvertSpace()
//
// Search for the list of descriptors that cover the range BaseAddress
// to BaseAddress+Length
//
CoreSearchGcdMapEntry()

CoreSearchGcdMapEntry() fails because the one entry (with type
"nonexistent") in the initial GCD memory space map is too small, and
GCD:Initial GCD Memory Space Map
GCDMemType Range Capabilities Attributes
========== ================================= ================ ================
NonExist 0000000000000000-0000000FFFFFFFFF 0000000000000000 0000000000000000
The size of this initial entry is determined from the CPU HOB
(CoreInitializeGcdServices()).

Set the SizeOfMemorySpace field in the CPU HOB to mPhysMemAddressWidth,
which is the narrowest valid value to cover the entire guest RAM.

Reported-by: Maoming <***@huawei.com>
Cc: Maoming <***@huawei.com>
Cc: Huangpeng (Peter) <***@huawei.com>
Cc: Wei Liu <***@citrix.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Tested-by: Wei Liu <***@citrix.com>
Tested-by: Maoming <***@huawei.com>
Reviewed-by: Jordan Justen <***@intel.com>
---
OvmfPkg/PlatformPei/Platform.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c
index 6557a33..fc98fc3 100644
--- a/OvmfPkg/PlatformPei/Platform.c
+++ b/OvmfPkg/PlatformPei/Platform.c
@@ -249,9 +249,11 @@ MiscInitialization (
IoOr8 (0x92, BIT1);

//
- // Build the CPU hob with 36-bit addressing and 16-bits of IO space.
+ // Build the CPU HOB with guest RAM size dependent address width and 16-bits
+ // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
+ // S3 resume as well, so we build it unconditionally.)
//
- BuildCpuHob (36, 16);
+ BuildCpuHob (mPhysMemAddressWidth, 16);

//
// Determine platform type and save Host Bridge DID to PCD
--
1.8.3.1
Laszlo Ersek
2015-06-23 19:53:48 UTC
Permalink
Build the memory HOBs in a tight block, in increasing base address order.

Cc: Maoming <***@huawei.com>
Cc: Huangpeng (Peter) <***@huawei.com>
Cc: Wei Liu <***@citrix.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Tested-by: Maoming <***@huawei.com>
Reviewed-by: Jordan Justen <***@intel.com>
---
OvmfPkg/PlatformPei/MemDetect.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c
index ceff1e2..b74308f 100644
--- a/OvmfPkg/PlatformPei/MemDetect.c
+++ b/OvmfPkg/PlatformPei/MemDetect.c
@@ -265,8 +265,11 @@ QemuInitializeRam (
//
// Create memory HOBs
//
- AddMemoryRangeHob (BASE_1MB, LowerMemorySize);
AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
+ AddMemoryRangeHob (BASE_1MB, LowerMemorySize);
+ if (UpperMemorySize != 0) {
+ AddUntestedMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);
+ }
}

MtrrSetMemoryAttribute (BASE_1MB, LowerMemorySize - BASE_1MB, CacheWriteBack);
@@ -274,10 +277,6 @@ QemuInitializeRam (
MtrrSetMemoryAttribute (0, BASE_512KB + BASE_128KB, CacheWriteBack);

if (UpperMemorySize != 0) {
- if (mBootMode != BOOT_ON_S3_RESUME) {
- AddUntestedMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);
- }
-
MtrrSetMemoryAttribute (BASE_4GB, UpperMemorySize, CacheWriteBack);
}
}
--
1.8.3.1
Laszlo Ersek
2015-06-23 19:53:49 UTC
Permalink
At the moment we work with a UC default MTRR type, and set three memory
ranges to WB:
- [0, 640 KB),
- [1 MB, LowerMemorySize),
- [4 GB, 4 GB + UpperMemorySize).

Unfortunately, coverage for the third range can fail with a high
likelihood. If the alignment of the base (ie. 4 GB) and the alignment of
the size (UpperMemorySize) differ, then MtrrLib creates a series of
variable MTRR entries, with power-of-two sized MTRR masks. And, it's
really easy to run out of variable MTRR entries, dependent on the
alignment difference.

This is a problem because a Linux guest will loudly reject any high memory
that is not covered my MTRR.

So, let's follow the inverse pattern (loosely inspired by SeaBIOS):
- flip the MTRR default type to WB,
- set [0, 640 KB) to WB -- fixed MTRRs have precedence over the default
type and variable MTRRs, so we can't avoid this,
- set [640 KB, 1 MB) to UC -- implemented with fixed MTRRs,
- set [LowerMemorySize, 4 GB) to UC -- should succeed with variable MTRRs
more likely than the other scheme (due to less chaotic alignment
differences).

Effects of this patch can be observed by setting DEBUG_CACHE (0x00200000)
in PcdDebugPrintErrorLevel.

Cc: Maoming <***@huawei.com>
Cc: Huangpeng (Peter) <***@huawei.com>
Cc: Wei Liu <***@citrix.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <***@redhat.com>
Tested-by: Maoming <***@huawei.com>
Reviewed-by: Jordan Justen <***@intel.com>
---

Notes:
v2:
- update comments [Jordan]
- calculate the size of the low 384 KB uncacheable hole as Jordan
suggested

OvmfPkg/PlatformPei/MemDetect.c | 46 ++++++++++++++++++--
1 file changed, 42 insertions(+), 4 deletions(-)

diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c
index b74308f..4778a55 100644
--- a/OvmfPkg/PlatformPei/MemDetect.c
+++ b/OvmfPkg/PlatformPei/MemDetect.c
@@ -252,6 +252,8 @@ QemuInitializeRam (
{
UINT64 LowerMemorySize;
UINT64 UpperMemorySize;
+ MTRR_SETTINGS MtrrSettings;
+ EFI_STATUS Status;

DEBUG ((EFI_D_INFO, "%a called\n", __FUNCTION__));

@@ -272,12 +274,48 @@ QemuInitializeRam (
}
}

- MtrrSetMemoryAttribute (BASE_1MB, LowerMemorySize - BASE_1MB, CacheWriteBack);
+ //
+ // We'd like to keep the following ranges uncached:
+ // - [640 KB, 1 MB)
+ // - [LowerMemorySize, 4 GB)
+ //
+ // Everything else should be WB. Unfortunately, programming the inverse (ie.
+ // keeping the default UC, and configuring the complement set of the above as
+ // WB) is not reliable in general, because the end of the upper RAM can have
+ // practically any alignment, and we may not have enough variable MTRRs to
+ // cover it exactly.
+ //
+ if (IsMtrrSupported ()) {
+ MtrrGetAllMtrrs (&MtrrSettings);

- MtrrSetMemoryAttribute (0, BASE_512KB + BASE_128KB, CacheWriteBack);
+ //
+ // MTRRs disabled, fixed MTRRs disabled, default type is uncached
+ //
+ ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);
+ ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
+ ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);

- if (UpperMemorySize != 0) {
- MtrrSetMemoryAttribute (BASE_4GB, UpperMemorySize, CacheWriteBack);
+ //
+ // flip default type to writeback
+ //
+ SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);
+ ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);
+ MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;
+ MtrrSetAllMtrrs (&MtrrSettings);
+
+ //
+ // Set memory from 640KB to 1MB to uncacheable
+ //
+ Status = MtrrSetMemoryAttribute (BASE_512KB + BASE_128KB,
+ BASE_1MB - (BASE_512KB + BASE_128KB), CacheUncacheable);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Set MMIO just below 4GB to uncacheable
+ //
+ Status = MtrrSetMemoryAttribute (LowerMemorySize,
+ SIZE_4GB - LowerMemorySize, CacheUncacheable);
+ ASSERT_EFI_ERROR (Status);
}
}
--
1.8.3.1
Jordan Justen
2015-06-23 22:12:39 UTC
Permalink
Post by Laszlo Ersek
At the moment we work with a UC default MTRR type, and set three memory
- [0, 640 KB),
- [1 MB, LowerMemorySize),
- [4 GB, 4 GB + UpperMemorySize).
Unfortunately, coverage for the third range can fail with a high
likelihood. If the alignment of the base (ie. 4 GB) and the alignment of
the size (UpperMemorySize) differ, then MtrrLib creates a series of
variable MTRR entries, with power-of-two sized MTRR masks. And, it's
really easy to run out of variable MTRR entries, dependent on the
alignment difference.
This is a problem because a Linux guest will loudly reject any high memory
that is not covered my MTRR.
- flip the MTRR default type to WB,
- set [0, 640 KB) to WB -- fixed MTRRs have precedence over the default
type and variable MTRRs, so we can't avoid this,
- set [640 KB, 1 MB) to UC -- implemented with fixed MTRRs,
- set [LowerMemorySize, 4 GB) to UC -- should succeed with variable MTRRs
more likely than the other scheme (due to less chaotic alignment
differences).
Effects of this patch can be observed by setting DEBUG_CACHE (0x00200000)
in PcdDebugPrintErrorLevel.
Contributed-under: TianoCore Contribution Agreement 1.0
---
- update comments [Jordan]
- calculate the size of the low 384 KB uncacheable hole as Jordan
suggested
OvmfPkg/PlatformPei/MemDetect.c | 46 ++++++++++++++++++--
1 file changed, 42 insertions(+), 4 deletions(-)
diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c
index b74308f..4778a55 100644
--- a/OvmfPkg/PlatformPei/MemDetect.c
+++ b/OvmfPkg/PlatformPei/MemDetect.c
@@ -252,6 +252,8 @@ QemuInitializeRam (
{
UINT64 LowerMemorySize;
UINT64 UpperMemorySize;
+ MTRR_SETTINGS MtrrSettings;
+ EFI_STATUS Status;
DEBUG ((EFI_D_INFO, "%a called\n", __FUNCTION__));
@@ -272,12 +274,48 @@ QemuInitializeRam (
}
}
- MtrrSetMemoryAttribute (BASE_1MB, LowerMemorySize - BASE_1MB, CacheWriteBack);
+ //
+ // - [640 KB, 1 MB)
+ // - [LowerMemorySize, 4 GB)
+ //
+ // Everything else should be WB. Unfortunately, programming the inverse (ie.
+ // keeping the default UC, and configuring the complement set of the above as
+ // WB) is not reliable in general, because the end of the upper RAM can have
+ // practically any alignment, and we may not have enough variable MTRRs to
+ // cover it exactly.
+ //
+ if (IsMtrrSupported ()) {
+ MtrrGetAllMtrrs (&MtrrSettings);
- MtrrSetMemoryAttribute (0, BASE_512KB + BASE_128KB, CacheWriteBack);
+ //
+ // MTRRs disabled, fixed MTRRs disabled, default type is uncached
+ //
+ ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);
+ ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
+ ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);
- if (UpperMemorySize != 0) {
- MtrrSetMemoryAttribute (BASE_4GB, UpperMemorySize, CacheWriteBack);
+ //
+ // flip default type to writeback
+ //
+ SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);
+ ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);
+ MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;
+ MtrrSetAllMtrrs (&MtrrSettings);
+
+ //
+ // Set memory from 640KB to 1MB to uncacheable
+ //
Thanks Laszlo. All the patches look good to me now.

If I have a nit pick remaining, it would be the comments I suggested
here. :)

I think maybe 'memory' => 'memory range' seems better. What do you
think?
Post by Laszlo Ersek
+ Status = MtrrSetMemoryAttribute (BASE_512KB + BASE_128KB,
+ BASE_1MB - (BASE_512KB + BASE_128KB), CacheUncacheable);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Set MMIO just below 4GB to uncacheable
+ //
You expressed some doubts about this, and I agree. To throw out
another option, maybe:

//
// Set memory range from the "top of lower RAM" (RAM below 4GB) to
// 4GB as uncacheable
//

Or, maybe:

//
// Set memory range for memory mapped IO below 4GB as uncacheable
//

Or, perhaps you have a better suggestion?

Anyway, I don't think it is critical, so with or without changes,
Post by Laszlo Ersek
+ Status = MtrrSetMemoryAttribute (LowerMemorySize,
+ SIZE_4GB - LowerMemorySize, CacheUncacheable);
+ ASSERT_EFI_ERROR (Status);
}
}
--
1.8.3.1
------------------------------------------------------------------------------
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
https://lists.sourceforge.net/lists/listinfo/edk2-devel
Laszlo Ersek
2015-06-24 07:05:21 UTC
Permalink
Post by Jordan Justen
Post by Laszlo Ersek
At the moment we work with a UC default MTRR type, and set three memory
- [0, 640 KB),
- [1 MB, LowerMemorySize),
- [4 GB, 4 GB + UpperMemorySize).
Unfortunately, coverage for the third range can fail with a high
likelihood. If the alignment of the base (ie. 4 GB) and the alignment of
the size (UpperMemorySize) differ, then MtrrLib creates a series of
variable MTRR entries, with power-of-two sized MTRR masks. And, it's
really easy to run out of variable MTRR entries, dependent on the
alignment difference.
This is a problem because a Linux guest will loudly reject any high memory
that is not covered my MTRR.
- flip the MTRR default type to WB,
- set [0, 640 KB) to WB -- fixed MTRRs have precedence over the default
type and variable MTRRs, so we can't avoid this,
- set [640 KB, 1 MB) to UC -- implemented with fixed MTRRs,
- set [LowerMemorySize, 4 GB) to UC -- should succeed with variable MTRRs
more likely than the other scheme (due to less chaotic alignment
differences).
Effects of this patch can be observed by setting DEBUG_CACHE (0x00200000)
in PcdDebugPrintErrorLevel.
Contributed-under: TianoCore Contribution Agreement 1.0
---
- update comments [Jordan]
- calculate the size of the low 384 KB uncacheable hole as Jordan
suggested
OvmfPkg/PlatformPei/MemDetect.c | 46 ++++++++++++++++++--
1 file changed, 42 insertions(+), 4 deletions(-)
diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c
index b74308f..4778a55 100644
--- a/OvmfPkg/PlatformPei/MemDetect.c
+++ b/OvmfPkg/PlatformPei/MemDetect.c
@@ -252,6 +252,8 @@ QemuInitializeRam (
{
UINT64 LowerMemorySize;
UINT64 UpperMemorySize;
+ MTRR_SETTINGS MtrrSettings;
+ EFI_STATUS Status;
DEBUG ((EFI_D_INFO, "%a called\n", __FUNCTION__));
@@ -272,12 +274,48 @@ QemuInitializeRam (
}
}
- MtrrSetMemoryAttribute (BASE_1MB, LowerMemorySize - BASE_1MB, CacheWriteBack);
+ //
+ // - [640 KB, 1 MB)
+ // - [LowerMemorySize, 4 GB)
+ //
+ // Everything else should be WB. Unfortunately, programming the inverse (ie.
+ // keeping the default UC, and configuring the complement set of the above as
+ // WB) is not reliable in general, because the end of the upper RAM can have
+ // practically any alignment, and we may not have enough variable MTRRs to
+ // cover it exactly.
+ //
+ if (IsMtrrSupported ()) {
+ MtrrGetAllMtrrs (&MtrrSettings);
- MtrrSetMemoryAttribute (0, BASE_512KB + BASE_128KB, CacheWriteBack);
+ //
+ // MTRRs disabled, fixed MTRRs disabled, default type is uncached
+ //
+ ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);
+ ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
+ ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);
- if (UpperMemorySize != 0) {
- MtrrSetMemoryAttribute (BASE_4GB, UpperMemorySize, CacheWriteBack);
+ //
+ // flip default type to writeback
+ //
+ SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);
+ ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);
+ MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;
+ MtrrSetAllMtrrs (&MtrrSettings);
+
+ //
+ // Set memory from 640KB to 1MB to uncacheable
+ //
Thanks Laszlo. All the patches look good to me now.
If I have a nit pick remaining, it would be the comments I suggested
here. :)
I think maybe 'memory' => 'memory range' seems better. What do you
think?
OK.
Post by Jordan Justen
Post by Laszlo Ersek
+ Status = MtrrSetMemoryAttribute (BASE_512KB + BASE_128KB,
+ BASE_1MB - (BASE_512KB + BASE_128KB), CacheUncacheable);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Set MMIO just below 4GB to uncacheable
+ //
You expressed some doubts about this, and I agree. To throw out
//
// Set memory range from the "top of lower RAM" (RAM below 4GB) to
// 4GB as uncacheable
//
Works for me.
Post by Jordan Justen
//
// Set memory range for memory mapped IO below 4GB as uncacheable
//
Or, perhaps you have a better suggestion?
Anyway, I don't think it is critical, so with or without changes,
Thanks! I'll update these comments when I commit the patches to SVN. But
first I'd like to give Wei Liu and Maoming one or two days to re-test; I
wouldn't like to lose their Tested-by tags for patch #1.

Cheers!
Laszlo
Post by Jordan Justen
Post by Laszlo Ersek
+ Status = MtrrSetMemoryAttribute (LowerMemorySize,
+ SIZE_4GB - LowerMemorySize, CacheUncacheable);
+ ASSERT_EFI_ERROR (Status);
}
}
--
1.8.3.1
------------------------------------------------------------------------------
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
https://lists.sourceforge.net/lists/listinfo/edk2-devel
Laszlo Ersek
2015-06-26 16:11:55 UTC
Permalink
Post by Laszlo Ersek
Updated patches #1 and #4, based on v1 review. Changes are noted on the
individual patches.
Since the v2 1/4 change is significant, I dropped Wei Liu's and
Maoming's Tested-by. Retesting would be appreciated. (I tested a 128 GB
guest on KVM.)
Public branch: <https://github.com/lersek/edk2/commits/bigram_v2>.
OvmfPkg: PlatformPei: enable larger permanent PEI RAM
OvmfPkg: PlatformPei: create the CPU HOB with dynamic memory space
width
OvmfPkg: PlatformPei: beautify memory HOB order in QemuInitializeRam()
OvmfPkg: PlatformPei: invert MTRR setup in QemuInitializeRam()
OvmfPkg/PlatformPei/PlatformPei.inf | 2 +
OvmfPkg/PlatformPei/Platform.h | 7 +
OvmfPkg/PlatformPei/MemDetect.c | 176 ++++++++++++++++++--
OvmfPkg/PlatformPei/Platform.c | 7 +-
4 files changed, 177 insertions(+), 15 deletions(-)
Committed as SVN r17719-r17722, with the comment changes discussed for
patch 4. Thanks all for the reviews and the v1 testing.

Laszlo

Loading...