]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/CpuPageTable.c
UefiCpuPkg: Update code to include register definitions from MdePkg
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuPageTable.c
index 97257fbe48dfa2a27599c6e626d31e5fe6647298..ec5cd424fca2e979842e578040a32e4c6577bf94 100644 (file)
@@ -1,47 +1,26 @@
 /** @file\r
   Page table management support.\r
 \r
-  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>\r
   Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
 \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
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include <Base.h>\r
 #include <Uefi.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/CpuLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/PeCoffGetEntryPointLib.h>\r
 #include <Library/SerialPortLib.h>\r
 #include <Library/SynchronizationLib.h>\r
 #include <Library/PrintLib.h>\r
-#include <Protocol/MpService.h>\r
 #include <Protocol/SmmBase2.h>\r
-#include <Register/Cpuid.h>\r
-#include <Register/Msr.h>\r
+#include <Register/Intel/Cpuid.h>\r
+#include <Register/Intel/Msr.h>\r
 \r
 #include "CpuDxe.h"\r
 #include "CpuPageTable.h"\r
 \r
-///\r
-/// Paging registers\r
-///\r
-#define CR0_WP                      BIT16\r
-#define CR0_PG                      BIT31\r
-#define CR4_PSE                     BIT4\r
-#define CR4_PAE                     BIT5\r
-\r
 ///\r
 /// Page Table Entry\r
 ///\r
@@ -107,6 +86,7 @@ PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {
 };\r
 \r
 PAGE_TABLE_POOL                   *mPageTablePool = NULL;\r
+BOOLEAN                           mPageTablePoolLock = FALSE;\r
 PAGE_TABLE_LIB_PAGING_CONTEXT     mPagingContext;\r
 EFI_SMM_BASE2_PROTOCOL            *mSmmBase2 = NULL;\r
 \r
@@ -173,6 +153,8 @@ GetCurrentPagingContext (
   UINT32                          RegEax;\r
   CPUID_EXTENDED_CPU_SIG_EDX      RegEdx;\r
   MSR_IA32_EFER_REGISTER          MsrEfer;\r
+  IA32_CR4                        Cr4;\r
+  IA32_CR0                        Cr0;\r
 \r
   //\r
   // Don't retrieve current paging context from processor if in SMM mode.\r
@@ -184,20 +166,26 @@ GetCurrentPagingContext (
     } else {\r
       mPagingContext.MachineType = IMAGE_FILE_MACHINE_I386;\r
     }\r
-    if ((AsmReadCr0 () & CR0_PG) != 0) {\r
+\r
+    Cr0.UintN = AsmReadCr0 ();\r
+    Cr4.UintN = AsmReadCr4 ();\r
+\r
+    if (Cr0.Bits.PG != 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 () & CR4_PSE) != 0) {\r
+    if (Cr0.Bits.WP  != 0) {\r
+      mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_WP_ENABLE;\r
+    }\r
+    if (Cr4.Bits.PSE != 0) {\r
       mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE;\r
     }\r
-    if ((AsmReadCr4 () & CR4_PAE) != 0) {\r
+    if (Cr4.Bits.PAE != 0) {\r
       mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE;\r
     }\r
-    if ((AsmReadCr0 () & CR0_WP) != 0) {\r
-      mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_WP_ENABLE;\r
+    if (Cr4.Bits.LA57 != 0) {\r
+      mPagingContext.ContextData.Ia32.Attributes |= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_5_LEVEL;\r
     }\r
 \r
     AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
@@ -288,14 +276,17 @@ GetPageTableEntry (
   UINTN                 Index2;\r
   UINTN                 Index3;\r
   UINTN                 Index4;\r
+  UINTN                 Index5;\r
   UINT64                *L1PageTable;\r
   UINT64                *L2PageTable;\r
   UINT64                *L3PageTable;\r
   UINT64                *L4PageTable;\r
+  UINT64                *L5PageTable;\r
   UINT64                AddressEncMask;\r
 \r
   ASSERT (PagingContext != NULL);\r
 \r
+  Index5 = ((UINTN)RShiftU64 (Address, 48)) & PAGING_PAE_INDEX_MASK;\r
   Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_PAE_INDEX_MASK;\r
   Index3 = ((UINTN)Address >> 30) & PAGING_PAE_INDEX_MASK;\r
   Index2 = ((UINTN)Address >> 21) & PAGING_PAE_INDEX_MASK;\r
@@ -306,7 +297,17 @@ GetPageTableEntry (
   AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;\r
 \r
   if (PagingContext->MachineType == IMAGE_FILE_MACHINE_X64) {\r
-    L4PageTable = (UINT64 *)(UINTN)PagingContext->ContextData.X64.PageTableBase;\r
+    if ((PagingContext->ContextData.X64.Attributes & PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_5_LEVEL) != 0) {\r
+      L5PageTable = (UINT64 *)(UINTN)PagingContext->ContextData.X64.PageTableBase;\r
+      if (L5PageTable[Index5] == 0) {\r
+        *PageAttribute = PageNone;\r
+        return NULL;\r
+      }\r
+\r
+      L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] & ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64);\r
+    } else {\r
+      L4PageTable = (UINT64 *)(UINTN)PagingContext->ContextData.X64.PageTableBase;\r
+    }\r
     if (L4PageTable[Index4] == 0) {\r
       *PageAttribute = PageNone;\r
       return NULL;\r
@@ -542,7 +543,7 @@ SplitPage (
     ASSERT (SplitAttribute == Page4K);\r
     if (SplitAttribute == Page4K) {\r
       NewPageEntry = AllocatePagesFunc (1);\r
-      DEBUG ((DEBUG_INFO, "Split - 0x%x\n", NewPageEntry));\r
+      DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));\r
       if (NewPageEntry == NULL) {\r
         return RETURN_OUT_OF_RESOURCES;\r
       }\r
@@ -563,7 +564,7 @@ SplitPage (
     ASSERT (SplitAttribute == Page2M || SplitAttribute == Page4K);\r
     if ((SplitAttribute == Page2M || SplitAttribute == Page4K)) {\r
       NewPageEntry = AllocatePagesFunc (1);\r
-      DEBUG ((DEBUG_INFO, "Split - 0x%x\n", NewPageEntry));\r
+      DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));\r
       if (NewPageEntry == NULL) {\r
         return RETURN_OUT_OF_RESOURCES;\r
       }\r
@@ -593,12 +594,14 @@ IsReadOnlyPageWriteProtected (
   VOID\r
   )\r
 {\r
+  IA32_CR0  Cr0;\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 () & CR0_WP) != 0);\r
+    Cr0.UintN = AsmReadCr0 ();\r
+    return (BOOLEAN) (Cr0.Bits.WP != 0);\r
   }\r
   return FALSE;\r
 }\r
@@ -611,12 +614,15 @@ DisableReadOnlyPageWriteProtect (
   VOID\r
   )\r
 {\r
+  IA32_CR0  Cr0;\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 () & ~CR0_WP);\r
+    Cr0.UintN = AsmReadCr0 ();\r
+    Cr0.Bits.WP = 0;\r
+    AsmWriteCr0 (Cr0.UintN);\r
   }\r
 }\r
 \r
@@ -628,12 +634,15 @@ EnableReadOnlyPageWriteProtect (
   VOID\r
   )\r
 {\r
+  IA32_CR0  Cr0;\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 () | CR0_WP);\r
+    Cr0.UintN = AsmReadCr0 ();\r
+    Cr0.Bits.WP = 1;\r
+    AsmWriteCr0 (Cr0.UintN);\r
   }\r
 }\r
 \r
@@ -1053,6 +1062,16 @@ InitializePageTablePool (
   VOID                      *Buffer;\r
   BOOLEAN                   IsModified;\r
 \r
+  //\r
+  // Do not allow re-entrance.\r
+  //\r
+  if (mPageTablePoolLock) {\r
+    return FALSE;\r
+  }\r
+\r
+  mPageTablePoolLock = TRUE;\r
+  IsModified = FALSE;\r
+\r
   //\r
   // Always reserve at least PAGE_TABLE_POOL_UNIT_PAGES, including one page for\r
   // header.\r
@@ -1063,9 +1082,15 @@ InitializePageTablePool (
   Buffer = AllocateAlignedPages (PoolPages, PAGE_TABLE_POOL_ALIGNMENT);\r
   if (Buffer == NULL) {\r
     DEBUG ((DEBUG_ERROR, "ERROR: Out of aligned pages\r\n"));\r
-    return FALSE;\r
+    goto Done;\r
   }\r
 \r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "Paging: added %lu pages to page table pool\r\n",\r
+    (UINT64)PoolPages\r
+    ));\r
+\r
   //\r
   // Link all pools into a list for easier track later.\r
   //\r
@@ -1099,7 +1124,9 @@ InitializePageTablePool (
     );\r
   ASSERT (IsModified == TRUE);\r
 \r
-  return TRUE;\r
+Done:\r
+  mPageTablePoolLock = FALSE;\r
+  return IsModified;\r
 }\r
 \r
 /**\r
@@ -1181,7 +1208,7 @@ DebugExceptionHandler (
 \r
   for (PFEntry = 0; PFEntry < mPFEntryCount[CpuIndex]; PFEntry++) {\r
     if (mLastPFEntryPointer[CpuIndex][PFEntry] != NULL) {\r
-      *mLastPFEntryPointer[CpuIndex][PFEntry] &= ~IA32_PG_P;\r
+      *mLastPFEntryPointer[CpuIndex][PFEntry] &= ~(UINT64)IA32_PG_P;\r
     }\r
   }\r
 \r
@@ -1288,7 +1315,16 @@ PageFaultExceptionHandler (
   // Display ExceptionType, CPU information and Image information\r
   //\r
   DumpCpuContext (ExceptionType, SystemContext);\r
-  if (!NonStopMode) {\r
+  if (NonStopMode) {\r
+    //\r
+    // Set TF in EFLAGS\r
+    //\r
+    if (mPagingContext.MachineType == IMAGE_FILE_MACHINE_I386) {\r
+      SystemContext.SystemContextIa32->Eflags |= (UINT32)BIT8;\r
+    } else {\r
+      SystemContext.SystemContextX64->Rflags |= (UINT64)BIT8;\r
+    }\r
+  } else {\r
     CpuDeadLoop ();\r
   }\r
 }\r