diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c index e890e36408..ae73c63d27 100644 --- a/OvmfPkg/PlatformPei/MemDetect.c +++ b/OvmfPkg/PlatformPei/MemDetect.c @@ -42,6 +42,8 @@ STATIC UINT32 mS3AcpiReservedMemorySize; STATIC UINT16 mQ35TsegMbytes; +UINT32 mQemuUc32Base; + VOID Q35TsegMbytesInitialization ( VOID @@ -663,6 +665,8 @@ QemuInitializeRam ( // cover it exactly. // if (IsMtrrSupported ()) { + UINT32 Uc32Size; + MtrrGetAllMtrrs (&MtrrSettings); // @@ -689,11 +693,24 @@ QemuInitializeRam ( // // Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB as - // uncacheable + // uncacheable. Make sure one variable MTRR suffices by truncating the size + // to a whole power of two. This will round the base *up*, and a gap (not + // used for either RAM or MMIO) may stay in the middle, marked as + // cacheable-by-default. // - Status = MtrrSetMemoryAttribute (LowerMemorySize, - SIZE_4GB - LowerMemorySize, CacheUncacheable); + Uc32Size = GetPowerOfTwo32 ((UINT32)(SIZE_4GB - LowerMemorySize)); + mQemuUc32Base = (UINT32)(SIZE_4GB - Uc32Size); + if (mQemuUc32Base != LowerMemorySize) { + DEBUG ((DEBUG_VERBOSE, "%a: rounded UC32 base from 0x%x up to 0x%x, for " + "an UC32 size of 0x%x\n", __FUNCTION__, (UINT32)LowerMemorySize, + mQemuUc32Base, Uc32Size)); + } + + Status = MtrrSetMemoryAttribute (mQemuUc32Base, Uc32Size, + CacheUncacheable); ASSERT_EFI_ERROR (Status); + } else { + mQemuUc32Base = (UINT32)LowerMemorySize; } } diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index fd8eccaf3e..c064b4ed9b 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -174,14 +174,12 @@ MemMapInitialization ( AddIoMemoryRangeHob (0x0A0000, BASE_1MB); if (!mXen) { - UINT32 TopOfLowRam; UINT64 PciExBarBase; UINT32 PciBase; UINT32 PciSize; - TopOfLowRam = GetSystemMemorySizeBelow4gb (); PciExBarBase = 0; - PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam; + PciBase = (mQemuUc32Base < BASE_2GB) ? BASE_2GB : mQemuUc32Base; if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) { // // The 32-bit PCI host aperture is expected to fall between the top of diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h index 81af8b7148..4476ddd871 100644 --- a/OvmfPkg/PlatformPei/Platform.h +++ b/OvmfPkg/PlatformPei/Platform.h @@ -114,4 +114,6 @@ extern UINT32 mMaxCpuCount; extern UINT16 mHostBridgeDevId; +extern UINT32 mQemuUc32Base; + #endif // _PLATFORM_PEI_H_INCLUDED_