{\r
UINT64 LowerMemorySize;\r
UINT64 UpperMemorySize;\r
+ MTRR_SETTINGS MtrrSettings;\r
+ EFI_STATUS Status;\r
\r
DEBUG ((EFI_D_INFO, "%a called\n", __FUNCTION__));\r
\r
}\r
}\r
\r
- MtrrSetMemoryAttribute (BASE_1MB, LowerMemorySize - BASE_1MB, CacheWriteBack);\r
+ //\r
+ // We'd like to keep the following ranges uncached:\r
+ // - [640 KB, 1 MB)\r
+ // - [LowerMemorySize, 4 GB)\r
+ //\r
+ // Everything else should be WB. Unfortunately, programming the inverse (ie.\r
+ // keeping the default UC, and configuring the complement set of the above as\r
+ // WB) is not reliable in general, because the end of the upper RAM can have\r
+ // practically any alignment, and we may not have enough variable MTRRs to\r
+ // cover it exactly.\r
+ //\r
+ if (IsMtrrSupported ()) {\r
+ MtrrGetAllMtrrs (&MtrrSettings);\r
+\r
+ //\r
+ // MTRRs disabled, fixed MTRRs disabled, default type is uncached\r
+ //\r
+ ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);\r
+ ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);\r
+ ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);\r
+\r
+ //\r
+ // flip default type to writeback\r
+ //\r
+ SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);\r
+ ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);\r
+ MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;\r
+ MtrrSetAllMtrrs (&MtrrSettings);\r
\r
- MtrrSetMemoryAttribute (0, BASE_512KB + BASE_128KB, CacheWriteBack);\r
+ //\r
+ // Set memory range from 640KB to 1MB to uncacheable\r
+ //\r
+ Status = MtrrSetMemoryAttribute (BASE_512KB + BASE_128KB,\r
+ BASE_1MB - (BASE_512KB + BASE_128KB), CacheUncacheable);\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- if (UpperMemorySize != 0) {\r
- MtrrSetMemoryAttribute (BASE_4GB, UpperMemorySize, CacheWriteBack);\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
+ ASSERT_EFI_ERROR (Status);\r
}\r
}\r
\r