summaryrefslogtreecommitdiff
path: root/OvmfPkg/Sec/SecMain.c
diff options
context:
space:
mode:
Diffstat (limited to 'OvmfPkg/Sec/SecMain.c')
-rw-r--r--OvmfPkg/Sec/SecMain.c144
1 files changed, 142 insertions, 2 deletions
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index 3882dadd63..56081c9b44 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -1,7 +1,7 @@
/** @file
Main SEC phase code. Transitions to PEI.
- Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2008 - 2013, 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
@@ -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,137 @@ 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;
+ 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 NextAllocAddress;
+ 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.
+ //
+ NumberOfPml4EntriesNeeded = 1;
+ NumberOfPdpEntriesNeeded = 4;
+
+ NextAllocAddress = (UINTN) Location;
+
+ //
+ // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
+ //
+ PageMap = (VOID *) NextAllocAddress;
+ NextAllocAddress += 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 *) NextAllocAddress;
+ NextAllocAddress += 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 *) NextAllocAddress;
+ NextAllocAddress += 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 +778,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.
//