Reviewed by: Yao, Jiewen <jiewen....@intel.com>

-----Original Message-----
From: Zeng, Star 
Sent: Friday, July 31, 2015 8:23 PM
To: edk2-devel@lists.01.org
Cc: Yao, Jiewen
Subject: [PATCH] MdeModulePkg DxeIpl: Add stack NX support

This feature is added for UEFI spec that says "Stack may be marked as 
non-executable in identity mapped page tables".
A PCD PcdSetNxForStack is added to turn on/off this feature, and it is FALSE by 
default.

Cc: Jiewen Yao <jiewen....@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.z...@intel.com>
---
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf          |   3 +-
 MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c  | 185 ++++++++++++++++++++++-
 MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c   |  10 +-
 MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 160 +++++++++++++++++---  
MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h |  61 +++++++-
 MdeModulePkg/MdeModulePkg.dec                    |  11 +-
 MdeModulePkg/MdeModulePkg.uni                    | Bin 166792 -> 168862 bytes
 7 files changed, 392 insertions(+), 38 deletions(-)

diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf 
b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
index 1473ccd..66c58b1 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
@@ -5,7 +5,7 @@
 #  PPI to discover and dispatch the DXE Foundation and components that are  #  
needed to run the DXE Foundation.
 #
-#  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2006 - 2015, Intel Corporation. All rights 
+reserved.<BR>
 #  This program and the accompanying materials  #  are licensed and made 
available under the terms and conditions of the BSD License  #  which 
accompanies this distribution.  The full text of the license may be found at @@ 
-104,6 +104,7 @@ [FeaturePcd]
 
 [Pcd.IA32,Pcd.X64]
   gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable              ## 
SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack               ## 
SOMETIMES_CONSUMES
 
 [Depex]
   gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiLoadFilePpiGuid AND 
gEfiPeiMasterBootModePpiGuid diff --git 
a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c 
b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
index 38832cc..c1ff4b7 100644
--- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
+++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
@@ -1,7 +1,7 @@
 /** @file
   Ia32-specific functionality for DxeLoad.
 
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials  are licensed and made available 
under the terms and conditions of the BSD License  which accompanies this 
distribution.  The full text of the license may be found at @@ -57,6 +57,151 @@ 
GLOBAL_REMOVE_IF_UNREFERENCED  IA32_DESCRIPTOR gLidtDescriptor = {  };
 
 /**
+  Allocates and fills in the Page Directory and Page Table Entries to  
+ establish a 4G page table.
+
+  @param[in] StackBase  Stack base address.
+  @param[in] StackSize  Stack size.
+
+  @return The address of page table.
+
+**/
+UINTN
+Create4GPageTablesIa32Pae (
+  IN EFI_PHYSICAL_ADDRESS   StackBase,
+  IN UINTN                  StackSize
+  )
+{  
+  UINT8                                         PhysicalAddressBits;
+  EFI_PHYSICAL_ADDRESS                          PhysicalAddress;
+  UINTN                                         IndexOfPdpEntries;
+  UINTN                                         IndexOfPageDirectoryEntries;
+  UINT32                                        NumberOfPdpEntriesNeeded;
+  PAGE_MAP_AND_DIRECTORY_POINTER                *PageMap;
+  PAGE_MAP_AND_DIRECTORY_POINTER                *PageDirectoryPointerEntry;
+  PAGE_TABLE_ENTRY                              *PageDirectoryEntry;
+  UINTN                                         TotalPagesNum;
+  UINTN                                         PageAddress;
+
+  PhysicalAddressBits = 32;
+
+  //
+  // Calculate the table entries needed.
+  //
+  NumberOfPdpEntriesNeeded = (UINT32) LShiftU64 (1, 
+ (PhysicalAddressBits - 30));
+
+  TotalPagesNum = NumberOfPdpEntriesNeeded + 1;  PageAddress = (UINTN) 
+ AllocatePages (TotalPagesNum);  ASSERT (PageAddress != 0);
+
+  PageMap = (VOID *) PageAddress;
+  PageAddress += SIZE_4KB;
+
+  PageDirectoryPointerEntry = PageMap;
+  PhysicalAddress = 0;
+
+  for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; 
IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
+    //
+    // Each Directory Pointer entries points to a page of Page Directory 
entires.
+    // So allocate space for them and fill them in in the 
IndexOfPageDirectoryEntries loop.
+    //       
+    PageDirectoryEntry = (VOID *) PageAddress;
+    PageAddress += SIZE_4KB;
+
+    //
+    // Fill in a Page Directory Pointer Entries
+    //
+    PageDirectoryPointerEntry->Uint64 = (UINT64) (UINTN) PageDirectoryEntry;
+    PageDirectoryPointerEntry->Bits.Present = 1;
+
+    for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; 
IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += 
SIZE_2MB) {
+      if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + 
SIZE_2MB) > StackBase)) {
+        //
+        // Need to split this 2M page that covers stack range.
+        //
+        Split2MPageTo4K (PhysicalAddress, (UINT64 *) PageDirectoryEntry, 
StackBase, StackSize);
+      } else {
+        //
+        // Fill in the Page Directory entries
+        //
+        PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress;
+        PageDirectoryEntry->Bits.ReadWrite = 1;
+        PageDirectoryEntry->Bits.Present = 1;
+        PageDirectoryEntry->Bits.MustBe1 = 1;
+      }
+    }
+  }
+
+  for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, 
PageDirectoryPointerEntry++) {
+    ZeroMem (
+      PageDirectoryPointerEntry,
+      sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
+      );
+  }
+
+  return (UINTN) PageMap;
+}
+
+/**
+  The function will check if IA32 PAE is supported.
+
+  @retval TRUE      IA32 PAE is supported.
+  @retval FALSE     IA32 PAE is not supported.
+
+**/
+BOOLEAN
+IsIa32PaeSupport (
+  VOID
+  )
+{
+  UINT32            RegEax;
+  UINT32            RegEdx;
+  BOOLEAN           Ia32PaeSupport;
+
+  Ia32PaeSupport = FALSE;
+  AsmCpuid (0x0, &RegEax, NULL, NULL, NULL);  if (RegEax >= 0x1) {
+    AsmCpuid (0x1, NULL, NULL, NULL, &RegEdx);
+    if ((RegEdx & BIT6) != 0) {
+      Ia32PaeSupport = TRUE;
+    }
+  }
+
+  return Ia32PaeSupport;
+}
+
+/**
+  The function will check if Execute Disable Bit is available.
+
+  @retval TRUE      Execute Disable Bit is available.
+  @retval FALSE     Execute Disable Bit is not available.
+
+**/
+BOOLEAN
+IsExecuteDisableBitAvailable (
+  VOID
+  )
+{
+  UINT32            RegEax;
+  UINT32            RegEdx;
+  BOOLEAN           Available;
+
+  Available = FALSE;
+  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);  if (RegEax >= 
+ 0x80000001) {
+    AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+    if ((RegEdx & BIT20) != 0) {
+      //
+      // Bit 20: Execute Disable Bit available.
+      //
+      Available = TRUE;
+    }
+  }
+
+  return Available;
+}
+
+/**
    Transfers control to DxeCore.
 
    This function performs a CPU architecture specific operations to execute @@ 
-85,6 +230,7 @@ HandOffToDxeCore (
   X64_IDT_TABLE             *IdtTableForX64;
   EFI_VECTOR_HANDOFF_INFO   *VectorInfo;
   EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
+  BOOLEAN                   BuildPageTablesIa32Pae;
 
   Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES 
(STACK_SIZE), &BaseOfStack);
   ASSERT_EFI_ERROR (Status);
@@ -114,7 +260,7 @@ HandOffToDxeCore (
     //
     // Create page table and save PageMapLevel4 to CR3
     //
-    PageTables = CreateIdentityMappingPageTables ();
+    PageTables = CreateIdentityMappingPageTables (BaseOfStack, 
+ STACK_SIZE);
 
     //
     // End of PEI phase signal
@@ -215,12 +361,26 @@ HandOffToDxeCore (
     TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE 
- CPU_STACK_ALIGNMENT;
     TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 
CPU_STACK_ALIGNMENT);
 
+    BuildPageTablesIa32Pae = (BOOLEAN) (PcdGetBool (PcdSetNxForStack) && 
IsIa32PaeSupport () && IsExecuteDisableBitAvailable ());
+    if (BuildPageTablesIa32Pae) {
+      PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);
+      EnableExecuteDisableBit ();
+    }
+
     //
     // End of PEI phase signal
     //
     Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
     ASSERT_EFI_ERROR (Status);
 
+    if (BuildPageTablesIa32Pae) {
+      AsmWriteCr3 (PageTables);
+      //
+      // Set Physical Address Extension (bit 5 of CR4).
+      //
+      AsmWriteCr4 (AsmReadCr4 () | BIT5);
+    }
+
     //
     // Update the contents of BSP stack HOB to reflect the real stack info 
passed to DxeCore.
     //
@@ -229,12 +389,21 @@ HandOffToDxeCore (
     //
     // Transfer the control to the entry point of DxeCore.
     //
-    SwitchStack (
-      (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
-      HobList.Raw,
-      NULL,
-      (VOID *) (UINTN) TopOfStack
-      );
+    if (BuildPageTablesIa32Pae) {
+      AsmEnablePaging32 (
+        (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
+        HobList.Raw,
+        NULL,
+        (VOID *) (UINTN) TopOfStack
+        );
+    } else {
+      SwitchStack (
+        (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
+        HobList.Raw,
+        NULL,
+        (VOID *) (UINTN) TopOfStack
+        );
+    }
   }
 }
 
diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c 
b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
index 88f1f47..6488880 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
@@ -1,7 +1,7 @@
 /** @file
   x64-specifc functionality for DxeLoad.
 
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials  are licensed and made available 
under the terms and conditions of the BSD License  which accompanies this 
distribution.  The full text of the license may be found at @@ -84,7 +84,13 @@ 
HandOffToDxeCore (
     //
     // Create page table and save PageMapLevel4 to CR3
     //
-    PageTables = CreateIdentityMappingPageTables ();
+    PageTables = CreateIdentityMappingPageTables 
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) BaseOfStack, STACK_SIZE);  } else {
+    //
+    // Set NX for stack feature also require PcdDxeIplBuildPageTables be TRUE
+    // for the DxeIpl and the DxeCore are both X64.
+    //
+    ASSERT (PcdGetBool (PcdSetNxForStack) == FALSE);
   }
   
   //
diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c 
b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
index 795ae70..ab1e914 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
@@ -15,7 +15,7 @@
     2) IA-32 Intel(R) Architecture Software Developer's Manual Volume 
2:Instruction Set Reference, Intel
     3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System 
Programmer's Guide, Intel
 
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials  are licensed and made available 
under the terms and conditions of the BSD License  which accompanies this 
distribution.  The full text of the license may be found at @@ -30,20 +30,125 
@@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "VirtualMemory.h"
 
 /**
+  Enable Execute Disable Bit.
+
+**/
+VOID
+EnableExecuteDisableBit (
+  VOID
+  )
+{
+  UINT64           MsrRegisters;
+
+  MsrRegisters = AsmReadMsr64 (0xC0000080);
+  MsrRegisters |= BIT11;
+  AsmWriteMsr64 (0xC0000080, MsrRegisters); }
+
+/**
+  Split 2M page to 4K.
+
+  @param[in]      PhysicalAddress       Start physical address the 2M page 
covered.
+  @param[in, out] PageEntry2M           Pointer to 2M page entry.
+  @param[in]      StackBase             Stack base address.
+  @param[in]      StackSize             Stack size.
+
+**/
+VOID
+Split2MPageTo4K (
+  IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,
+  IN OUT UINT64                         *PageEntry2M,
+  IN EFI_PHYSICAL_ADDRESS               StackBase,
+  IN UINTN                              StackSize
+  )
+{
+  EFI_PHYSICAL_ADDRESS                  PhysicalAddress4K;
+  UINTN                                 IndexOfPageTableEntries;
+  PAGE_TABLE_4K_ENTRY                   *PageTableEntry;
+
+  PageTableEntry = AllocatePages (1);
+  //
+  // Fill in 2M page entry.
+  //
+  *PageEntry2M = (UINT64) (UINTN) PageTableEntry | IA32_PG_P | 
+ IA32_PG_RW;
+
+  PhysicalAddress4K = PhysicalAddress;
+  for (IndexOfPageTableEntries = 0; IndexOfPageTableEntries < 512; 
IndexOfPageTableEntries++, PageTableEntry++, PhysicalAddress4K += SIZE_4KB) {
+    //
+    // Fill in the Page Table entries
+    //
+    PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K;
+    PageTableEntry->Bits.ReadWrite = 1;
+    PageTableEntry->Bits.Present = 1;
+    if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + 
StackSize)) {
+      //
+      // Set Nx bit for stack.
+      //
+      PageTableEntry->Bits.Nx = 1;
+    }
+  }
+}
+
+/**
+  Split 1G page to 2M.
+
+  @param[in]      PhysicalAddress       Start physical address the 1G page 
covered.
+  @param[in, out] PageEntry1G           Pointer to 1G page entry.
+  @param[in]      StackBase             Stack base address.
+  @param[in]      StackSize             Stack size.
+
+**/
+VOID
+Split1GPageTo2M (
+  IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,
+  IN OUT UINT64                         *PageEntry1G,
+  IN EFI_PHYSICAL_ADDRESS               StackBase,
+  IN UINTN                              StackSize
+  )
+{
+  EFI_PHYSICAL_ADDRESS                  PhysicalAddress2M;
+  UINTN                                 IndexOfPageDirectoryEntries;
+  PAGE_TABLE_ENTRY                      *PageDirectoryEntry;
+
+  PageDirectoryEntry = AllocatePages (1);  //  // Fill in 1G page 
+ entry.
+  //
+  *PageEntry1G = (UINT64) (UINTN) PageDirectoryEntry | IA32_PG_P | 
+ IA32_PG_RW;
+
+  PhysicalAddress2M = PhysicalAddress;
+  for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; 
IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += 
SIZE_2MB) {
+    if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + 
SIZE_2MB) > StackBase)) {
+      //
+      // Need to split this 2M page that covers stack range.
+      //
+      Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, 
StackBase, StackSize);
+    } else {
+      //
+      // Fill in the Page Directory entries
+      //
+      PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress2M;
+      PageDirectoryEntry->Bits.ReadWrite = 1;
+      PageDirectoryEntry->Bits.Present = 1;
+      PageDirectoryEntry->Bits.MustBe1 = 1;
+    }
+  }
+}
+
+/**
   Allocates and fills in the Page Directory and Page Table Entries to
   establish a 1:1 Virtual to Physical mapping.
 
-  @param  NumberOfProcessorPhysicalAddressBits  Number of processor address 
bits 
-                                                to use. Limits the number of 
page 
-                                                table entries  to the physical 
-                                                address space. 
+  @param[in] StackBase  Stack base address.
+  @param[in] StackSize  Stack size.
 
   @return The address of 4 level page map.
 
 **/
 UINTN
 CreateIdentityMappingPageTables (
-  VOID
+  IN EFI_PHYSICAL_ADDRESS   StackBase,
+  IN UINTN                  StackSize
   )
 {  
   UINT32                                        RegEax;
@@ -149,13 +254,17 @@ CreateIdentityMappingPageTables (
       PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
     
       for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; 
IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) 
{
-        //
-        // Fill in the Page Directory entries
-        //
-        PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
-        PageDirectory1GEntry->Bits.ReadWrite = 1;
-        PageDirectory1GEntry->Bits.Present = 1;
-        PageDirectory1GEntry->Bits.MustBe1 = 1;
+        if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + 
StackSize) && ((PageAddress + SIZE_1GB) > StackBase)) {
+          Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, 
StackBase, StackSize);
+        } else {
+          //
+          // Fill in the Page Directory entries
+          //
+          PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
+          PageDirectory1GEntry->Bits.ReadWrite = 1;
+          PageDirectory1GEntry->Bits.Present = 1;
+          PageDirectory1GEntry->Bits.MustBe1 = 1;
+        }
       }
     } else {
       for (IndexOfPdpEntries = 0; IndexOfPdpEntries < 
NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { 
@@ -174,13 +283,20 @@ CreateIdentityMappingPageTables (
         PageDirectoryPointerEntry->Bits.Present = 1;
 
         for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 
512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += 
SIZE_2MB) {
-          //
-          // Fill in the Page Directory entries
-          //
-          PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
-          PageDirectoryEntry->Bits.ReadWrite = 1;
-          PageDirectoryEntry->Bits.Present = 1;
-          PageDirectoryEntry->Bits.MustBe1 = 1;
+          if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + 
StackSize) && ((PageAddress + SIZE_2MB) > StackBase)) {
+            //
+            // Need to split this 2M page that covers stack range.
+            //
+            Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, 
StackBase, StackSize);
+          } else {
+            //
+            // Fill in the Page Directory entries
+            //
+            PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
+            PageDirectoryEntry->Bits.ReadWrite = 1;
+            PageDirectoryEntry->Bits.Present = 1;
+            PageDirectoryEntry->Bits.MustBe1 = 1;
+          }
         }
       }
 
@@ -203,6 +319,10 @@ CreateIdentityMappingPageTables (
       );
   }
 
+  if (PcdGetBool (PcdSetNxForStack)) {
+    EnableExecuteDisableBit ();
+  }
+
   return (UINTN)PageMap;
 }
 
diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h 
b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
index 87a27b0..20c31f5 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
@@ -7,7 +7,7 @@
     3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System 
Programmer's Guide, Intel
     4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
 
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials  are licensed and made available 
under the terms and conditions of the BSD License  which accompanies this 
distribution.  The full text of the license may be found at @@ -74,6 +74,28 @@ 
typedef union {  } PAGE_MAP_AND_DIRECTORY_POINTER;
 
 //
+// Page Table Entry 4KB
+//
+typedef union {
+  struct {
+    UINT64  Present:1;                // 0 = Not present in memory, 1 = 
Present in memory
+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write
+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User
+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 
1=Write-Through caching
+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached
+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set 
by CPU)
+    UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by 
processor on access to page
+    UINT64  PAT:1;                    //
+    UINT64  Global:1;                 // 0 = Not global page, 1 = global page 
TLB not cleared on CR3 write
+    UINT64  Available:3;              // Available for use by system software
+    UINT64  PageTableBaseAddress:40;  // Page Table Base Address
+    UINT64  AvabilableHigh:11;        // Available for use by system software
+    UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code 
Execution
+  } Bits;
+  UINT64    Uint64;
+} PAGE_TABLE_4K_ENTRY;
+
+//
 // Page Table Entry 2MB
 //
 typedef union {
@@ -123,22 +145,49 @@ typedef union {
 
 #pragma pack()
 
+#define IA32_PG_P                   BIT0
+#define IA32_PG_RW                  BIT1
+
+/**
+  Enable Execute Disable Bit.
+
+**/
+VOID
+EnableExecuteDisableBit (
+  VOID
+  );
+
+/**
+  Split 2M page to 4K.
+
+  @param[in]      PhysicalAddress       Start physical address the 2M page 
covered.
+  @param[in, out] PageEntry2M           Pointer to 2M page entry.
+  @param[in]      StackBase             Stack base address.
+  @param[in]      StackSize             Stack size.
+
+**/
+VOID
+Split2MPageTo4K (
+  IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,
+  IN OUT UINT64                         *PageEntry2M,
+  IN EFI_PHYSICAL_ADDRESS               StackBase,
+  IN UINTN                              StackSize
+  );
 
 /**
   Allocates and fills in the Page Directory and Page Table Entries to
   establish a 1:1 Virtual to Physical mapping.
 
-  @param  NumberOfProcessorPhysicalAddressBits  Number of processor address 
bits 
-                                                to use. Limits the number of 
page 
-                                                table entries  to the physical 
-                                                address space. 
+  @param[in] StackBase  Stack base address.
+  @param[in] StackSize  Stack size.
 
   @return The address of 4 level page map.
 
 **/
 UINTN
 CreateIdentityMappingPageTables (
-  VOID
+  IN EFI_PHYSICAL_ADDRESS   StackBase,
+  IN UINTN                  StackSize
   );
 
 
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec 
index 4a1acac..3b5617a 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -948,7 +948,16 @@ [PcdsFixedAtBuild, PcdsPatchableInModule]
   ## The number of bytes between registers in serial device.  The default is 1 
byte.
   # @Prompt Serial Port Register Stride in Bytes
   gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1|UINT32|0x0001006d
-  
+
+  ## Indicates if to set NX for stack.<BR><BR>  #  For the DxeIpl and 
+ the DxeCore are both X64, set NX for stack feature also require 
+ PcdDxeIplBuildPageTables be TRUE.<BR>  #  For the DxeIpl and the 
+ DxeCore are both IA32 (PcdDxeIplSwitchToLongMode is FALSE), set NX for stack 
feature also require  #  IA32 PAE is supported and Execute Disable Bit is 
available.<BR>
+  #   TRUE  - to set NX for stack.<BR>
+  #   FALSE - Not to set NX for stack.<BR>
+  # @Prompt Set NX for stack.
+  
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack|FALSE|BOOLEAN|0x000100
+ 6f
+
 [PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## This PCD defines the Console output row. The default value is 25 
according to UEFI spec.
   #  This PCD could be set to 0 then console output would be at max column and 
max row.
diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni 
index 
e90e7d1e8fdeb0ead04bf689ddf83c1237aba855..da6649cd9176ff5cc801d3039e43bef613f831bc
 100644 GIT binary patch delta 574 
zcmeB}&NXj2*M>tZn~$(edpg;nhDEf5!H=PW!HprGp@<=vp@bokA(<h2y5M9+bJ<iN
zR{<y;0VLDF3KSTMVM-<!c4Z4=(LDWO43qC<zttQBv@?nePgdeyHF-ik3p3E}>2J%J
z0+n@uHWf4Ax3`{8R6GZ$Dj%q}2&lG@p_CyL%u<-{sKO*X{X+?poTLIn5>QToA%r1_
zA(X+DL65<P!3oH=o2<ya8rf2BZcheB24e;zpkfV>0ix4)<uS=kR%#Yf)np*jL84e4
z1hy){mW3B)egM!W*UA3+vbu>3c?>B)8(o26p9&1|Qed!xoa+MgN-;1Fk{EKpd?z5k
zWcprZChf@@+)E}aR0`>rfPGFNlra1&r0WON2Z~Rk^iNi_FPyCKMP~8_M}g+HSKHfO
IF)}R#0Esh#_5c6?

delta 25
hcmbQYoU3Cx*M>tZj0&3%vP^&4T<~do!6!z&g#eQY3(^1p

--
1.9.5.msysgit.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to