summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--OvmfPkg/PlatformPei/MemDetect.c59
-rw-r--r--OvmfPkg/PlatformPei/Platform.c5
-rw-r--r--OvmfPkg/PlatformPei/Platform.h7
3 files changed, 66 insertions, 5 deletions
diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c
index e890e36..d451989 100644
--- a/OvmfPkg/PlatformPei/MemDetect.c
+++ b/OvmfPkg/PlatformPei/MemDetect.c
@@ -14,6 +14,7 @@ Module Name:
// The package level header files this module uses
//
#include <IndustryStandard/E820.h>
+#include <IndustryStandard/I440FxPiix4.h>
#include <IndustryStandard/Q35MchIch9.h>
#include <PiPei.h>
@@ -42,6 +43,8 @@ STATIC UINT32 mS3AcpiReservedMemorySize;
STATIC UINT16 mQ35TsegMbytes;
+UINT32 mQemuUc32Base;
+
VOID
Q35TsegMbytesInitialization (
VOID
@@ -98,6 +101,54 @@ Q35TsegMbytesInitialization (
}
+VOID
+QemuUc32BaseInitialization (
+ VOID
+ )
+{
+ UINT32 LowerMemorySize;
+ UINT32 Uc32Size;
+
+ if (mXen) {
+ return;
+ }
+
+ if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
+ //
+ // On q35, the 32-bit area that we'll mark as UC, through variable MTRRs,
+ // starts at PcdPciExpressBaseAddress. The platform DSC is responsible for
+ // setting PcdPciExpressBaseAddress such that describing the
+ // [PcdPciExpressBaseAddress, 4GB) range require a very small number of
+ // variable MTRRs (preferably 1 or 2).
+ //
+ ASSERT (FixedPcdGet64 (PcdPciExpressBaseAddress) <= MAX_UINT32);
+ mQemuUc32Base = (UINT32)FixedPcdGet64 (PcdPciExpressBaseAddress);
+ return;
+ }
+
+ ASSERT (mHostBridgeDevId == INTEL_82441_DEVICE_ID);
+ //
+ // On i440fx, start with the [LowerMemorySize, 4GB) range. Make sure one
+ // variable MTRR suffices by truncating the size to a whole power of two,
+ // while keeping the end affixed to 4GB. This will round the base up.
+ //
+ LowerMemorySize = GetSystemMemorySizeBelow4gb ();
+ Uc32Size = GetPowerOfTwo32 ((UINT32)(SIZE_4GB - LowerMemorySize));
+ mQemuUc32Base = (UINT32)(SIZE_4GB - Uc32Size);
+ //
+ // Assuming that LowerMemorySize is at least 1 byte, Uc32Size is at most 2GB.
+ // Therefore mQemuUc32Base is at least 2GB.
+ //
+ ASSERT (mQemuUc32Base >= BASE_2GB);
+
+ 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__, LowerMemorySize, mQemuUc32Base,
+ Uc32Size));
+ }
+}
+
+
/**
Iterate over the RAM entries in QEMU's fw_cfg E820 RAM map that start outside
of the 32-bit address range.
@@ -688,11 +739,11 @@ QemuInitializeRam (
ASSERT_EFI_ERROR (Status);
//
- // Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB as
- // uncacheable
+ // Set the memory range from the start of the 32-bit MMIO area (32-bit PCI
+ // MMIO aperture on i440fx, PCIEXBAR on q35) to 4GB as uncacheable.
//
- Status = MtrrSetMemoryAttribute (LowerMemorySize,
- SIZE_4GB - LowerMemorySize, CacheUncacheable);
+ Status = MtrrSetMemoryAttribute (mQemuUc32Base, SIZE_4GB - mQemuUc32Base,
+ CacheUncacheable);
ASSERT_EFI_ERROR (Status);
}
}
diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c
index 0876316..3ba2459 100644
--- a/OvmfPkg/PlatformPei/Platform.c
+++ b/OvmfPkg/PlatformPei/Platform.c
@@ -191,7 +191,8 @@ MemMapInitialization (
ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB);
PciBase = (UINT32)(PciExBarBase + SIZE_256MB);
} else {
- PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam;
+ ASSERT (TopOfLowRam <= mQemuUc32Base);
+ PciBase = mQemuUc32Base;
}
//
@@ -650,6 +651,8 @@ InitializePlatform (
PublishPeiMemory ();
+ QemuUc32BaseInitialization ();
+
InitializeRamRegions ();
if (mXen) {
diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h
index 81af8b7..2f3cebc 100644
--- a/OvmfPkg/PlatformPei/Platform.h
+++ b/OvmfPkg/PlatformPei/Platform.h
@@ -63,6 +63,11 @@ GetSystemMemorySizeBelow4gb (
);
VOID
+QemuUc32BaseInitialization (
+ VOID
+ );
+
+VOID
InitializeRamRegions (
VOID
);
@@ -114,4 +119,6 @@ extern UINT32 mMaxCpuCount;
extern UINT16 mHostBridgeDevId;
+extern UINT32 mQemuUc32Base;
+
#endif // _PLATFORM_PEI_H_INCLUDED_