@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[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
@retval RETURN_SUCCESS The cache type was updated successfully\r
@retval RETURN_UNSUPPORTED The requested range or cache type was invalid\r
**/\r
RETURN_STATUS\r
ProgramFixedMtrr (\r
- IN UINT64 MemoryCacheType,\r
- IN OUT UINT64 *Base,\r
- IN OUT UINT64 *Length\r
+ IN UINT64 MemoryCacheType,\r
+ IN OUT UINT64 *Base,\r
+ IN OUT UINT64 *Length,\r
+ OUT UINT32 *ReturnMsrNum,\r
+ OUT UINT64 *ReturnClearMask,\r
+ OUT UINT64 *ReturnOrMask\r
)\r
{\r
UINT32 MsrNum;\r
return RETURN_UNSUPPORTED;\r
}\r
\r
- TempQword =\r
- (AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask;\r
- AsmWriteMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr, TempQword);\r
+ *ReturnMsrNum = MsrNum;\r
+ *ReturnClearMask = ClearMask;\r
+ *ReturnOrMask = OrMask;\r
+\r
return RETURN_SUCCESS;\r
}\r
\r
UINT32 FirmwareVariableMtrrCount;\r
UINT32 VariableMtrrEnd;\r
MTRR_CONTEXT MtrrContext;\r
+ BOOLEAN MtrrContextValid;\r
+ BOOLEAN FixedSettingsValid[MTRR_NUMBER_OF_FIXED_MTRR];\r
+ BOOLEAN FixedSettingsModified[MTRR_NUMBER_OF_FIXED_MTRR];\r
+ MTRR_FIXED_SETTINGS WorkingFixedSettings;\r
UINT32 VariableMtrrCount;\r
MTRR_VARIABLE_SETTINGS OriginalVariableSettings;\r
MTRR_VARIABLE_SETTINGS WorkingVariableSettings;\r
+ UINT32 Index;\r
+ UINT64 ClearMask;\r
+ UINT64 OrMask;\r
+ UINT64 NewValue;\r
MTRR_VARIABLE_SETTINGS *VariableSettings;\r
\r
DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
+ MtrrContextValid = FALSE;\r
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+ FixedSettingsValid[Index] = FALSE;\r
+ FixedSettingsModified[Index] = FALSE;\r
+ }\r
\r
if (!IsMtrrSupported ()) {\r
Status = RETURN_UNSUPPORTED;\r
// Check if Fixed MTRR\r
//\r
Status = RETURN_SUCCESS;\r
- while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) {\r
- PreMtrrChange (&MtrrContext);\r
- Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length);\r
- PostMtrrChange (&MtrrContext);\r
- if (RETURN_ERROR (Status)) {\r
- goto Done;\r
+ if (BaseAddress < BASE_1MB) {\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
+ goto Done;\r
+ }\r
+ if (!FixedSettingsValid[MsrNum]) {\r
+ WorkingFixedSettings.Mtrr[MsrNum] = AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr);\r
+ FixedSettingsValid[MsrNum] = TRUE;\r
+ }\r
+ NewValue = (WorkingFixedSettings.Mtrr[MsrNum] & ~ClearMask) | OrMask;\r
+ if (WorkingFixedSettings.Mtrr[MsrNum] != NewValue) {\r
+ WorkingFixedSettings.Mtrr[MsrNum] = NewValue;\r
+ FixedSettingsModified[MsrNum] = TRUE;\r
+ }\r
}\r
- }\r
\r
- if (Length == 0) {\r
- //\r
- // A Length of 0 can only make sense for fixed MTTR ranges.\r
- // Since we just handled the fixed MTRRs, we can skip the\r
- // variable MTRR section.\r
- //\r
- goto Done;\r
+ if (Length == 0) {\r
+ //\r
+ // A Length of 0 can only make sense for fixed MTTR ranges.\r
+ // Since we just handled the fixed MTRRs, we can skip the\r
+ // variable MTRR section.\r
+ //\r
+ goto Done;\r
+ }\r
}\r
\r
//\r
} while (TempQword > 0);\r
\r
Done:\r
+\r
+ //\r
+ // Write fixed MTRRs that have been modified\r
+ //\r
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+ if (FixedSettingsModified[Index]) {\r
+ if (!MtrrContextValid) {\r
+ PreMtrrChange (&MtrrContext);\r
+ MtrrContextValid = TRUE;\r
+ }\r
+ AsmWriteMsr64 (\r
+ mMtrrLibFixedMtrrTable[Index].Msr,\r
+ WorkingFixedSettings.Mtrr[Index]\r
+ );\r
+ }\r
+ }\r
+\r
+ if (MtrrContextValid) {\r
+ PostMtrrChange (&MtrrContext);\r
+ }\r
+\r
DEBUG((DEBUG_CACHE, " Status = %r\n", Status));\r
if (!RETURN_ERROR (Status)) {\r
MtrrDebugPrintAllMtrrs ();\r