PostMtrrChangeEnableCache (MtrrContext);\r
}\r
\r
+/**\r
+ Worker function gets the content in fixed MTRRs\r
+\r
+ @param[out] FixedSettings A buffer to hold fixed MTRRs content.\r
+\r
+ @retval The pointer of FixedSettings\r
+\r
+**/\r
+MTRR_FIXED_SETTINGS*\r
+MtrrGetFixedMtrrWorker (\r
+ OUT MTRR_FIXED_SETTINGS *FixedSettings\r
+ )\r
+{\r
+ UINT32 Index;\r
+\r
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+ FixedSettings->Mtrr[Index] =\r
+ AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);\r
+ }\r
+\r
+ return FixedSettings;\r
+}\r
+\r
+\r
+/**\r
+ This function gets the content in fixed MTRRs\r
+\r
+ @param[out] FixedSettings A buffer to hold fixed MTRRs content.\r
+\r
+ @retval The pointer of FixedSettings\r
+\r
+**/\r
+MTRR_FIXED_SETTINGS*\r
+EFIAPI\r
+MtrrGetFixedMtrr (\r
+ OUT MTRR_FIXED_SETTINGS *FixedSettings\r
+ )\r
+{\r
+ if (!IsMtrrSupported ()) {\r
+ return FixedSettings;\r
+ }\r
+\r
+ return MtrrGetFixedMtrrWorker (FixedSettings);\r
+}\r
+\r
+\r
+/**\r
+ Worker function will get the raw value in variable MTRRs\r
+\r
+ @param[out] VariableSettings A buffer to hold variable MTRRs content.\r
+\r
+ @return The VariableSettings input pointer\r
+\r
+**/\r
+MTRR_VARIABLE_SETTINGS*\r
+MtrrGetVariableMtrrWorker (\r
+ IN UINT32 VariableMtrrCount,\r
+ OUT MTRR_VARIABLE_SETTINGS *VariableSettings\r
+ )\r
+{\r
+ UINT32 Index;\r
+\r
+ ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+\r
+ for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+ VariableSettings->Mtrr[Index].Base =\r
+ AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1));\r
+ VariableSettings->Mtrr[Index].Mask =\r
+ AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1);\r
+ }\r
+\r
+ return VariableSettings;\r
+}\r
+\r
+/**\r
+ This function will get the raw value in variable MTRRs\r
+\r
+ @param[out] VariableSettings A buffer to hold variable MTRRs content.\r
+\r
+ @return The VariableSettings input pointer\r
+\r
+**/\r
+MTRR_VARIABLE_SETTINGS*\r
+EFIAPI\r
+MtrrGetVariableMtrr (\r
+ OUT MTRR_VARIABLE_SETTINGS *VariableSettings\r
+ )\r
+{\r
+ if (!IsMtrrSupported ()) {\r
+ return VariableSettings;\r
+ }\r
+\r
+ return MtrrGetVariableMtrrWorker (\r
+ GetVariableMtrrCountWorker (),\r
+ VariableSettings\r
+ );\r
+}\r
\r
/**\r
Programs fixed MTRRs registers.\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[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
\r
+/**\r
+ Worker function gets the attribute of variable MTRRs.\r
+\r
+ This function shadows the content of variable MTRRs into an\r
+ internal array: VariableMtrr.\r
+\r
+ @param[in] VariableSettings The variable MTRR values to shadow\r
+ @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware\r
+ @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR\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 parameter indicates the\r
+ number of MTRRs which has been used.\r
+\r
+**/\r
+UINT32\r
+MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+ IN MTRR_VARIABLE_SETTINGS *VariableSettings,\r
+ IN UINTN FirmwareVariableMtrrCount,\r
+ IN UINT64 MtrrValidBitsMask,\r
+ IN UINT64 MtrrValidAddressMask,\r
+ OUT VARIABLE_MTRR *VariableMtrr\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT32 UsedMtrr;\r
+\r
+ ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+ for (Index = 0, UsedMtrr = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
+ if ((VariableSettings->Mtrr[Index].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {\r
+ VariableMtrr[Index].Msr = (UINT32)Index;\r
+ VariableMtrr[Index].BaseAddress = (VariableSettings->Mtrr[Index].Base & MtrrValidAddressMask);\r
+ VariableMtrr[Index].Length = ((~(VariableSettings->Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;\r
+ VariableMtrr[Index].Type = (VariableSettings->Mtrr[Index].Base & 0x0ff);\r
+ VariableMtrr[Index].Valid = TRUE;\r
+ VariableMtrr[Index].Used = TRUE;\r
+ UsedMtrr++;\r
+ }\r
+ }\r
+ return UsedMtrr;\r
+}\r
+\r
+\r
/**\r
Gets the attribute of variable MTRRs.\r
\r
OUT VARIABLE_MTRR *VariableMtrr\r
)\r
{\r
- UINTN Index;\r
- UINT32 MsrNum;\r
- UINT32 UsedMtrr;\r
- UINT32 FirmwareVariableMtrrCount;\r
- UINT32 VariableMtrrEnd;\r
+ MTRR_VARIABLE_SETTINGS VariableSettings;\r
\r
if (!IsMtrrSupported ()) {\r
return 0;\r
}\r
\r
- FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
- VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;\r
-\r
- ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);\r
- UsedMtrr = 0;\r
+ MtrrGetVariableMtrrWorker (\r
+ GetVariableMtrrCountWorker (),\r
+ &VariableSettings\r
+ );\r
\r
- for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE, Index = 0;\r
- (\r
- (MsrNum < VariableMtrrEnd) &&\r
- (Index < FirmwareVariableMtrrCount)\r
- );\r
- MsrNum += 2\r
- ) {\r
- if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {\r
- VariableMtrr[Index].Msr = MsrNum;\r
- VariableMtrr[Index].BaseAddress = (AsmReadMsr64 (MsrNum) &\r
- MtrrValidAddressMask);\r
- VariableMtrr[Index].Length = ((~(AsmReadMsr64 (MsrNum + 1) &\r
- MtrrValidAddressMask)\r
- ) &\r
- MtrrValidBitsMask\r
- ) + 1;\r
- VariableMtrr[Index].Type = (AsmReadMsr64 (MsrNum) & 0x0ff);\r
- VariableMtrr[Index].Valid = TRUE;\r
- VariableMtrr[Index].Used = TRUE;\r
- UsedMtrr = UsedMtrr + 1;\r
- Index++;\r
- }\r
- }\r
- return UsedMtrr;\r
+ return MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+ &VariableSettings,\r
+ GetFirmwareVariableMtrrCountWorker (),\r
+ MtrrValidBitsMask,\r
+ MtrrValidAddressMask,\r
+ VariableMtrr\r
+ );\r
}\r
\r
\r
/**\r
Checks overlap between given memory range and MTRRs.\r
\r
+ @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available\r
+ to firmware.\r
@param[in] Start The start address of memory range.\r
@param[in] End The end address of memory range.\r
@param[in] VariableMtrr The array to shadow variable MTRRs content\r
**/\r
BOOLEAN\r
CheckMemoryAttributeOverlap (\r
- IN PHYSICAL_ADDRESS Start,\r
- IN PHYSICAL_ADDRESS End,\r
- IN VARIABLE_MTRR *VariableMtrr\r
+ IN UINTN FirmwareVariableMtrrCount,\r
+ IN PHYSICAL_ADDRESS Start,\r
+ IN PHYSICAL_ADDRESS End,\r
+ IN VARIABLE_MTRR *VariableMtrr\r
)\r
{\r
UINT32 Index;\r
\r
- for (Index = 0; Index < 6; Index++) {\r
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
if (\r
VariableMtrr[Index].Valid &&\r
!(\r
\r
If overlap exists between given memory range and MTRRs, try to combine them.\r
\r
+ @param[in] FirmwareVariableMtrrCount The number of variable MTRRs\r
+ available to firmware.\r
@param[in] Attributes 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
**/\r
RETURN_STATUS\r
CombineMemoryAttribute (\r
+ IN UINT32 FirmwareVariableMtrrCount,\r
IN UINT64 Attributes,\r
IN OUT UINT64 *Base,\r
IN OUT UINT64 *Length,\r
UINT64 CombineEnd;\r
UINT64 MtrrEnd;\r
UINT64 EndAddress;\r
- UINT32 FirmwareVariableMtrrCount;\r
BOOLEAN CoveredByExistingMtrr;\r
\r
- FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
-\r
*OverwriteExistingMtrr = FALSE;\r
CoveredByExistingMtrr = FALSE;\r
EndAddress = *Base +*Length - 1;\r
This function programs MTRRs according to the values specified\r
in the shadow array.\r
\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 UINTN VariableMtrrCount,\r
IN OUT VARIABLE_MTRR *VariableMtrr\r
)\r
{\r
UINTN Index;\r
- UINTN VariableMtrrCount;\r
MTRR_CONTEXT MtrrContext;\r
\r
PreMtrrChange (&MtrrContext);\r
Index = 0;\r
- VariableMtrrCount = GetVariableMtrrCount ();\r
while (Index < VariableMtrrCount) {\r
if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) {\r
AsmWriteMsr64 (VariableMtrr[Index].Msr, 0);\r
}\r
\r
\r
+\r
/**\r
- This function attempts to set the attributes for a memory range.\r
+ This function will get the memory cache type of the specific address.\r
\r
- @param[in] BaseAddress The physical address that is the start\r
- address of a memory region.\r
- @param[in] Length The size in bytes of the memory region.\r
- @param[in] Attribute The bit mask of attributes to set for the\r
- memory region.\r
+ This function is mainly for debug purpose.\r
\r
- @retval RETURN_SUCCESS The attributes were set for the memory\r
- region.\r
- @retval RETURN_INVALID_PARAMETER Length is zero.\r
- @retval RETURN_UNSUPPORTED The processor does not support one or\r
- more bytes of the memory resource range\r
- specified by BaseAddress and Length.\r
- @retval RETURN_UNSUPPORTED The bit mask of attributes is not support\r
- for the memory resource range specified\r
- by BaseAddress and Length.\r
- @retval RETURN_ACCESS_DENIED The attributes for the memory resource\r
- range specified by BaseAddress and Length\r
- cannot be modified.\r
- @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to\r
- modify the attributes of the memory\r
- resource range.\r
+ @param[in] Address The specific address\r
+\r
+ @return Memory cache type of the specific address\r
\r
**/\r
-RETURN_STATUS\r
+MTRR_MEMORY_CACHE_TYPE\r
EFIAPI\r
-MtrrSetMemoryAttribute (\r
- IN PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN MTRR_MEMORY_CACHE_TYPE Attribute\r
+MtrrGetMemoryAttribute (\r
+ IN PHYSICAL_ADDRESS Address\r
)\r
{\r
- UINT64 TempQword;\r
- RETURN_STATUS Status;\r
- UINT64 MemoryType;\r
- UINT64 Alignment;\r
- BOOLEAN OverLap;\r
- BOOLEAN Positive;\r
- UINT32 MsrNum;\r
- UINTN MtrrNumber;\r
- VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
- UINT32 UsedMtrr;\r
- UINT64 MtrrValidBitsMask;\r
- UINT64 MtrrValidAddressMask;\r
- BOOLEAN OverwriteExistingMtrr;\r
- UINT32 FirmwareVariableMtrrCount;\r
- UINT32 VariableMtrrEnd;\r
- MTRR_CONTEXT MtrrContext;\r
-\r
- DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
+ UINT64 TempQword;\r
+ UINTN Index;\r
+ UINTN SubIndex;\r
+ UINT64 MtrrType;\r
+ UINT64 TempMtrrType;\r
+ MTRR_MEMORY_CACHE_TYPE CacheType;\r
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
+ UINT64 MtrrValidBitsMask;\r
+ UINT64 MtrrValidAddressMask;\r
+ UINTN VariableMtrrCount;\r
+ MTRR_VARIABLE_SETTINGS VariableSettings;\r
\r
if (!IsMtrrSupported ()) {\r
- Status = RETURN_UNSUPPORTED;\r
- goto Done;\r
+ return CacheUncacheable;\r
}\r
\r
- FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
- VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;\r
-\r
- MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
-\r
- TempQword = 0;\r
- MemoryType = (UINT64)Attribute;\r
- OverwriteExistingMtrr = FALSE;\r
-\r
//\r
- // Check for an invalid parameter\r
+ // Check if MTRR is enabled, if not, return UC as attribute\r
//\r
- if (Length == 0) {\r
- Status = RETURN_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
+ TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);\r
+ MtrrType = MTRR_CACHE_INVALID_TYPE;\r
\r
- if (\r
- (BaseAddress & ~MtrrValidAddressMask) != 0 ||\r
- (Length & ~MtrrValidAddressMask) != 0\r
- ) {\r
- Status = RETURN_UNSUPPORTED;\r
- goto Done;\r
+ if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+ return CacheUncacheable;\r
}\r
\r
//\r
- // Check if Fixed MTRR\r
+ // If address is less than 1M, then try to go through the 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 (Address < BASE_1MB) {\r
+ if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) {\r
+ //\r
+ // Go through the fixed MTRR\r
+ //\r
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+ if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress &&\r
+ Address < (\r
+ mMtrrLibFixedMtrrTable[Index].BaseAddress +\r
+ (mMtrrLibFixedMtrrTable[Index].Length * 8)\r
+ )\r
+ ) {\r
+ SubIndex =\r
+ ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) /\r
+ mMtrrLibFixedMtrrTable[Index].Length;\r
+ TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);\r
+ MtrrType = RShiftU64 (TempQword, SubIndex * 8) & 0xFF;\r
+ return GetMemoryCacheTypeFromMtrrType (MtrrType);\r
+ }\r
+ }\r
}\r
}\r
+ MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\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
- }\r
+ MtrrGetVariableMtrrWorker (\r
+ GetVariableMtrrCountWorker (),\r
+ &VariableSettings\r
+ );\r
+\r
+ MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+ &VariableSettings,\r
+ GetFirmwareVariableMtrrCountWorker (),\r
+ MtrrValidBitsMask,\r
+ MtrrValidAddressMask,\r
+ VariableMtrr\r
+ );\r
+\r
+ //\r
+ // Go through the variable MTRR\r
+ //\r
+ VariableMtrrCount = GetVariableMtrrCountWorker ();\r
+ ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+\r
+ for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+ if (VariableMtrr[Index].Valid) {\r
+ if (Address >= VariableMtrr[Index].BaseAddress &&\r
+ Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) {\r
+ TempMtrrType = VariableMtrr[Index].Type;\r
+ MtrrType = MtrrPrecedence (MtrrType, TempMtrrType);\r
+ }\r
+ }\r
+ }\r
+ CacheType = GetMemoryCacheTypeFromMtrrType (MtrrType);\r
+\r
+ return CacheType;\r
+}\r
+\r
+\r
+\r
+/**\r
+ This function prints all MTRRs for debugging.\r
+**/\r
+VOID\r
+EFIAPI\r
+MtrrDebugPrintAllMtrrs (\r
+ VOID\r
+ )\r
+{\r
+ DEBUG_CODE (\r
+ MTRR_SETTINGS MtrrSettings;\r
+ UINTN Index;\r
+ UINTN Index1;\r
+ UINTN VariableMtrrCount;\r
+ UINT64 Base;\r
+ UINT64 Limit;\r
+ UINT64 MtrrBase;\r
+ UINT64 MtrrLimit;\r
+ UINT64 RangeBase;\r
+ UINT64 RangeLimit;\r
+ UINT64 NoRangeBase;\r
+ UINT64 NoRangeLimit;\r
+ UINT32 RegEax;\r
+ UINTN MemoryType;\r
+ UINTN PreviousMemoryType;\r
+ BOOLEAN Found;\r
+\r
+ if (!IsMtrrSupported ()) {\r
+ return;\r
+ }\r
+\r
+ DEBUG((DEBUG_CACHE, "MTRR Settings\n"));\r
+ DEBUG((DEBUG_CACHE, "=============\n"));\r
+\r
+ MtrrGetAllMtrrs (&MtrrSettings);\r
+ DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", MtrrSettings.MtrrDefType));\r
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+ DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, MtrrSettings.Fixed.Mtrr[Index]));\r
+ }\r
+\r
+ VariableMtrrCount = GetVariableMtrrCount ();\r
+ for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+ DEBUG((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",\r
+ Index,\r
+ MtrrSettings.Variables.Mtrr[Index].Base,\r
+ MtrrSettings.Variables.Mtrr[Index].Mask\r
+ ));\r
+ }\r
+ DEBUG((DEBUG_CACHE, "\n"));\r
+ DEBUG((DEBUG_CACHE, "MTRR Ranges\n"));\r
+ DEBUG((DEBUG_CACHE, "====================================\n"));\r
+\r
+ Base = 0;\r
+ PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;\r
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+ Base = mMtrrLibFixedMtrrTable[Index].BaseAddress;\r
+ for (Index1 = 0; Index1 < 8; Index1++) {\r
+ MemoryType = (UINTN)(RShiftU64 (MtrrSettings.Fixed.Mtrr[Index], Index1 * 8) & 0xff);\r
+ if (MemoryType > CacheWriteBack) {\r
+ MemoryType = MTRR_CACHE_INVALID_TYPE;\r
+ }\r
+ if (MemoryType != PreviousMemoryType) {\r
+ if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {\r
+ DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
+ }\r
+ PreviousMemoryType = MemoryType;\r
+ DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));\r
+ }\r
+ Base += mMtrrLibFixedMtrrTable[Index].Length;\r
+ }\r
+ }\r
+ DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
+\r
+ VariableMtrrCount = GetVariableMtrrCount ();\r
+\r
+ Limit = BIT36 - 1;\r
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+ if (RegEax >= 0x80000008) {\r
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+ Limit = LShiftU64 (1, RegEax & 0xff) - 1;\r
+ }\r
+ Base = BASE_1MB;\r
+ PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;\r
+ do {\r
+ MemoryType = MtrrGetMemoryAttribute (Base);\r
+ if (MemoryType > CacheWriteBack) {\r
+ MemoryType = MTRR_CACHE_INVALID_TYPE;\r
+ }\r
+\r
+ if (MemoryType != PreviousMemoryType) {\r
+ if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {\r
+ DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
+ }\r
+ PreviousMemoryType = MemoryType;\r
+ DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));\r
+ }\r
+\r
+ RangeBase = BASE_1MB;\r
+ NoRangeBase = BASE_1MB;\r
+ RangeLimit = Limit;\r
+ NoRangeLimit = Limit;\r
+\r
+ for (Index = 0, Found = FALSE; Index < VariableMtrrCount; Index++) {\r
+ if ((MtrrSettings.Variables.Mtrr[Index].Mask & BIT11) == 0) {\r
+ //\r
+ // If mask is not valid, then do not display range\r
+ //\r
+ continue;\r
+ }\r
+ MtrrBase = (MtrrSettings.Variables.Mtrr[Index].Base & (~(SIZE_4KB - 1)));\r
+ MtrrLimit = MtrrBase + ((~(MtrrSettings.Variables.Mtrr[Index].Mask & (~(SIZE_4KB - 1)))) & Limit);\r
+\r
+ if (Base >= MtrrBase && Base < MtrrLimit) {\r
+ Found = TRUE;\r
+ }\r
+\r
+ if (Base >= MtrrBase && MtrrBase > RangeBase) {\r
+ RangeBase = MtrrBase;\r
+ }\r
+ if (Base > MtrrLimit && MtrrLimit > RangeBase) {\r
+ RangeBase = MtrrLimit + 1;\r
+ }\r
+ if (Base < MtrrBase && MtrrBase < RangeLimit) {\r
+ RangeLimit = MtrrBase - 1;\r
+ }\r
+ if (Base < MtrrLimit && MtrrLimit <= RangeLimit) {\r
+ RangeLimit = MtrrLimit;\r
+ }\r
+\r
+ if (Base > MtrrLimit && NoRangeBase < MtrrLimit) {\r
+ NoRangeBase = MtrrLimit + 1;\r
+ }\r
+ if (Base < MtrrBase && NoRangeLimit > MtrrBase) {\r
+ NoRangeLimit = MtrrBase - 1;\r
+ }\r
+ }\r
+\r
+ if (Found) {\r
+ Base = RangeLimit + 1;\r
+ } else {\r
+ Base = NoRangeLimit + 1;\r
+ }\r
+ } while (Base < Limit);\r
+ DEBUG((DEBUG_CACHE, "%016lx\n\n", Base - 1));\r
+ );\r
+}\r
+/**\r
+ This function attempts to set the attributes for a memory range.\r
+\r
+ @param[in] BaseAddress The physical address that is the start\r
+ address of a memory region.\r
+ @param[in] Length The size in bytes of the memory region.\r
+ @param[in] Attribute The bit mask of attributes to set for the\r
+ memory region.\r
+\r
+ @retval RETURN_SUCCESS The attributes were set for the memory\r
+ region.\r
+ @retval RETURN_INVALID_PARAMETER Length is zero.\r
+ @retval RETURN_UNSUPPORTED The processor does not support one or\r
+ more bytes of the memory resource range\r
+ specified by BaseAddress and Length.\r
+ @retval RETURN_UNSUPPORTED The bit mask of attributes is not support\r
+ for the memory resource range specified\r
+ by BaseAddress and Length.\r
+ @retval RETURN_ACCESS_DENIED The attributes for the memory resource\r
+ range specified by BaseAddress and Length\r
+ cannot be modified.\r
+ @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to\r
+ modify the attributes of the memory\r
+ resource range.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+MtrrSetMemoryAttribute (\r
+ IN PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN MTRR_MEMORY_CACHE_TYPE Attribute\r
+ )\r
+{\r
+ UINT64 TempQword;\r
+ RETURN_STATUS Status;\r
+ UINT64 MemoryType;\r
+ UINT64 Alignment;\r
+ BOOLEAN OverLap;\r
+ BOOLEAN Positive;\r
+ UINT32 MsrNum;\r
+ UINTN MtrrNumber;\r
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
+ UINT32 UsedMtrr;\r
+ UINT64 MtrrValidBitsMask;\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
+ 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
+ goto Done;\r
+ }\r
+\r
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();\r
+ VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;\r
+\r
+ MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
+\r
+ TempQword = 0;\r
+ MemoryType = (UINT64)Attribute;\r
+ OverwriteExistingMtrr = FALSE;\r
+\r
+ //\r
+ // Check for an invalid parameter\r
+ //\r
+ if (Length == 0) {\r
+ Status = RETURN_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ if (\r
+ (BaseAddress & ~MtrrValidAddressMask) != 0 ||\r
+ (Length & ~MtrrValidAddressMask) != 0\r
+ ) {\r
+ Status = RETURN_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check if Fixed MTRR\r
+ //\r
+ Status = RETURN_SUCCESS;\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
+ 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
// Since memory ranges below 1MB will be overridden by the fixed MTRRs,\r
Length += SIZE_1MB;\r
}\r
\r
+ //\r
+ // Read all variable MTRRs\r
+ //\r
+ VariableMtrrCount = GetVariableMtrrCountWorker ();\r
+ MtrrGetVariableMtrrWorker (VariableMtrrCount, &OriginalVariableSettings);\r
+ CopyMem (&WorkingVariableSettings, &OriginalVariableSettings, sizeof (WorkingVariableSettings));\r
+ VariableSettings = &WorkingVariableSettings;\r
+\r
//\r
// Check for overlap\r
//\r
- UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);\r
- OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);\r
+ UsedMtrr = MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+ VariableSettings,\r
+ FirmwareVariableMtrrCount,\r
+ MtrrValidBitsMask,\r
+ MtrrValidAddressMask,\r
+ VariableMtrr\r
+ );\r
+ OverLap = CheckMemoryAttributeOverlap (\r
+ FirmwareVariableMtrrCount,\r
+ BaseAddress,\r
+ BaseAddress + Length - 1,\r
+ VariableMtrr\r
+ );\r
+\r
if (OverLap) {\r
- Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr);\r
+ Status = CombineMemoryAttribute (\r
+ FirmwareVariableMtrrCount,\r
+ MemoryType,\r
+ &BaseAddress,\r
+ &Length,\r
+ VariableMtrr,\r
+ &UsedMtrr,\r
+ &OverwriteExistingMtrr\r
+ );\r
if (RETURN_ERROR (Status)) {\r
goto Done;\r
}\r
//\r
// Combined successfully, invalidate the now-unused MTRRs\r
//\r
- InvalidateMtrr(VariableMtrr);\r
+ InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
Status = RETURN_SUCCESS;\r
goto Done;\r
}\r
//\r
// Invalidate the now-unused MTRRs\r
//\r
- InvalidateMtrr(VariableMtrr);\r
+ InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
goto Done;\r
}\r
\r
//\r
// Invalidate the now-unused MTRRs\r
//\r
- InvalidateMtrr(VariableMtrr);\r
+ InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
\r
//\r
// Find first unused MTRR\r
);\r
BaseAddress += Length;\r
TempQword = Length - TempQword;\r
- MemoryType = MTRR_CACHE_UNCACHEABLE;\r
- }\r
-\r
- do {\r
- //\r
- // Find unused MTRR\r
- //\r
- for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {\r
- if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
- break;\r
- }\r
- }\r
-\r
- Length = Power2MaxMemory (TempQword);\r
- if (!Positive) {\r
- BaseAddress -= Length;\r
- }\r
-\r
- ProgramVariableMtrr (\r
- MsrNum,\r
- BaseAddress,\r
- Length,\r
- MemoryType,\r
- MtrrValidAddressMask\r
- );\r
-\r
- if (Positive) {\r
- BaseAddress += Length;\r
- }\r
- TempQword -= Length;\r
-\r
- } while (TempQword > 0);\r
-\r
-Done:\r
- DEBUG((DEBUG_CACHE, " Status = %r\n", Status));\r
- if (!RETURN_ERROR (Status)) {\r
- MtrrDebugPrintAllMtrrs ();\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- This function will get the memory cache type of the specific address.\r
-\r
- This function is mainly for debug purpose.\r
-\r
- @param[in] Address The specific address\r
-\r
- @return Memory cache type of the specific address\r
-\r
-**/\r
-MTRR_MEMORY_CACHE_TYPE\r
-EFIAPI\r
-MtrrGetMemoryAttribute (\r
- IN PHYSICAL_ADDRESS Address\r
- )\r
-{\r
- UINT64 TempQword;\r
- UINTN Index;\r
- UINTN SubIndex;\r
- UINT64 MtrrType;\r
- UINT64 TempMtrrType;\r
- MTRR_MEMORY_CACHE_TYPE CacheType;\r
- VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
- UINT64 MtrrValidBitsMask;\r
- UINT64 MtrrValidAddressMask;\r
- UINTN VariableMtrrCount;\r
-\r
- if (!IsMtrrSupported ()) {\r
- return CacheUncacheable;\r
- }\r
-\r
- //\r
- // Check if MTRR is enabled, if not, return UC as attribute\r
- //\r
- TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE);\r
- MtrrType = MTRR_CACHE_INVALID_TYPE;\r
-\r
- if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
- return CacheUncacheable;\r
- }\r
-\r
- //\r
- // If address is less than 1M, then try to go through the fixed MTRR\r
- //\r
- if (Address < BASE_1MB) {\r
- if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) {\r
- //\r
- // Go through the fixed MTRR\r
- //\r
- for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
- if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress &&\r
- Address < (\r
- mMtrrLibFixedMtrrTable[Index].BaseAddress +\r
- (mMtrrLibFixedMtrrTable[Index].Length * 8)\r
- )\r
- ) {\r
- SubIndex =\r
- ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) /\r
- mMtrrLibFixedMtrrTable[Index].Length;\r
- TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);\r
- MtrrType = RShiftU64 (TempQword, SubIndex * 8) & 0xFF;\r
- return GetMemoryCacheTypeFromMtrrType (MtrrType);\r
- }\r
- }\r
- }\r
- }\r
- MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
- MtrrGetMemoryAttributeInVariableMtrr(\r
- MtrrValidBitsMask,\r
- MtrrValidAddressMask,\r
- VariableMtrr\r
- );\r
-\r
- //\r
- // Go through the variable MTRR\r
- //\r
- VariableMtrrCount = GetVariableMtrrCount ();\r
- ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
-\r
- for (Index = 0; Index < VariableMtrrCount; Index++) {\r
- if (VariableMtrr[Index].Valid) {\r
- if (Address >= VariableMtrr[Index].BaseAddress &&\r
- Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) {\r
- TempMtrrType = VariableMtrr[Index].Type;\r
- MtrrType = MtrrPrecedence (MtrrType, TempMtrrType);\r
- }\r
- }\r
- }\r
- CacheType = GetMemoryCacheTypeFromMtrrType (MtrrType);\r
-\r
- return CacheType;\r
-}\r
-\r
-\r
-/**\r
- Worker function will get the raw value in variable MTRRs\r
-\r
- @param[out] VariableSettings A buffer to hold variable MTRRs content.\r
-\r
- @return The VariableSettings input pointer\r
-\r
-**/\r
-MTRR_VARIABLE_SETTINGS*\r
-MtrrGetVariableMtrrWorker (\r
- OUT MTRR_VARIABLE_SETTINGS *VariableSettings\r
- )\r
-{\r
- UINT32 Index;\r
- UINT32 VariableMtrrCount;\r
-\r
- VariableMtrrCount = GetVariableMtrrCount ();\r
- ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
-\r
- for (Index = 0; Index < VariableMtrrCount; Index++) {\r
- VariableSettings->Mtrr[Index].Base =\r
- AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1));\r
- VariableSettings->Mtrr[Index].Mask =\r
- AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1);\r
+ MemoryType = MTRR_CACHE_UNCACHEABLE;\r
}\r
\r
- return VariableSettings;\r
-}\r
+ do {\r
+ //\r
+ // Find unused MTRR\r
+ //\r
+ for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {\r
+ if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+ break;\r
+ }\r
+ }\r
\r
-/**\r
- This function will get the raw value in variable MTRRs\r
+ Length = Power2MaxMemory (TempQword);\r
+ if (!Positive) {\r
+ BaseAddress -= Length;\r
+ }\r
\r
- @param[out] VariableSettings A buffer to hold variable MTRRs content.\r
+ ProgramVariableMtrr (\r
+ MsrNum,\r
+ BaseAddress,\r
+ Length,\r
+ MemoryType,\r
+ MtrrValidAddressMask\r
+ );\r
\r
- @return The VariableSettings input pointer\r
+ if (Positive) {\r
+ BaseAddress += Length;\r
+ }\r
+ TempQword -= Length;\r
\r
-**/\r
-MTRR_VARIABLE_SETTINGS*\r
-EFIAPI\r
-MtrrGetVariableMtrr (\r
- OUT MTRR_VARIABLE_SETTINGS *VariableSettings\r
- )\r
-{\r
- if (!IsMtrrSupported ()) {\r
- return VariableSettings;\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
- return MtrrGetVariableMtrrWorker (\r
- VariableSettings\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
+ }\r
\r
+ return Status;\r
+}\r
/**\r
Worker function setting variable MTRRs\r
\r
UINT32 Index;\r
UINT32 VariableMtrrCount;\r
\r
- VariableMtrrCount = GetVariableMtrrCount ();\r
+ VariableMtrrCount = GetVariableMtrrCountWorker ();\r
ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
\r
for (Index = 0; Index < VariableMtrrCount; Index++) {\r
return VariableSettings;\r
}\r
\r
-/**\r
- Worker function gets the content in fixed MTRRs\r
-\r
- @param[out] FixedSettings A buffer to hold fixed MTRRs content.\r
-\r
- @retval The pointer of FixedSettings\r
-\r
-**/\r
-MTRR_FIXED_SETTINGS*\r
-MtrrGetFixedMtrrWorker (\r
- OUT MTRR_FIXED_SETTINGS *FixedSettings\r
- )\r
-{\r
- UINT32 Index;\r
-\r
- for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
- FixedSettings->Mtrr[Index] =\r
- AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);\r
- }\r
-\r
- return FixedSettings;\r
-}\r
-\r
-\r
-/**\r
- This function gets the content in fixed MTRRs\r
-\r
- @param[out] FixedSettings A buffer to hold fixed MTRRs content.\r
-\r
- @retval The pointer of FixedSettings\r
-\r
-**/\r
-MTRR_FIXED_SETTINGS*\r
-EFIAPI\r
-MtrrGetFixedMtrr (\r
- OUT MTRR_FIXED_SETTINGS *FixedSettings\r
- )\r
-{\r
- if (!IsMtrrSupported ()) {\r
- return FixedSettings;\r
- }\r
-\r
- return MtrrGetFixedMtrrWorker (FixedSettings);\r
-}\r
-\r
/**\r
Worker function setting fixed MTRRs\r
\r
- @param[in] FixedSettings A buffer to hold fixed Mtrrs content.\r
+ @param[in] FixedSettings A buffer to hold fixed MTRRs content.\r
\r
**/\r
VOID\r
/**\r
This function sets fixed MTRRs\r
\r
- @param[in] FixedSettings A buffer to hold fixed Mtrrs content.\r
+ @param[in] FixedSettings A buffer to hold fixed MTRRs content.\r
\r
@retval The pointer of FixedSettings\r
\r
/**\r
This function gets the content in all MTRRs (variable and fixed)\r
\r
- @param[out] MtrrSetting A buffer to hold all Mtrrs content.\r
+ @param[out] MtrrSetting A buffer to hold all MTRRs content.\r
\r
@retval the pointer of MtrrSetting\r
\r
//\r
// Get fixed MTRRs\r
//\r
- MtrrGetFixedMtrr (&MtrrSetting->Fixed);\r
+ MtrrGetFixedMtrrWorker (&MtrrSetting->Fixed);\r
\r
//\r
// Get variable MTRRs\r
//\r
- MtrrGetVariableMtrr (&MtrrSetting->Variables);\r
+ MtrrGetVariableMtrrWorker (\r
+ GetVariableMtrrCountWorker (),\r
+ &MtrrSetting->Variables\r
+ );\r
\r
//\r
// Get MTRR_DEF_TYPE value\r
return MtrrSetting;\r
}\r
\r
-/**\r
- This function prints all MTRRs for debugging.\r
-**/\r
-VOID\r
-EFIAPI\r
-MtrrDebugPrintAllMtrrs (\r
- VOID\r
- )\r
-{\r
- DEBUG_CODE (\r
- MTRR_SETTINGS MtrrSettings;\r
- UINTN Index;\r
- UINTN Index1;\r
- UINTN VariableMtrrCount;\r
- UINT64 Base;\r
- UINT64 Limit;\r
- UINT64 MtrrBase;\r
- UINT64 MtrrLimit;\r
- UINT64 RangeBase;\r
- UINT64 RangeLimit;\r
- UINT64 NoRangeBase;\r
- UINT64 NoRangeLimit;\r
- UINT32 RegEax;\r
- UINTN MemoryType;\r
- UINTN PreviousMemoryType;\r
- BOOLEAN Found;\r
-\r
- if (!IsMtrrSupported ()) {\r
- return;\r
- }\r
-\r
- DEBUG((DEBUG_CACHE, "MTRR Settings\n"));\r
- DEBUG((DEBUG_CACHE, "=============\n"));\r
-\r
- MtrrGetAllMtrrs (&MtrrSettings);\r
- DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", MtrrSettings.MtrrDefType));\r
- for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
- DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, MtrrSettings.Fixed.Mtrr[Index]));\r
- }\r
-\r
- VariableMtrrCount = GetVariableMtrrCount ();\r
- for (Index = 0; Index < VariableMtrrCount; Index++) {\r
- DEBUG((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",\r
- Index,\r
- MtrrSettings.Variables.Mtrr[Index].Base,\r
- MtrrSettings.Variables.Mtrr[Index].Mask\r
- ));\r
- }\r
- DEBUG((DEBUG_CACHE, "\n"));\r
- DEBUG((DEBUG_CACHE, "MTRR Ranges\n"));\r
- DEBUG((DEBUG_CACHE, "====================================\n"));\r
-\r
- Base = 0;\r
- PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;\r
- for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
- Base = mMtrrLibFixedMtrrTable[Index].BaseAddress;\r
- for (Index1 = 0; Index1 < 8; Index1++) {\r
- MemoryType = (UINTN)(RShiftU64 (MtrrSettings.Fixed.Mtrr[Index], Index1 * 8) & 0xff);\r
- if (MemoryType > CacheWriteBack) {\r
- MemoryType = MTRR_CACHE_INVALID_TYPE;\r
- }\r
- if (MemoryType != PreviousMemoryType) {\r
- if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {\r
- DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
- }\r
- PreviousMemoryType = MemoryType;\r
- DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));\r
- }\r
- Base += mMtrrLibFixedMtrrTable[Index].Length;\r
- }\r
- }\r
- DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
-\r
- VariableMtrrCount = GetVariableMtrrCount ();\r
-\r
- Limit = BIT36 - 1;\r
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
- if (RegEax >= 0x80000008) {\r
- AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
- Limit = LShiftU64 (1, RegEax & 0xff) - 1;\r
- }\r
- Base = BASE_1MB;\r
- PreviousMemoryType = MTRR_CACHE_INVALID_TYPE;\r
- do {\r
- MemoryType = MtrrGetMemoryAttribute (Base);\r
- if (MemoryType > CacheWriteBack) {\r
- MemoryType = MTRR_CACHE_INVALID_TYPE;\r
- }\r
-\r
- if (MemoryType != PreviousMemoryType) {\r
- if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) {\r
- DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1));\r
- }\r
- PreviousMemoryType = MemoryType;\r
- DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base));\r
- }\r
-\r
- RangeBase = BASE_1MB;\r
- NoRangeBase = BASE_1MB;\r
- RangeLimit = Limit;\r
- NoRangeLimit = Limit;\r
-\r
- for (Index = 0, Found = FALSE; Index < VariableMtrrCount; Index++) {\r
- if ((MtrrSettings.Variables.Mtrr[Index].Mask & BIT11) == 0) {\r
- //\r
- // If mask is not valid, then do not display range\r
- //\r
- continue;\r
- }\r
- MtrrBase = (MtrrSettings.Variables.Mtrr[Index].Base & (~(SIZE_4KB - 1)));\r
- MtrrLimit = MtrrBase + ((~(MtrrSettings.Variables.Mtrr[Index].Mask & (~(SIZE_4KB - 1)))) & Limit);\r
-\r
- if (Base >= MtrrBase && Base < MtrrLimit) {\r
- Found = TRUE;\r
- }\r
-\r
- if (Base >= MtrrBase && MtrrBase > RangeBase) {\r
- RangeBase = MtrrBase;\r
- }\r
- if (Base > MtrrLimit && MtrrLimit > RangeBase) {\r
- RangeBase = MtrrLimit + 1;\r
- }\r
- if (Base < MtrrBase && MtrrBase < RangeLimit) {\r
- RangeLimit = MtrrBase - 1;\r
- }\r
- if (Base < MtrrLimit && MtrrLimit <= RangeLimit) {\r
- RangeLimit = MtrrLimit;\r
- }\r
-\r
- if (Base > MtrrLimit && NoRangeBase < MtrrLimit) {\r
- NoRangeBase = MtrrLimit + 1;\r
- }\r
- if (Base < MtrrBase && NoRangeLimit > MtrrBase) {\r
- NoRangeLimit = MtrrBase - 1;\r
- }\r
- }\r
-\r
- if (Found) {\r
- Base = RangeLimit + 1;\r
- } else {\r
- Base = NoRangeLimit + 1;\r
- }\r
- } while (Base < Limit);\r
- DEBUG((DEBUG_CACHE, "%016lx\n\n", Base - 1));\r
- );\r
-}\r
-\r
/**\r
Checks if MTRR is supported.\r
\r