]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
MdeModulePkg/DxeIplPeim: reserve page 0 for NULL pointer detection
[mirror_edk2.git] / MdeModulePkg / Core / DxeIplPeim / Ia32 / DxeLoadFunc.c
index c1ff4b7e64340526485ed7d6467f15834e5c70f3..6e8ca824d469e9db51405fc673c41d539e750436 100644 (file)
@@ -1,14 +1,10 @@
 /** @file\r
   Ia32-specific functionality for DxeLoad.\r
 \r
-Copyright (c) 2006 - 2015, 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
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\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
@@ -71,7 +67,7 @@ Create4GPageTablesIa32Pae (
   IN EFI_PHYSICAL_ADDRESS   StackBase,\r
   IN UINTN                  StackSize\r
   )\r
-{  \r
+{\r
   UINT8                                         PhysicalAddressBits;\r
   EFI_PHYSICAL_ADDRESS                          PhysicalAddress;\r
   UINTN                                         IndexOfPdpEntries;\r
@@ -82,6 +78,12 @@ Create4GPageTablesIa32Pae (
   PAGE_TABLE_ENTRY                              *PageDirectoryEntry;\r
   UINTN                                         TotalPagesNum;\r
   UINTN                                         PageAddress;\r
+  UINT64                                        AddressEncMask;\r
+\r
+  //\r
+  // Make sure AddressEncMask is contained to smallest supported address field\r
+  //\r
+  AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;\r
 \r
   PhysicalAddressBits = 32;\r
 \r
@@ -91,7 +93,7 @@ Create4GPageTablesIa32Pae (
   NumberOfPdpEntriesNeeded = (UINT32) LShiftU64 (1, (PhysicalAddressBits - 30));\r
 \r
   TotalPagesNum = NumberOfPdpEntriesNeeded + 1;\r
-  PageAddress = (UINTN) AllocatePages (TotalPagesNum);\r
+  PageAddress = (UINTN) AllocatePageTableMemory (TotalPagesNum);\r
   ASSERT (PageAddress != 0);\r
 \r
   PageMap = (VOID *) PageAddress;\r
@@ -104,18 +106,20 @@ Create4GPageTablesIa32Pae (
     //\r
     // Each Directory Pointer entries points to a page of Page Directory entires.\r
     // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.\r
-    //       \r
+    //\r
     PageDirectoryEntry = (VOID *) PageAddress;\r
     PageAddress += SIZE_4KB;\r
 \r
     //\r
     // Fill in a Page Directory Pointer Entries\r
     //\r
-    PageDirectoryPointerEntry->Uint64 = (UINT64) (UINTN) PageDirectoryEntry;\r
+    PageDirectoryPointerEntry->Uint64 = (UINT64) (UINTN) PageDirectoryEntry | AddressEncMask;\r
     PageDirectoryPointerEntry->Bits.Present = 1;\r
 \r
     for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {\r
-      if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase)) {\r
+      if ((IsNullDetectionEnabled () && PhysicalAddress == 0)\r
+          || ((PhysicalAddress < StackBase + StackSize)\r
+              && ((PhysicalAddress + SIZE_2MB) > StackBase))) {\r
         //\r
         // Need to split this 2M page that covers stack range.\r
         //\r
@@ -124,7 +128,7 @@ Create4GPageTablesIa32Pae (
         //\r
         // Fill in the Page Directory entries\r
         //\r
-        PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress;\r
+        PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress | AddressEncMask;\r
         PageDirectoryEntry->Bits.ReadWrite = 1;\r
         PageDirectoryEntry->Bits.Present = 1;\r
         PageDirectoryEntry->Bits.MustBe1 = 1;\r
@@ -139,6 +143,12 @@ Create4GPageTablesIa32Pae (
       );\r
   }\r
 \r
+  //\r
+  // Protect the page table by marking the memory used for page table to be\r
+  // read-only.\r
+  //\r
+  EnablePageTableProtection ((UINTN)PageMap, FALSE);\r
+\r
   return (UINTN) PageMap;\r
 }\r
 \r
@@ -171,34 +181,38 @@ IsIa32PaeSupport (
 }\r
 \r
 /**\r
-  The function will check if Execute Disable Bit is available.\r
+  The function will check if page table should be setup or not.\r
 \r
-  @retval TRUE      Execute Disable Bit is available.\r
-  @retval FALSE     Execute Disable Bit is not available.\r
+  @retval TRUE      Page table should be created.\r
+  @retval FALSE     Page table should not be created.\r
 \r
 **/\r
 BOOLEAN\r
-IsExecuteDisableBitAvailable (\r
+ToBuildPageTable (\r
   VOID\r
   )\r
 {\r
-  UINT32            RegEax;\r
-  UINT32            RegEdx;\r
-  BOOLEAN           Available;\r
+  if (!IsIa32PaeSupport ()) {\r
+    return FALSE;\r
+  }\r
 \r
-  Available = FALSE;\r
-  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
-  if (RegEax >= 0x80000001) {\r
-    AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);\r
-    if ((RegEdx & BIT20) != 0) {\r
-      //\r
-      // Bit 20: Execute Disable Bit available.\r
-      //\r
-      Available = TRUE;\r
-    }\r
+  if (IsNullDetectionEnabled ()) {\r
+    return TRUE;\r
+  }\r
+\r
+  if (PcdGet8 (PcdHeapGuardPropertyMask) != 0) {\r
+    return TRUE;\r
   }\r
 \r
-  return Available;\r
+  if (PcdGetBool (PcdCpuStackGuard)) {\r
+    return TRUE;\r
+  }\r
+\r
+  if (IsEnableNonExecNeeded ()) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
 }\r
 \r
 /**\r
@@ -232,6 +246,14 @@ HandOffToDxeCore (
   EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;\r
   BOOLEAN                   BuildPageTablesIa32Pae;\r
 \r
+  //\r
+  // Clear page 0 and mark it as allocated if NULL pointer detection is enabled.\r
+  //\r
+  if (IsNullDetectionEnabled ()) {\r
+    ClearFirst4KPage (HobList.Raw);\r
+    BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData);\r
+  }\r
+\r
   Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -265,9 +287,16 @@ HandOffToDxeCore (
     //\r
     // End of PEI phase signal\r
     //\r
+    PERF_EVENT_SIGNAL_BEGIN (gEndOfPeiSignalPpi.Guid);\r
     Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);\r
+    PERF_EVENT_SIGNAL_END (gEndOfPeiSignalPpi.Guid);\r
     ASSERT_EFI_ERROR (Status);\r
 \r
+    //\r
+    // Paging might be already enabled. To avoid conflict configuration,\r
+    // disable paging first anyway.\r
+    //\r
+    AsmWriteCr0 (AsmReadCr0 () & (~BIT31));\r
     AsmWriteCr3 (PageTables);\r
 \r
     //\r
@@ -280,7 +309,7 @@ HandOffToDxeCore (
     Status = PeiServicesAllocatePages (\r
                EfiBootServicesData,\r
                EFI_SIZE_TO_PAGES(sizeof (X64_IDT_TABLE) + SizeOfTemplate * IDT_ENTRY_COUNT),\r
-               (EFI_PHYSICAL_ADDRESS *) &IdtTableForX64\r
+               &VectorAddress\r
                );\r
     ASSERT_EFI_ERROR (Status);\r
 \r
@@ -288,6 +317,7 @@ HandOffToDxeCore (
     // Store EFI_PEI_SERVICES** in the 4 bytes immediately preceding IDT to avoid that\r
     // it may not be gotten correctly after IDT register is re-written.\r
     //\r
+    IdtTableForX64 = (X64_IDT_TABLE *) (UINTN) VectorAddress;\r
     IdtTableForX64->PeiService = GetPeiServicesTablePointer ();\r
 \r
     VectorAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (IdtTableForX64 + 1);\r
@@ -317,6 +347,14 @@ HandOffToDxeCore (
 \r
     AsmWriteIdtr (&gLidtDescriptor);\r
 \r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n",\r
+      __FUNCTION__,\r
+      BaseOfStack,\r
+      STACK_SIZE\r
+      ));\r
+\r
     //\r
     // Go to Long Mode and transfer control to DxeCore.\r
     // Interrupts will not get turned on until the CPU AP is loaded.\r
@@ -361,19 +399,29 @@ HandOffToDxeCore (
     TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;\r
     TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
 \r
-    BuildPageTablesIa32Pae = (BOOLEAN) (PcdGetBool (PcdSetNxForStack) && IsIa32PaeSupport () && IsExecuteDisableBitAvailable ());\r
+    PageTables = 0;\r
+    BuildPageTablesIa32Pae = ToBuildPageTable ();\r
     if (BuildPageTablesIa32Pae) {\r
       PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);\r
-      EnableExecuteDisableBit ();\r
+      if (IsEnableNonExecNeeded ()) {\r
+        EnableExecuteDisableBit();\r
+      }\r
     }\r
 \r
     //\r
     // End of PEI phase signal\r
     //\r
+    PERF_EVENT_SIGNAL_BEGIN (gEndOfPeiSignalPpi.Guid);\r
     Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);\r
+    PERF_EVENT_SIGNAL_END (gEndOfPeiSignalPpi.Guid);\r
     ASSERT_EFI_ERROR (Status);\r
 \r
     if (BuildPageTablesIa32Pae) {\r
+      //\r
+      // Paging might be already enabled. To avoid conflict configuration,\r
+      // disable paging first anyway.\r
+      //\r
+      AsmWriteCr0 (AsmReadCr0 () & (~BIT31));\r
       AsmWriteCr3 (PageTables);\r
       //\r
       // Set Physical Address Extension (bit 5 of CR4).\r
@@ -386,6 +434,14 @@ HandOffToDxeCore (
     //\r
     UpdateStackHob (BaseOfStack, STACK_SIZE);\r
 \r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n",\r
+      __FUNCTION__,\r
+      BaseOfStack,\r
+      STACK_SIZE\r
+      ));\r
+\r
     //\r
     // Transfer the control to the entry point of DxeCore.\r
     //\r