--- /dev/null
+/** @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
--- /dev/null
+/** @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