@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
This function programs MTRRs according to the values specified\r
in the shadow array.\r
\r
+ @param[in, out] VariableSettings Variable MTRR settings\r
@param[in] VariableMtrrCount Number of variable MTRRs\r
@param[in, out] VariableMtrr Shadow of variable MTRR contents\r
\r
**/\r
VOID\r
InvalidateMtrr (\r
+ IN OUT MTRR_VARIABLE_SETTINGS *VariableSettings,\r
IN UINTN VariableMtrrCount,\r
IN OUT VARIABLE_MTRR *VariableMtrr\r
)\r
{\r
UINTN Index;\r
- MTRR_CONTEXT MtrrContext;\r
\r
- PreMtrrChange (&MtrrContext);\r
- Index = 0;\r
- while (Index < VariableMtrrCount) {\r
+ for (Index = 0; Index < VariableMtrrCount; Index++) {\r
if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) {\r
- AsmWriteMsr64 (VariableMtrr[Index].Msr, 0);\r
- AsmWriteMsr64 (VariableMtrr[Index].Msr + 1, 0);\r
+ VariableSettings->Mtrr[Index].Base = 0;\r
+ VariableSettings->Mtrr[Index].Mask = 0;\r
VariableMtrr[Index].Used = FALSE;\r
}\r
- Index ++;\r
}\r
- PostMtrrChange (&MtrrContext);\r
}\r
\r
\r
\r
This function programs variable MTRRs\r
\r
+ @param[in, out] VariableSettings Variable MTRR settings.\r
@param[in] MtrrNumber Index of MTRR to program.\r
@param[in] BaseAddress Base address of memory region.\r
@param[in] Length Length of memory region.\r
**/\r
VOID\r
ProgramVariableMtrr (\r
- IN UINTN MtrrNumber,\r
- IN PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 MemoryCacheType,\r
- IN UINT64 MtrrValidAddressMask\r
+ IN OUT MTRR_VARIABLE_SETTINGS *VariableSettings,\r
+ IN UINTN MtrrNumber,\r
+ IN PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 MemoryCacheType,\r
+ IN UINT64 MtrrValidAddressMask\r
)\r
{\r
UINT64 TempQword;\r
- MTRR_CONTEXT MtrrContext;\r
-\r
- PreMtrrChange (&MtrrContext);\r
\r
//\r
// MTRR Physical Base\r
//\r
TempQword = (BaseAddress & MtrrValidAddressMask) | MemoryCacheType;\r
- AsmWriteMsr64 ((UINT32) MtrrNumber, TempQword);\r
+ VariableSettings->Mtrr[MtrrNumber].Base = TempQword;\r
\r
//\r
// MTRR Physical Mask\r
//\r
TempQword = ~(Length - 1);\r
- AsmWriteMsr64 (\r
- (UINT32) (MtrrNumber + 1),\r
- (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED\r
- );\r
-\r
- PostMtrrChange (&MtrrContext);\r
+ VariableSettings->Mtrr[MtrrNumber].Mask = (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED;\r
}\r
\r
\r
UINT64 MtrrValidAddressMask;\r
BOOLEAN OverwriteExistingMtrr;\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
+ BOOLEAN ProgramVariableSettings;\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
+ ProgramVariableSettings = FALSE;\r
\r
if (!IsMtrrSupported ()) {\r
Status = RETURN_UNSUPPORTED;\r
goto Done;\r
}\r
\r
- FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();\r
- VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;\r
-\r
- MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
+ MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);\r
\r
TempQword = 0;\r
MemoryType = (UINT64)Attribute;\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
// Read all variable MTRRs\r
//\r
VariableMtrrCount = GetVariableMtrrCountWorker ();\r
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();\r
MtrrGetVariableMtrrWorker (VariableMtrrCount, &OriginalVariableSettings);\r
CopyMem (&WorkingVariableSettings, &OriginalVariableSettings, sizeof (WorkingVariableSettings));\r
+ ProgramVariableSettings = TRUE;\r
VariableSettings = &WorkingVariableSettings;\r
\r
//\r
BaseAddress + Length - 1,\r
VariableMtrr\r
);\r
-\r
if (OverLap) {\r
Status = CombineMemoryAttribute (\r
FirmwareVariableMtrrCount,\r
//\r
// Combined successfully, invalidate the now-unused MTRRs\r
//\r
- InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
+ InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
Status = RETURN_SUCCESS;\r
goto Done;\r
}\r
//\r
// Invalidate the now-unused MTRRs\r
//\r
- InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
+ InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
goto Done;\r
}\r
\r
//\r
// Invalidate the now-unused MTRRs\r
//\r
- InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
+ InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
\r
//\r
// Find first unused MTRR\r
//\r
- for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE;\r
- MsrNum < VariableMtrrEnd;\r
- MsrNum += 2\r
- ) {\r
- if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+ for (MsrNum = 0; MsrNum < VariableMtrrCount; MsrNum++) {\r
+ if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
break;\r
}\r
}\r
//\r
// Find unused MTRR\r
//\r
- for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {\r
- if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+ for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
+ if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
break;\r
}\r
}\r
\r
ProgramVariableMtrr (\r
+ VariableSettings,\r
MsrNum,\r
BaseAddress,\r
Alignment,\r
//\r
// Find unused MTRR\r
//\r
- for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {\r
- if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+ for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
+ if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
break;\r
}\r
}\r
\r
ProgramVariableMtrr (\r
+ VariableSettings,\r
MsrNum,\r
BaseAddress,\r
Length,\r
//\r
// Find unused MTRR\r
//\r
- for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {\r
- if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+ for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
+ if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
break;\r
}\r
}\r
}\r
\r
ProgramVariableMtrr (\r
+ VariableSettings,\r
MsrNum,\r
BaseAddress,\r
Length,\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
+ //\r
+ // Write variable MTRRs\r
+ //\r
+ if (ProgramVariableSettings) {\r
+ for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+ if (WorkingVariableSettings.Mtrr[Index].Base != OriginalVariableSettings.Mtrr[Index].Base ||\r
+ WorkingVariableSettings.Mtrr[Index].Mask != OriginalVariableSettings.Mtrr[Index].Mask ) {\r
+ if (!MtrrContextValid) {\r
+ PreMtrrChange (&MtrrContext);\r
+ MtrrContextValid = TRUE;\r
+ }\r
+ AsmWriteMsr64 (\r
+ MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1),\r
+ WorkingVariableSettings.Mtrr[Index].Base\r
+ );\r
+ AsmWriteMsr64 (\r
+ MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1,\r
+ WorkingVariableSettings.Mtrr[Index].Mask\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