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;