#define OR_SEED 0x0101010101010101ull\r
#define CLEAR_SEED 0xFFFFFFFFFFFFFFFFull\r
\r
+#define MTRR_LIB_ASSERT_ALIGNED(B, L) ASSERT ((B & ~(L - 1)) == B);\r
//\r
// Context to save and restore when MTRRs are programmed\r
//\r
BOOLEAN InterruptState;\r
} MTRR_CONTEXT;\r
\r
+typedef struct {\r
+ UINT64 BaseAddress;\r
+ UINT64 Length;\r
+ MTRR_MEMORY_CACHE_TYPE Type;\r
+} MEMORY_RANGE;\r
+\r
//\r
// This table defines the offset, base and length of the fixed MTRRs\r
//\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
+ Return the least alignment of address.\r
\r
- @retval TRUE Overlap exists.\r
- @retval FALSE No overlap.\r
+ @param Address The address to return the alignment.\r
+ @param Alignment0 The alignment to return when Address is 0.\r
\r
+ @return The least alignment of the Address.\r
**/\r
-BOOLEAN\r
-CheckMemoryAttributeOverlap (\r
- IN UINTN FirmwareVariableMtrrCount,\r
- IN PHYSICAL_ADDRESS Start,\r
- IN PHYSICAL_ADDRESS End,\r
- IN VARIABLE_MTRR *VariableMtrr\r
- )\r
+UINT64\r
+MtrrLibLeastAlignment (\r
+ UINT64 Address,\r
+ UINT64 Alignment0\r
+)\r
{\r
- UINT32 Index;\r
-\r
- for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
- if (\r
- VariableMtrr[Index].Valid &&\r
- !(\r
- (Start > (VariableMtrr[Index].BaseAddress +\r
- VariableMtrr[Index].Length - 1)\r
- ) ||\r
- (End < VariableMtrr[Index].BaseAddress)\r
- )\r
- ) {\r
- return TRUE;\r
- }\r
+ if (Address == 0) {\r
+ return Alignment0;\r
}\r
\r
- return FALSE;\r
-}\r
-\r
-\r
-/**\r
- Marks a variable MTRR as non-valid.\r
-\r
- @param[in] Index The index of the array VariableMtrr to be invalidated\r
- @param[in] VariableMtrr The array to shadow variable MTRRs content\r
- @param[out] UsedMtrr The number of MTRRs which has already been used\r
-\r
-**/\r
-VOID\r
-InvalidateShadowMtrr (\r
- IN UINTN Index,\r
- IN VARIABLE_MTRR *VariableMtrr,\r
- OUT UINT32 *UsedMtrr\r
- )\r
-{\r
- VariableMtrr[Index].Valid = FALSE;\r
- *UsedMtrr = *UsedMtrr - 1;\r
+ return LShiftU64 (1, (UINTN) LowBitSet64 (Address));\r
}\r
\r
-\r
/**\r
- Combines memory attributes.\r
+ Return the number of required variable MTRRs to positively cover the\r
+ specified range.\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
- @param[in] VariableMtrr The array to shadow variable MTRRs content\r
- @param[in, out] UsedMtrr The number of MTRRs which has already been used\r
- @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used\r
-\r
- @retval EFI_SUCCESS Memory region successfully combined.\r
- @retval EFI_ACCESS_DENIED Memory region cannot be combined.\r
+ @param BaseAddress Base address of the range.\r
+ @param Length Length of the range.\r
+ @param Alignment0 Alignment of 0.\r
\r
+ @return The number of the required variable MTRRs.\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
- IN VARIABLE_MTRR *VariableMtrr,\r
- IN OUT UINT32 *UsedMtrr,\r
- OUT BOOLEAN *OverwriteExistingMtrr\r
- )\r
+UINT32\r
+MtrrLibGetPositiveMtrrNumber (\r
+ IN UINT64 BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Alignment0\r
+)\r
{\r
- UINT32 Index;\r
- UINT64 CombineStart;\r
- UINT64 CombineEnd;\r
- UINT64 MtrrEnd;\r
- UINT64 EndAddress;\r
- BOOLEAN CoveredByExistingMtrr;\r
-\r
- *OverwriteExistingMtrr = FALSE;\r
- CoveredByExistingMtrr = FALSE;\r
- EndAddress = *Base +*Length - 1;\r
-\r
- for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
+ UINT64 SubLength;\r
+ UINT32 MtrrNumber;\r
+ BOOLEAN UseLeastAlignment;\r
\r
- MtrrEnd = VariableMtrr[Index].BaseAddress + VariableMtrr[Index].Length - 1;\r
- if (\r
- !VariableMtrr[Index].Valid ||\r
- (\r
- *Base > (MtrrEnd) ||\r
- (EndAddress < VariableMtrr[Index].BaseAddress)\r
- )\r
- ) {\r
- continue;\r
- }\r
+ UseLeastAlignment = TRUE;\r
\r
- //\r
- // Combine same attribute MTRR range\r
- //\r
- if (Attributes == VariableMtrr[Index].Type) {\r
- //\r
- // if the MTRR range contain the request range, set a flag, then continue to\r
- // invalidate any MTRR of the same request range with higher priority cache type.\r
- //\r
- if (VariableMtrr[Index].BaseAddress <= *Base && MtrrEnd >= EndAddress) {\r
- CoveredByExistingMtrr = TRUE;\r
- continue;\r
- }\r
- //\r
- // invalid this MTRR, and program the combine range\r
- //\r
- CombineStart =\r
- (*Base) < VariableMtrr[Index].BaseAddress ?\r
- (*Base) :\r
- VariableMtrr[Index].BaseAddress;\r
- CombineEnd = EndAddress > MtrrEnd ? EndAddress : MtrrEnd;\r
+ //\r
+ // Calculate the alignment of the base address.\r
+ //\r
+ for (MtrrNumber = 0; Length != 0; MtrrNumber++) {\r
+ if (UseLeastAlignment) {\r
+ SubLength = MtrrLibLeastAlignment (BaseAddress, Alignment0);\r
\r
- //\r
- // Record the MTRR usage status in VariableMtrr array.\r
- //\r
- InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);\r
- *Base = CombineStart;\r
- *Length = CombineEnd - CombineStart + 1;\r
- EndAddress = CombineEnd;\r
- *OverwriteExistingMtrr = TRUE;\r
- continue;\r
- } else {\r
- //\r
- // The cache type is different, but the range is covered by one MTRR\r
- //\r
- if (VariableMtrr[Index].BaseAddress == *Base && MtrrEnd == EndAddress) {\r
- InvalidateShadowMtrr (Index, VariableMtrr, UsedMtrr);\r
- continue;\r
+ if (SubLength > Length) {\r
+ //\r
+ // Set a flag when remaining length is too small\r
+ // so that MtrrLibLeastAlignment() is not called in following loops.\r
+ //\r
+ UseLeastAlignment = FALSE;\r
}\r
-\r
}\r
\r
- if ((Attributes== MTRR_CACHE_WRITE_THROUGH &&\r
- VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) ||\r
- (Attributes == MTRR_CACHE_WRITE_BACK &&\r
- VariableMtrr[Index].Type == MTRR_CACHE_WRITE_THROUGH) ||\r
- (Attributes == MTRR_CACHE_UNCACHEABLE) ||\r
- (VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE)\r
- ) {\r
- *OverwriteExistingMtrr = TRUE;\r
- continue;\r
+ if (!UseLeastAlignment) {\r
+ SubLength = GetPowerOfTwo64 (Length);\r
}\r
- //\r
- // Other type memory overlap is invalid\r
- //\r
- return RETURN_ACCESS_DENIED;\r
- }\r
\r
- if (CoveredByExistingMtrr) {\r
- *Length = 0;\r
+ BaseAddress += SubLength;\r
+ Length -= SubLength;\r
}\r
\r
- return RETURN_SUCCESS;\r
+ return MtrrNumber;\r
}\r
\r
-\r
/**\r
- Calculates the maximum value which is a power of 2, but less the MemoryLength.\r
+ Return whether the left MTRR type precedes the right MTRR type.\r
\r
- @param[in] MemoryLength The number to pass in.\r
+ The MTRR type precedence rules are:\r
+ 1. UC precedes any other type\r
+ 2. WT precedes WB\r
\r
- @return The maximum value which is align to power of 2 and less the MemoryLength\r
+ @param Left The left MTRR type.\r
+ @param Right The right MTRR type.\r
\r
+ @retval TRUE Left precedes Right.\r
+ @retval FALSE Left doesn't precede Right.\r
**/\r
-UINT64\r
-Power2MaxMemory (\r
- IN UINT64 MemoryLength\r
- )\r
+BOOLEAN\r
+MtrrLibTypeLeftPrecedeRight (\r
+ IN MTRR_MEMORY_CACHE_TYPE Left,\r
+ IN MTRR_MEMORY_CACHE_TYPE Right\r
+)\r
{\r
- UINT64 Result;\r
-\r
- if (RShiftU64 (MemoryLength, 32) != 0) {\r
- Result = LShiftU64 (\r
- (UINT64) GetPowerOfTwo32 (\r
- (UINT32) RShiftU64 (MemoryLength, 32)\r
- ),\r
- 32\r
- );\r
- } else {\r
- Result = (UINT64) GetPowerOfTwo32 ((UINT32) MemoryLength);\r
- }\r
-\r
- return Result;\r
+ return (BOOLEAN) (Left == CacheUncacheable || (Left == CacheWriteThrough && Right == CacheWriteBack));\r
}\r
\r
\r
/**\r
- Determines the MTRR numbers used to program a memory range.\r
+ Return whether the type of the specified range can precede the specified type.\r
+\r
+ @param Ranges Memory range array holding memory type settings for all\r
+ the memory address.\r
+ @param RangeCount Count of memory ranges.\r
+ @param Type Type to check precedence.\r
+ @param SubBase Base address of the specified range.\r
+ @param SubLength Length of the specified range.\r
+\r
+ @retval TRUE The type of the specified range can precede the Type.\r
+ @retval FALSE The type of the specified range cannot precede the Type.\r
+ So the subtraction is not applicable.\r
+**/\r
+BOOLEAN\r
+MtrrLibSubstractable (\r
+ IN CONST MEMORY_RANGE *Ranges,\r
+ IN UINT32 RangeCount,\r
+ IN MTRR_MEMORY_CACHE_TYPE Type,\r
+ IN UINT64 SubBase,\r
+ IN UINT64 SubLength\r
+)\r
+{\r
+ UINT32 Index;\r
+ UINT64 Length;\r
+ // WT > WB\r
+ // UC > *\r
+ for (Index = 0; Index < RangeCount; Index++) {\r
+ if (Ranges[Index].BaseAddress <= SubBase && SubBase < Ranges[Index].BaseAddress + Ranges[Index].Length) {\r
\r
- This function first checks the alignment of the base address.\r
- If the alignment of the base address <= Length, cover the memory range\r
- (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and\r
- Length -= alignment. Repeat the step until alignment > Length.\r
+ if (Ranges[Index].BaseAddress + Ranges[Index].Length >= SubBase + SubLength) {\r
+ return MtrrLibTypeLeftPrecedeRight (Ranges[Index].Type, Type);\r
\r
- Then this function determines which direction of programming the variable\r
- MTRRs for the remaining length will use fewer MTRRs.\r
+ } else {\r
+ if (!MtrrLibTypeLeftPrecedeRight (Ranges[Index].Type, Type)) {\r
+ return FALSE;\r
+ }\r
\r
- @param[in] BaseAddress Length of Memory to program MTRR\r
- @param[in] Length Length of Memory to program MTRR\r
- @param[in] MtrrNumber Pointer to the number of necessary MTRRs\r
+ Length = Ranges[Index].BaseAddress + Ranges[Index].Length - SubBase;\r
+ SubBase += Length;\r
+ SubLength -= Length;\r
+ }\r
+ }\r
+ }\r
\r
- @retval TRUE Positive direction is better.\r
- FALSE Negative direction is better.\r
+ ASSERT (FALSE);\r
+ return FALSE;\r
+}\r
\r
+/**\r
+ Return the number of required variable MTRRs to cover the specified range.\r
+\r
+ The routine considers subtraction in the both side of the range to find out\r
+ the most optimal solution (which uses the least MTRRs).\r
+\r
+ @param Ranges Array holding memory type settings of all memory\r
+ address.\r
+ @param RangeCount Count of memory ranges.\r
+ @param VariableMtrr Array holding allocated variable MTRRs.\r
+ @param VariableMtrrCount Count of allocated variable MTRRs.\r
+ @param BaseAddress Base address of the specified range.\r
+ @param Length Length of the specified range.\r
+ @param Type MTRR type of the specified range.\r
+ @param Alignment0 Alignment of 0.\r
+ @param SubLeft Return the count of left subtraction.\r
+ @param SubRight Return the count of right subtraction.\r
+\r
+ @return Number of required variable MTRRs.\r
**/\r
-BOOLEAN\r
-GetMtrrNumberAndDirection (\r
- IN UINT64 BaseAddress,\r
- IN UINT64 Length,\r
- IN UINTN *MtrrNumber\r
- )\r
+UINT32\r
+MtrrLibGetMtrrNumber (\r
+ IN CONST MEMORY_RANGE *Ranges,\r
+ IN UINT32 RangeCount,\r
+ IN CONST VARIABLE_MTRR *VariableMtrr,\r
+ IN UINT32 VariableMtrrCount,\r
+ IN UINT64 BaseAddress,\r
+ IN UINT64 Length,\r
+ IN MTRR_MEMORY_CACHE_TYPE Type,\r
+ IN UINT64 Alignment0,\r
+ OUT UINT32 *SubLeft, // subtractive from BaseAddress to get more aligned address, to save MTRR\r
+ OUT UINT32 *SubRight // subtractive from BaseAddress + Length, to save MTRR\r
+)\r
{\r
- UINT64 TempQword;\r
UINT64 Alignment;\r
- UINT32 Positive;\r
- UINT32 Subtractive;\r
+ UINT32 LeastLeftMtrrNumber;\r
+ UINT32 MiddleMtrrNumber;\r
+ UINT32 LeastRightMtrrNumber;\r
+ UINT32 CurrentMtrrNumber;\r
+ UINT32 SubtractiveCount;\r
+ UINT32 SubtractiveMtrrNumber;\r
+ UINT32 LeastSubtractiveMtrrNumber;\r
+ UINT64 SubtractiveBaseAddress;\r
+ UINT64 SubtractiveLength;\r
+ UINT64 BaseAlignment;\r
+ UINT32 Index;\r
\r
- *MtrrNumber = 0;\r
+ *SubLeft = 0;\r
+ *SubRight = 0;\r
+ LeastSubtractiveMtrrNumber = 0;\r
\r
+ //\r
+ // Get the optimal left subtraction solution.\r
+ //\r
if (BaseAddress != 0) {\r
- do {\r
+ //\r
+ // Get the MTRR number needed without left subtraction.\r
+ //\r
+ LeastLeftMtrrNumber = MtrrLibGetPositiveMtrrNumber (BaseAddress, Length, Alignment0);\r
+\r
+ //\r
+ // Left subtraction bit by bit, to find the optimal left subtraction solution.\r
+ //\r
+ for (SubtractiveMtrrNumber = 0, SubtractiveCount = 1; BaseAddress != 0; SubtractiveCount++) {\r
+ Alignment = MtrrLibLeastAlignment (BaseAddress, Alignment0);\r
+\r
//\r
- // Calculate the alignment of the base address.\r
+ // Check whether the memory type of [BaseAddress - Alignment, BaseAddress) can override Type.\r
+ // IA32 Manual defines the following override rules:\r
+ // WT > WB\r
+ // UC > * (any)\r
//\r
- Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));\r
-\r
- if (Alignment > Length) {\r
+ if (!MtrrLibSubstractable (Ranges, RangeCount, Type, BaseAddress - Alignment, Alignment)) {\r
break;\r
}\r
\r
- (*MtrrNumber)++;\r
- BaseAddress += Alignment;\r
- Length -= Alignment;\r
- } while (TRUE);\r
-\r
- if (Length == 0) {\r
- return TRUE;\r
- }\r
- }\r
-\r
- TempQword = Length;\r
- Positive = 0;\r
- Subtractive = 0;\r
+ for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+ if ((VariableMtrr[Index].BaseAddress == BaseAddress - Alignment) &&\r
+ (VariableMtrr[Index].Length == Alignment)) {\r
+ break;\r
+ }\r
+ }\r
+ if (Index == VariableMtrrCount) {\r
+ //\r
+ // Increment SubtractiveMtrrNumber when [BaseAddress - Alignment, BaseAddress) is not be planed as a MTRR\r
+ //\r
+ SubtractiveMtrrNumber++;\r
+ }\r
\r
- do {\r
- TempQword -= Power2MaxMemory (TempQword);\r
- Positive++;\r
- } while (TempQword != 0);\r
+ BaseAddress -= Alignment;\r
+ Length += Alignment;\r
\r
- TempQword = Power2MaxMemory (LShiftU64 (Length, 1)) - Length;\r
- Subtractive++;\r
- do {\r
- TempQword -= Power2MaxMemory (TempQword);\r
- Subtractive++;\r
- } while (TempQword != 0);\r
+ CurrentMtrrNumber = SubtractiveMtrrNumber + MtrrLibGetPositiveMtrrNumber (BaseAddress, Length, Alignment0);\r
+ if (CurrentMtrrNumber <= LeastLeftMtrrNumber) {\r
+ LeastLeftMtrrNumber = CurrentMtrrNumber;\r
+ LeastSubtractiveMtrrNumber = SubtractiveMtrrNumber;\r
+ *SubLeft = SubtractiveCount;\r
+ SubtractiveBaseAddress = BaseAddress;\r
+ SubtractiveLength = Length;\r
+ }\r
+ }\r
\r
- if (Positive <= Subtractive) {\r
- *MtrrNumber += Positive;\r
- return TRUE;\r
- } else {\r
- *MtrrNumber += Subtractive;\r
- return FALSE;\r
+ //\r
+ // If left subtraction is better, subtract BaseAddress to left, and enlarge Length\r
+ //\r
+ if (*SubLeft != 0) {\r
+ BaseAddress = SubtractiveBaseAddress;\r
+ Length = SubtractiveLength;\r
+ }\r
}\r
-}\r
-\r
-/**\r
- Invalid variable MTRRs according to the value in the shadow array.\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
\r
- for (Index = 0; Index < VariableMtrrCount; Index++) {\r
- if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) {\r
- VariableSettings->Mtrr[Index].Base = 0;\r
- VariableSettings->Mtrr[Index].Mask = 0;\r
- VariableMtrr[Index].Used = FALSE;\r
+ //\r
+ // Increment BaseAddress greedily until (BaseAddress + Alignment) exceeds (BaseAddress + Length)\r
+ //\r
+ MiddleMtrrNumber = 0;\r
+ while (Length != 0) {\r
+ BaseAlignment = MtrrLibLeastAlignment (BaseAddress, Alignment0);\r
+ if (BaseAlignment > Length) {\r
+ break;\r
}\r
+ BaseAddress += BaseAlignment;\r
+ Length -= BaseAlignment;\r
+ MiddleMtrrNumber++;\r
}\r
-}\r
\r
\r
-/**\r
- Programs variable MTRRs\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
- @param[in] MemoryCacheType Memory type to set.\r
- @param[in] MtrrValidAddressMask The valid address mask for MTRR\r
+ if (Length == 0) {\r
+ return LeastSubtractiveMtrrNumber + MiddleMtrrNumber;\r
+ }\r
\r
-**/\r
-VOID\r
-ProgramVariableMtrr (\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
\r
//\r
- // MTRR Physical Base\r
+ // Get the optimal right subtraction solution.\r
//\r
- TempQword = (BaseAddress & MtrrValidAddressMask) | MemoryCacheType;\r
- VariableSettings->Mtrr[MtrrNumber].Base = TempQword;\r
\r
//\r
- // MTRR Physical Mask\r
+ // Get the MTRR number needed without right subtraction.\r
//\r
- TempQword = ~(Length - 1);\r
- VariableSettings->Mtrr[MtrrNumber].Mask = (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED;\r
+ LeastRightMtrrNumber = MtrrLibGetPositiveMtrrNumber (BaseAddress, Length, Alignment0);\r
+\r
+ for (SubtractiveCount = 1; Length < BaseAlignment; SubtractiveCount++) {\r
+ Alignment = MtrrLibLeastAlignment (BaseAddress + Length, Alignment0);\r
+ if (!MtrrLibSubstractable (Ranges, RangeCount, Type, BaseAddress + Length, Alignment)) {\r
+ break;\r
+ }\r
+\r
+ Length += Alignment;\r
+\r
+ //\r
+ // SubtractiveCount = Number of MTRRs used for subtraction\r
+ //\r
+ CurrentMtrrNumber = SubtractiveCount + MtrrLibGetPositiveMtrrNumber (BaseAddress, Length, Alignment0);\r
+ if (CurrentMtrrNumber <= LeastRightMtrrNumber) {\r
+ LeastRightMtrrNumber = CurrentMtrrNumber;\r
+ *SubRight = SubtractiveCount;\r
+ SubtractiveLength = Length;\r
+ }\r
+ }\r
+\r
+ return LeastSubtractiveMtrrNumber + MiddleMtrrNumber + LeastRightMtrrNumber;\r
}\r
\r
\r
MtrrDebugPrintAllMtrrsWorker (NULL);\r
}\r
\r
+/**\r
+ Update the Ranges array to change the specified range identified by\r
+ BaseAddress and Length to Type.\r
+\r
+ @param Ranges Array holding memory type settings for all memory regions.\r
+ @param Capacity The maximum count of memory ranges the array can hold.\r
+ @param Count Return the new memory range count in the array.\r
+ @param BaseAddress The base address of the memory range to change type.\r
+ @param Length The length of the memory range to change type.\r
+ @param Type The new type of the specified memory range.\r
+\r
+ @retval RETURN_SUCCESS The type of the specified memory range is\r
+ changed successfully.\r
+ @retval RETURN_OUT_OF_RESOURCES The new type set causes the count of memory\r
+ range exceeds capacity.\r
+**/\r
+RETURN_STATUS\r
+MtrrLibSetMemoryType (\r
+ IN MEMORY_RANGE *Ranges,\r
+ IN UINT32 Capacity,\r
+ IN OUT UINT32 *Count,\r
+ IN UINT64 BaseAddress,\r
+ IN UINT64 Length,\r
+ IN MTRR_MEMORY_CACHE_TYPE Type\r
+ )\r
+{\r
+ UINT32 Index;\r
+ UINT64 Limit;\r
+ UINT64 LengthLeft;\r
+ UINT64 LengthRight;\r
+ UINT32 StartIndex;\r
+ UINT32 EndIndex;\r
+ UINT32 DeltaCount;\r
+\r
+ Limit = BaseAddress + Length;\r
+ StartIndex = *Count;\r
+ EndIndex = *Count;\r
+ for (Index = 0; Index < *Count; Index++) {\r
+ if ((StartIndex == *Count) &&\r
+ (Ranges[Index].BaseAddress <= BaseAddress) &&\r
+ (BaseAddress < Ranges[Index].BaseAddress + Ranges[Index].Length)) {\r
+ StartIndex = Index;\r
+ LengthLeft = BaseAddress - Ranges[Index].BaseAddress;\r
+ }\r
+\r
+ if ((EndIndex == *Count) &&\r
+ (Ranges[Index].BaseAddress < Limit) &&\r
+ (Limit <= Ranges[Index].BaseAddress + Ranges[Index].Length)) {\r
+ EndIndex = Index;\r
+ LengthRight = Ranges[Index].BaseAddress + Ranges[Index].Length - Limit;\r
+ break;\r
+ }\r
+ }\r
+\r
+ ASSERT (StartIndex != *Count && EndIndex != *Count);\r
+ if (StartIndex == EndIndex && Ranges[StartIndex].Type == Type) {\r
+ return RETURN_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // The type change may cause merging with previous range or next range.\r
+ // Update the StartIndex, EndIndex, BaseAddress, Length so that following\r
+ // logic doesn't need to consider merging.\r
+ //\r
+ if (StartIndex != 0) {\r
+ if (LengthLeft == 0 && Ranges[StartIndex - 1].Type == Type) {\r
+ StartIndex--;\r
+ Length += Ranges[StartIndex].Length;\r
+ BaseAddress -= Ranges[StartIndex].Length;\r
+ }\r
+ }\r
+ if (EndIndex != (*Count) - 1) {\r
+ if (LengthRight == 0 && Ranges[EndIndex + 1].Type == Type) {\r
+ EndIndex++;\r
+ Length += Ranges[EndIndex].Length;\r
+ }\r
+ }\r
+\r
+ //\r
+ // |- 0 -|- 1 -|- 2 -|- 3 -| StartIndex EndIndex DeltaCount Count (Count = 4)\r
+ // |++++++++++++++++++| 0 3 1=3-0-2 3\r
+ // |+++++++| 0 1 -1=1-0-2 5\r
+ // |+| 0 0 -2=0-0-2 6\r
+ // |+++| 0 0 -1=0-0-2+1 5\r
+ //\r
+ //\r
+ DeltaCount = EndIndex - StartIndex - 2;\r
+ if (LengthLeft == 0) {\r
+ DeltaCount++;\r
+ }\r
+ if (LengthRight == 0) {\r
+ DeltaCount++;\r
+ }\r
+ if (*Count - DeltaCount > Capacity) {\r
+ return RETURN_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Reserve (-DeltaCount) space\r
+ //\r
+ CopyMem (&Ranges[EndIndex + 1 - DeltaCount], &Ranges[EndIndex + 1], (*Count - EndIndex - 1) * sizeof (Ranges[0]));\r
+ *Count -= DeltaCount;\r
+\r
+ if (LengthLeft != 0) {\r
+ Ranges[StartIndex].Length = LengthLeft;\r
+ StartIndex++;\r
+ }\r
+ if (LengthRight != 0) {\r
+ Ranges[EndIndex - DeltaCount].BaseAddress = BaseAddress + Length;\r
+ Ranges[EndIndex - DeltaCount].Length = LengthRight;\r
+ Ranges[EndIndex - DeltaCount].Type = Ranges[EndIndex].Type;\r
+ }\r
+ Ranges[StartIndex].BaseAddress = BaseAddress;\r
+ Ranges[StartIndex].Length = Length;\r
+ Ranges[StartIndex].Type = Type;\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Allocate one or more variable MTRR to cover the range identified by\r
+ BaseAddress and Length.\r
+\r
+ @param Ranges Memory range array holding the memory type\r
+ settings for all memory address.\r
+ @param RangeCount Count of memory ranges.\r
+ @param VariableMtrr Variable MTRR array.\r
+ @param VariableMtrrCapacity Capacity of variable MTRR array.\r
+ @param VariableMtrrCount Count of variable MTRR.\r
+ @param BaseAddress Base address of the memory range.\r
+ @param Length Length of the memory range.\r
+ @param Type MTRR type of the memory range.\r
+ @param Alignment0 Alignment of 0.\r
+\r
+ @retval RETURN_SUCCESS Variable MTRRs are allocated successfully.\r
+ @retval RETURN_OUT_OF_RESOURCES Count of variable MTRRs exceeds capacity.\r
+**/\r
+RETURN_STATUS\r
+MtrrLibSetMemoryAttributeInVariableMtrr (\r
+ IN CONST MEMORY_RANGE *Ranges,\r
+ IN UINT32 RangeCount,\r
+ IN OUT VARIABLE_MTRR *VariableMtrr,\r
+ IN UINT32 VariableMtrrCapacity,\r
+ IN OUT UINT32 *VariableMtrrCount,\r
+ IN UINT64 BaseAddress,\r
+ IN UINT64 Length,\r
+ IN MTRR_MEMORY_CACHE_TYPE Type,\r
+ IN UINT64 Alignment0\r
+ );\r
+\r
+/**\r
+ Allocate one or more variable MTRR to cover the range identified by\r
+ BaseAddress and Length.\r
+\r
+ The routine recursively calls MtrrLibSetMemoryAttributeInVariableMtrr()\r
+ to allocate variable MTRRs when the range contains several sub-ranges\r
+ with different attributes.\r
+\r
+ @param Ranges Memory range array holding the memory type\r
+ settings for all memory address.\r
+ @param RangeCount Count of memory ranges.\r
+ @param VariableMtrr Variable MTRR array.\r
+ @param VariableMtrrCapacity Capacity of variable MTRR array.\r
+ @param VariableMtrrCount Count of variable MTRR.\r
+ @param BaseAddress Base address of the memory range.\r
+ @param Length Length of the memory range.\r
+ @param Type MTRR type of the range.\r
+ If it's CacheInvalid, the memory range may\r
+ contains several sub-ranges with different\r
+ attributes.\r
+ @param Alignment0 Alignment of 0.\r
+\r
+ @retval RETURN_SUCCESS Variable MTRRs are allocated successfully.\r
+ @retval RETURN_OUT_OF_RESOURCES Count of variable MTRRs exceeds capacity.\r
+**/\r
+RETURN_STATUS\r
+MtrrLibAddVariableMtrr (\r
+ IN CONST MEMORY_RANGE *Ranges,\r
+ IN UINT32 RangeCount,\r
+ IN OUT VARIABLE_MTRR *VariableMtrr,\r
+ IN UINT32 VariableMtrrCapacity,\r
+ IN OUT UINT32 *VariableMtrrCount,\r
+ IN PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN MTRR_MEMORY_CACHE_TYPE Type,\r
+ IN UINT64 Alignment0\r
+)\r
+{\r
+ RETURN_STATUS Status;\r
+ UINT32 Index;\r
+ UINT64 SubLength;\r
+\r
+ MTRR_LIB_ASSERT_ALIGNED (BaseAddress, Length);\r
+ if (Type == CacheInvalid) {\r
+ for (Index = 0; Index < RangeCount; Index++) {\r
+ if (Ranges[Index].BaseAddress <= BaseAddress && BaseAddress < Ranges[Index].BaseAddress + Ranges[Index].Length) {\r
+\r
+ //\r
+ // Because the Length may not be aligned to BaseAddress, below code calls\r
+ // MtrrLibSetMemoryAttributeInVariableMtrr() instead of itself.\r
+ // MtrrLibSetMemoryAttributeInVariableMtrr() splits the range to several\r
+ // aligned ranges.\r
+ //\r
+ if (Ranges[Index].BaseAddress + Ranges[Index].Length >= BaseAddress + Length) {\r
+ return MtrrLibSetMemoryAttributeInVariableMtrr (\r
+ Ranges, RangeCount, VariableMtrr, VariableMtrrCapacity, VariableMtrrCount,\r
+ BaseAddress, Length, Ranges[Index].Type, Alignment0\r
+ );\r
+ } else {\r
+ SubLength = Ranges[Index].BaseAddress + Ranges[Index].Length - BaseAddress;\r
+ Status = MtrrLibSetMemoryAttributeInVariableMtrr (\r
+ Ranges, RangeCount, VariableMtrr, VariableMtrrCapacity, VariableMtrrCount,\r
+ BaseAddress, SubLength, Ranges[Index].Type, Alignment0\r
+ );\r
+ if (RETURN_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ BaseAddress += SubLength;\r
+ Length -= SubLength;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Because memory ranges cover all the memory addresses, it's impossible to be here.\r
+ //\r
+ ASSERT (FALSE);\r
+ return RETURN_DEVICE_ERROR;\r
+ } else {\r
+ for (Index = 0; Index < *VariableMtrrCount; Index++) {\r
+ if (VariableMtrr[Index].BaseAddress == BaseAddress && VariableMtrr[Index].Length == Length) {\r
+ ASSERT (VariableMtrr[Index].Type == Type);\r
+ break;\r
+ }\r
+ }\r
+ if (Index == *VariableMtrrCount) {\r
+ if (*VariableMtrrCount == VariableMtrrCapacity) {\r
+ return RETURN_OUT_OF_RESOURCES;\r
+ }\r
+ VariableMtrr[Index].BaseAddress = BaseAddress;\r
+ VariableMtrr[Index].Length = Length;\r
+ VariableMtrr[Index].Type = Type;\r
+ VariableMtrr[Index].Valid = TRUE;\r
+ VariableMtrr[Index].Used = TRUE;\r
+ (*VariableMtrrCount)++;\r
+ }\r
+ return RETURN_SUCCESS;\r
+ }\r
+}\r
+\r
+/**\r
+ Allocate one or more variable MTRR to cover the range identified by\r
+ BaseAddress and Length.\r
+\r
+ @param Ranges Memory range array holding the memory type\r
+ settings for all memory address.\r
+ @param RangeCount Count of memory ranges.\r
+ @param VariableMtrr Variable MTRR array.\r
+ @param VariableMtrrCapacity Capacity of variable MTRR array.\r
+ @param VariableMtrrCount Count of variable MTRR.\r
+ @param BaseAddress Base address of the memory range.\r
+ @param Length Length of the memory range.\r
+ @param Type MTRR type of the memory range.\r
+ @param Alignment0 Alignment of 0.\r
+\r
+ @retval RETURN_SUCCESS Variable MTRRs are allocated successfully.\r
+ @retval RETURN_OUT_OF_RESOURCES Count of variable MTRRs exceeds capacity.\r
+**/\r
+RETURN_STATUS\r
+MtrrLibSetMemoryAttributeInVariableMtrr (\r
+ IN CONST MEMORY_RANGE *Ranges,\r
+ IN UINT32 RangeCount,\r
+ IN OUT VARIABLE_MTRR *VariableMtrr,\r
+ IN UINT32 VariableMtrrCapacity,\r
+ IN OUT UINT32 *VariableMtrrCount,\r
+ IN UINT64 BaseAddress,\r
+ IN UINT64 Length,\r
+ IN MTRR_MEMORY_CACHE_TYPE Type,\r
+ IN UINT64 Alignment0\r
+)\r
+{\r
+ UINT64 Alignment;\r
+ UINT32 MtrrNumber;\r
+ UINT32 SubtractiveLeft;\r
+ UINT32 SubtractiveRight;\r
+ BOOLEAN UseLeastAlignment;\r
+\r
+ MtrrNumber = MtrrLibGetMtrrNumber (Ranges, RangeCount, VariableMtrr, *VariableMtrrCount,\r
+ BaseAddress, Length, Type, Alignment0, &SubtractiveLeft, &SubtractiveRight);\r
+\r
+ if (MtrrNumber + *VariableMtrrCount > VariableMtrrCapacity) {\r
+ return RETURN_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ while (SubtractiveLeft-- != 0) {\r
+ Alignment = MtrrLibLeastAlignment (BaseAddress, Alignment0);\r
+ ASSERT (Alignment <= Length);\r
+\r
+ MtrrLibAddVariableMtrr (Ranges, RangeCount, VariableMtrr, VariableMtrrCapacity, VariableMtrrCount,\r
+ BaseAddress - Alignment, Alignment, CacheInvalid, Alignment0);\r
+ BaseAddress -= Alignment;\r
+ Length += Alignment;\r
+ }\r
+\r
+ while (Length != 0) {\r
+ Alignment = MtrrLibLeastAlignment (BaseAddress, Alignment0);\r
+ if (Alignment > Length) {\r
+ break;\r
+ }\r
+ MtrrLibAddVariableMtrr (NULL, 0, VariableMtrr, VariableMtrrCapacity, VariableMtrrCount,\r
+ BaseAddress, Alignment, Type, Alignment0);\r
+ BaseAddress += Alignment;\r
+ Length -= Alignment;\r
+ }\r
+\r
+ while (SubtractiveRight-- != 0) {\r
+ Alignment = MtrrLibLeastAlignment (BaseAddress + Length, Alignment0);\r
+ MtrrLibAddVariableMtrr (Ranges, RangeCount, VariableMtrr, VariableMtrrCapacity, VariableMtrrCount,\r
+ BaseAddress + Length, Alignment, CacheInvalid, Alignment0);\r
+ Length += Alignment;\r
+ }\r
+\r
+ UseLeastAlignment = TRUE;\r
+ while (Length != 0) {\r
+ if (UseLeastAlignment) {\r
+ Alignment = MtrrLibLeastAlignment (BaseAddress, Alignment0);\r
+ if (Alignment > Length) {\r
+ UseLeastAlignment = FALSE;\r
+ }\r
+ }\r
+\r
+ if (!UseLeastAlignment) {\r
+ Alignment = GetPowerOfTwo64 (Length);\r
+ }\r
+\r
+ MtrrLibAddVariableMtrr (NULL, 0, VariableMtrr, VariableMtrrCapacity, VariableMtrrCount,\r
+ BaseAddress, Alignment, Type, Alignment0);\r
+ BaseAddress += Alignment;\r
+ Length -= Alignment;\r
+ }\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Return an array of memory ranges holding memory type settings for all memory\r
+ address.\r
+\r
+ @param DefaultType The default memory type.\r
+ @param TotalLength The total length of the memory.\r
+ @param VariableMtrr The variable MTRR array.\r
+ @param VariableMtrrCount The count of variable MTRRs.\r
+ @param Ranges Return the memory range array holding memory type\r
+ settings for all memory address.\r
+ @param RangeCapacity The capacity of memory range array.\r
+ @param RangeCount Return the count of memory range.\r
+\r
+ @retval RETURN_SUCCESS The memory range array is returned successfully.\r
+ @retval RETURN_OUT_OF_RESOURCES The count of memory ranges exceeds capacity.\r
+**/\r
+RETURN_STATUS\r
+MtrrLibGetMemoryTypes (\r
+ IN MTRR_MEMORY_CACHE_TYPE DefaultType,\r
+ IN UINT64 TotalLength,\r
+ IN CONST VARIABLE_MTRR *VariableMtrr,\r
+ IN UINT32 VariableMtrrCount,\r
+ OUT MEMORY_RANGE *Ranges,\r
+ IN UINT32 RangeCapacity,\r
+ OUT UINT32 *RangeCount\r
+)\r
+{\r
+ RETURN_STATUS Status;\r
+ UINTN Index;\r
+\r
+ //\r
+ // WT > WB\r
+ // UC > *\r
+ // UC > * (except WB, UC) > WB\r
+ //\r
+\r
+ //\r
+ // 0. Set whole range as DefaultType\r
+ //\r
+ *RangeCount = 1;\r
+ Ranges[0].BaseAddress = 0;\r
+ Ranges[0].Length = TotalLength;\r
+ Ranges[0].Type = DefaultType;\r
+\r
+ //\r
+ // 1. Set WB\r
+ //\r
+ for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+ if (VariableMtrr[Index].Valid && VariableMtrr[Index].Type == CacheWriteBack) {\r
+ Status = MtrrLibSetMemoryType (\r
+ Ranges, RangeCapacity, RangeCount,\r
+ VariableMtrr[Index].BaseAddress, VariableMtrr[Index].Length, (MTRR_MEMORY_CACHE_TYPE) VariableMtrr[Index].Type\r
+ );\r
+ if (RETURN_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // 2. Set other types than WB or UC\r
+ //\r
+ for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+ if (VariableMtrr[Index].Valid && VariableMtrr[Index].Type != CacheWriteBack && VariableMtrr[Index].Type != CacheUncacheable) {\r
+ Status = MtrrLibSetMemoryType (\r
+ Ranges, RangeCapacity, RangeCount,\r
+ VariableMtrr[Index].BaseAddress, VariableMtrr[Index].Length, (MTRR_MEMORY_CACHE_TYPE) VariableMtrr[Index].Type\r
+ );\r
+ if (RETURN_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // 3. Set UC\r
+ //\r
+ for (Index = 0; Index < VariableMtrrCount; Index++) {\r
+ if (VariableMtrr[Index].Valid && VariableMtrr[Index].Type == CacheUncacheable) {\r
+ Status = MtrrLibSetMemoryType (\r
+ Ranges, RangeCapacity, RangeCount,\r
+ VariableMtrr[Index].BaseAddress, VariableMtrr[Index].Length, (MTRR_MEMORY_CACHE_TYPE) VariableMtrr[Index].Type\r
+ );\r
+ if (RETURN_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ }\r
+ return RETURN_SUCCESS;\r
+}\r
\r
/**\r
Worker function attempts to set the attributes for a memory range.\r
\r
- If MtrrSettings is not NULL, set the attributes into the input MTRR\r
+ If MtrrSetting is not NULL, set the attributes into the input MTRR\r
settings buffer.\r
- If MtrrSettings is NULL, set the attributes into MTRRs registers.\r
+ If MtrrSetting is NULL, set the attributes into MTRRs registers.\r
\r
@param[in, out] MtrrSetting A buffer holding all MTRRs content.\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
+ address of a memory range.\r
+ @param[in] Length The size in bytes of the memory range.\r
+ @param[in] Type The MTRR type to set for the memory range.\r
\r
@retval RETURN_SUCCESS The attributes were set for the memory\r
- region.\r
+ range.\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
+ @retval RETURN_UNSUPPORTED The MTRR type is not support for the\r
+ 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
IN OUT MTRR_SETTINGS *MtrrSetting,\r
IN PHYSICAL_ADDRESS BaseAddress,\r
IN UINT64 Length,\r
- IN MTRR_MEMORY_CACHE_TYPE Attribute\r
+ IN MTRR_MEMORY_CACHE_TYPE Type\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
+ UINT32 Index;\r
+ UINT32 WorkingIndex;\r
+ //\r
+ // N variable MTRRs can maximumly separate (2N + 1) Ranges, plus 1 range for [0, 1M).\r
+ //\r
+ MEMORY_RANGE Ranges[MTRR_NUMBER_OF_VARIABLE_MTRR * 2 + 2];\r
+ UINT32 RangeCount;\r
UINT64 MtrrValidBitsMask;\r
UINT64 MtrrValidAddressMask;\r
- BOOLEAN OverwriteExistingMtrr;\r
- UINT32 FirmwareVariableMtrrCount;\r
+ UINT64 Alignment0;\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
+\r
+ MTRR_MEMORY_CACHE_TYPE DefaultType;\r
+\r
+ UINT32 MsrIndex;\r
UINT64 ClearMask;\r
UINT64 OrMask;\r
UINT64 NewValue;\r
- MTRR_VARIABLE_SETTINGS *VariableSettings;\r
+ BOOLEAN FixedSettingsValid[MTRR_NUMBER_OF_FIXED_MTRR];\r
+ BOOLEAN FixedSettingsModified[MTRR_NUMBER_OF_FIXED_MTRR];\r
+ MTRR_FIXED_SETTINGS WorkingFixedSettings;\r
\r
- MtrrContextValid = FALSE;\r
- VariableMtrrCount = 0;\r
- ZeroMem (&WorkingFixedSettings, sizeof (WorkingFixedSettings));\r
- for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
- FixedSettingsValid[Index] = FALSE;\r
- FixedSettingsModified[Index] = FALSE;\r
- }\r
- ProgramVariableSettings = FALSE;\r
+ UINT32 FirmwareVariableMtrrCount;\r
+ MTRR_VARIABLE_SETTINGS *VariableSettings;\r
+ MTRR_VARIABLE_SETTINGS OriginalVariableSettings;\r
+ UINT32 OriginalVariableMtrrCount;\r
+ VARIABLE_MTRR OriginalVariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
+ UINT32 WorkingVariableMtrrCount;\r
+ VARIABLE_MTRR WorkingVariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
+ BOOLEAN VariableSettingModified[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
+ UINTN FreeVariableMtrrCount;\r
\r
- if (!IsMtrrSupported ()) {\r
- Status = RETURN_UNSUPPORTED;\r
- goto Done;\r
+ if (Length == 0) {\r
+ return RETURN_INVALID_PARAMETER;\r
}\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
+ if (((BaseAddress & ~MtrrValidAddressMask) != 0) || (Length & ~MtrrValidAddressMask) != 0) {\r
+ return RETURN_UNSUPPORTED;\r
}\r
\r
- if (\r
- (BaseAddress & ~MtrrValidAddressMask) != 0 ||\r
- (Length & ~MtrrValidAddressMask) != 0\r
- ) {\r
- Status = RETURN_UNSUPPORTED;\r
- goto Done;\r
+ ZeroMem (&WorkingFixedSettings, sizeof (WorkingFixedSettings));\r
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+ FixedSettingsValid[Index] = FALSE;\r
+ FixedSettingsModified[Index] = FALSE;\r
}\r
\r
//\r
// Check if Fixed MTRR\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 = MtrrLibProgramFixedMtrr (Attribute, &BaseAddress, &Length, &MsrNum, &ClearMask, &OrMask);\r
+ MsrIndex = (UINT32)-1;\r
+ while ((BaseAddress < BASE_1MB) && (Length != 0)) {\r
+ Status = MtrrLibProgramFixedMtrr (Type, &BaseAddress, &Length, &MsrIndex, &ClearMask, &OrMask);\r
if (RETURN_ERROR (Status)) {\r
- goto Done;\r
+ return Status;\r
}\r
if (MtrrSetting != NULL) {\r
- MtrrSetting->Fixed.Mtrr[MsrNum] = (MtrrSetting->Fixed.Mtrr[MsrNum] & ~ClearMask) | OrMask;\r
- MtrrSetting->MtrrDefType |= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED;\r
+ MtrrSetting->Fixed.Mtrr[MsrIndex] = (MtrrSetting->Fixed.Mtrr[MsrIndex] & ~ClearMask) | OrMask;\r
+ ((MSR_IA32_MTRR_DEF_TYPE_REGISTER *) &MtrrSetting->MtrrDefType)->Bits.FE = 1;\r
} else {\r
- if (!FixedSettingsValid[MsrNum]) {\r
- WorkingFixedSettings.Mtrr[MsrNum] = AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr);\r
- FixedSettingsValid[MsrNum] = TRUE;\r
+ if (!FixedSettingsValid[MsrIndex]) {\r
+ WorkingFixedSettings.Mtrr[MsrIndex] = AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrIndex].Msr);\r
+ FixedSettingsValid[MsrIndex] = 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
+ NewValue = (WorkingFixedSettings.Mtrr[MsrIndex] & ~ClearMask) | OrMask;\r
+ if (WorkingFixedSettings.Mtrr[MsrIndex] != NewValue) {\r
+ WorkingFixedSettings.Mtrr[MsrIndex] = NewValue;\r
+ FixedSettingsModified[MsrIndex] = TRUE;\r
}\r
}\r
}\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
+ // Read the default MTRR type\r
//\r
- if (BaseAddress == BASE_1MB) {\r
- BaseAddress = 0;\r
- Length += SIZE_1MB;\r
- }\r
+ DefaultType = MtrrGetDefaultMemoryTypeWorker (MtrrSetting);\r
\r
//\r
- // Read all variable MTRRs\r
+ // Read all variable MTRRs and convert to Ranges.\r
//\r
- VariableMtrrCount = GetVariableMtrrCountWorker ();\r
- FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();\r
- if (MtrrSetting != NULL) {\r
- VariableSettings = &MtrrSetting->Variables;\r
+ OriginalVariableMtrrCount = GetVariableMtrrCountWorker ();\r
+ if (MtrrSetting == NULL) {\r
+ ZeroMem (&OriginalVariableSettings, sizeof (OriginalVariableSettings));\r
+ MtrrGetVariableMtrrWorker (NULL, OriginalVariableMtrrCount, &OriginalVariableSettings);\r
+ VariableSettings = &OriginalVariableSettings;\r
} else {\r
- MtrrGetVariableMtrrWorker (NULL, VariableMtrrCount, &OriginalVariableSettings);\r
- CopyMem (&WorkingVariableSettings, &OriginalVariableSettings, sizeof (WorkingVariableSettings));\r
- ProgramVariableSettings = TRUE;\r
- VariableSettings = &WorkingVariableSettings;\r
- }\r
-\r
- //\r
- // Check for overlap\r
- //\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
- if (OverLap) {\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
- if (Length == 0) {\r
- //\r
- // Combined successfully, invalidate the now-unused MTRRs\r
- //\r
- InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
- Status = RETURN_SUCCESS;\r
- goto Done;\r
- }\r
+ VariableSettings = &MtrrSetting->Variables;\r
}\r
+ MtrrGetMemoryAttributeInVariableMtrrWorker (VariableSettings, OriginalVariableMtrrCount, MtrrValidBitsMask, MtrrValidAddressMask, OriginalVariableMtrr);\r
+\r
+ Status = MtrrLibGetMemoryTypes (\r
+ DefaultType, MtrrValidBitsMask + 1, OriginalVariableMtrr, OriginalVariableMtrrCount,\r
+ Ranges, 2 * OriginalVariableMtrrCount + 1, &RangeCount\r
+ );\r
+ ASSERT (Status == RETURN_SUCCESS);\r
+\r
+ FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();\r
+ ASSERT (RangeCount <= 2 * FirmwareVariableMtrrCount + 1);\r
\r
//\r
- // The memory type is the same with the type specified by\r
- // MTRR_LIB_IA32_MTRR_DEF_TYPE.\r
+ // Force [0, 1M) to UC, so that it doesn't impact left subtraction algorithm.\r
//\r
- if ((!OverwriteExistingMtrr) && (Attribute == MtrrGetDefaultMemoryTypeWorker (MtrrSetting))) {\r
- //\r
- // Invalidate the now-unused MTRRs\r
- //\r
- InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
- goto Done;\r
+ Status = MtrrLibSetMemoryType (Ranges, 2 * FirmwareVariableMtrrCount + 2, &RangeCount, 0, SIZE_1MB, CacheUncacheable);\r
+ ASSERT (Status == RETURN_SUCCESS);\r
+ //\r
+ // Apply Type to [BaseAddress, BaseAddress + Length)\r
+ //\r
+ Status = MtrrLibSetMemoryType (Ranges, 2 * FirmwareVariableMtrrCount + 2, &RangeCount, BaseAddress, Length, Type);\r
+ if (RETURN_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
- Positive = GetMtrrNumberAndDirection (BaseAddress, Length, &MtrrNumber);\r
-\r
- if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) {\r
- Status = RETURN_OUT_OF_RESOURCES;\r
- goto Done;\r
+ Alignment0 = LShiftU64 (1, (UINTN) HighBitSet64 (MtrrValidBitsMask));\r
+ WorkingVariableMtrrCount = 0;\r
+ ZeroMem (&WorkingVariableMtrr, sizeof (WorkingVariableMtrr));\r
+ for (Index = 0; Index < RangeCount; Index++) {\r
+ if (Ranges[Index].Type != DefaultType) {\r
+ //\r
+ // Maximum allowed MTRR count is (FirmwareVariableMtrrCount + 1)\r
+ // Because potentially the range [0, 1MB) is not merged, but can be ignored because fixed MTRR covers that\r
+ //\r
+ Status = MtrrLibSetMemoryAttributeInVariableMtrr (\r
+ Ranges, RangeCount,\r
+ WorkingVariableMtrr, FirmwareVariableMtrrCount + 1, &WorkingVariableMtrrCount,\r
+ Ranges[Index].BaseAddress, Ranges[Index].Length,\r
+ Ranges[Index].Type, Alignment0\r
+ );\r
+ if (RETURN_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
}\r
\r
//\r
- // Invalidate the now-unused MTRRs\r
+ // Remove the [0, 1MB) MTRR if it still exists (not merged with other range)\r
//\r
- InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr);\r
+ if (WorkingVariableMtrr[0].BaseAddress == 0 && WorkingVariableMtrr[0].Length == SIZE_1MB) {\r
+ ASSERT (WorkingVariableMtrr[0].Type == CacheUncacheable);\r
+ WorkingVariableMtrrCount--;\r
+ CopyMem (&WorkingVariableMtrr[0], &WorkingVariableMtrr[1], WorkingVariableMtrrCount * sizeof (VARIABLE_MTRR));\r
+ }\r
\r
- //\r
- // Find first unused MTRR\r
- //\r
- for (MsrNum = 0; MsrNum < VariableMtrrCount; MsrNum++) {\r
- if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
- break;\r
- }\r
+ if (WorkingVariableMtrrCount > FirmwareVariableMtrrCount) {\r
+ return RETURN_OUT_OF_RESOURCES;\r
}\r
\r
- if (BaseAddress != 0) {\r
- do {\r
- //\r
- // Calculate the alignment of the base address.\r
- //\r
- Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress));\r
+ for (Index = 0; Index < OriginalVariableMtrrCount; Index++) {\r
+ VariableSettingModified[Index] = FALSE;\r
\r
- if (Alignment > Length) {\r
+ if (!OriginalVariableMtrr[Index].Valid) {\r
+ continue;\r
+ }\r
+ for (WorkingIndex = 0; WorkingIndex < WorkingVariableMtrrCount; WorkingIndex++) {\r
+ if (OriginalVariableMtrr[Index].BaseAddress == WorkingVariableMtrr[WorkingIndex].BaseAddress &&\r
+ OriginalVariableMtrr[Index].Length == WorkingVariableMtrr[WorkingIndex].Length &&\r
+ OriginalVariableMtrr[Index].Type == WorkingVariableMtrr[WorkingIndex].Type) {\r
break;\r
}\r
+ }\r
\r
+ if (WorkingIndex == WorkingVariableMtrrCount) {\r
//\r
- // Find unused MTRR\r
+ // Remove the one from OriginalVariableMtrr which is not in WorkingVariableMtrr\r
//\r
- for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
- if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
+ OriginalVariableMtrr[Index].Valid = FALSE;\r
+ VariableSettingModified[Index] = TRUE;\r
+ } else {\r
+ //\r
+ // Remove the one from WorkingVariableMtrr which is also in OriginalVariableMtrr\r
+ //\r
+ WorkingVariableMtrr[WorkingIndex].Valid = FALSE;\r
+ }\r
+ //\r
+ // The above two operations cause that valid MTRR only exists in either OriginalVariableMtrr or WorkingVariableMtrr.\r
+ //\r
+ }\r
+\r
+ //\r
+ // Merge remaining MTRRs from WorkingVariableMtrr to OriginalVariableMtrr\r
+ //\r
+ for (FreeVariableMtrrCount = 0, WorkingIndex = 0, Index = 0; Index < OriginalVariableMtrrCount; Index++) {\r
+ if (!OriginalVariableMtrr[Index].Valid) {\r
+ for (; WorkingIndex < WorkingVariableMtrrCount; WorkingIndex++) {\r
+ if (WorkingVariableMtrr[WorkingIndex].Valid) {\r
break;\r
}\r
}\r
-\r
- ProgramVariableMtrr (\r
- VariableSettings,\r
- MsrNum,\r
- BaseAddress,\r
- Alignment,\r
- MemoryType,\r
- MtrrValidAddressMask\r
- );\r
- BaseAddress += Alignment;\r
- Length -= Alignment;\r
- } while (TRUE);\r
-\r
- if (Length == 0) {\r
- goto Done;\r
+ if (WorkingIndex == WorkingVariableMtrrCount) {\r
+ FreeVariableMtrrCount++;\r
+ } else {\r
+ CopyMem (&OriginalVariableMtrr[Index], &WorkingVariableMtrr[WorkingIndex], sizeof (VARIABLE_MTRR));\r
+ VariableSettingModified[Index] = TRUE;\r
+ WorkingIndex++;\r
+ }\r
}\r
}\r
+ ASSERT (OriginalVariableMtrrCount - FreeVariableMtrrCount <= FirmwareVariableMtrrCount);\r
\r
- TempQword = Length;\r
-\r
- if (!Positive) {\r
- Length = Power2MaxMemory (LShiftU64 (TempQword, 1));\r
+ //\r
+ // Move MTRRs after the FirmwraeVariableMtrrCount position to beginning\r
+ //\r
+ WorkingIndex = FirmwareVariableMtrrCount;\r
+ for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
+ if (!OriginalVariableMtrr[Index].Valid) {\r
+ //\r
+ // Found an empty MTRR in WorkingIndex position\r
+ //\r
+ for (; WorkingIndex < OriginalVariableMtrrCount; WorkingIndex++) {\r
+ if (OriginalVariableMtrr[WorkingIndex].Valid) {\r
+ break;\r
+ }\r
+ }\r
\r
- //\r
- // Find unused MTRR\r
- //\r
- for (; MsrNum < VariableMtrrCount; MsrNum++) {\r
- if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
- break;\r
+ if (WorkingIndex != OriginalVariableMtrrCount) {\r
+ CopyMem (&OriginalVariableMtrr[Index], &OriginalVariableMtrr[WorkingIndex], sizeof (VARIABLE_MTRR));\r
+ VariableSettingModified[Index] = TRUE;\r
+ VariableSettingModified[WorkingIndex] = TRUE;\r
+ OriginalVariableMtrr[WorkingIndex].Valid = FALSE;\r
}\r
}\r
-\r
- ProgramVariableMtrr (\r
- VariableSettings,\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 < VariableMtrrCount; MsrNum++) {\r
- if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) {\r
- break;\r
+ //\r
+ // Convert OriginalVariableMtrr to VariableSettings\r
+ // NOTE: MTRR from FirmwareVariableMtrr to OriginalVariableMtrr need to update as well.\r
+ //\r
+ for (Index = 0; Index < OriginalVariableMtrrCount; Index++) {\r
+ if (VariableSettingModified[Index]) {\r
+ if (OriginalVariableMtrr[Index].Valid) {\r
+ VariableSettings->Mtrr[Index].Base = (OriginalVariableMtrr[Index].BaseAddress & MtrrValidAddressMask) | (UINT8) OriginalVariableMtrr[Index].Type;\r
+ VariableSettings->Mtrr[Index].Mask = (~(OriginalVariableMtrr[Index].Length - 1)) & MtrrValidAddressMask | BIT11;\r
+ } else {\r
+ VariableSettings->Mtrr[Index].Base = 0;\r
+ VariableSettings->Mtrr[Index].Mask = 0;\r
}\r
}\r
-\r
- Length = Power2MaxMemory (TempQword);\r
- if (!Positive) {\r
- BaseAddress -= Length;\r
- }\r
-\r
- ProgramVariableMtrr (\r
- VariableSettings,\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
\r
Done:\r
+ if (MtrrSetting != NULL) {\r
+ ((MSR_IA32_MTRR_DEF_TYPE_REGISTER *) &MtrrSetting->MtrrDefType)->Bits.E = 1;\r
+ return RETURN_SUCCESS;\r
+ }\r
\r
+ MtrrContextValid = FALSE;\r
//\r
// Write fixed MTRRs that have been modified\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
- MtrrLibPreMtrrChange (&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
+ for (Index = 0; Index < OriginalVariableMtrrCount; Index++) {\r
+ if (VariableSettingModified[Index]) {\r
+ if (!MtrrContextValid) {\r
+ MtrrLibPreMtrrChange (&MtrrContext);\r
+ MtrrContextValid = TRUE;\r
}\r
+ AsmWriteMsr64 (\r
+ MSR_IA32_MTRR_PHYSBASE0 + (Index << 1),\r
+ VariableSettings->Mtrr[Index].Base\r
+ );\r
+ AsmWriteMsr64 (\r
+ MSR_IA32_MTRR_PHYSMASK0 + (Index << 1),\r
+ VariableSettings->Mtrr[Index].Mask\r
+ );\r
}\r
}\r
if (MtrrContextValid) {\r
MtrrLibPostMtrrChange (&MtrrContext);\r
}\r
\r
- DEBUG((DEBUG_CACHE, " Status = %r\n", Status));\r
- if (!RETURN_ERROR (Status)) {\r
- if (MtrrSetting != NULL) {\r
- MtrrSetting->MtrrDefType |= MTRR_LIB_CACHE_MTRR_ENABLED;\r
- }\r
- MtrrDebugPrintAllMtrrsWorker (MtrrSetting);\r
- }\r
-\r
return Status;\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
+ address of a memory range.\r
+ @param[in] Length The size in bytes of the memory range.\r
@param[in] Attributes The bit mask of attributes to set for the\r
- memory region.\r
+ memory range.\r
\r
@retval RETURN_SUCCESS The attributes were set for the memory\r
- region.\r
+ range.\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
IN MTRR_MEMORY_CACHE_TYPE Attribute\r
)\r
{\r
- DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
- return MtrrSetMemoryAttributeWorker (\r
- NULL,\r
- BaseAddress,\r
- Length,\r
- Attribute\r
- );\r
+ RETURN_STATUS Status;\r
+\r
+ if (!IsMtrrSupported ()) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ Status = MtrrSetMemoryAttributeWorker (NULL, BaseAddress, Length, Attribute);\r
+ DEBUG ((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a: [%016lx, %016lx) - %r\n",\r
+ mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, BaseAddress + Length, Status));\r
+\r
+ if (!RETURN_ERROR (Status)) {\r
+ MtrrDebugPrintAllMtrrsWorker (NULL);\r
+ }\r
+ return Status;\r
}\r
\r
/**\r
\r
@param[in, out] MtrrSetting MTRR setting buffer to be set.\r
@param[in] BaseAddress The physical address that is the start address\r
- of a memory region.\r
- @param[in] Length The size in bytes of the memory region.\r
+ of a memory range.\r
+ @param[in] Length The size in bytes of the memory range.\r
@param[in] Attribute The bit mask of attributes to set for the\r
- memory region.\r
+ memory range.\r
\r
- @retval RETURN_SUCCESS The attributes were set for the memory region.\r
+ @retval RETURN_SUCCESS The attributes were set for the memory range.\r
@retval RETURN_INVALID_PARAMETER Length is zero.\r
@retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the\r
memory resource range specified by BaseAddress and Length.\r
IN MTRR_MEMORY_CACHE_TYPE Attribute\r
)\r
{\r
- DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting, mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
- return MtrrSetMemoryAttributeWorker (\r
- MtrrSetting,\r
- BaseAddress,\r
- Length,\r
- Attribute\r
- );\r
+ RETURN_STATUS Status;\r
+ Status = MtrrSetMemoryAttributeWorker (MtrrSetting, BaseAddress, Length, Attribute);\r
+ DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttributeMtrrSettings(%p) %a: [%016lx, %016lx) - %r\n",\r
+ MtrrSetting, mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, BaseAddress + Length, Status));\r
+\r
+ if (!RETURN_ERROR (Status)) {\r
+ MtrrDebugPrintAllMtrrsWorker (MtrrSetting);\r
+ }\r
+\r
+ return Status;\r
}\r
\r
/**\r
}\r
return TRUE;\r
}\r
+\r