]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MtrrLib/MtrrLib.c
UefiCpuPkg/MtrrLib: Add MtrrGetMemoryAttributeInVariableMtrrWorker ()
[mirror_edk2.git] / UefiCpuPkg / Library / MtrrLib / MtrrLib.c
index ea2b211e0580191a5bde922fc5cac6efcb0741b1..697dc4352f61dd1540035ebdd139ed97d0c9e16f 100644 (file)
@@ -367,13 +367,12 @@ MtrrGetFixedMtrr (
 **/\r
 MTRR_VARIABLE_SETTINGS*\r
 MtrrGetVariableMtrrWorker (\r
+  IN  UINT32                  VariableMtrrCount,\r
   OUT MTRR_VARIABLE_SETTINGS  *VariableSettings\r
   )\r
 {\r
   UINT32  Index;\r
-  UINT32  VariableMtrrCount;\r
 \r
-  VariableMtrrCount = GetVariableMtrrCount ();\r
   ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
 \r
   for (Index = 0; Index < VariableMtrrCount; Index++) {\r
@@ -405,6 +404,7 @@ MtrrGetVariableMtrr (
   }\r
 \r
   return MtrrGetVariableMtrrWorker (\r
+           GetVariableMtrrCountWorker (),\r
            VariableSettings\r
            );\r
 }\r
@@ -495,6 +495,50 @@ ProgramFixedMtrr (
 }\r
 \r
 \r
+/**\r
+  Worker function gets the attribute of variable MTRRs.\r
+\r
+  This function shadows the content of variable MTRRs into an\r
+  internal array: VariableMtrr.\r
+\r
+  @param[in]   VariableSettings           The variable MTRR values to shadow\r
+  @param[in]   FirmwareVariableMtrrCount  The number of variable MTRRs available to firmware\r
+  @param[in]   MtrrValidBitsMask          The mask for the valid bit of the MTRR\r
+  @param[in]   MtrrValidAddressMask       The valid address mask for MTRR\r
+  @param[out]  VariableMtrr               The array to shadow variable MTRRs content\r
+\r
+  @return                       The return value of this parameter indicates the\r
+                                number of MTRRs which has been used.\r
+\r
+**/\r
+UINT32\r
+MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+  IN  MTRR_VARIABLE_SETTINGS  *VariableSettings,\r
+  IN  UINTN                   FirmwareVariableMtrrCount,\r
+  IN  UINT64                  MtrrValidBitsMask,\r
+  IN  UINT64                  MtrrValidAddressMask,\r
+  OUT VARIABLE_MTRR           *VariableMtrr\r
+  )\r
+{\r
+  UINTN   Index;\r
+  UINT32  UsedMtrr;\r
+\r
+  ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);\r
+  for (Index = 0, UsedMtrr = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
+    if ((VariableSettings->Mtrr[Index].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {\r
+      VariableMtrr[Index].Msr         = (UINT32)Index;\r
+      VariableMtrr[Index].BaseAddress = (VariableSettings->Mtrr[Index].Base & MtrrValidAddressMask);\r
+      VariableMtrr[Index].Length      = ((~(VariableSettings->Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;\r
+      VariableMtrr[Index].Type        = (VariableSettings->Mtrr[Index].Base & 0x0ff);\r
+      VariableMtrr[Index].Valid       = TRUE;\r
+      VariableMtrr[Index].Used        = TRUE;\r
+      UsedMtrr++;\r
+    }\r
+  }\r
+  return UsedMtrr;\r
+}\r
+\r
+\r
 /**\r
   Gets the attribute of variable MTRRs.\r
 \r
@@ -517,52 +561,32 @@ MtrrGetMemoryAttributeInVariableMtrr (
   OUT VARIABLE_MTRR             *VariableMtrr\r
   )\r
 {\r
-  UINTN   Index;\r
-  UINT32  MsrNum;\r
-  UINT32  UsedMtrr;\r
-  UINT32  FirmwareVariableMtrrCount;\r
-  UINT32  VariableMtrrEnd;\r
+  MTRR_VARIABLE_SETTINGS  VariableSettings;\r
 \r
   if (!IsMtrrSupported ()) {\r
     return 0;\r
   }\r
 \r
-  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
-  VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;\r
-\r
-  ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);\r
-  UsedMtrr = 0;\r
+  MtrrGetVariableMtrrWorker (\r
+    GetVariableMtrrCountWorker (),\r
+    &VariableSettings\r
+    );\r
 \r
-  for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE, Index = 0;\r
-       (\r
-         (MsrNum < VariableMtrrEnd) &&\r
-         (Index < FirmwareVariableMtrrCount)\r
-       );\r
-       MsrNum += 2\r
-      ) {\r
-    if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {\r
-      VariableMtrr[Index].Msr          = MsrNum;\r
-      VariableMtrr[Index].BaseAddress  = (AsmReadMsr64 (MsrNum) &\r
-                                          MtrrValidAddressMask);\r
-      VariableMtrr[Index].Length       = ((~(AsmReadMsr64 (MsrNum + 1) &\r
-                                             MtrrValidAddressMask)\r
-                                          ) &\r
-                                          MtrrValidBitsMask\r
-                                         ) + 1;\r
-      VariableMtrr[Index].Type         = (AsmReadMsr64 (MsrNum) & 0x0ff);\r
-      VariableMtrr[Index].Valid        = TRUE;\r
-      VariableMtrr[Index].Used         = TRUE;\r
-      UsedMtrr = UsedMtrr  + 1;\r
-      Index++;\r
-    }\r
-  }\r
-  return UsedMtrr;\r
+  return MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+           &VariableSettings,\r
+           GetFirmwareVariableMtrrCountWorker (),\r
+           MtrrValidBitsMask,\r
+           MtrrValidAddressMask,\r
+           VariableMtrr\r
+           );\r
 }\r
 \r
 \r
 /**\r
   Checks overlap between given memory range and MTRRs.\r
 \r
+  @param[in]  FirmwareVariableMtrrCount  The number of variable MTRRs available\r
+                                         to firmware.\r
   @param[in]  Start                      The start address of memory range.\r
   @param[in]  End                        The end address of memory range.\r
   @param[in]  VariableMtrr               The array to shadow variable MTRRs content\r
@@ -573,14 +597,15 @@ MtrrGetMemoryAttributeInVariableMtrr (
 **/\r
 BOOLEAN\r
 CheckMemoryAttributeOverlap (\r
-  IN PHYSICAL_ADDRESS     Start,\r
-  IN PHYSICAL_ADDRESS     End,\r
-  IN VARIABLE_MTRR      *VariableMtrr\r
+  IN UINTN             FirmwareVariableMtrrCount,\r
+  IN PHYSICAL_ADDRESS  Start,\r
+  IN PHYSICAL_ADDRESS  End,\r
+  IN VARIABLE_MTRR     *VariableMtrr\r
   )\r
 {\r
   UINT32  Index;\r
 \r
-  for (Index = 0; Index < 6; Index++) {\r
+  for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
     if (\r
          VariableMtrr[Index].Valid &&\r
          !(\r
@@ -623,6 +648,8 @@ InvalidateShadowMtrr (
 \r
   If overlap exists between given memory range and MTRRs, try to combine them.\r
 \r
+  @param[in]       FirmwareVariableMtrrCount  The number of variable MTRRs\r
+                                              available to firmware.\r
   @param[in]       Attributes                 The memory type to set.\r
   @param[in, out]  Base                       The base address of memory range.\r
   @param[in, out]  Length                     The length of memory range.\r
@@ -636,6 +663,7 @@ InvalidateShadowMtrr (
 **/\r
 RETURN_STATUS\r
 CombineMemoryAttribute (\r
+  IN     UINT32             FirmwareVariableMtrrCount,\r
   IN     UINT64             Attributes,\r
   IN OUT UINT64             *Base,\r
   IN OUT UINT64             *Length,\r
@@ -649,11 +677,8 @@ CombineMemoryAttribute (
   UINT64  CombineEnd;\r
   UINT64  MtrrEnd;\r
   UINT64  EndAddress;\r
-  UINT32  FirmwareVariableMtrrCount;\r
   BOOLEAN CoveredByExistingMtrr;\r
 \r
-  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
-\r
   *OverwriteExistingMtrr = FALSE;\r
   CoveredByExistingMtrr = FALSE;\r
   EndAddress = *Base +*Length - 1;\r
@@ -851,21 +876,21 @@ GetMtrrNumberAndDirection (
   This function programs MTRRs according to the values specified\r
   in the shadow array.\r
 \r
+  @param[in]       VariableMtrrCount  Number of variable MTRRs\r
   @param[in, out]  VariableMtrr       Shadow of variable MTRR contents\r
 \r
 **/\r
 VOID\r
 InvalidateMtrr (\r
+  IN     UINTN                   VariableMtrrCount,\r
   IN OUT VARIABLE_MTRR           *VariableMtrr\r
   )\r
 {\r
   UINTN         Index;\r
-  UINTN         VariableMtrrCount;\r
   MTRR_CONTEXT  MtrrContext;\r
 \r
   PreMtrrChange (&MtrrContext);\r
   Index = 0;\r
-  VariableMtrrCount = GetVariableMtrrCount ();\r
   while (Index < VariableMtrrCount) {\r
     if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) {\r
        AsmWriteMsr64 (VariableMtrr[Index].Msr, 0);\r
@@ -1089,6 +1114,7 @@ MtrrGetMemoryAttribute (
   UINT64                  MtrrValidBitsMask;\r
   UINT64                  MtrrValidAddressMask;\r
   UINTN                   VariableMtrrCount;\r
+  MTRR_VARIABLE_SETTINGS  VariableSettings;\r
 \r
   if (!IsMtrrSupported ()) {\r
     return CacheUncacheable;\r
@@ -1130,16 +1156,24 @@ MtrrGetMemoryAttribute (
     }\r
   }\r
   MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
-  MtrrGetMemoryAttributeInVariableMtrr(\r
-    MtrrValidBitsMask,\r
-    MtrrValidAddressMask,\r
-    VariableMtrr\r
+\r
+  MtrrGetVariableMtrrWorker (\r
+    GetVariableMtrrCountWorker (),\r
+    &VariableSettings\r
     );\r
 \r
+  MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+           &VariableSettings,\r
+           GetFirmwareVariableMtrrCountWorker (),\r
+           MtrrValidBitsMask,\r
+           MtrrValidAddressMask,\r
+           VariableMtrr\r
+           );\r
+\r
   //\r
   // Go through the variable MTRR\r
   //\r
-  VariableMtrrCount = GetVariableMtrrCount ();\r
+  VariableMtrrCount = GetVariableMtrrCountWorker ();\r
   ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
 \r
   for (Index = 0; Index < VariableMtrrCount; Index++) {\r
@@ -1354,6 +1388,10 @@ MtrrSetMemoryAttribute (
   UINT32                    FirmwareVariableMtrrCount;\r
   UINT32                    VariableMtrrEnd;\r
   MTRR_CONTEXT              MtrrContext;\r
+  UINT32                    VariableMtrrCount;\r
+  MTRR_VARIABLE_SETTINGS    OriginalVariableSettings;\r
+  MTRR_VARIABLE_SETTINGS    WorkingVariableSettings;\r
+  MTRR_VARIABLE_SETTINGS    *VariableSettings;\r
 \r
   DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length));\r
 \r
@@ -1362,7 +1400,7 @@ MtrrSetMemoryAttribute (
     goto Done;\r
   }\r
 \r
-  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
+  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker ();\r
   VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1;\r
 \r
   MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);\r
@@ -1418,13 +1456,41 @@ MtrrSetMemoryAttribute (
     Length += SIZE_1MB;\r
   }\r
 \r
+  //\r
+  // Read all variable MTRRs\r
+  //\r
+  VariableMtrrCount = GetVariableMtrrCountWorker ();\r
+  MtrrGetVariableMtrrWorker (VariableMtrrCount, &OriginalVariableSettings);\r
+  CopyMem (&WorkingVariableSettings, &OriginalVariableSettings, sizeof (WorkingVariableSettings));\r
+  VariableSettings = &WorkingVariableSettings;\r
+\r
   //\r
   // Check for overlap\r
   //\r
-  UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr);\r
-  OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr);\r
+  UsedMtrr = MtrrGetMemoryAttributeInVariableMtrrWorker (\r
+               VariableSettings,\r
+               FirmwareVariableMtrrCount,\r
+               MtrrValidBitsMask,\r
+               MtrrValidAddressMask,\r
+               VariableMtrr\r
+               );\r
+  OverLap = CheckMemoryAttributeOverlap (\r
+              FirmwareVariableMtrrCount,\r
+              BaseAddress,\r
+              BaseAddress + Length - 1,\r
+              VariableMtrr\r
+              );\r
+\r
   if (OverLap) {\r
-    Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr);\r
+    Status = CombineMemoryAttribute (\r
+               FirmwareVariableMtrrCount,\r
+               MemoryType,\r
+               &BaseAddress,\r
+               &Length,\r
+               VariableMtrr,\r
+               &UsedMtrr,\r
+               &OverwriteExistingMtrr\r
+               );\r
     if (RETURN_ERROR (Status)) {\r
       goto Done;\r
     }\r
@@ -1433,7 +1499,7 @@ MtrrSetMemoryAttribute (
       //\r
       // Combined successfully, invalidate the now-unused MTRRs\r
       //\r
-      InvalidateMtrr(VariableMtrr);\r
+      InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
       Status = RETURN_SUCCESS;\r
       goto Done;\r
     }\r
@@ -1447,7 +1513,7 @@ MtrrSetMemoryAttribute (
     //\r
     // Invalidate the now-unused MTRRs\r
     //\r
-    InvalidateMtrr(VariableMtrr);\r
+    InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
     goto Done;\r
   }\r
 \r
@@ -1461,7 +1527,7 @@ MtrrSetMemoryAttribute (
   //\r
   // Invalidate the now-unused MTRRs\r
   //\r
-  InvalidateMtrr(VariableMtrr);\r
+  InvalidateMtrr(VariableMtrrCount, VariableMtrr);\r
 \r
   //\r
   // Find first unused MTRR\r
@@ -1589,7 +1655,7 @@ MtrrSetVariableMtrrWorker (
   UINT32  Index;\r
   UINT32  VariableMtrrCount;\r
 \r
-  VariableMtrrCount = GetVariableMtrrCount ();\r
+  VariableMtrrCount = GetVariableMtrrCountWorker ();\r
   ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
 \r
   for (Index = 0; Index < VariableMtrrCount; Index++) {\r
@@ -1634,7 +1700,7 @@ MtrrSetVariableMtrr (
 /**\r
   Worker function setting fixed MTRRs\r
 \r
-  @param[in]  FixedSettings  A buffer to hold fixed Mtrrs content.\r
+  @param[in]  FixedSettings  A buffer to hold fixed MTRRs content.\r
 \r
 **/\r
 VOID\r
@@ -1656,7 +1722,7 @@ MtrrSetFixedMtrrWorker (
 /**\r
   This function sets fixed MTRRs\r
 \r
-  @param[in]  FixedSettings  A buffer to hold fixed Mtrrs content.\r
+  @param[in]  FixedSettings  A buffer to hold fixed MTRRs content.\r
 \r
   @retval The pointer of FixedSettings\r
 \r
@@ -1684,7 +1750,7 @@ MtrrSetFixedMtrr (
 /**\r
   This function gets the content in all MTRRs (variable and fixed)\r
 \r
-  @param[out]  MtrrSetting  A buffer to hold all Mtrrs content.\r
+  @param[out]  MtrrSetting  A buffer to hold all MTRRs content.\r
 \r
   @retval the pointer of MtrrSetting\r
 \r
@@ -1702,12 +1768,15 @@ MtrrGetAllMtrrs (
   //\r
   // Get fixed MTRRs\r
   //\r
-  MtrrGetFixedMtrr (&MtrrSetting->Fixed);\r
+  MtrrGetFixedMtrrWorker (&MtrrSetting->Fixed);\r
 \r
   //\r
   // Get variable MTRRs\r
   //\r
-  MtrrGetVariableMtrr (&MtrrSetting->Variables);\r
+  MtrrGetVariableMtrrWorker (\r
+    GetVariableMtrrCountWorker (),\r
+    &MtrrSetting->Variables\r
+    );\r
 \r
   //\r
   // Get MTRR_DEF_TYPE value\r