]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/PlatformPei/MemDetect.c
OvmfPkg/PlatformPei: fix MTRR for low-RAM sizes that have many bits clear
[mirror_edk2.git] / OvmfPkg / PlatformPei / MemDetect.c
index e890e36408a6ad7530581995e926e18968d4f38b..ae73c63d27d544e58470ad3c502a1b2a5ec4339b 100644 (file)
@@ -42,6 +42,8 @@ STATIC UINT32 mS3AcpiReservedMemorySize;
 \r
 STATIC UINT16 mQ35TsegMbytes;\r
 \r
+UINT32 mQemuUc32Base;\r
+\r
 VOID\r
 Q35TsegMbytesInitialization (\r
   VOID\r
@@ -663,6 +665,8 @@ QemuInitializeRam (
   // cover it exactly.\r
   //\r
   if (IsMtrrSupported ()) {\r
+    UINT32 Uc32Size;\r
+\r
     MtrrGetAllMtrrs (&MtrrSettings);\r
 \r
     //\r
@@ -689,11 +693,24 @@ QemuInitializeRam (
 \r
     //\r
     // Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB as\r
-    // uncacheable\r
-    //\r
-    Status = MtrrSetMemoryAttribute (LowerMemorySize,\r
-               SIZE_4GB - LowerMemorySize, CacheUncacheable);\r
+    // uncacheable. Make sure one variable MTRR suffices by truncating the size\r
+    // to a whole power of two. This will round the base *up*, and a gap (not\r
+    // used for either RAM or MMIO) may stay in the middle, marked as\r
+    // cacheable-by-default.\r
+    //\r
+    Uc32Size = GetPowerOfTwo32 ((UINT32)(SIZE_4GB - LowerMemorySize));\r
+    mQemuUc32Base = (UINT32)(SIZE_4GB - Uc32Size);\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__, (UINT32)LowerMemorySize,\r
+        mQemuUc32Base, Uc32Size));\r
+    }\r
+\r
+    Status = MtrrSetMemoryAttribute (mQemuUc32Base, Uc32Size,\r
+               CacheUncacheable);\r
     ASSERT_EFI_ERROR (Status);\r
+  } else {\r
+    mQemuUc32Base = (UINT32)LowerMemorySize;\r
   }\r
 }\r
 \r