]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Create X64 mode page tables in memory even when PEI is already X64
authormdkinney <mdkinney@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 15 Nov 2008 23:59:07 +0000 (23:59 +0000)
committermdkinney <mdkinney@6f19259b-4bc3-4df7-8a09-765794883524>
Sat, 15 Nov 2008 23:59:07 +0000 (23:59 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@6550 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c [new file with mode: 0644]
MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h [new file with mode: 0644]

index 29f03173abba55756b6b1525f61a2a81376949c5..94dfcab7a3bd234b780b9eaa4687396876acdea5 100644 (file)
@@ -46,6 +46,8 @@
   Ia32/IdtVectorAsm.S | GCC\r
 \r
 [Sources.X64, Sources.EBC]\r
+  X64/VirtualMemory.h\r
+  X64/VirtualMemory.c\r
   X64/DxeLoadFunc.c\r
   Ia32/ImageRead.c\r
 \r
index 51055e157aa87f08ed947714b31f8de7eaf0ca95..05c5203d820f5706a2b4ba6c27b577f21e21b3cd 100644 (file)
@@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 \r
 #include "DxeIpl.h"\r
+#include "X64/VirtualMemory.h"\r
 \r
 \r
 \r
@@ -36,6 +37,7 @@ HandOffToDxeCore (
   VOID                *BaseOfStack;\r
   VOID                *TopOfStack;\r
   EFI_STATUS          Status;\r
+  UINTN               PageTables;\r
 \r
   //\r
   // Allocate 128KB for the Stack\r
@@ -50,12 +52,19 @@ HandOffToDxeCore (
   TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);\r
   TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
 \r
+  //\r
+  // Create page table and save PageMapLevel4 to CR3\r
+  //\r
+  PageTables = CreateIdentityMappingPageTables ();\r
+\r
   //\r
   // End of PEI phase singal\r
   //\r
   Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  AsmWriteCr3 (PageTables);\r
+\r
   //\r
   // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.\r
   //    \r
diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
new file mode 100644 (file)
index 0000000..35e92c6
--- /dev/null
@@ -0,0 +1,162 @@
+/** @file\r
+  x64 Virtual Memory Management Services in the form of an IA-32 driver.  \r
+  Used to establish a 1:1 Virtual to Physical Mapping that is required to\r
+  enter Long Mode (x64 64-bit mode).\r
+\r
+  While we make a 1:1 mapping (identity mapping) for all physical pages \r
+  we still need to use the MTRR's to ensure that the cachability attirbutes\r
+  for all memory regions is correct.\r
+\r
+  The basic idea is to use 2MB page table entries where ever possible. If\r
+  more granularity of cachability is required then 4K page tables are used.\r
+\r
+  References:\r
+    1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel\r
+    2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel\r
+    3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel\r
+\r
+Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+\r
+**/  \r
+\r
+#include "DxeIpl.h"\r
+#include "VirtualMemory.h"\r
+\r
+\r
+\r
+\r
+\r
+\r
+/**\r
+  Allocates and fills in the Page Directory and Page Table Entries to\r
+  establish a 1:1 Virtual to Physical mapping.\r
+\r
+  @param  NumberOfProcessorPhysicalAddressBits  Number of processor address bits \r
+                                                to use. Limits the number of page \r
+                                                table entries  to the physical \r
+                                                address space. \r
+\r
+  @return EFI_SUCCESS           The 1:1 Virtual to Physical identity mapping was created\r
+\r
+**/\r
+UINTN\r
+CreateIdentityMappingPageTables (\r
+  VOID\r
+  )\r
+{  \r
+  UINT8                                         PhysicalAddressBits;\r
+  EFI_PHYSICAL_ADDRESS                          PageAddress;\r
+  UINTN                                         IndexOfPml4Entries;\r
+  UINTN                                         IndexOfPdpEntries;\r
+  UINTN                                         IndexOfPageDirectoryEntries;\r
+  UINTN                                         NumberOfPml4EntriesNeeded;\r
+  UINTN                                         NumberOfPdpEntriesNeeded;\r
+  PAGE_MAP_AND_DIRECTORY_POINTER                *PageMapLevel4Entry;\r
+  PAGE_MAP_AND_DIRECTORY_POINTER                *PageMap;\r
+  PAGE_MAP_AND_DIRECTORY_POINTER                *PageDirectoryPointerEntry;\r
+  PAGE_TABLE_ENTRY                              *PageDirectoryEntry;\r
+  UINTN                                         TotalPagesNum;\r
+  UINTN                                         BigPageAddress;\r
+  VOID                                          *Hob;\r
+\r
+  //\r
+  // Get physical address bits supported from CPU HOB.\r
+  //\r
+  PhysicalAddressBits = 36;\r
+  \r
+  Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
+  if (Hob != NULL) {\r
+    PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;    \r
+  }\r
+\r
+  //\r
+  // Calculate the table entries needed.\r
+  //\r
+  if (PhysicalAddressBits <= 39 ) {\r
+    NumberOfPml4EntriesNeeded = 1;\r
+    NumberOfPdpEntriesNeeded =  LShiftU64 (1, (PhysicalAddressBits - 30));\r
+  } else {\r
+    NumberOfPml4EntriesNeeded = LShiftU64 (1, (PhysicalAddressBits - 39));\r
+    NumberOfPdpEntriesNeeded = 512;\r
+  }\r
+\r
+  //\r
+  // Pre-allocate big pages to avoid later allocations. \r
+  //\r
+  TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1;\r
+  BigPageAddress = (UINTN) AllocatePages (TotalPagesNum);\r
+  ASSERT (BigPageAddress != 0);\r
+\r
+  //\r
+  // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.\r
+  //\r
+  PageMap         = (VOID *) BigPageAddress;\r
+  BigPageAddress += EFI_PAGE_SIZE;\r
+\r
+  PageMapLevel4Entry = PageMap;\r
+  PageAddress        = 0;\r
+  for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) {\r
+    //\r
+    // Each PML4 entry points to a page of Page Directory Pointer entires.\r
+    // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.\r
+    //\r
+    PageDirectoryPointerEntry = (VOID *) BigPageAddress;\r
+    BigPageAddress += EFI_PAGE_SIZE;\r
+\r
+    //\r
+    // Make a PML4 Entry\r
+    //\r
+    PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;\r
+    PageMapLevel4Entry->Bits.ReadWrite = 1;\r
+    PageMapLevel4Entry->Bits.Present = 1;\r
+\r
+    for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
+      //\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
+      PageDirectoryEntry = (VOID *) BigPageAddress;\r
+      BigPageAddress += EFI_PAGE_SIZE;\r
+\r
+      //\r
+      // Fill in a Page Directory Pointer Entries\r
+      //\r
+      PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;\r
+      PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
+      PageDirectoryPointerEntry->Bits.Present = 1;\r
+\r
+      for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += 0x200000) {\r
+        //\r
+        // Fill in the Page Directory entries\r
+        //\r
+        PageDirectoryEntry->Uint64 = (UINT64)PageAddress;\r
+        PageDirectoryEntry->Bits.ReadWrite = 1;\r
+        PageDirectoryEntry->Bits.Present = 1;\r
+        PageDirectoryEntry->Bits.MustBe1 = 1;\r
+\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // For the PML4 entries we are not using fill in a null entry.\r
+  // For now we just copy the first entry.\r
+  //\r
+  for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) {\r
+     CopyMem (\r
+       PageMapLevel4Entry,\r
+       PageMap,\r
+       sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)\r
+       );\r
+  }\r
+\r
+  return (UINTN)PageMap;\r
+}\r
+\r
diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
new file mode 100644 (file)
index 0000000..be9a739
--- /dev/null
@@ -0,0 +1,161 @@
+/** @file\r
+  x64 Long Mode Virtual Memory Management Definitions  \r
+\r
+  References:\r
+    1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel\r
+    2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel\r
+    3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel\r
+    4) AMD64 Architecture Programmer's Manual Volume 2: System Programming\r
+\r
+Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+\r
+**/  \r
+#ifndef _VIRTUAL_MEMORY_H_\r
+#define _VIRTUAL_MEMORY_H_\r
+\r
+\r
+#define SYS_CODE64_SEL 0x38\r
+\r
+#pragma pack(1)\r
+\r
+typedef union {\r
+  struct {\r
+    UINT32  LimitLow    : 16;\r
+    UINT32  BaseLow     : 16;\r
+    UINT32  BaseMid     : 8;\r
+    UINT32  Type        : 4;\r
+    UINT32  System      : 1;\r
+    UINT32  Dpl         : 2;\r
+    UINT32  Present     : 1;\r
+    UINT32  LimitHigh   : 4;\r
+    UINT32  Software    : 1;\r
+    UINT32  Reserved    : 1;\r
+    UINT32  DefaultSize : 1;\r
+    UINT32  Granularity : 1;\r
+    UINT32  BaseHigh    : 8;\r
+  } Bits;\r
+  UINT64  Uint64;\r
+} IA32_GDT;\r
+\r
+typedef struct {\r
+  IA32_IDT_GATE_DESCRIPTOR  Ia32IdtEntry;\r
+  UINT32                    Offset32To63;\r
+  UINT32                    Reserved;\r
+} X64_IDT_GATE_DESCRIPTOR;\r
+\r
+//\r
+// Page-Map Level-4 Offset (PML4) and\r
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB\r
+//\r
+\r
+typedef union {\r
+  struct {\r
+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory\r
+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write\r
+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User\r
+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching\r
+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached\r
+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)\r
+    UINT64  Reserved:1;               // Reserved\r
+    UINT64  MustBeZero:2;             // Must Be Zero\r
+    UINT64  Available:3;              // Available for use by system software\r
+    UINT64  PageTableBaseAddress:40;  // Page Table Base Address\r
+    UINT64  AvabilableHigh:11;        // Available for use by system software\r
+    UINT64  Nx:1;                     // No Execute bit\r
+  } Bits;\r
+  UINT64    Uint64;\r
+} PAGE_MAP_AND_DIRECTORY_POINTER;\r
+\r
+//\r
+// Page Table Entry 2MB\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory\r
+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write\r
+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User\r
+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching\r
+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached\r
+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)\r
+    UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page\r
+    UINT64  MustBe1:1;                // Must be 1 \r
+    UINT64  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write\r
+    UINT64  Available:3;              // Available for use by system software\r
+    UINT64  PAT:1;                    //\r
+    UINT64  MustBeZero:8;             // Must be zero;\r
+    UINT64  PageTableBaseAddress:31;  // Page Table Base Address\r
+    UINT64  AvabilableHigh:11;        // Available for use by system software\r
+    UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code Execution\r
+  } Bits;\r
+  UINT64    Uint64;\r
+} PAGE_TABLE_ENTRY;\r
+\r
+#pragma pack()\r
+\r
+\r
+\r
+/**\r
+  Allocates and fills in the Page Directory and Page Table Entries to\r
+  establish a 1:1 Virtual to Physical mapping.\r
+\r
+  @param  NumberOfProcessorPhysicalAddressBits  Number of processor address bits \r
+                                                to use. Limits the number of page \r
+                                                table entries  to the physical \r
+                                                address space. \r
+\r
+  @return EFI_SUCCESS           The 1:1 Virtual to Physical identity mapping was created\r
+\r
+**/\r
+UINTN\r
+CreateIdentityMappingPageTables (\r
+  VOID\r
+  );\r
+\r
+\r
+\r
+\r
+\r
+/**\r
\r
+  Fix up the vector number in the vector code.\r
\r
+  @param VectorBase   Base address of the vector handler.\r
\r
+  @param VectorNum    Index of vector.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+AsmVectorFixup (\r
+  VOID    *VectorBase,\r
+  UINT8   VectorNum\r
+  );\r
+\r
+\r
+\r
+\r
+\r
+/**\r
\r
+  Get the information of vector template.\r
+  \r
+  @param TemplateBase   Base address of the template code.\r
\r
+  @return               Size of the Template code.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+AsmGetVectorTemplatInfo (\r
+  OUT   VOID  **TemplateBase\r
+  );\r
+\r
+\r
+#endif \r