/** @file\r
MTRR setting library\r
\r
+ @par Note: \r
+ Most of services in this library instance are suggested to be invoked by BSP only,\r
+ except for MtrrSetAllMtrrs() which is used to sync BSP's MTRR setting to APs.\r
+\r
Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
\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
{\r
UINT32 MsrNum;\r
- UINT32 ByteShift;\r
+ UINT32 LeftByteShift;\r
+ UINT32 RightByteShift;\r
UINT64 OrMask;\r
UINT64 ClearMask;\r
+ UINT64 SubLength;\r
\r
- OrMask = 0;\r
- 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
}\r
\r
//\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
//\r
- ByteShift = ((UINT32)*Base - mMtrrLibFixedMtrrTable[MsrNum].BaseAddress)\r
+ LeftByteShift = ((UINT32)*Base - mMtrrLibFixedMtrrTable[MsrNum].BaseAddress)\r
/ mMtrrLibFixedMtrrTable[MsrNum].Length;\r
\r
- if (ByteShift >= 8) {\r
+ if (LeftByteShift >= 8) {\r
return RETURN_UNSUPPORTED;\r
}\r
\r
- for (\r
- ;\r
- ((ByteShift < 8) && (*Length >= mMtrrLibFixedMtrrTable[MsrNum].Length));\r
- ByteShift++\r
- ) {\r
- OrMask |= LShiftU64 ((UINT64) MemoryCacheType, (UINT32) (ByteShift * 8));\r
- ClearMask |= LShiftU64 ((UINT64) 0xFF, (UINT32) (ByteShift * 8));\r
- *Length -= mMtrrLibFixedMtrrTable[MsrNum].Length;\r
- *Base += mMtrrLibFixedMtrrTable[MsrNum].Length;\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
+ } else {\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
+ }\r
+\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 (ByteShift < 8 && (*Length != 0)) {\r
- return RETURN_UNSUPPORTED;\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
*ReturnClearMask = ClearMask;\r
*ReturnOrMask = OrMask;\r
@param[in] MtrrValidAddressMask The valid address mask for MTRR\r
@param[out] VariableMtrr The array to shadow variable MTRRs content\r
\r
- @return The return value of this paramter indicates the\r
+ @return The return value of this parameter indicates the\r
number of MTRRs which has been used.\r
\r
**/\r
\r
PostMtrrChangeEnableCache (&MtrrContext);\r
\r
- MtrrDebugPrintAllMtrrs ();\r
-\r
return MtrrSetting;\r
}\r
\r