]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MtrrLib/MtrrLib.c
UefiCpuPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / UefiCpuPkg / Library / MtrrLib / MtrrLib.c
index 8e46e46cd437de8c418d88c5afc7fed761fb9ac4..9415897b481983ac4e723d85ad4583cd079da64f 100644 (file)
@@ -1,18 +1,12 @@
 /** @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
@@ -32,8 +26,8 @@
 #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
@@ -47,7 +41,7 @@ typedef struct {
   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
@@ -449,13 +443,10 @@ MtrrGetVariableMtrrWorker (
 \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
@@ -1142,21 +1133,21 @@ MtrrLibGetNumberOfTypes (
 }\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
@@ -1170,52 +1161,51 @@ MtrrLibCalculateLeastMtrrs (
   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
@@ -1288,17 +1278,17 @@ MtrrLibIsPowerOfTwo (
 }\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
@@ -1315,8 +1305,8 @@ MtrrLibCalculateSubtractivePath (
   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
@@ -1342,8 +1332,8 @@ MtrrLibCalculateSubtractivePath (
   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
@@ -1404,18 +1394,18 @@ MtrrLibCalculateSubtractivePath (
       // 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
@@ -1429,7 +1419,7 @@ MtrrLibCalculateSubtractivePath (
           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
@@ -1439,21 +1429,22 @@ MtrrLibCalculateSubtractivePath (
         }\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
@@ -1463,7 +1454,7 @@ MtrrLibCalculateSubtractivePath (
               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
@@ -1526,10 +1517,10 @@ MtrrLibCalculateMtrrs (
   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
@@ -1542,10 +1533,10 @@ MtrrLibCalculateMtrrs (
   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
@@ -1554,58 +1545,71 @@ MtrrLibCalculateMtrrs (
       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
@@ -1613,7 +1617,7 @@ MtrrLibCalculateMtrrs (
         }\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
@@ -1621,7 +1625,7 @@ MtrrLibCalculateMtrrs (
             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
@@ -1638,17 +1642,17 @@ MtrrLibCalculateMtrrs (
   }\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
@@ -1662,13 +1666,13 @@ MtrrLibCalculateMtrrs (
       //\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
@@ -1683,7 +1687,7 @@ MtrrLibCalculateMtrrs (
 \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
@@ -1775,7 +1779,7 @@ MtrrLibApplyVariableMtrrs (
   // 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
@@ -1968,7 +1972,7 @@ MtrrLibSetMemoryRanges (
   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
@@ -2089,8 +2093,8 @@ MtrrLibSetMemoryRanges (
   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
@@ -2101,8 +2105,8 @@ MtrrLibSetMemoryRanges (
 **/\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
@@ -2112,36 +2116,17 @@ MtrrLibSetBelow1MBMemoryAttribute (
   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
@@ -2158,7 +2143,7 @@ MtrrLibSetBelow1MBMemoryAttribute (
                                 When range overlap happens, the last one takes higher priority.\r
                                 When the function returns, either all the attributes are set successfully,\r
                                 or none of them is set.\r
-  @param[in]                    Count of MTRR_MEMORY_RANGE.\r
+  @param[in]       RangeCount   Count of MTRR_MEMORY_RANGE.\r
 \r
   @retval RETURN_SUCCESS            The attributes were set for all the memory ranges.\r
   @retval RETURN_INVALID_PARAMETER  Length in any range is zero.\r
@@ -2203,22 +2188,19 @@ MtrrSetMemoryAttributesInMtrrSettings (
   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
@@ -2226,24 +2208,53 @@ MtrrSetMemoryAttributesInMtrrSettings (
   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
@@ -2309,7 +2320,7 @@ MtrrSetMemoryAttributesInMtrrSettings (
       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
@@ -2327,7 +2338,7 @@ MtrrSetMemoryAttributesInMtrrSettings (
                  WorkingVariableMtrr, FirmwareVariableMtrrCount + 1, &WorkingVariableMtrrCount\r
                  );\r
       if (RETURN_ERROR (Status)) {\r
-        return Status;\r
+        goto Exit;\r
       }\r
 \r
       //\r
@@ -2346,7 +2357,8 @@ MtrrSetMemoryAttributesInMtrrSettings (
       }\r
 \r
       if (WorkingVariableMtrrCount > FirmwareVariableMtrrCount) {\r
-        return RETURN_OUT_OF_RESOURCES;\r
+        Status = RETURN_OUT_OF_RESOURCES;\r
+        goto Exit;\r
       }\r
 \r
       //\r
@@ -2364,18 +2376,21 @@ MtrrSetMemoryAttributesInMtrrSettings (
   //\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
@@ -2383,19 +2398,16 @@ MtrrSetMemoryAttributesInMtrrSettings (
   //\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
@@ -2441,7 +2453,12 @@ MtrrSetMemoryAttributesInMtrrSettings (
     }\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
@@ -2464,7 +2481,14 @@ MtrrSetMemoryAttributesInMtrrSettings (
                                     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
@@ -2475,28 +2499,15 @@ MtrrSetMemoryAttributeInMtrrSettings (
   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) %s: [%016lx, %016lx) - %x\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
@@ -2523,7 +2534,14 @@ MtrrSetMemoryAttributeInMtrrSettings (
   @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
@@ -2554,14 +2572,14 @@ MtrrSetVariableMtrrWorker (
   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
@@ -2788,6 +2806,7 @@ MtrrDebugPrintAllMtrrsWorker (
     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
@@ -2809,32 +2828,36 @@ MtrrDebugPrintAllMtrrsWorker (
     //\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