]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/CpuDxe.c
UefiCpuPkg/CpuDxe: Add memory attribute setting.
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuDxe.c
index daf97bd4a6cf6b762b103d6db7d35205e204c89a..3f3ddad8d928f1786f98fd72219f6159d0192e12 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
-  CPU DXE Module.\r
+  CPU DXE Module to produce CPU ARCH Protocol.\r
 \r
-  Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>\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
 \r
 #include "CpuDxe.h"\r
 #include "CpuMp.h"\r
+#include "CpuPageTable.h"\r
+\r
+#define CACHE_ATTRIBUTE_MASK   (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP)\r
+#define MEMORY_ATTRIBUTE_MASK  (EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RO)\r
 \r
 //\r
 // Global Variables\r
@@ -313,6 +317,21 @@ CpuGetTimerValue (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  A minimal wrapper function that allows MtrrSetAllMtrrs() to be passed to\r
+  EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() as Procedure.\r
+\r
+  @param[in] Buffer  Pointer to an MTRR_SETTINGS object, to be passed to\r
+                     MtrrSetAllMtrrs().\r
+**/\r
+VOID\r
+EFIAPI\r
+SetMtrrsFromBuffer (\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  MtrrSetAllMtrrs (Buffer);\r
+}\r
 \r
 /**\r
   Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.\r
@@ -353,10 +372,9 @@ CpuSetMemoryAttributes (
   EFI_STATUS                MpStatus;\r
   EFI_MP_SERVICES_PROTOCOL  *MpService;\r
   MTRR_SETTINGS             MtrrSettings;\r
-\r
-  if (!IsMtrrSupported ()) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
+  UINT64                    CacheAttributes;\r
+  UINT64                    MemoryAttributes;\r
+  MTRR_MEMORY_CACHE_TYPE    CurrentCacheType;\r
 \r
   //\r
   // If this function is called because GCD SetMemorySpaceAttributes () is called\r
@@ -369,69 +387,87 @@ CpuSetMemoryAttributes (
     return EFI_SUCCESS;\r
   }\r
 \r
-  switch (Attributes) {\r
-  case EFI_MEMORY_UC:\r
-    CacheType = CacheUncacheable;\r
-    break;\r
 \r
-  case EFI_MEMORY_WC:\r
-    CacheType = CacheWriteCombining;\r
-    break;\r
+  CacheAttributes = Attributes & CACHE_ATTRIBUTE_MASK;\r
+  MemoryAttributes = Attributes & MEMORY_ATTRIBUTE_MASK;\r
 \r
-  case EFI_MEMORY_WT:\r
-    CacheType = CacheWriteThrough;\r
-    break;\r
+  if (Attributes != (CacheAttributes | MemoryAttributes)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
-  case EFI_MEMORY_WP:\r
-    CacheType = CacheWriteProtected;\r
-    break;\r
+  if (CacheAttributes != 0) {\r
+    if (!IsMtrrSupported ()) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
 \r
-  case EFI_MEMORY_WB:\r
-    CacheType = CacheWriteBack;\r
-    break;\r
+    switch (CacheAttributes) {\r
+    case EFI_MEMORY_UC:\r
+      CacheType = CacheUncacheable;\r
+      break;\r
 \r
-  case EFI_MEMORY_UCE:\r
-  case EFI_MEMORY_RP:\r
-  case EFI_MEMORY_XP:\r
-  case EFI_MEMORY_RUNTIME:\r
-    return EFI_UNSUPPORTED;\r
+    case EFI_MEMORY_WC:\r
+      CacheType = CacheWriteCombining;\r
+      break;\r
 \r
-  default:\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  // call MTRR libary function\r
-  //\r
-  Status = MtrrSetMemoryAttribute (\r
-             BaseAddress,\r
-             Length,\r
-             CacheType\r
-             );\r
+    case EFI_MEMORY_WT:\r
+      CacheType = CacheWriteThrough;\r
+      break;\r
 \r
-  if (!RETURN_ERROR (Status)) {\r
-    MpStatus = gBS->LocateProtocol (\r
-                      &gEfiMpServiceProtocolGuid,\r
-                      NULL,\r
-                      (VOID **)&MpService\r
-                      );\r
-    //\r
-    // Synchronize the update with all APs\r
-    //\r
-    if (!EFI_ERROR (MpStatus)) {\r
-      MtrrGetAllMtrrs (&MtrrSettings);\r
-      MpStatus = MpService->StartupAllAPs (\r
-                              MpService,          // This\r
-                              SetMtrrsFromBuffer, // Procedure\r
-                              TRUE,               // SingleThread\r
-                              NULL,               // WaitEvent\r
-                              0,                  // TimeoutInMicrosecsond\r
-                              &MtrrSettings,      // ProcedureArgument\r
-                              NULL                // FailedCpuList\r
-                              );\r
-      ASSERT (MpStatus == EFI_SUCCESS || MpStatus == EFI_NOT_STARTED);\r
+    case EFI_MEMORY_WP:\r
+      CacheType = CacheWriteProtected;\r
+      break;\r
+\r
+    case EFI_MEMORY_WB:\r
+      CacheType = CacheWriteBack;\r
+      break;\r
+\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    CurrentCacheType = MtrrGetMemoryAttribute(BaseAddress);\r
+    if (CurrentCacheType != CacheType) {\r
+      //\r
+      // call MTRR libary function\r
+      //\r
+      Status = MtrrSetMemoryAttribute (\r
+                 BaseAddress,\r
+                 Length,\r
+                 CacheType\r
+                 );\r
+\r
+      if (!RETURN_ERROR (Status)) {\r
+        MpStatus = gBS->LocateProtocol (\r
+                          &gEfiMpServiceProtocolGuid,\r
+                          NULL,\r
+                          (VOID **)&MpService\r
+                          );\r
+        //\r
+        // Synchronize the update with all APs\r
+        //\r
+        if (!EFI_ERROR (MpStatus)) {\r
+          MtrrGetAllMtrrs (&MtrrSettings);\r
+          MpStatus = MpService->StartupAllAPs (\r
+                                  MpService,          // This\r
+                                  SetMtrrsFromBuffer, // Procedure\r
+                                  FALSE,              // SingleThread\r
+                                  NULL,               // WaitEvent\r
+                                  0,                  // TimeoutInMicrosecsond\r
+                                  &MtrrSettings,      // ProcedureArgument\r
+                                  NULL                // FailedCpuList\r
+                                  );\r
+          ASSERT (MpStatus == EFI_SUCCESS || MpStatus == EFI_NOT_STARTED);\r
+        }\r
+      }\r
+      if (EFI_ERROR(Status)) {\r
+        return Status;\r
+      }\r
     }\r
   }\r
-  return (EFI_STATUS) Status;\r
+\r
+  //\r
+  // Set memory attribute by page table\r
+  //\r
+  return AssignMemoryPageAttributes (NULL, BaseAddress, Length, MemoryAttributes, AllocatePages);\r
 }\r
 \r
 /**\r
@@ -873,6 +909,8 @@ InitializeCpu (
 {\r
   EFI_STATUS  Status;\r
   EFI_EVENT   IdleLoopEvent;\r
+  \r
+  InitializePageTableLib();\r
 \r
   InitializeFloatingPointUnits ();\r
 \r