/** @file\r
MTRR setting library\r
\r
- @par Note: \r
+ @par Note:\r
Most of services in this library instance are suggested to be invoked by BSP only,\r
except for MtrrSetAllMtrrs() which is used to sync BSP's MTRR setting to APs.\r
\r
- Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#define SCRATCH_BUFFER_SIZE (4 * SIZE_4KB)\r
#define MTRR_LIB_ASSERT_ALIGNED(B, L) ASSERT ((B & ~(L - 1)) == B);\r
\r
-#define M(x,y) ((x) * VectorCount + (y))\r
-#define O(x,y) ((y) * VectorCount + (x))\r
+#define M(x,y) ((x) * VertexCount + (y))\r
+#define O(x,y) ((y) * VertexCount + (x))\r
\r
//\r
// Context to save and restore when MTRRs are programmed\r
UINT64 Address;\r
UINT64 Alignment;\r
UINT64 Length;\r
- UINT8 Type : 7;\r
+ MTRR_MEMORY_CACHE_TYPE Type : 7;\r
\r
//\r
// Temprary use for calculating the best MTRR settings.\r
\r
for (Index = 0; Index < VariableMtrrCount; Index++) {\r
if (MtrrSetting == NULL) {\r
- VariableSettings->Mtrr[Index].Mask = AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1));\r
- //\r
- // Skip to read the Base MSR when the Mask.V is not set.\r
- //\r
- if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&VariableSettings->Mtrr[Index].Mask)->Bits.V != 0) {\r
- VariableSettings->Mtrr[Index].Base = AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1));\r
- }\r
+ VariableSettings->Mtrr[Index].Base =\r
+ AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1));\r
+ VariableSettings->Mtrr[Index].Mask =\r
+ AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1));\r
} else {\r
VariableSettings->Mtrr[Index].Base = MtrrSetting->Variables.Mtrr[Index].Base;\r
VariableSettings->Mtrr[Index].Mask = MtrrSetting->Variables.Mtrr[Index].Mask;\r
}\r
\r
/**\r
- Calculate the least MTRR number from vector Start to Stop and update\r
- the Previous of all vectors from Start to Stop is updated to reflect\r
+ Calculate the least MTRR number from vertex Start to Stop and update\r
+ the Previous of all vertices from Start to Stop is updated to reflect\r
how the memory range is covered by MTRR.\r
\r
- @param VectorCount The count of vectors in the graph.\r
- @param Vector Array holding all vectors.\r
- @param Weight 2-dimention array holding weights between vectors.\r
- @param Start Start vector.\r
- @param Stop Stop vector.\r
+ @param VertexCount The count of vertices in the graph.\r
+ @param Vertices Array holding all vertices.\r
+ @param Weight 2-dimention array holding weights between vertices.\r
+ @param Start Start vertex.\r
+ @param Stop Stop vertex.\r
@param IncludeOptional TRUE to count the optional weight.\r
**/\r
VOID\r
MtrrLibCalculateLeastMtrrs (\r
- IN UINT16 VectorCount,\r
- IN MTRR_LIB_ADDRESS *Vector,\r
+ IN UINT16 VertexCount,\r
+ IN MTRR_LIB_ADDRESS *Vertices,\r
IN OUT CONST UINT8 *Weight,\r
IN UINT16 Start,\r
IN UINT16 Stop,\r
UINT8 Optional;\r
\r
for (Index = Start; Index <= Stop; Index++) {\r
- Vector[Index].Visited = FALSE;\r
- Vector[Index].Previous = VectorCount;\r
+ Vertices[Index].Visited = FALSE;\r
Mandatory = Weight[M(Start,Index)];\r
- Vector[Index].Weight = Mandatory;\r
+ Vertices[Index].Weight = Mandatory;\r
if (Mandatory != MAX_WEIGHT) {\r
Optional = IncludeOptional ? Weight[O(Start, Index)] : 0;\r
- Vector[Index].Weight += Optional;\r
- ASSERT (Vector[Index].Weight >= Optional);\r
+ Vertices[Index].Weight += Optional;\r
+ ASSERT (Vertices[Index].Weight >= Optional);\r
}\r
}\r
\r
MinI = Start;\r
MinWeight = 0;\r
- while (!Vector[Stop].Visited) {\r
+ while (!Vertices[Stop].Visited) {\r
//\r
- // Update the weight from the shortest vector to other unvisited vectors\r
+ // Update the weight from the shortest vertex to other unvisited vertices\r
//\r
for (Index = Start + 1; Index <= Stop; Index++) {\r
- if (!Vector[Index].Visited) {\r
+ if (!Vertices[Index].Visited) {\r
Mandatory = Weight[M(MinI, Index)];\r
if (Mandatory != MAX_WEIGHT) {\r
Optional = IncludeOptional ? Weight[O(MinI, Index)] : 0;\r
- if (MinWeight + Mandatory + Optional <= Vector[Index].Weight) {\r
- Vector[Index].Weight = MinWeight + Mandatory + Optional;\r
- Vector[Index].Previous = MinI; // Previous is Start based.\r
+ if (MinWeight + Mandatory + Optional <= Vertices[Index].Weight) {\r
+ Vertices[Index].Weight = MinWeight + Mandatory + Optional;\r
+ Vertices[Index].Previous = MinI; // Previous is Start based.\r
}\r
}\r
}\r
}\r
\r
//\r
- // Find the shortest vector from Start\r
+ // Find the shortest vertex from Start\r
//\r
- MinI = VectorCount;\r
+ MinI = VertexCount;\r
MinWeight = MAX_WEIGHT;\r
for (Index = Start + 1; Index <= Stop; Index++) {\r
- if (!Vector[Index].Visited && MinWeight > Vector[Index].Weight) {\r
+ if (!Vertices[Index].Visited && MinWeight > Vertices[Index].Weight) {\r
MinI = Index;\r
- MinWeight = Vector[Index].Weight;\r
+ MinWeight = Vertices[Index].Weight;\r
}\r
}\r
\r
//\r
- // Mark the shortest vector from Start as visited\r
+ // Mark the shortest vertex from Start as visited\r
//\r
- Vector[MinI].Visited = TRUE;\r
+ Vertices[MinI].Visited = TRUE;\r
}\r
}\r
\r
}\r
\r
/**\r
- Calculate the subtractive path from vector Start to Stop.\r
+ Calculate the subtractive path from vertex Start to Stop.\r
\r
@param DefaultType Default memory type.\r
@param A0 Alignment to use when base address is 0.\r
@param Ranges Array holding memory type settings for all memory regions.\r
@param RangeCount The count of memory ranges the array holds.\r
- @param VectorCount The count of vectors in the graph.\r
- @param Vector Array holding all vectors.\r
- @param Weight 2-dimention array holding weights between vectors.\r
- @param Start Start vector.\r
- @param Stop Stop vector.\r
+ @param VertexCount The count of vertices in the graph.\r
+ @param Vertices Array holding all vertices.\r
+ @param Weight 2-dimention array holding weights between vertices.\r
+ @param Start Start vertex.\r
+ @param Stop Stop vertex.\r
@param Types Type bit mask of memory range from Start to Stop.\r
@param TypeCount Number of different memory types from Start to Stop.\r
@param Mtrrs Array holding all MTRR settings.\r
IN UINT64 A0,\r
IN CONST MTRR_MEMORY_RANGE *Ranges,\r
IN UINTN RangeCount,\r
- IN UINT16 VectorCount,\r
- IN MTRR_LIB_ADDRESS *Vector,\r
+ IN UINT16 VertexCount,\r
+ IN MTRR_LIB_ADDRESS *Vertices,\r
IN OUT UINT8 *Weight,\r
IN UINT16 Start,\r
IN UINT16 Stop,\r
MTRR_MEMORY_CACHE_TYPE LowestType;\r
MTRR_MEMORY_CACHE_TYPE LowestPrecedentType;\r
\r
- Base = Vector[Start].Address;\r
- Length = Vector[Stop].Address - Base;\r
+ Base = Vertices[Start].Address;\r
+ Length = Vertices[Stop].Address - Base;\r
\r
LowestType = MtrrLibLowestType (Types);\r
\r
// We might use positive or subtractive, depending on which way uses less MTRR\r
//\r
for (SubStart = Start; SubStart <= Stop; SubStart++) {\r
- if (Vector[SubStart].Address == HBase) {\r
+ if (Vertices[SubStart].Address == HBase) {\r
break;\r
}\r
}\r
\r
for (SubStop = SubStart; SubStop <= Stop; SubStop++) {\r
- if (Vector[SubStop].Address == HBase + HLength) {\r
+ if (Vertices[SubStop].Address == HBase + HLength) {\r
break;\r
}\r
}\r
- ASSERT (Vector[SubStart].Address == HBase);\r
- ASSERT (Vector[SubStop].Address == HBase + HLength);\r
+ ASSERT (Vertices[SubStart].Address == HBase);\r
+ ASSERT (Vertices[SubStop].Address == HBase + HLength);\r
\r
if ((TypeCount == 2) || (SubStart == SubStop - 1)) {\r
//\r
while (SubStart != SubStop) {\r
Status = MtrrLibAppendVariableMtrr (\r
Mtrrs, MtrrCapacity, MtrrCount,\r
- Vector[SubStart].Address, Vector[SubStart].Length, (MTRR_MEMORY_CACHE_TYPE) Vector[SubStart].Type\r
+ Vertices[SubStart].Address, Vertices[SubStart].Length, Vertices[SubStart].Type\r
);\r
if (RETURN_ERROR (Status)) {\r
return Status;\r
}\r
} else {\r
ASSERT (TypeCount == 3);\r
- MtrrLibCalculateLeastMtrrs (VectorCount, Vector, Weight, SubStart, SubStop, TRUE);\r
+ MtrrLibCalculateLeastMtrrs (VertexCount, Vertices, Weight, SubStart, SubStop, TRUE);\r
\r
if (Mtrrs == NULL) {\r
- Weight[M (Start, Stop)] += Vector[SubStop].Weight;\r
+ Weight[M (Start, Stop)] += Vertices[SubStop].Weight;\r
} else {\r
// When we need to collect the optimal path from SubStart to SubStop\r
while (SubStop != SubStart) {\r
Cur = SubStop;\r
- Pre = Vector[Cur].Previous;\r
+ Pre = Vertices[Cur].Previous;\r
SubStop = Pre;\r
\r
- if (Weight[M (Pre, Cur)] != 0) {\r
+ if (Weight[M (Pre, Cur)] + Weight[O (Pre, Cur)] != 0) {\r
Status = MtrrLibAppendVariableMtrr (\r
Mtrrs, MtrrCapacity, MtrrCount,\r
- Vector[Pre].Address, Vector[Cur].Address - Vector[Pre].Address, LowestPrecedentType\r
+ Vertices[Pre].Address, Vertices[Cur].Address - Vertices[Pre].Address,\r
+ (Pre != Cur - 1) ? LowestPrecedentType : Vertices[Pre].Type\r
);\r
if (RETURN_ERROR (Status)) {\r
return Status;\r
Status = MtrrLibCalculateSubtractivePath (\r
DefaultType, A0,\r
Ranges, RangeCount,\r
- VectorCount, Vector, Weight,\r
+ VertexCount, Vertices, Weight,\r
Pre, Cur, PrecedentTypes, 2,\r
Mtrrs, MtrrCapacity, MtrrCount\r
);\r
UINT64 Length;\r
UINT64 Alignment;\r
UINT64 SubLength;\r
- MTRR_LIB_ADDRESS *Vector;\r
+ MTRR_LIB_ADDRESS *Vertices;\r
UINT8 *Weight;\r
- UINT32 VectorIndex;\r
- UINT32 VectorCount;\r
+ UINT32 VertexIndex;\r
+ UINT32 VertexCount;\r
UINTN RequiredScratchSize;\r
UINT8 TypeCount;\r
UINT16 Start;\r
MTRR_LIB_ASSERT_ALIGNED (Base0, Base1 - Base0);\r
\r
//\r
- // Count the number of vectors.\r
+ // Count the number of vertices.\r
//\r
- Vector = (MTRR_LIB_ADDRESS*)Scratch;\r
- for (VectorIndex = 0, Index = 0; Index < RangeCount; Index++) {\r
+ Vertices = (MTRR_LIB_ADDRESS*)Scratch;\r
+ for (VertexIndex = 0, Index = 0; Index < RangeCount; Index++) {\r
Base = Ranges[Index].BaseAddress;\r
Length = Ranges[Index].Length;\r
while (Length != 0) {\r
if (SubLength > Length) {\r
SubLength = GetPowerOfTwo64 (Length);\r
}\r
- if (VectorIndex < *ScratchSize / sizeof (*Vector)) {\r
- Vector[VectorIndex].Address = Base;\r
- Vector[VectorIndex].Alignment = Alignment;\r
- Vector[VectorIndex].Type = Ranges[Index].Type;\r
- Vector[VectorIndex].Length = SubLength;\r
+ if (VertexIndex < *ScratchSize / sizeof (*Vertices)) {\r
+ Vertices[VertexIndex].Address = Base;\r
+ Vertices[VertexIndex].Alignment = Alignment;\r
+ Vertices[VertexIndex].Type = Ranges[Index].Type;\r
+ Vertices[VertexIndex].Length = SubLength;\r
}\r
Base += SubLength;\r
Length -= SubLength;\r
- VectorIndex++;\r
+ VertexIndex++;\r
}\r
}\r
//\r
- // Vector[VectorIndex] = Base1, so whole vector count is (VectorIndex + 1).\r
+ // Vertices[VertexIndex] = Base1, so whole vertex count is (VertexIndex + 1).\r
//\r
- VectorCount = VectorIndex + 1;\r
+ VertexCount = VertexIndex + 1;\r
DEBUG ((\r
- DEBUG_CACHE, "VectorCount (%016lx - %016lx) = %d\n", \r
- Ranges[0].BaseAddress, Ranges[RangeCount - 1].BaseAddress + Ranges[RangeCount - 1].Length, VectorCount\r
+ DEBUG_CACHE, " Count of vertices (%016llx - %016llx) = %d\n",\r
+ Ranges[0].BaseAddress, Ranges[RangeCount - 1].BaseAddress + Ranges[RangeCount - 1].Length, VertexCount\r
));\r
- ASSERT (VectorCount < MAX_UINT16);\r
+ ASSERT (VertexCount < MAX_UINT16);\r
\r
- RequiredScratchSize = VectorCount * sizeof (*Vector) + VectorCount * VectorCount * sizeof (*Weight);\r
+ RequiredScratchSize = VertexCount * sizeof (*Vertices) + VertexCount * VertexCount * sizeof (*Weight);\r
if (*ScratchSize < RequiredScratchSize) {\r
*ScratchSize = RequiredScratchSize;\r
return RETURN_BUFFER_TOO_SMALL;\r
}\r
- Vector[VectorCount - 1].Address = Base1;\r
+ Vertices[VertexCount - 1].Address = Base1;\r
+\r
+ Weight = (UINT8 *) &Vertices[VertexCount];\r
+ for (VertexIndex = 0; VertexIndex < VertexCount; VertexIndex++) {\r
+ //\r
+ // Set optional weight between vertices and self->self to 0\r
+ //\r
+ SetMem (&Weight[M(VertexIndex, 0)], VertexIndex + 1, 0);\r
+ //\r
+ // Set mandatory weight between vertices to MAX_WEIGHT\r
+ //\r
+ SetMem (&Weight[M (VertexIndex, VertexIndex + 1)], VertexCount - VertexIndex - 1, MAX_WEIGHT);\r
+\r
+ // Final result looks like:\r
+ // 00 FF FF FF\r
+ // 00 00 FF FF\r
+ // 00 00 00 FF\r
+ // 00 00 00 00\r
+ }\r
\r
- Weight = (UINT8 *) &Vector[VectorCount];\r
//\r
- // Set mandatory weight between any vector to max\r
- // Set optional weight and between any vector and self->self to 0\r
- // E.g.:\r
- // 00 FF FF FF\r
- // 00 00 FF FF\r
- // 00 00 00 FF\r
- // 00 00 00 00\r
+ // Set mandatory weight and optional weight for adjacent vertices\r
//\r
- for (VectorIndex = 0; VectorIndex < VectorCount; VectorIndex++) {\r
- SetMem (&Weight[M(VectorIndex, 0)], VectorIndex + 1, 0);\r
- if (VectorIndex != VectorCount - 1) {\r
- Weight[M (VectorIndex, VectorIndex + 1)] = (DefaultType == Vector[VectorIndex].Type) ? 0 : 1;\r
- SetMem (&Weight[M (VectorIndex, VectorIndex + 2)], VectorCount - VectorIndex - 2, MAX_WEIGHT);\r
+ for (VertexIndex = 0; VertexIndex < VertexCount - 1; VertexIndex++) {\r
+ if (Vertices[VertexIndex].Type != DefaultType) {\r
+ Weight[M (VertexIndex, VertexIndex + 1)] = 1;\r
+ Weight[O (VertexIndex, VertexIndex + 1)] = 0;\r
+ } else {\r
+ Weight[M (VertexIndex, VertexIndex + 1)] = 0;\r
+ Weight[O (VertexIndex, VertexIndex + 1)] = 1;\r
}\r
}\r
\r
for (TypeCount = 2; TypeCount <= 3; TypeCount++) {\r
- for (Start = 0; Start < VectorCount; Start++) {\r
- for (Stop = Start + 2; Stop < VectorCount; Stop++) {\r
- ASSERT (Vector[Stop].Address > Vector[Start].Address);\r
- Length = Vector[Stop].Address - Vector[Start].Address;\r
- if (Length > Vector[Start].Alignment) {\r
+ for (Start = 0; Start < VertexCount; Start++) {\r
+ for (Stop = Start + 2; Stop < VertexCount; Stop++) {\r
+ ASSERT (Vertices[Stop].Address > Vertices[Start].Address);\r
+ Length = Vertices[Stop].Address - Vertices[Start].Address;\r
+ if (Length > Vertices[Start].Alignment) {\r
//\r
// Pickup a new Start when [Start, Stop) cannot be described by one MTRR.\r
//\r
}\r
if ((Weight[M(Start, Stop)] == MAX_WEIGHT) && MtrrLibIsPowerOfTwo (Length)) {\r
if (MtrrLibGetNumberOfTypes (\r
- Ranges, RangeCount, Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address, &Type\r
+ Ranges, RangeCount, Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address, &Type\r
) == TypeCount) {\r
//\r
// Update the Weight[Start, Stop] using subtractive path.\r
MtrrLibCalculateSubtractivePath (\r
DefaultType, A0,\r
Ranges, RangeCount,\r
- (UINT16)VectorCount, Vector, Weight,\r
+ (UINT16)VertexCount, Vertices, Weight,\r
Start, Stop, Type, TypeCount,\r
NULL, 0, NULL\r
);\r
}\r
\r
Status = RETURN_SUCCESS;\r
- MtrrLibCalculateLeastMtrrs ((UINT16) VectorCount, Vector, Weight, 0, (UINT16) VectorCount - 1, FALSE);\r
- Stop = (UINT16) VectorCount - 1;\r
+ MtrrLibCalculateLeastMtrrs ((UINT16) VertexCount, Vertices, Weight, 0, (UINT16) VertexCount - 1, FALSE);\r
+ Stop = (UINT16) VertexCount - 1;\r
while (Stop != 0) {\r
- Start = Vector[Stop].Previous;\r
+ Start = Vertices[Stop].Previous;\r
TypeCount = MAX_UINT8;\r
Type = 0;\r
if (Weight[M(Start, Stop)] != 0) {\r
- TypeCount = MtrrLibGetNumberOfTypes (Ranges, RangeCount, Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address, &Type);\r
+ TypeCount = MtrrLibGetNumberOfTypes (Ranges, RangeCount, Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address, &Type);\r
Status = MtrrLibAppendVariableMtrr (\r
Mtrrs, MtrrCapacity, MtrrCount,\r
- Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address, \r
+ Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address,\r
MtrrLibLowestType (Type)\r
);\r
if (RETURN_ERROR (Status)) {\r
//\r
if (TypeCount == MAX_UINT8) {\r
TypeCount = MtrrLibGetNumberOfTypes (\r
- Ranges, RangeCount, Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address, &Type\r
+ Ranges, RangeCount, Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address, &Type\r
);\r
}\r
Status = MtrrLibCalculateSubtractivePath (\r
DefaultType, A0,\r
Ranges, RangeCount,\r
- (UINT16) VectorCount, Vector, Weight, Start, Stop,\r
+ (UINT16) VertexCount, Vertices, Weight, Start, Stop,\r
Type, TypeCount,\r
Mtrrs, MtrrCapacity, MtrrCount\r
);\r
\r
\r
/**\r
- Apply the variable MTRR settings to memory range array.\r
+ Apply the fixed MTRR settings to memory range array.\r
\r
@param Fixed The fixed MTRR settings.\r
@param Ranges Return the memory range array holding memory type\r
// 2. Set other types than WB or UC\r
//\r
for (Index = 0; Index < VariableMtrrCount; Index++) {\r
- if ((VariableMtrr[Index].Length != 0) && \r
+ if ((VariableMtrr[Index].Length != 0) &&\r
(VariableMtrr[Index].Type != CacheWriteBack) && (VariableMtrr[Index].Type != CacheUncacheable)) {\r
Status = MtrrLibSetMemoryType (\r
Ranges, RangeCapacity, RangeCount,\r
UINTN BiggestScratchSize;\r
\r
*VariableMtrrCount = 0;\r
- \r
+\r
//\r
// Since the whole ranges need multiple calls of MtrrLibCalculateMtrrs().\r
// Each call needs different scratch buffer size.\r
Set the below-1MB memory attribute to fixed MTRR buffer.\r
Modified flag array indicates which fixed MTRR is modified.\r
\r
- @param [in, out] FixedSettings Fixed MTRR buffer.\r
- @param [out] Modified Flag array indicating which MTRR is modified.\r
+ @param [in, out] ClearMasks The bits (when set) to clear in the fixed MTRR MSR.\r
+ @param [in, out] OrMasks The bits to set in the fixed MTRR MSR.\r
@param [in] BaseAddress Base address.\r
@param [in] Length Length.\r
@param [in] Type Memory type.\r
**/\r
RETURN_STATUS\r
MtrrLibSetBelow1MBMemoryAttribute (\r
- IN OUT MTRR_FIXED_SETTINGS *FixedSettings,\r
- OUT BOOLEAN *Modified,\r
+ IN OUT UINT64 *ClearMasks,\r
+ IN OUT UINT64 *OrMasks,\r
IN PHYSICAL_ADDRESS BaseAddress,\r
IN UINT64 Length,\r
IN MTRR_MEMORY_CACHE_TYPE Type\r
UINT32 MsrIndex;\r
UINT64 ClearMask;\r
UINT64 OrMask;\r
- UINT64 ClearMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
- UINT64 OrMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
- BOOLEAN LocalModified[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
\r
ASSERT (BaseAddress < BASE_1MB);\r
\r
- SetMem (LocalModified, sizeof (LocalModified), FALSE);\r
-\r
- //\r
- // (Value & ~0 | 0) still equals to (Value)\r
- //\r
- SetMem (ClearMasks, sizeof (ClearMasks), 0);\r
- SetMem (OrMasks, sizeof (OrMasks), 0);\r
-\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
return Status;\r
}\r
- ClearMasks[MsrIndex] = ClearMask;\r
- OrMasks[MsrIndex] = OrMask;\r
- Modified[MsrIndex] = TRUE;\r
- LocalModified[MsrIndex] = TRUE;\r
- }\r
-\r
- for (MsrIndex = 0; MsrIndex < ARRAY_SIZE (mMtrrLibFixedMtrrTable); MsrIndex++) {\r
- if (LocalModified[MsrIndex]) {\r
- FixedSettings->Mtrr[MsrIndex] = (FixedSettings->Mtrr[MsrIndex] & ~ClearMasks[MsrIndex]) | OrMasks[MsrIndex];\r
- }\r
+ ClearMasks[MsrIndex] = ClearMasks[MsrIndex] | ClearMask;\r
+ OrMasks[MsrIndex] = (OrMasks[MsrIndex] & ~ClearMask) | OrMask;\r
}\r
return RETURN_SUCCESS;\r
}\r
MTRR_MEMORY_RANGE WorkingVariableMtrr[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];\r
BOOLEAN VariableSettingModified[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];\r
\r
- BOOLEAN FixedSettingsModified[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
- MTRR_FIXED_SETTINGS WorkingFixedSettings;\r
+ UINT64 ClearMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
+ UINT64 OrMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
\r
MTRR_CONTEXT MtrrContext;\r
BOOLEAN MtrrContextValid;\r
\r
+ Status = RETURN_SUCCESS;\r
MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);\r
\r
//\r
// TRUE indicating the accordingly Variable setting needs modificaiton in OriginalVariableMtrr.\r
//\r
SetMem (VariableSettingModified, ARRAY_SIZE (VariableSettingModified), FALSE);\r
- //\r
- // TRUE indicating the accordingly Fixed setting needs modification in WorkingFixedSettings.\r
- //\r
- SetMem (FixedSettingsModified, ARRAY_SIZE (FixedSettingsModified), FALSE);\r
\r
//\r
// TRUE indicating the caller requests to set variable MTRRs.\r
Above1MbExist = FALSE;\r
OriginalVariableMtrrCount = 0;\r
\r
+ //\r
+ // 0. Dump the requests.\r
+ //\r
+ DEBUG_CODE (\r
+ DEBUG ((DEBUG_CACHE, "Mtrr: Set Mem Attribute to %a, ScratchSize = %x%a",\r
+ (MtrrSetting == NULL) ? "Hardware" : "Buffer", *ScratchSize,\r
+ (RangeCount <= 1) ? "," : "\n"\r
+ ));\r
+ for (Index = 0; Index < RangeCount; Index++) {\r
+ DEBUG ((DEBUG_CACHE, " %a: [%016lx, %016lx)\n",\r
+ mMtrrMemoryCacheTypeShortName[MIN (Ranges[Index].Type, CacheInvalid)],\r
+ Ranges[Index].BaseAddress, Ranges[Index].BaseAddress + Ranges[Index].Length\r
+ ));\r
+ }\r
+ );\r
+\r
//\r
// 1. Validate the parameters.\r
//\r
+ if (!IsMtrrSupported ()) {\r
+ Status = RETURN_UNSUPPORTED;\r
+ goto Exit;\r
+ }\r
+\r
for (Index = 0; Index < RangeCount; Index++) {\r
if (Ranges[Index].Length == 0) {\r
- return RETURN_INVALID_PARAMETER;\r
+ Status = RETURN_INVALID_PARAMETER;\r
+ goto Exit;\r
}\r
if (((Ranges[Index].BaseAddress & ~MtrrValidAddressMask) != 0) ||\r
- ((Ranges[Index].Length & ~MtrrValidAddressMask) != 0)\r
+ ((((Ranges[Index].BaseAddress + Ranges[Index].Length) & ~MtrrValidAddressMask) != 0) &&\r
+ (Ranges[Index].BaseAddress + Ranges[Index].Length) != MtrrValidBitsMask + 1)\r
) {\r
- return RETURN_UNSUPPORTED;\r
+ //\r
+ // Either the BaseAddress or the Limit doesn't follow the alignment requirement.\r
+ // Note: It's still valid if Limit doesn't follow the alignment requirement but equals to MAX Address.\r
+ //\r
+ Status = RETURN_UNSUPPORTED;\r
+ goto Exit;\r
}\r
if ((Ranges[Index].Type != CacheUncacheable) &&\r
(Ranges[Index].Type != CacheWriteCombining) &&\r
(Ranges[Index].Type != CacheWriteThrough) &&\r
(Ranges[Index].Type != CacheWriteProtected) &&\r
(Ranges[Index].Type != CacheWriteBack)) {\r
- return RETURN_INVALID_PARAMETER;\r
+ Status = RETURN_INVALID_PARAMETER;\r
+ goto Exit;\r
}\r
if (Ranges[Index].BaseAddress + Ranges[Index].Length > BASE_1MB) {\r
Above1MbExist = TRUE;\r
if (Status == RETURN_ALREADY_STARTED) {\r
Status = RETURN_SUCCESS;\r
} else if (Status == RETURN_OUT_OF_RESOURCES) {\r
- return Status;\r
+ goto Exit;\r
} else {\r
ASSERT_RETURN_ERROR (Status);\r
Modified = TRUE;\r
WorkingVariableMtrr, FirmwareVariableMtrrCount + 1, &WorkingVariableMtrrCount\r
);\r
if (RETURN_ERROR (Status)) {\r
- return Status;\r
+ goto Exit;\r
}\r
\r
//\r
}\r
\r
if (WorkingVariableMtrrCount > FirmwareVariableMtrrCount) {\r
- return RETURN_OUT_OF_RESOURCES;\r
+ Status = RETURN_OUT_OF_RESOURCES;\r
+ goto Exit;\r
}\r
\r
//\r
//\r
// 3. Apply the below-1MB memory attribute settings.\r
//\r
- ZeroMem (WorkingFixedSettings.Mtrr, sizeof (WorkingFixedSettings.Mtrr));\r
+ // (Value & ~0 | 0) still equals to (Value)\r
+ //\r
+ ZeroMem (ClearMasks, sizeof (ClearMasks));\r
+ ZeroMem (OrMasks, sizeof (OrMasks));\r
for (Index = 0; Index < RangeCount; Index++) {\r
if (Ranges[Index].BaseAddress >= BASE_1MB) {\r
continue;\r
}\r
\r
Status = MtrrLibSetBelow1MBMemoryAttribute (\r
- &WorkingFixedSettings, FixedSettingsModified,\r
+ ClearMasks, OrMasks,\r
Ranges[Index].BaseAddress, Ranges[Index].Length, Ranges[Index].Type\r
);\r
if (RETURN_ERROR (Status)) {\r
- return Status;\r
+ goto Exit;\r
}\r
}\r
\r
//\r
// 4. Write fixed MTRRs that have been modified\r
//\r
- for (Index = 0; Index < ARRAY_SIZE (FixedSettingsModified); Index++) {\r
- if (FixedSettingsModified[Index]) {\r
+ for (Index = 0; Index < ARRAY_SIZE (ClearMasks); Index++) {\r
+ if (ClearMasks[Index] != 0) {\r
if (MtrrSetting != NULL) {\r
- MtrrSetting->Fixed.Mtrr[Index] = WorkingFixedSettings.Mtrr[Index];\r
+ MtrrSetting->Fixed.Mtrr[Index] = (MtrrSetting->Fixed.Mtrr[Index] & ~ClearMasks[Index]) | OrMasks[Index];\r
} else {\r
if (!MtrrContextValid) {\r
MtrrLibPreMtrrChange (&MtrrContext);\r
MtrrContextValid = TRUE;\r
}\r
- AsmWriteMsr64 (\r
- mMtrrLibFixedMtrrTable[Index].Msr,\r
- WorkingFixedSettings.Mtrr[Index]\r
- );\r
+ AsmMsrAndThenOr64 (mMtrrLibFixedMtrrTable[Index].Msr, ~ClearMasks[Index], OrMasks[Index]);\r
}\r
}\r
}\r
}\r
}\r
\r
- return RETURN_SUCCESS;\r
+Exit:\r
+ DEBUG ((DEBUG_CACHE, " Result = %r\n", Status));\r
+ if (!RETURN_ERROR (Status)) {\r
+ MtrrDebugPrintAllMtrrsWorker (MtrrSetting);\r
+ }\r
+ return Status;\r
}\r
\r
/**\r
BaseAddress and Length cannot be modified.\r
@retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
the memory resource range.\r
- @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.\r
+ Multiple memory range attributes setting by calling this API multiple\r
+ times may fail with status RETURN_OUT_OF_RESOURCES. It may not mean\r
+ the number of CPU MTRRs are too small to set such memory attributes.\r
+ Pass the multiple memory range attributes to one call of\r
+ MtrrSetMemoryAttributesInMtrrSettings() may succeed.\r
+ @retval RETURN_BUFFER_TOO_SMALL The fixed internal scratch buffer is too small for MTRR calculation.\r
+ Caller should use MtrrSetMemoryAttributesInMtrrSettings() to specify\r
+ external scratch buffer.\r
**/\r
RETURN_STATUS\r
EFIAPI\r
IN MTRR_MEMORY_CACHE_TYPE Attribute\r
)\r
{\r
- RETURN_STATUS Status;\r
UINT8 Scratch[SCRATCH_BUFFER_SIZE];\r
UINTN ScratchSize;\r
MTRR_MEMORY_RANGE Range;\r
\r
- if (!IsMtrrSupported ()) {\r
- return RETURN_UNSUPPORTED;\r
- }\r
-\r
Range.BaseAddress = BaseAddress;\r
Range.Length = Length;\r
Range.Type = Attribute;\r
ScratchSize = sizeof (Scratch);\r
- Status = MtrrSetMemoryAttributesInMtrrSettings (MtrrSetting, Scratch, &ScratchSize, &Range, 1);\r
- DEBUG ((DEBUG_CACHE, "MtrrSetMemoryAttribute(MtrrSettings = %p) %a: [%016lx, %016lx) - %r\n",\r
- MtrrSetting,\r
- mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, BaseAddress + Length, Status));\r
-\r
- if (!RETURN_ERROR (Status)) {\r
- MtrrDebugPrintAllMtrrsWorker (MtrrSetting);\r
- }\r
- return Status;\r
+ return MtrrSetMemoryAttributesInMtrrSettings (MtrrSetting, Scratch, &ScratchSize, &Range, 1);\r
}\r
\r
/**\r
@retval RETURN_OUT_OF_RESOURCES There are not enough system resources to\r
modify the attributes of the memory\r
resource range.\r
- @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.\r
+ Multiple memory range attributes setting by calling this API multiple\r
+ times may fail with status RETURN_OUT_OF_RESOURCES. It may not mean\r
+ the number of CPU MTRRs are too small to set such memory attributes.\r
+ Pass the multiple memory range attributes to one call of\r
+ MtrrSetMemoryAttributesInMtrrSettings() may succeed.\r
+ @retval RETURN_BUFFER_TOO_SMALL The fixed internal scratch buffer is too small for MTRR calculation.\r
+ Caller should use MtrrSetMemoryAttributesInMtrrSettings() to specify\r
+ external scratch buffer.\r
**/\r
RETURN_STATUS\r
EFIAPI\r
ASSERT (VariableMtrrCount <= ARRAY_SIZE (VariableSettings->Mtrr));\r
\r
for (Index = 0; Index < VariableMtrrCount; Index++) {\r
- //\r
- // Mask MSR is always updated since caller might need to invalidate the MSR pair.\r
- // Base MSR is skipped when Mask.V is not set.\r
- //\r
- AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableSettings->Mtrr[Index].Mask);\r
- if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&VariableSettings->Mtrr[Index].Mask)->Bits.V != 0) {\r
- AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableSettings->Mtrr[Index].Base);\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
\r
UINT64 MtrrValidBitsMask;\r
UINT64 MtrrValidAddressMask;\r
UINT32 VariableMtrrCount;\r
+ BOOLEAN ContainVariableMtrr;\r
MTRR_MEMORY_RANGE Ranges[\r
ARRAY_SIZE (mMtrrLibFixedMtrrTable) * sizeof (UINT64) + 2 * ARRAY_SIZE (Mtrrs->Variables.Mtrr) + 1\r
];\r
//\r
// Dump RAW MTRR contents\r
//\r
- DEBUG((DEBUG_CACHE, "MTRR Settings\n"));\r
- DEBUG((DEBUG_CACHE, "=============\n"));\r
- DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", Mtrrs->MtrrDefType));\r
+ DEBUG ((DEBUG_CACHE, "MTRR Settings:\n"));\r
+ DEBUG ((DEBUG_CACHE, "=============\n"));\r
+ DEBUG ((DEBUG_CACHE, "MTRR Default Type: %016lx\n", Mtrrs->MtrrDefType));\r
for (Index = 0; Index < ARRAY_SIZE (mMtrrLibFixedMtrrTable); Index++) {\r
- DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, Mtrrs->Fixed.Mtrr[Index]));\r
+ DEBUG ((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, Mtrrs->Fixed.Mtrr[Index]));\r
}\r
-\r
+ ContainVariableMtrr = FALSE;\r
for (Index = 0; Index < VariableMtrrCount; Index++) {\r
- if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&Mtrrs->Variables.Mtrr[Index].Mask)->Bits.V == 0) {\r
+ if ((Mtrrs->Variables.Mtrr[Index].Mask & BIT11) == 0) {\r
//\r
// If mask is not valid, then do not display range\r
//\r
continue;\r
}\r
+ ContainVariableMtrr = TRUE;\r
DEBUG ((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",\r
Index,\r
Mtrrs->Variables.Mtrr[Index].Base,\r
Mtrrs->Variables.Mtrr[Index].Mask\r
));\r
}\r
+ if (!ContainVariableMtrr) {\r
+ DEBUG ((DEBUG_CACHE, "Variable MTRR : None.\n"));\r
+ }\r
DEBUG((DEBUG_CACHE, "\n"));\r
\r
//\r
// Dump MTRR setting in ranges\r
//\r
- DEBUG((DEBUG_CACHE, "MTRR Ranges\n"));\r
+ DEBUG((DEBUG_CACHE, "Memory Ranges:\n"));\r
DEBUG((DEBUG_CACHE, "====================================\n"));\r
MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);\r
Ranges[0].BaseAddress = 0;\r