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
+ 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
+ }\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
+ VariableSettings\r
+ );\r
+}\r
\r
/**\r
Programs fixed MTRRs registers.\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
\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
-\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
+ MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
+ MtrrGetMemoryAttributeInVariableMtrr(\r
+ MtrrValidBitsMask,\r
+ MtrrValidAddressMask,\r
+ VariableMtrr\r
+ );\r
\r
//\r
- // Since memory ranges below 1MB will be overridden by the fixed MTRRs,\r
- // we can set the base to 0 to save variable MTRRs.\r
+ // Go through the variable MTRR\r
//\r
- if (BaseAddress == BASE_1MB) {\r
- BaseAddress = 0;\r
- Length += SIZE_1MB;\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
- //\r
- // Check for overlap\r
- //\r
- UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);\r
- OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);\r
- if (OverLap) {\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
+\r
+ DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
+\r
+ if (!IsMtrrSupported ()) {\r
+ Status = RETURN_UNSUPPORTED;\r
+ goto Done;\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
+ //\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
+ 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
+ }\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
+ // Since memory ranges below 1MB will be overridden by the fixed MTRRs,\r
+ // we can set the base to 0 to save variable MTRRs.\r
+ //\r
+ if (BaseAddress == BASE_1MB) {\r
+ BaseAddress = 0;\r
+ Length += SIZE_1MB;\r
+ }\r
+\r
+ //\r
+ // Check for overlap\r
+ //\r
+ UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);\r
+ OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);\r
+ if (OverLap) {\r
Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr);\r
if (RETURN_ERROR (Status)) {\r
goto Done;\r
for (; MsrNum < VariableMtrrEnd; MsrNum += 2) {\r
if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
break;\r
- }\r
- }\r
-\r
- ProgramVariableMtrr (\r
- MsrNum,\r
- BaseAddress,\r
- Length,\r
- MemoryType,\r
- MtrrValidAddressMask\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
+ }\r
+ }\r
+\r
+ ProgramVariableMtrr (\r
+ MsrNum,\r
+ BaseAddress,\r
+ Length,\r
+ MemoryType,\r
+ MtrrValidAddressMask\r
+ );\r
+ BaseAddress += Length;\r
+ TempQword = Length - TempQword;\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
+ DEBUG((DEBUG_CACHE, " Status = %r\n", Status));\r
+ if (!RETURN_ERROR (Status)) {\r
+ MtrrDebugPrintAllMtrrs ();\r
}\r
\r
- return MtrrGetVariableMtrrWorker (\r
- VariableSettings\r
- );\r
+ return Status;\r
}\r
-\r
-\r
/**\r
Worker function setting variable MTRRs\r
\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
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