]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/CpuPageTable.c
UefiCpuPkg/CpuDxe: allow accessing (DXE) page table in SMM mode
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuPageTable.c
index e2595b4d892d948c50dfddc7843eaac1ff6b2ac2..d4e385139a8b49351bf9e6923bce4bb980b93494 100644 (file)
@@ -23,6 +23,7 @@
 #include <Library/DebugLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Protocol/MpService.h>\r
+#include <Protocol/SmmBase2.h>\r
 \r
 #include "CpuDxe.h"\r
 #include "CpuPageTable.h"\r
@@ -87,7 +88,46 @@ PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {
   {Page1G,  SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},\r
 };\r
 \r
-PAGE_TABLE_POOL   *mPageTablePool = NULL;\r
+PAGE_TABLE_POOL                   *mPageTablePool = NULL;\r
+PAGE_TABLE_LIB_PAGING_CONTEXT     mPagingContext;\r
+EFI_SMM_BASE2_PROTOCOL            *mSmmBase2 = NULL;\r
+\r
+/**\r
+ Check if current execution environment is in SMM mode or not, via\r
+ EFI_SMM_BASE2_PROTOCOL.\r
+\r
+ This is necessary because of the fact that MdePkg\Library\SmmMemoryAllocationLib\r
+ supports to free memory outside SMRAM. The library will call gBS->FreePool() or\r
+ gBS->FreePages() and then SetMemorySpaceAttributes interface in turn to change\r
+ memory paging attributes during free operation, if some memory related features\r
+ are enabled (like Heap Guard).\r
+\r
+ This means that SetMemorySpaceAttributes() has chance to run in SMM mode. This\r
+ will cause incorrect result because SMM mode always loads its own page tables,\r
+ which are usually different from DXE. This function can be used to detect such\r
+ situation and help to avoid further misoperations.\r
+\r
+  @retval TRUE    In SMM mode.\r
+  @retval FALSE   Not in SMM mode.\r
+**/\r
+BOOLEAN\r
+IsInSmm (\r
+  VOID\r
+  )\r
+{\r
+  BOOLEAN                 InSmm;\r
+\r
+  InSmm = FALSE;\r
+  if (mSmmBase2 == NULL) {\r
+    gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **)&mSmmBase2);\r
+  }\r
+\r
+  if (mSmmBase2 != NULL) {\r
+    mSmmBase2->InSmm (mSmmBase2, &InSmm);\r
+  }\r
+\r
+  return InSmm;\r
+}\r
 \r
 /**\r
   Return current paging context.\r
@@ -102,42 +142,53 @@ GetCurrentPagingContext (
   UINT32                         RegEax;\r
   UINT32                         RegEdx;\r
 \r
-  ZeroMem(PagingContext, sizeof(*PagingContext));\r
-  if (sizeof(UINTN) == sizeof(UINT64)) {\r
-    PagingContext->MachineType = IMAGE_FILE_MACHINE_X64;\r
-  } else {\r
-    PagingContext->MachineType = IMAGE_FILE_MACHINE_I386;\r
-  }\r
-  if ((AsmReadCr0 () & BIT31) != 0) {\r
-    PagingContext->ContextData.X64.PageTableBase = (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);\r
-  } else {\r
-    PagingContext->ContextData.X64.PageTableBase = 0;\r
-  }\r
+  //\r
+  // Don't retrieve current paging context from processor if in SMM mode.\r
+  //\r
+  if (!IsInSmm ()) {\r
+    ZeroMem (&mPagingContext, sizeof(mPagingContext));\r
+    if (sizeof(UINTN) == sizeof(UINT64)) {\r
+      mPagingContext.MachineType = IMAGE_FILE_MACHINE_X64;\r
+    } else {\r
+      mPagingContext.MachineType = IMAGE_FILE_MACHINE_I386;\r
+    }\r
+    if ((AsmReadCr0 () & BIT31) != 0) {\r
+      mPagingContext.ContextData.X64.PageTableBase = (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);\r
+    } else {\r
+      mPagingContext.ContextData.X64.PageTableBase = 0;\r
+    }\r
 \r
-  if ((AsmReadCr4 () & BIT4) != 0) {\r
-    PagingContext->ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE;\r
-  }\r
-  if ((AsmReadCr4 () & BIT5) != 0) {\r
-    PagingContext->ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE;\r
-  }\r
-  if ((AsmReadCr0 () & BIT16) != 0) {\r
-    PagingContext->ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_WP_ENABLE;\r
-  }\r
+    if ((AsmReadCr4 () & BIT4) != 0) {\r
+      mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE;\r
+    }\r
+    if ((AsmReadCr4 () & BIT5) != 0) {\r
+      mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE;\r
+    }\r
+    if ((AsmReadCr0 () & BIT16) != 0) {\r
+      mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_WP_ENABLE;\r
+    }\r
 \r
-  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
-  if (RegEax > 0x80000000) {\r
-    AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
-    if ((RegEdx & BIT20) != 0) {\r
-      // XD supported\r
-      if ((AsmReadMsr64 (0xC0000080) & BIT11) != 0) {\r
-        // XD activated\r
-        PagingContext->ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED;\r
+    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+    if (RegEax > 0x80000000) {\r
+      AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
+      if ((RegEdx & BIT20) != 0) {\r
+        // XD supported\r
+        if ((AsmReadMsr64 (0xC0000080) & BIT11) != 0) {\r
+          // XD activated\r
+          mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED;\r
+        }\r
+      }\r
+      if ((RegEdx & BIT26) != 0) {\r
+        mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAGE_1G_SUPPORT;\r
       }\r
-    }\r
-    if ((RegEdx & BIT26) != 0) {\r
-      PagingContext->ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAGE_1G_SUPPORT;\r
     }\r
   }\r
+\r
+  //\r
+  // This can avoid getting SMM paging context if in SMM mode. We cannot assume\r
+  // SMM mode shares the same paging context as DXE.\r
+  //\r
+  CopyMem (PagingContext, &mPagingContext, sizeof (mPagingContext));\r
 }\r
 \r
 /**\r
@@ -507,7 +558,14 @@ IsReadOnlyPageWriteProtected (
   VOID\r
   )\r
 {\r
-  return ((AsmReadCr0 () & BIT16) != 0);\r
+  //\r
+  // To avoid unforseen consequences, don't touch paging settings in SMM mode\r
+  // in this driver.\r
+  //\r
+  if (!IsInSmm ()) {\r
+    return ((AsmReadCr0 () & BIT16) != 0);\r
+  }\r
+  return FALSE;\r
 }\r
 \r
 /**\r
@@ -518,7 +576,13 @@ DisableReadOnlyPageWriteProtect (
   VOID\r
   )\r
 {\r
-  AsmWriteCr0 (AsmReadCr0() & ~BIT16);\r
+  //\r
+  // To avoid unforseen consequences, don't touch paging settings in SMM mode\r
+  // in this driver.\r
+  //\r
+  if (!IsInSmm ()) {\r
+    AsmWriteCr0 (AsmReadCr0 () & ~BIT16);\r
+  }\r
 }\r
 \r
 /**\r
@@ -529,7 +593,13 @@ EnableReadOnlyPageWriteProtect (
   VOID\r
   )\r
 {\r
-  AsmWriteCr0 (AsmReadCr0() | BIT16);\r
+  //\r
+  // To avoid unforseen consequences, don't touch paging settings in SMM mode\r
+  // in this driver.\r
+  //\r
+  if (!IsInSmm ()) {\r
+    AsmWriteCr0 (AsmReadCr0 () | BIT16);\r
+  }\r
 }\r
 \r
 /**\r