mirror of https://github.com/acidanthera/audk.git
OvmfPkg: PlatformPei: invert MTRR setup in QemuInitializeRam()
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 <maoming.maoming@huawei.com> Cc: Huangpeng (Peter) <peter.huangpeng@huawei.com> Cc: Wei Liu <wei.liu2@citrix.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Maoming <maoming.maoming@huawei.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17722 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
cfc80e2e95
commit
79d274b8b6
|
@ -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,49 @@ 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 range from 640KB to 1MB to uncacheable
|
||||
//
|
||||
Status = MtrrSetMemoryAttribute (BASE_512KB + BASE_128KB,
|
||||
BASE_1MB - (BASE_512KB + BASE_128KB), CacheUncacheable);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB as
|
||||
// uncacheable
|
||||
//
|
||||
Status = MtrrSetMemoryAttribute (LowerMemorySize,
|
||||
SIZE_4GB - LowerMemorySize, CacheUncacheable);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue