Currently, if the memory length to be programmed is less than the remaining size
of one Fixed-MTRR supported, RETURN_UNSUPPORTED returned. This is not correct.
This is one regression at
07e889209034ba94bfac9e765b8a50ef344daef2 when we
updated ProgramFixedMtrr() to remove the loop of calculating Fixed-MTRR Mask.
This fix will calculate Right offset in Fixed-MTRR beside left offset. It
supports small length (less than remaining size supported by Fixed-MTRR) to be
programmed.
Cc: Eric Dong <eric.dong@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
\r
-#define OR_SEED 0x01010101\r
-#define CLEAR_SEED 0xFFFFFFFF\r
+#define OR_SEED 0x0101010101010101ull\r
+#define CLEAR_SEED 0xFFFFFFFFFFFFFFFFull\r
\r
//\r
// Context to save and restore when MTRRs are programmed\r
\r
//\r
// Context to save and restore when MTRRs are programmed\r
- UINT32 ByteShift;\r
- UINT32 OrMask[2];\r
- UINT32 ClearMask[2];\r
+ UINT32 LeftByteShift;\r
+ UINT32 RightByteShift;\r
+ UINT64 OrMask;\r
+ UINT64 ClearMask;\r
- *(UINT64 *)OrMask = 0;\r
- *(UINT64 *)ClearMask = 0;\r
-\r
+ //\r
+ // Find the fixed MTRR index to be programmed\r
+ //\r
for (MsrNum = *LastMsrNum + 1; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {\r
if ((*Base >= mMtrrLibFixedMtrrTable[MsrNum].BaseAddress) &&\r
(*Base <\r
for (MsrNum = *LastMsrNum + 1; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {\r
if ((*Base >= mMtrrLibFixedMtrrTable[MsrNum].BaseAddress) &&\r
(*Base <\r
- // We found the fixed MTRR to be programmed\r
+ // Find the begin offset in fixed MTRR and calculate byte offset of left shift\r
- ByteShift = ((UINT32)*Base - mMtrrLibFixedMtrrTable[MsrNum].BaseAddress)\r
+ LeftByteShift = ((UINT32)*Base - mMtrrLibFixedMtrrTable[MsrNum].BaseAddress)\r
/ mMtrrLibFixedMtrrTable[MsrNum].Length;\r
\r
/ mMtrrLibFixedMtrrTable[MsrNum].Length;\r
\r
- if (ByteShift >= 8) {\r
+ if (LeftByteShift >= 8) {\r
return RETURN_UNSUPPORTED;\r
}\r
\r
return RETURN_UNSUPPORTED;\r
}\r
\r
- if (ByteShift < 4) {\r
- OrMask[0] = OR_SEED * (UINT32)MemoryCacheType;\r
- ClearMask[0] = CLEAR_SEED;\r
- OrMask[1] = (OR_SEED * (UINT32)MemoryCacheType) >> ((4 - ByteShift) * 8);\r
- ClearMask[1] = CLEAR_SEED >> ((4 - ByteShift) * 8);\r
+ //\r
+ // Find the end offset in fixed MTRR and calculate byte offset of right shift\r
+ //\r
+ SubLength = mMtrrLibFixedMtrrTable[MsrNum].Length * (8 - LeftByteShift);\r
+ if (*Length >= SubLength) {\r
+ RightByteShift = 0;\r
- OrMask[0] = (OR_SEED * (UINT32)MemoryCacheType) >> ((8 - ByteShift) * 8);\r
- ClearMask[0] = CLEAR_SEED >> ((8 - ByteShift) * 8);\r
+ RightByteShift = 8 - LeftByteShift -\r
+ (UINT32)(*Length) / mMtrrLibFixedMtrrTable[MsrNum].Length;\r
+ if ((LeftByteShift >= 8) ||\r
+ (((UINT32)(*Length) % mMtrrLibFixedMtrrTable[MsrNum].Length) != 0)\r
+ ) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+ //\r
+ // Update SubLength by actual length\r
+ //\r
+ SubLength = *Length;\r
- SubLength = mMtrrLibFixedMtrrTable[MsrNum].Length * (8 - ByteShift);\r
- if (*Length < SubLength) {\r
- return RETURN_UNSUPPORTED;\r
+ ClearMask = CLEAR_SEED;\r
+ OrMask = MultU64x32 (OR_SEED, (UINT32)MemoryCacheType);\r
+\r
+ if (LeftByteShift != 0) {\r
+ //\r
+ // Clear the low bits by LeftByteShift\r
+ //\r
+ ClearMask &= LShiftU64 (ClearMask, LeftByteShift * 8);\r
+ OrMask &= LShiftU64 (OrMask, LeftByteShift * 8);\r
+ }\r
+\r
+ if (RightByteShift != 0) {\r
+ //\r
+ // Clear the high bits by RightByteShift\r
+ //\r
+ ClearMask &= RShiftU64 (ClearMask, RightByteShift * 8);\r
+ OrMask &= RShiftU64 (OrMask, RightByteShift * 8);\r
}\r
\r
*Length -= SubLength;\r
*Base += SubLength;\r
\r
*LastMsrNum = MsrNum;\r
}\r
\r
*Length -= SubLength;\r
*Base += SubLength;\r
\r
*LastMsrNum = MsrNum;\r
- *ReturnClearMask = *(UINT64 *)ClearMask;\r
- *ReturnOrMask = *(UINT64 *)OrMask;\r
+ *ReturnClearMask = ClearMask;\r
+ *ReturnOrMask = OrMask;\r
\r
return RETURN_SUCCESS;\r
}\r
\r
return RETURN_SUCCESS;\r
}\r