]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/PlatformPei/MemDetect.c
OvmfPkg/PlatformPei: set 32-bit UC area at PciBase / PciExBarBase (pc/q35)
[mirror_edk2.git] / OvmfPkg / PlatformPei / MemDetect.c
index e890e36408a6ad7530581995e926e18968d4f38b..d451989f31c9b20b2154f8d65be89f6b02e296ce 100644 (file)
@@ -14,6 +14,7 @@ Module Name:
 // The package level header files this module uses\r
 //\r
 #include <IndustryStandard/E820.h>\r
+#include <IndustryStandard/I440FxPiix4.h>\r
 #include <IndustryStandard/Q35MchIch9.h>\r
 #include <PiPei.h>\r
 \r
@@ -42,6 +43,8 @@ STATIC UINT32 mS3AcpiReservedMemorySize;
 \r
 STATIC UINT16 mQ35TsegMbytes;\r
 \r
+UINT32 mQemuUc32Base;\r
+\r
 VOID\r
 Q35TsegMbytesInitialization (\r
   VOID\r
@@ -98,6 +101,54 @@ Q35TsegMbytesInitialization (
 }\r
 \r
 \r
+VOID\r
+QemuUc32BaseInitialization (\r
+  VOID\r
+  )\r
+{\r
+  UINT32 LowerMemorySize;\r
+  UINT32 Uc32Size;\r
+\r
+  if (mXen) {\r
+    return;\r
+  }\r
+\r
+  if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {\r
+    //\r
+    // On q35, the 32-bit area that we'll mark as UC, through variable MTRRs,\r
+    // starts at PcdPciExpressBaseAddress. The platform DSC is responsible for\r
+    // setting PcdPciExpressBaseAddress such that describing the\r
+    // [PcdPciExpressBaseAddress, 4GB) range require a very small number of\r
+    // variable MTRRs (preferably 1 or 2).\r
+    //\r
+    ASSERT (FixedPcdGet64 (PcdPciExpressBaseAddress) <= MAX_UINT32);\r
+    mQemuUc32Base = (UINT32)FixedPcdGet64 (PcdPciExpressBaseAddress);\r
+    return;\r
+  }\r
+\r
+  ASSERT (mHostBridgeDevId == INTEL_82441_DEVICE_ID);\r
+  //\r
+  // On i440fx, start with the [LowerMemorySize, 4GB) range. Make sure one\r
+  // variable MTRR suffices by truncating the size to a whole power of two,\r
+  // while keeping the end affixed to 4GB. This will round the base up.\r
+  //\r
+  LowerMemorySize = GetSystemMemorySizeBelow4gb ();\r
+  Uc32Size = GetPowerOfTwo32 ((UINT32)(SIZE_4GB - LowerMemorySize));\r
+  mQemuUc32Base = (UINT32)(SIZE_4GB - Uc32Size);\r
+  //\r
+  // Assuming that LowerMemorySize is at least 1 byte, Uc32Size is at most 2GB.\r
+  // Therefore mQemuUc32Base is at least 2GB.\r
+  //\r
+  ASSERT (mQemuUc32Base >= BASE_2GB);\r
+\r
+  if (mQemuUc32Base != LowerMemorySize) {\r
+    DEBUG ((DEBUG_VERBOSE, "%a: rounded UC32 base from 0x%x up to 0x%x, for "\r
+      "an UC32 size of 0x%x\n", __FUNCTION__, LowerMemorySize, mQemuUc32Base,\r
+      Uc32Size));\r
+  }\r
+}\r
+\r
+\r
 /**\r
   Iterate over the RAM entries in QEMU's fw_cfg E820 RAM map that start outside\r
   of the 32-bit address range.\r
@@ -688,11 +739,11 @@ QemuInitializeRam (
     ASSERT_EFI_ERROR (Status);\r
 \r
     //\r
-    // Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB as\r
-    // uncacheable\r
+    // Set the memory range from the start of the 32-bit MMIO area (32-bit PCI\r
+    // MMIO aperture on i440fx, PCIEXBAR on q35) to 4GB as uncacheable.\r
     //\r
-    Status = MtrrSetMemoryAttribute (LowerMemorySize,\r
-               SIZE_4GB - LowerMemorySize, CacheUncacheable);\r
+    Status = MtrrSetMemoryAttribute (mQemuUc32Base, SIZE_4GB - mQemuUc32Base,\r
+               CacheUncacheable);\r
     ASSERT_EFI_ERROR (Status);\r
   }\r
 }\r