X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=UefiCpuPkg%2FLibrary%2FMtrrLib%2FMtrrLib.c;h=9415897b481983ac4e723d85ad4583cd079da64f;hp=619b500c1de0a997fa91987b35d3bcafd6606a0e;hb=0acd869796ded1266e69487dff717cd69d6031f9;hpb=82b95709185c15f68c9c254f652ffe46ebbba239
diff --git a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
index 619b500c1d..9415897b48 100644
--- a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
+++ b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
@@ -1,18 +1,12 @@
/** @file
MTRR setting library
- @par Note:
+ @par Note:
Most of services in this library instance are suggested to be invoked by BSP only,
except for MtrrSetAllMtrrs() which is used to sync BSP's MTRR setting to APs.
- Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -32,8 +26,8 @@
#define SCRATCH_BUFFER_SIZE (4 * SIZE_4KB)
#define MTRR_LIB_ASSERT_ALIGNED(B, L) ASSERT ((B & ~(L - 1)) == B);
-#define M(x,y) ((x) * VectorCount + (y))
-#define O(x,y) ((y) * VectorCount + (x))
+#define M(x,y) ((x) * VertexCount + (y))
+#define O(x,y) ((y) * VertexCount + (x))
//
// Context to save and restore when MTRRs are programmed
@@ -47,7 +41,7 @@ typedef struct {
UINT64 Address;
UINT64 Alignment;
UINT64 Length;
- UINT8 Type : 7;
+ MTRR_MEMORY_CACHE_TYPE Type : 7;
//
// Temprary use for calculating the best MTRR settings.
@@ -449,13 +443,10 @@ MtrrGetVariableMtrrWorker (
for (Index = 0; Index < VariableMtrrCount; Index++) {
if (MtrrSetting == NULL) {
- VariableSettings->Mtrr[Index].Mask = AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1));
- //
- // Skip to read the Base MSR when the Mask.V is not set.
- //
- if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&VariableSettings->Mtrr[Index].Mask)->Bits.V != 0) {
- VariableSettings->Mtrr[Index].Base = AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1));
- }
+ VariableSettings->Mtrr[Index].Base =
+ AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1));
+ VariableSettings->Mtrr[Index].Mask =
+ AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1));
} else {
VariableSettings->Mtrr[Index].Base = MtrrSetting->Variables.Mtrr[Index].Base;
VariableSettings->Mtrr[Index].Mask = MtrrSetting->Variables.Mtrr[Index].Mask;
@@ -1142,21 +1133,21 @@ MtrrLibGetNumberOfTypes (
}
/**
- Calculate the least MTRR number from vector Start to Stop and update
- the Previous of all vectors from Start to Stop is updated to reflect
+ Calculate the least MTRR number from vertex Start to Stop and update
+ the Previous of all vertices from Start to Stop is updated to reflect
how the memory range is covered by MTRR.
- @param VectorCount The count of vectors in the graph.
- @param Vector Array holding all vectors.
- @param Weight 2-dimention array holding weights between vectors.
- @param Start Start vector.
- @param Stop Stop vector.
+ @param VertexCount The count of vertices in the graph.
+ @param Vertices Array holding all vertices.
+ @param Weight 2-dimention array holding weights between vertices.
+ @param Start Start vertex.
+ @param Stop Stop vertex.
@param IncludeOptional TRUE to count the optional weight.
**/
VOID
MtrrLibCalculateLeastMtrrs (
- IN UINT16 VectorCount,
- IN MTRR_LIB_ADDRESS *Vector,
+ IN UINT16 VertexCount,
+ IN MTRR_LIB_ADDRESS *Vertices,
IN OUT CONST UINT8 *Weight,
IN UINT16 Start,
IN UINT16 Stop,
@@ -1170,52 +1161,51 @@ MtrrLibCalculateLeastMtrrs (
UINT8 Optional;
for (Index = Start; Index <= Stop; Index++) {
- Vector[Index].Visited = FALSE;
- Vector[Index].Previous = VectorCount;
+ Vertices[Index].Visited = FALSE;
Mandatory = Weight[M(Start,Index)];
- Vector[Index].Weight = Mandatory;
+ Vertices[Index].Weight = Mandatory;
if (Mandatory != MAX_WEIGHT) {
Optional = IncludeOptional ? Weight[O(Start, Index)] : 0;
- Vector[Index].Weight += Optional;
- ASSERT (Vector[Index].Weight >= Optional);
+ Vertices[Index].Weight += Optional;
+ ASSERT (Vertices[Index].Weight >= Optional);
}
}
MinI = Start;
MinWeight = 0;
- while (!Vector[Stop].Visited) {
+ while (!Vertices[Stop].Visited) {
//
- // Update the weight from the shortest vector to other unvisited vectors
+ // Update the weight from the shortest vertex to other unvisited vertices
//
for (Index = Start + 1; Index <= Stop; Index++) {
- if (!Vector[Index].Visited) {
+ if (!Vertices[Index].Visited) {
Mandatory = Weight[M(MinI, Index)];
if (Mandatory != MAX_WEIGHT) {
Optional = IncludeOptional ? Weight[O(MinI, Index)] : 0;
- if (MinWeight + Mandatory + Optional <= Vector[Index].Weight) {
- Vector[Index].Weight = MinWeight + Mandatory + Optional;
- Vector[Index].Previous = MinI; // Previous is Start based.
+ if (MinWeight + Mandatory + Optional <= Vertices[Index].Weight) {
+ Vertices[Index].Weight = MinWeight + Mandatory + Optional;
+ Vertices[Index].Previous = MinI; // Previous is Start based.
}
}
}
}
//
- // Find the shortest vector from Start
+ // Find the shortest vertex from Start
//
- MinI = VectorCount;
+ MinI = VertexCount;
MinWeight = MAX_WEIGHT;
for (Index = Start + 1; Index <= Stop; Index++) {
- if (!Vector[Index].Visited && MinWeight > Vector[Index].Weight) {
+ if (!Vertices[Index].Visited && MinWeight > Vertices[Index].Weight) {
MinI = Index;
- MinWeight = Vector[Index].Weight;
+ MinWeight = Vertices[Index].Weight;
}
}
//
- // Mark the shortest vector from Start as visited
+ // Mark the shortest vertex from Start as visited
//
- Vector[MinI].Visited = TRUE;
+ Vertices[MinI].Visited = TRUE;
}
}
@@ -1288,17 +1278,17 @@ MtrrLibIsPowerOfTwo (
}
/**
- Calculate the subtractive path from vector Start to Stop.
+ Calculate the subtractive path from vertex Start to Stop.
@param DefaultType Default memory type.
@param A0 Alignment to use when base address is 0.
@param Ranges Array holding memory type settings for all memory regions.
@param RangeCount The count of memory ranges the array holds.
- @param VectorCount The count of vectors in the graph.
- @param Vector Array holding all vectors.
- @param Weight 2-dimention array holding weights between vectors.
- @param Start Start vector.
- @param Stop Stop vector.
+ @param VertexCount The count of vertices in the graph.
+ @param Vertices Array holding all vertices.
+ @param Weight 2-dimention array holding weights between vertices.
+ @param Start Start vertex.
+ @param Stop Stop vertex.
@param Types Type bit mask of memory range from Start to Stop.
@param TypeCount Number of different memory types from Start to Stop.
@param Mtrrs Array holding all MTRR settings.
@@ -1315,8 +1305,8 @@ MtrrLibCalculateSubtractivePath (
IN UINT64 A0,
IN CONST MTRR_MEMORY_RANGE *Ranges,
IN UINTN RangeCount,
- IN UINT16 VectorCount,
- IN MTRR_LIB_ADDRESS *Vector,
+ IN UINT16 VertexCount,
+ IN MTRR_LIB_ADDRESS *Vertices,
IN OUT UINT8 *Weight,
IN UINT16 Start,
IN UINT16 Stop,
@@ -1342,8 +1332,8 @@ MtrrLibCalculateSubtractivePath (
MTRR_MEMORY_CACHE_TYPE LowestType;
MTRR_MEMORY_CACHE_TYPE LowestPrecedentType;
- Base = Vector[Start].Address;
- Length = Vector[Stop].Address - Base;
+ Base = Vertices[Start].Address;
+ Length = Vertices[Stop].Address - Base;
LowestType = MtrrLibLowestType (Types);
@@ -1404,18 +1394,18 @@ MtrrLibCalculateSubtractivePath (
// We might use positive or subtractive, depending on which way uses less MTRR
//
for (SubStart = Start; SubStart <= Stop; SubStart++) {
- if (Vector[SubStart].Address == HBase) {
+ if (Vertices[SubStart].Address == HBase) {
break;
}
}
for (SubStop = SubStart; SubStop <= Stop; SubStop++) {
- if (Vector[SubStop].Address == HBase + HLength) {
+ if (Vertices[SubStop].Address == HBase + HLength) {
break;
}
}
- ASSERT (Vector[SubStart].Address == HBase);
- ASSERT (Vector[SubStop].Address == HBase + HLength);
+ ASSERT (Vertices[SubStart].Address == HBase);
+ ASSERT (Vertices[SubStop].Address == HBase + HLength);
if ((TypeCount == 2) || (SubStart == SubStop - 1)) {
//
@@ -1429,7 +1419,7 @@ MtrrLibCalculateSubtractivePath (
while (SubStart != SubStop) {
Status = MtrrLibAppendVariableMtrr (
Mtrrs, MtrrCapacity, MtrrCount,
- Vector[SubStart].Address, Vector[SubStart].Length, (MTRR_MEMORY_CACHE_TYPE) Vector[SubStart].Type
+ Vertices[SubStart].Address, Vertices[SubStart].Length, Vertices[SubStart].Type
);
if (RETURN_ERROR (Status)) {
return Status;
@@ -1439,21 +1429,22 @@ MtrrLibCalculateSubtractivePath (
}
} else {
ASSERT (TypeCount == 3);
- MtrrLibCalculateLeastMtrrs (VectorCount, Vector, Weight, SubStart, SubStop, TRUE);
+ MtrrLibCalculateLeastMtrrs (VertexCount, Vertices, Weight, SubStart, SubStop, TRUE);
if (Mtrrs == NULL) {
- Weight[M (Start, Stop)] += Vector[SubStop].Weight;
+ Weight[M (Start, Stop)] += Vertices[SubStop].Weight;
} else {
// When we need to collect the optimal path from SubStart to SubStop
while (SubStop != SubStart) {
Cur = SubStop;
- Pre = Vector[Cur].Previous;
+ Pre = Vertices[Cur].Previous;
SubStop = Pre;
- if (Weight[M (Pre, Cur)] != 0) {
+ if (Weight[M (Pre, Cur)] + Weight[O (Pre, Cur)] != 0) {
Status = MtrrLibAppendVariableMtrr (
Mtrrs, MtrrCapacity, MtrrCount,
- Vector[Pre].Address, Vector[Cur].Address - Vector[Pre].Address, LowestPrecedentType
+ Vertices[Pre].Address, Vertices[Cur].Address - Vertices[Pre].Address,
+ (Pre != Cur - 1) ? LowestPrecedentType : Vertices[Pre].Type
);
if (RETURN_ERROR (Status)) {
return Status;
@@ -1463,7 +1454,7 @@ MtrrLibCalculateSubtractivePath (
Status = MtrrLibCalculateSubtractivePath (
DefaultType, A0,
Ranges, RangeCount,
- VectorCount, Vector, Weight,
+ VertexCount, Vertices, Weight,
Pre, Cur, PrecedentTypes, 2,
Mtrrs, MtrrCapacity, MtrrCount
);
@@ -1526,10 +1517,10 @@ MtrrLibCalculateMtrrs (
UINT64 Length;
UINT64 Alignment;
UINT64 SubLength;
- MTRR_LIB_ADDRESS *Vector;
+ MTRR_LIB_ADDRESS *Vertices;
UINT8 *Weight;
- UINT32 VectorIndex;
- UINT32 VectorCount;
+ UINT32 VertexIndex;
+ UINT32 VertexCount;
UINTN RequiredScratchSize;
UINT8 TypeCount;
UINT16 Start;
@@ -1542,10 +1533,10 @@ MtrrLibCalculateMtrrs (
MTRR_LIB_ASSERT_ALIGNED (Base0, Base1 - Base0);
//
- // Count the number of vectors.
+ // Count the number of vertices.
//
- Vector = (MTRR_LIB_ADDRESS*)Scratch;
- for (VectorIndex = 0, Index = 0; Index < RangeCount; Index++) {
+ Vertices = (MTRR_LIB_ADDRESS*)Scratch;
+ for (VertexIndex = 0, Index = 0; Index < RangeCount; Index++) {
Base = Ranges[Index].BaseAddress;
Length = Ranges[Index].Length;
while (Length != 0) {
@@ -1554,58 +1545,71 @@ MtrrLibCalculateMtrrs (
if (SubLength > Length) {
SubLength = GetPowerOfTwo64 (Length);
}
- if (VectorIndex < *ScratchSize / sizeof (*Vector)) {
- Vector[VectorIndex].Address = Base;
- Vector[VectorIndex].Alignment = Alignment;
- Vector[VectorIndex].Type = Ranges[Index].Type;
- Vector[VectorIndex].Length = SubLength;
+ if (VertexIndex < *ScratchSize / sizeof (*Vertices)) {
+ Vertices[VertexIndex].Address = Base;
+ Vertices[VertexIndex].Alignment = Alignment;
+ Vertices[VertexIndex].Type = Ranges[Index].Type;
+ Vertices[VertexIndex].Length = SubLength;
}
Base += SubLength;
Length -= SubLength;
- VectorIndex++;
+ VertexIndex++;
}
}
//
- // Vector[VectorIndex] = Base1, so whole vector count is (VectorIndex + 1).
+ // Vertices[VertexIndex] = Base1, so whole vertex count is (VertexIndex + 1).
//
- VectorCount = VectorIndex + 1;
+ VertexCount = VertexIndex + 1;
DEBUG ((
- DEBUG_CACHE, "VectorCount (%016lx - %016lx) = %d\n",
- Ranges[0].BaseAddress, Ranges[RangeCount - 1].BaseAddress + Ranges[RangeCount - 1].Length, VectorCount
+ DEBUG_CACHE, " Count of vertices (%016llx - %016llx) = %d\n",
+ Ranges[0].BaseAddress, Ranges[RangeCount - 1].BaseAddress + Ranges[RangeCount - 1].Length, VertexCount
));
- ASSERT (VectorCount < MAX_UINT16);
+ ASSERT (VertexCount < MAX_UINT16);
- RequiredScratchSize = VectorCount * sizeof (*Vector) + VectorCount * VectorCount * sizeof (*Weight);
+ RequiredScratchSize = VertexCount * sizeof (*Vertices) + VertexCount * VertexCount * sizeof (*Weight);
if (*ScratchSize < RequiredScratchSize) {
*ScratchSize = RequiredScratchSize;
return RETURN_BUFFER_TOO_SMALL;
}
- Vector[VectorCount - 1].Address = Base1;
+ Vertices[VertexCount - 1].Address = Base1;
+
+ Weight = (UINT8 *) &Vertices[VertexCount];
+ for (VertexIndex = 0; VertexIndex < VertexCount; VertexIndex++) {
+ //
+ // Set optional weight between vertices and self->self to 0
+ //
+ SetMem (&Weight[M(VertexIndex, 0)], VertexIndex + 1, 0);
+ //
+ // Set mandatory weight between vertices to MAX_WEIGHT
+ //
+ SetMem (&Weight[M (VertexIndex, VertexIndex + 1)], VertexCount - VertexIndex - 1, MAX_WEIGHT);
+
+ // Final result looks like:
+ // 00 FF FF FF
+ // 00 00 FF FF
+ // 00 00 00 FF
+ // 00 00 00 00
+ }
- Weight = (UINT8 *) &Vector[VectorCount];
//
- // Set mandatory weight between any vector to max
- // Set optional weight and between any vector and self->self to 0
- // E.g.:
- // 00 FF FF FF
- // 00 00 FF FF
- // 00 00 00 FF
- // 00 00 00 00
+ // Set mandatory weight and optional weight for adjacent vertices
//
- for (VectorIndex = 0; VectorIndex < VectorCount; VectorIndex++) {
- SetMem (&Weight[M(VectorIndex, 0)], VectorIndex + 1, 0);
- if (VectorIndex != VectorCount - 1) {
- Weight[M (VectorIndex, VectorIndex + 1)] = (DefaultType == Vector[VectorIndex].Type) ? 0 : 1;
- SetMem (&Weight[M (VectorIndex, VectorIndex + 2)], VectorCount - VectorIndex - 2, MAX_WEIGHT);
+ for (VertexIndex = 0; VertexIndex < VertexCount - 1; VertexIndex++) {
+ if (Vertices[VertexIndex].Type != DefaultType) {
+ Weight[M (VertexIndex, VertexIndex + 1)] = 1;
+ Weight[O (VertexIndex, VertexIndex + 1)] = 0;
+ } else {
+ Weight[M (VertexIndex, VertexIndex + 1)] = 0;
+ Weight[O (VertexIndex, VertexIndex + 1)] = 1;
}
}
for (TypeCount = 2; TypeCount <= 3; TypeCount++) {
- for (Start = 0; Start < VectorCount; Start++) {
- for (Stop = Start + 2; Stop < VectorCount; Stop++) {
- ASSERT (Vector[Stop].Address > Vector[Start].Address);
- Length = Vector[Stop].Address - Vector[Start].Address;
- if (Length > Vector[Start].Alignment) {
+ for (Start = 0; Start < VertexCount; Start++) {
+ for (Stop = Start + 2; Stop < VertexCount; Stop++) {
+ ASSERT (Vertices[Stop].Address > Vertices[Start].Address);
+ Length = Vertices[Stop].Address - Vertices[Start].Address;
+ if (Length > Vertices[Start].Alignment) {
//
// Pickup a new Start when [Start, Stop) cannot be described by one MTRR.
//
@@ -1613,7 +1617,7 @@ MtrrLibCalculateMtrrs (
}
if ((Weight[M(Start, Stop)] == MAX_WEIGHT) && MtrrLibIsPowerOfTwo (Length)) {
if (MtrrLibGetNumberOfTypes (
- Ranges, RangeCount, Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address, &Type
+ Ranges, RangeCount, Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address, &Type
) == TypeCount) {
//
// Update the Weight[Start, Stop] using subtractive path.
@@ -1621,7 +1625,7 @@ MtrrLibCalculateMtrrs (
MtrrLibCalculateSubtractivePath (
DefaultType, A0,
Ranges, RangeCount,
- (UINT16)VectorCount, Vector, Weight,
+ (UINT16)VertexCount, Vertices, Weight,
Start, Stop, Type, TypeCount,
NULL, 0, NULL
);
@@ -1638,17 +1642,17 @@ MtrrLibCalculateMtrrs (
}
Status = RETURN_SUCCESS;
- MtrrLibCalculateLeastMtrrs ((UINT16) VectorCount, Vector, Weight, 0, (UINT16) VectorCount - 1, FALSE);
- Stop = (UINT16) VectorCount - 1;
+ MtrrLibCalculateLeastMtrrs ((UINT16) VertexCount, Vertices, Weight, 0, (UINT16) VertexCount - 1, FALSE);
+ Stop = (UINT16) VertexCount - 1;
while (Stop != 0) {
- Start = Vector[Stop].Previous;
+ Start = Vertices[Stop].Previous;
TypeCount = MAX_UINT8;
Type = 0;
if (Weight[M(Start, Stop)] != 0) {
- TypeCount = MtrrLibGetNumberOfTypes (Ranges, RangeCount, Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address, &Type);
+ TypeCount = MtrrLibGetNumberOfTypes (Ranges, RangeCount, Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address, &Type);
Status = MtrrLibAppendVariableMtrr (
Mtrrs, MtrrCapacity, MtrrCount,
- Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address,
+ Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address,
MtrrLibLowestType (Type)
);
if (RETURN_ERROR (Status)) {
@@ -1662,13 +1666,13 @@ MtrrLibCalculateMtrrs (
//
if (TypeCount == MAX_UINT8) {
TypeCount = MtrrLibGetNumberOfTypes (
- Ranges, RangeCount, Vector[Start].Address, Vector[Stop].Address - Vector[Start].Address, &Type
+ Ranges, RangeCount, Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address, &Type
);
}
Status = MtrrLibCalculateSubtractivePath (
DefaultType, A0,
Ranges, RangeCount,
- (UINT16) VectorCount, Vector, Weight, Start, Stop,
+ (UINT16) VertexCount, Vertices, Weight, Start, Stop,
Type, TypeCount,
Mtrrs, MtrrCapacity, MtrrCount
);
@@ -1683,7 +1687,7 @@ MtrrLibCalculateMtrrs (
/**
- Apply the variable MTRR settings to memory range array.
+ Apply the fixed MTRR settings to memory range array.
@param Fixed The fixed MTRR settings.
@param Ranges Return the memory range array holding memory type
@@ -1775,7 +1779,7 @@ MtrrLibApplyVariableMtrrs (
// 2. Set other types than WB or UC
//
for (Index = 0; Index < VariableMtrrCount; Index++) {
- if ((VariableMtrr[Index].Length != 0) &&
+ if ((VariableMtrr[Index].Length != 0) &&
(VariableMtrr[Index].Type != CacheWriteBack) && (VariableMtrr[Index].Type != CacheUncacheable)) {
Status = MtrrLibSetMemoryType (
Ranges, RangeCapacity, RangeCount,
@@ -1968,7 +1972,7 @@ MtrrLibSetMemoryRanges (
UINTN BiggestScratchSize;
*VariableMtrrCount = 0;
-
+
//
// Since the whole ranges need multiple calls of MtrrLibCalculateMtrrs().
// Each call needs different scratch buffer size.
@@ -2089,8 +2093,8 @@ MtrrLibSetMemoryRanges (
Set the below-1MB memory attribute to fixed MTRR buffer.
Modified flag array indicates which fixed MTRR is modified.
- @param [in, out] FixedSettings Fixed MTRR buffer.
- @param [out] Modified Flag array indicating which MTRR is modified.
+ @param [in, out] ClearMasks The bits (when set) to clear in the fixed MTRR MSR.
+ @param [in, out] OrMasks The bits to set in the fixed MTRR MSR.
@param [in] BaseAddress Base address.
@param [in] Length Length.
@param [in] Type Memory type.
@@ -2101,8 +2105,8 @@ MtrrLibSetMemoryRanges (
**/
RETURN_STATUS
MtrrLibSetBelow1MBMemoryAttribute (
- IN OUT MTRR_FIXED_SETTINGS *FixedSettings,
- OUT BOOLEAN *Modified,
+ IN OUT UINT64 *ClearMasks,
+ IN OUT UINT64 *OrMasks,
IN PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN MTRR_MEMORY_CACHE_TYPE Type
@@ -2112,36 +2116,17 @@ MtrrLibSetBelow1MBMemoryAttribute (
UINT32 MsrIndex;
UINT64 ClearMask;
UINT64 OrMask;
- UINT64 ClearMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
- UINT64 OrMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
- BOOLEAN LocalModified[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
ASSERT (BaseAddress < BASE_1MB);
- SetMem (LocalModified, sizeof (LocalModified), FALSE);
-
- //
- // (Value & ~0 | 0) still equals to (Value)
- //
- SetMem (ClearMasks, sizeof (ClearMasks), 0);
- SetMem (OrMasks, sizeof (OrMasks), 0);
-
MsrIndex = (UINT32)-1;
while ((BaseAddress < BASE_1MB) && (Length != 0)) {
Status = MtrrLibProgramFixedMtrr (Type, &BaseAddress, &Length, &MsrIndex, &ClearMask, &OrMask);
if (RETURN_ERROR (Status)) {
return Status;
}
- ClearMasks[MsrIndex] = ClearMask;
- OrMasks[MsrIndex] = OrMask;
- Modified[MsrIndex] = TRUE;
- LocalModified[MsrIndex] = TRUE;
- }
-
- for (MsrIndex = 0; MsrIndex < ARRAY_SIZE (mMtrrLibFixedMtrrTable); MsrIndex++) {
- if (LocalModified[MsrIndex]) {
- FixedSettings->Mtrr[MsrIndex] = (FixedSettings->Mtrr[MsrIndex] & ~ClearMasks[MsrIndex]) | OrMasks[MsrIndex];
- }
+ ClearMasks[MsrIndex] = ClearMasks[MsrIndex] | ClearMask;
+ OrMasks[MsrIndex] = (OrMasks[MsrIndex] & ~ClearMask) | OrMask;
}
return RETURN_SUCCESS;
}
@@ -2203,22 +2188,19 @@ MtrrSetMemoryAttributesInMtrrSettings (
MTRR_MEMORY_RANGE WorkingVariableMtrr[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];
BOOLEAN VariableSettingModified[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];
- BOOLEAN FixedSettingsModified[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
- MTRR_FIXED_SETTINGS WorkingFixedSettings;
+ UINT64 ClearMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
+ UINT64 OrMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
MTRR_CONTEXT MtrrContext;
BOOLEAN MtrrContextValid;
+ Status = RETURN_SUCCESS;
MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);
//
// TRUE indicating the accordingly Variable setting needs modificaiton in OriginalVariableMtrr.
//
SetMem (VariableSettingModified, ARRAY_SIZE (VariableSettingModified), FALSE);
- //
- // TRUE indicating the accordingly Fixed setting needs modification in WorkingFixedSettings.
- //
- SetMem (FixedSettingsModified, ARRAY_SIZE (FixedSettingsModified), FALSE);
//
// TRUE indicating the caller requests to set variable MTRRs.
@@ -2226,24 +2208,53 @@ MtrrSetMemoryAttributesInMtrrSettings (
Above1MbExist = FALSE;
OriginalVariableMtrrCount = 0;
+ //
+ // 0. Dump the requests.
+ //
+ DEBUG_CODE (
+ DEBUG ((DEBUG_CACHE, "Mtrr: Set Mem Attribute to %a, ScratchSize = %x%a",
+ (MtrrSetting == NULL) ? "Hardware" : "Buffer", *ScratchSize,
+ (RangeCount <= 1) ? "," : "\n"
+ ));
+ for (Index = 0; Index < RangeCount; Index++) {
+ DEBUG ((DEBUG_CACHE, " %a: [%016lx, %016lx)\n",
+ mMtrrMemoryCacheTypeShortName[MIN (Ranges[Index].Type, CacheInvalid)],
+ Ranges[Index].BaseAddress, Ranges[Index].BaseAddress + Ranges[Index].Length
+ ));
+ }
+ );
+
//
// 1. Validate the parameters.
//
+ if (!IsMtrrSupported ()) {
+ Status = RETURN_UNSUPPORTED;
+ goto Exit;
+ }
+
for (Index = 0; Index < RangeCount; Index++) {
if (Ranges[Index].Length == 0) {
- return RETURN_INVALID_PARAMETER;
+ Status = RETURN_INVALID_PARAMETER;
+ goto Exit;
}
if (((Ranges[Index].BaseAddress & ~MtrrValidAddressMask) != 0) ||
- ((Ranges[Index].Length & ~MtrrValidAddressMask) != 0)
+ ((((Ranges[Index].BaseAddress + Ranges[Index].Length) & ~MtrrValidAddressMask) != 0) &&
+ (Ranges[Index].BaseAddress + Ranges[Index].Length) != MtrrValidBitsMask + 1)
) {
- return RETURN_UNSUPPORTED;
+ //
+ // Either the BaseAddress or the Limit doesn't follow the alignment requirement.
+ // Note: It's still valid if Limit doesn't follow the alignment requirement but equals to MAX Address.
+ //
+ Status = RETURN_UNSUPPORTED;
+ goto Exit;
}
if ((Ranges[Index].Type != CacheUncacheable) &&
(Ranges[Index].Type != CacheWriteCombining) &&
(Ranges[Index].Type != CacheWriteThrough) &&
(Ranges[Index].Type != CacheWriteProtected) &&
(Ranges[Index].Type != CacheWriteBack)) {
- return RETURN_INVALID_PARAMETER;
+ Status = RETURN_INVALID_PARAMETER;
+ goto Exit;
}
if (Ranges[Index].BaseAddress + Ranges[Index].Length > BASE_1MB) {
Above1MbExist = TRUE;
@@ -2309,7 +2320,7 @@ MtrrSetMemoryAttributesInMtrrSettings (
if (Status == RETURN_ALREADY_STARTED) {
Status = RETURN_SUCCESS;
} else if (Status == RETURN_OUT_OF_RESOURCES) {
- return Status;
+ goto Exit;
} else {
ASSERT_RETURN_ERROR (Status);
Modified = TRUE;
@@ -2327,7 +2338,7 @@ MtrrSetMemoryAttributesInMtrrSettings (
WorkingVariableMtrr, FirmwareVariableMtrrCount + 1, &WorkingVariableMtrrCount
);
if (RETURN_ERROR (Status)) {
- return Status;
+ goto Exit;
}
//
@@ -2346,7 +2357,8 @@ MtrrSetMemoryAttributesInMtrrSettings (
}
if (WorkingVariableMtrrCount > FirmwareVariableMtrrCount) {
- return RETURN_OUT_OF_RESOURCES;
+ Status = RETURN_OUT_OF_RESOURCES;
+ goto Exit;
}
//
@@ -2364,18 +2376,21 @@ MtrrSetMemoryAttributesInMtrrSettings (
//
// 3. Apply the below-1MB memory attribute settings.
//
- ZeroMem (WorkingFixedSettings.Mtrr, sizeof (WorkingFixedSettings.Mtrr));
+ // (Value & ~0 | 0) still equals to (Value)
+ //
+ ZeroMem (ClearMasks, sizeof (ClearMasks));
+ ZeroMem (OrMasks, sizeof (OrMasks));
for (Index = 0; Index < RangeCount; Index++) {
if (Ranges[Index].BaseAddress >= BASE_1MB) {
continue;
}
Status = MtrrLibSetBelow1MBMemoryAttribute (
- &WorkingFixedSettings, FixedSettingsModified,
+ ClearMasks, OrMasks,
Ranges[Index].BaseAddress, Ranges[Index].Length, Ranges[Index].Type
);
if (RETURN_ERROR (Status)) {
- return Status;
+ goto Exit;
}
}
@@ -2383,19 +2398,16 @@ MtrrSetMemoryAttributesInMtrrSettings (
//
// 4. Write fixed MTRRs that have been modified
//
- for (Index = 0; Index < ARRAY_SIZE (FixedSettingsModified); Index++) {
- if (FixedSettingsModified[Index]) {
+ for (Index = 0; Index < ARRAY_SIZE (ClearMasks); Index++) {
+ if (ClearMasks[Index] != 0) {
if (MtrrSetting != NULL) {
- MtrrSetting->Fixed.Mtrr[Index] = WorkingFixedSettings.Mtrr[Index];
+ MtrrSetting->Fixed.Mtrr[Index] = (MtrrSetting->Fixed.Mtrr[Index] & ~ClearMasks[Index]) | OrMasks[Index];
} else {
if (!MtrrContextValid) {
MtrrLibPreMtrrChange (&MtrrContext);
MtrrContextValid = TRUE;
}
- AsmWriteMsr64 (
- mMtrrLibFixedMtrrTable[Index].Msr,
- WorkingFixedSettings.Mtrr[Index]
- );
+ AsmMsrAndThenOr64 (mMtrrLibFixedMtrrTable[Index].Msr, ~ClearMasks[Index], OrMasks[Index]);
}
}
}
@@ -2441,7 +2453,12 @@ MtrrSetMemoryAttributesInMtrrSettings (
}
}
- return RETURN_SUCCESS;
+Exit:
+ DEBUG ((DEBUG_CACHE, " Result = %r\n", Status));
+ if (!RETURN_ERROR (Status)) {
+ MtrrDebugPrintAllMtrrsWorker (MtrrSetting);
+ }
+ return Status;
}
/**
@@ -2464,7 +2481,14 @@ MtrrSetMemoryAttributesInMtrrSettings (
BaseAddress and Length cannot be modified.
@retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
the memory resource range.
- @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.
+ Multiple memory range attributes setting by calling this API multiple
+ times may fail with status RETURN_OUT_OF_RESOURCES. It may not mean
+ the number of CPU MTRRs are too small to set such memory attributes.
+ Pass the multiple memory range attributes to one call of
+ MtrrSetMemoryAttributesInMtrrSettings() may succeed.
+ @retval RETURN_BUFFER_TOO_SMALL The fixed internal scratch buffer is too small for MTRR calculation.
+ Caller should use MtrrSetMemoryAttributesInMtrrSettings() to specify
+ external scratch buffer.
**/
RETURN_STATUS
EFIAPI
@@ -2475,28 +2499,15 @@ MtrrSetMemoryAttributeInMtrrSettings (
IN MTRR_MEMORY_CACHE_TYPE Attribute
)
{
- RETURN_STATUS Status;
UINT8 Scratch[SCRATCH_BUFFER_SIZE];
UINTN ScratchSize;
MTRR_MEMORY_RANGE Range;
- if (!IsMtrrSupported ()) {
- return RETURN_UNSUPPORTED;
- }
-
Range.BaseAddress = BaseAddress;
Range.Length = Length;
Range.Type = Attribute;
ScratchSize = sizeof (Scratch);
- Status = MtrrSetMemoryAttributesInMtrrSettings (MtrrSetting, Scratch, &ScratchSize, &Range, 1);
- DEBUG ((DEBUG_CACHE, "MtrrSetMemoryAttribute(MtrrSettings = %p) %a: [%016lx, %016lx) - %r\n",
- MtrrSetting,
- mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, BaseAddress + Length, Status));
-
- if (!RETURN_ERROR (Status)) {
- MtrrDebugPrintAllMtrrsWorker (MtrrSetting);
- }
- return Status;
+ return MtrrSetMemoryAttributesInMtrrSettings (MtrrSetting, Scratch, &ScratchSize, &Range, 1);
}
/**
@@ -2523,7 +2534,14 @@ MtrrSetMemoryAttributeInMtrrSettings (
@retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
modify the attributes of the memory
resource range.
- @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.
+ Multiple memory range attributes setting by calling this API multiple
+ times may fail with status RETURN_OUT_OF_RESOURCES. It may not mean
+ the number of CPU MTRRs are too small to set such memory attributes.
+ Pass the multiple memory range attributes to one call of
+ MtrrSetMemoryAttributesInMtrrSettings() may succeed.
+ @retval RETURN_BUFFER_TOO_SMALL The fixed internal scratch buffer is too small for MTRR calculation.
+ Caller should use MtrrSetMemoryAttributesInMtrrSettings() to specify
+ external scratch buffer.
**/
RETURN_STATUS
EFIAPI
@@ -2554,14 +2572,14 @@ MtrrSetVariableMtrrWorker (
ASSERT (VariableMtrrCount <= ARRAY_SIZE (VariableSettings->Mtrr));
for (Index = 0; Index < VariableMtrrCount; Index++) {
- //
- // Mask MSR is always updated since caller might need to invalidate the MSR pair.
- // Base MSR is skipped when Mask.V is not set.
- //
- AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableSettings->Mtrr[Index].Mask);
- if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&VariableSettings->Mtrr[Index].Mask)->Bits.V != 0) {
- AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableSettings->Mtrr[Index].Base);
- }
+ AsmWriteMsr64 (
+ MSR_IA32_MTRR_PHYSBASE0 + (Index << 1),
+ VariableSettings->Mtrr[Index].Base
+ );
+ AsmWriteMsr64 (
+ MSR_IA32_MTRR_PHYSMASK0 + (Index << 1),
+ VariableSettings->Mtrr[Index].Mask
+ );
}
}
@@ -2788,6 +2806,7 @@ MtrrDebugPrintAllMtrrsWorker (
UINT64 MtrrValidBitsMask;
UINT64 MtrrValidAddressMask;
UINT32 VariableMtrrCount;
+ BOOLEAN ContainVariableMtrr;
MTRR_MEMORY_RANGE Ranges[
ARRAY_SIZE (mMtrrLibFixedMtrrTable) * sizeof (UINT64) + 2 * ARRAY_SIZE (Mtrrs->Variables.Mtrr) + 1
];
@@ -2809,32 +2828,36 @@ MtrrDebugPrintAllMtrrsWorker (
//
// Dump RAW MTRR contents
//
- DEBUG((DEBUG_CACHE, "MTRR Settings\n"));
- DEBUG((DEBUG_CACHE, "=============\n"));
- DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", Mtrrs->MtrrDefType));
+ DEBUG ((DEBUG_CACHE, "MTRR Settings:\n"));
+ DEBUG ((DEBUG_CACHE, "=============\n"));
+ DEBUG ((DEBUG_CACHE, "MTRR Default Type: %016lx\n", Mtrrs->MtrrDefType));
for (Index = 0; Index < ARRAY_SIZE (mMtrrLibFixedMtrrTable); Index++) {
- DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, Mtrrs->Fixed.Mtrr[Index]));
+ DEBUG ((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, Mtrrs->Fixed.Mtrr[Index]));
}
-
+ ContainVariableMtrr = FALSE;
for (Index = 0; Index < VariableMtrrCount; Index++) {
- if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&Mtrrs->Variables.Mtrr[Index].Mask)->Bits.V == 0) {
+ if ((Mtrrs->Variables.Mtrr[Index].Mask & BIT11) == 0) {
//
// If mask is not valid, then do not display range
//
continue;
}
+ ContainVariableMtrr = TRUE;
DEBUG ((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
Index,
Mtrrs->Variables.Mtrr[Index].Base,
Mtrrs->Variables.Mtrr[Index].Mask
));
}
+ if (!ContainVariableMtrr) {
+ DEBUG ((DEBUG_CACHE, "Variable MTRR : None.\n"));
+ }
DEBUG((DEBUG_CACHE, "\n"));
//
// Dump MTRR setting in ranges
//
- DEBUG((DEBUG_CACHE, "MTRR Ranges\n"));
+ DEBUG((DEBUG_CACHE, "Memory Ranges:\n"));
DEBUG((DEBUG_CACHE, "====================================\n"));
MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);
Ranges[0].BaseAddress = 0;