/** @file\r
MTRR setting library\r
\r
- Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\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
which accompanies this distribution. The full text of the license may be found at\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
@param[in] MemoryCacheType The memory type to set.\r
@param[in, out] Base The base address of memory range.\r
@param[in, out] Length The length of memory range.\r
- @param[out] ReturnMsrNum The index of the fixed MTRR MSR to program.\r
+ @param[in, out] LastMsrNum On input, the last index of the fixed MTRR MSR to program.\r
+ On return, the current index of the fixed MTRR MSR to program.\r
@param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.\r
@param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.\r
\r
IN UINT64 MemoryCacheType,\r
IN OUT UINT64 *Base,\r
IN OUT UINT64 *Length,\r
- OUT UINT32 *ReturnMsrNum,\r
+ IN OUT UINT32 *LastMsrNum,\r
OUT UINT64 *ReturnClearMask,\r
OUT UINT64 *ReturnOrMask\r
)\r
{\r
UINT32 MsrNum;\r
- UINT32 ByteShift;\r
- UINT64 TempQword;\r
+ UINT32 LeftByteShift;\r
+ UINT32 RightByteShift;\r
UINT64 OrMask;\r
UINT64 ClearMask;\r
+ UINT64 SubLength;\r
\r
- TempQword = 0;\r
- OrMask = 0;\r
- ClearMask = 0;\r
-\r
- for (MsrNum = 0; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) {\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
\r
- if (MsrNum == MTRR_NUMBER_OF_FIXED_MTRR) {\r
+ if (MsrNum >= MTRR_NUMBER_OF_FIXED_MTRR) {\r
return RETURN_UNSUPPORTED;\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
- for (ByteShift = 0; ByteShift < 8; ByteShift++) {\r
- if (*Base ==\r
- (\r
- mMtrrLibFixedMtrrTable[MsrNum].BaseAddress +\r
- (ByteShift * mMtrrLibFixedMtrrTable[MsrNum].Length)\r
- )\r
- ) {\r
- break;\r
- }\r
- }\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
- *ReturnMsrNum = MsrNum;\r
+ *Length -= SubLength;\r
+ *Base += SubLength;\r
+\r
+ *LastMsrNum = MsrNum;\r
*ReturnClearMask = ClearMask;\r
*ReturnOrMask = OrMask;\r
\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
Status = RETURN_SUCCESS;\r
if (BaseAddress < BASE_1MB) {\r
+ MsrNum = (UINT32)-1;\r
while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {\r
Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length, &MsrNum, &ClearMask, &OrMask);\r
if (RETURN_ERROR (Status)) {\r
\r
PostMtrrChangeEnableCache (&MtrrContext);\r
\r
- MtrrDebugPrintAllMtrrs ();\r
-\r
return MtrrSetting;\r
}\r
\r