Previously we would run using page tables built into the
firmware device.

If a flash memory is available, it is unsafe for the page
tables to be stored in memory since the processor may try
to write to the page table data structures.

Additionally, when KVM ROM support is enabled for the
firmware device, then PEI fails to boot when the page
tables are in the firmware device.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.jus...@intel.com>
---
 OvmfPkg/Sec/SecMain.c |  165 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 164 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index 3882dad..0f2b9c9 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -31,6 +31,8 @@
 
 #include <Ppi/TemporaryRamSupport.h>
 
+#include <IndustryStandard/X64Paging.h>
+
 #define SEC_IDT_ENTRY_COUNT  34
 
 typedef struct _SEC_IDT_TABLE {
@@ -523,6 +525,160 @@ FindImageBase (
   }
 }
 
+#if defined (MDE_CPU_X64)
+/**
+  Allocates and fills in the Page Directory and Page Table Entries to
+  establish a 1:1 Virtual to Physical mapping.
+
+  @param  Location   Memory to build the page tables in
+
+**/
+VOID
+Create4GbIdentityMappingPageTables (
+  VOID *Location
+  )
+{
+  UINT32                                        RegEax;
+  UINT32                                        RegEdx;
+  UINT8                                         PhysicalAddressBits;
+  EFI_PHYSICAL_ADDRESS                          PageAddress;
+  UINTN                                         IndexOfPml4Entries;
+  UINTN                                         IndexOfPdpEntries;
+  UINTN                                         IndexOfPageDirectoryEntries;
+  UINT32                                        NumberOfPml4EntriesNeeded;
+  UINT32                                        NumberOfPdpEntriesNeeded;
+  X64_PAGE_MAP_AND_DIRECTORY_POINTER            *PageMapLevel4Entry;
+  X64_PAGE_MAP_AND_DIRECTORY_POINTER            *PageMap;
+  X64_PAGE_MAP_AND_DIRECTORY_POINTER            *PageDirectoryPointerEntry;
+  X64_PAGE_TABLE_ENTRY                          *PageDirectoryEntry;
+  UINTN                                         TotalPagesNum;
+  UINTN                                         BigPageAddress;
+  BOOLEAN                                       Page1GSupport;
+  X64_PAGE_TABLE_1G_ENTRY                       *PageDirectory1GEntry;
+
+  Page1GSupport = FALSE;
+  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+  if (RegEax >= 0x80000001) {
+    AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+    if ((RegEdx & BIT26) != 0) {
+      Page1GSupport = TRUE;
+    }
+  }
+
+  //
+  // Only build entries for the first 4GB at this stage.
+  //
+  // DXE IPL will build tables for the rest of the processor's
+  // address space.
+  //
+  PhysicalAddressBits = 32;
+
+  //
+  // Calculate the table entries needed.
+  //
+  if (PhysicalAddressBits <= 39 ) {
+    NumberOfPml4EntriesNeeded = 1;
+    NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 
30));
+  } else {
+    NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 
39));
+    NumberOfPdpEntriesNeeded = 512;
+  }
+
+  //
+  // Pre-allocate big pages to avoid later allocations. 
+  //
+  if (!Page1GSupport) {
+    TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded 
+ 1;
+  } else {
+    TotalPagesNum = NumberOfPml4EntriesNeeded + 1;
+  }
+  BigPageAddress = (UINTN) Location;
+
+  //
+  // By architecture only one PageMapLevel4 exists - so lets allocate storage 
for it.
+  //
+  PageMap         = (VOID *) BigPageAddress;
+  BigPageAddress += SIZE_4KB;
+
+  PageMapLevel4Entry = PageMap;
+  PageAddress        = 0;
+  for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; 
IndexOfPml4Entries++, PageMapLevel4Entry++) {
+    //
+    // Each PML4 entry points to a page of Page Directory Pointer entires.
+    // So lets allocate space for them and fill them in in the 
IndexOfPdpEntries loop.
+    //
+    PageDirectoryPointerEntry = (VOID *) BigPageAddress;
+    BigPageAddress += SIZE_4KB;
+
+    //
+    // Make a PML4 Entry
+    //
+    PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
+    PageMapLevel4Entry->Bits.ReadWrite = 1;
+    PageMapLevel4Entry->Bits.Present = 1;
+
+    if (Page1GSupport) {
+      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;
+      }
+    } else {
+      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 *) BigPageAddress;
+        BigPageAddress += SIZE_4KB;
+
+        //
+        // Fill in a Page Directory Pointer Entries
+        //
+        PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;
+        PageDirectoryPointerEntry->Bits.ReadWrite = 1;
+        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;
+        }
+      }
+
+      for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, 
PageDirectoryPointerEntry++) {
+        ZeroMem (
+          PageDirectoryPointerEntry,
+          sizeof(X64_PAGE_MAP_AND_DIRECTORY_POINTER)
+          );
+      }
+    }
+  }
+
+  //
+  // For the PML4 entries we are not using fill in a null entry.
+  //
+  for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) 
{
+    ZeroMem (
+      PageMapLevel4Entry,
+      sizeof (X64_PAGE_MAP_AND_DIRECTORY_POINTER)
+      );
+  }
+
+  AsmWriteCr3 ((UINTN) PageMap);
+}
+#endif
+
 /*
   Find and return Pei Core entry point.
 
@@ -645,7 +801,14 @@ SecCoreStartupWithStack (
   //
   IoWrite8 (0x21, 0xff);
   IoWrite8 (0xA1, 0xff);
-  
+
+#if defined (MDE_CPU_X64)
+  //
+  // Create Identity Mapped Pages in RAM
+  //
+  Create4GbIdentityMappingPageTables (TopOfCurrentStack);
+#endif
+
   //
   // Initialize Debug Agent to support source level debug in SEC/PEI phases 
before memory ready.
   //
-- 
1.7.10.4


------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to