From f3b33289f064619ffd64fcdf124bf68d7403abc6 Mon Sep 17 00:00:00 2001 From: mdkinney Date: Sat, 15 Nov 2008 23:59:07 +0000 Subject: [PATCH] Create X64 mode page tables in memory even when PEI is already X64 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@6550 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 2 + .../Core/DxeIplPeim/X64/DxeLoadFunc.c | 9 + .../Core/DxeIplPeim/X64/VirtualMemory.c | 162 ++++++++++++++++++ .../Core/DxeIplPeim/X64/VirtualMemory.h | 161 +++++++++++++++++ 4 files changed, 334 insertions(+) create mode 100644 MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c create mode 100644 MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf index 29f03173ab..94dfcab7a3 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -46,6 +46,8 @@ Ia32/IdtVectorAsm.S | GCC [Sources.X64, Sources.EBC] + X64/VirtualMemory.h + X64/VirtualMemory.c X64/DxeLoadFunc.c Ia32/ImageRead.c diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c index 51055e157a..05c5203d82 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c +++ b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c @@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include "DxeIpl.h" +#include "X64/VirtualMemory.h" @@ -36,6 +37,7 @@ HandOffToDxeCore ( VOID *BaseOfStack; VOID *TopOfStack; EFI_STATUS Status; + UINTN PageTables; // // Allocate 128KB for the Stack @@ -50,12 +52,19 @@ HandOffToDxeCore ( TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); + // + // Create page table and save PageMapLevel4 to CR3 + // + PageTables = CreateIdentityMappingPageTables (); + // // End of PEI phase singal // Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi); ASSERT_EFI_ERROR (Status); + AsmWriteCr3 (PageTables); + // // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. // diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c new file mode 100644 index 0000000000..35e92c641a --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c @@ -0,0 +1,162 @@ +/** @file + x64 Virtual Memory Management Services in the form of an IA-32 driver. + Used to establish a 1:1 Virtual to Physical Mapping that is required to + enter Long Mode (x64 64-bit mode). + + While we make a 1:1 mapping (identity mapping) for all physical pages + we still need to use the MTRR's to ensure that the cachability attirbutes + for all memory regions is correct. + + The basic idea is to use 2MB page table entries where ever possible. If + more granularity of cachability is required then 4K page tables are used. + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + +Copyright (c) 2006 - 2008, Intel Corporation.
+All rights reserved. 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 +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "DxeIpl.h" +#include "VirtualMemory.h" + + + + + + +/** + 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. + + @return EFI_SUCCESS The 1:1 Virtual to Physical identity mapping was created + +**/ +UINTN +CreateIdentityMappingPageTables ( + VOID + ) +{ + UINT8 PhysicalAddressBits; + EFI_PHYSICAL_ADDRESS PageAddress; + UINTN IndexOfPml4Entries; + UINTN IndexOfPdpEntries; + UINTN IndexOfPageDirectoryEntries; + UINTN NumberOfPml4EntriesNeeded; + UINTN NumberOfPdpEntriesNeeded; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageMap; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINTN TotalPagesNum; + UINTN BigPageAddress; + VOID *Hob; + + // + // Get physical address bits supported from CPU HOB. + // + PhysicalAddressBits = 36; + + Hob = GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob != NULL) { + PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; + } + + // + // Calculate the table entries needed. + // + if (PhysicalAddressBits <= 39 ) { + NumberOfPml4EntriesNeeded = 1; + NumberOfPdpEntriesNeeded = LShiftU64 (1, (PhysicalAddressBits - 30)); + } else { + NumberOfPml4EntriesNeeded = LShiftU64 (1, (PhysicalAddressBits - 39)); + NumberOfPdpEntriesNeeded = 512; + } + + // + // Pre-allocate big pages to avoid later allocations. + // + TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1; + BigPageAddress = (UINTN) AllocatePages (TotalPagesNum); + ASSERT (BigPageAddress != 0); + + // + // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. + // + PageMap = (VOID *) BigPageAddress; + BigPageAddress += EFI_PAGE_SIZE; + + 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 += EFI_PAGE_SIZE; + + // + // Make a PML4 Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry; + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + 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 += EFI_PAGE_SIZE; + + // + // 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 += 0x200000) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 = (UINT64)PageAddress; + PageDirectoryEntry->Bits.ReadWrite = 1; + PageDirectoryEntry->Bits.Present = 1; + PageDirectoryEntry->Bits.MustBe1 = 1; + + } + } + } + + // + // For the PML4 entries we are not using fill in a null entry. + // For now we just copy the first entry. + // + for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) { + CopyMem ( + PageMapLevel4Entry, + PageMap, + sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) + ); + } + + return (UINTN)PageMap; +} + diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h new file mode 100644 index 0000000000..be9a7391b6 --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h @@ -0,0 +1,161 @@ +/** @file + x64 Long Mode Virtual Memory Management Definitions + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming + +Copyright (c) 2006 - 2008, Intel Corporation.
+All rights reserved. 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 +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + + +#define SYS_CODE64_SEL 0x38 + +#pragma pack(1) + +typedef union { + struct { + UINT32 LimitLow : 16; + UINT32 BaseLow : 16; + UINT32 BaseMid : 8; + UINT32 Type : 4; + UINT32 System : 1; + UINT32 Dpl : 2; + UINT32 Present : 1; + UINT32 LimitHigh : 4; + UINT32 Software : 1; + UINT32 Reserved : 1; + UINT32 DefaultSize : 1; + UINT32 Granularity : 1; + UINT32 BaseHigh : 8; + } Bits; + UINT64 Uint64; +} IA32_GDT; + +typedef struct { + IA32_IDT_GATE_DESCRIPTOR Ia32IdtEntry; + UINT32 Offset32To63; + UINT32 Reserved; +} X64_IDT_GATE_DESCRIPTOR; + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +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 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + 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; // No Execute bit + } Bits; + UINT64 Uint64; +} PAGE_MAP_AND_DIRECTORY_POINTER; + +// +// Page Table Entry 2MB +// +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 MustBe1:1; // Must be 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 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // 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_ENTRY; + +#pragma pack() + + + +/** + 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. + + @return EFI_SUCCESS The 1:1 Virtual to Physical identity mapping was created + +**/ +UINTN +CreateIdentityMappingPageTables ( + VOID + ); + + + + + +/** + + Fix up the vector number in the vector code. + + @param VectorBase Base address of the vector handler. + + @param VectorNum Index of vector. + +**/ +VOID +EFIAPI +AsmVectorFixup ( + VOID *VectorBase, + UINT8 VectorNum + ); + + + + + +/** + + Get the information of vector template. + + @param TemplateBase Base address of the template code. + + @return Size of the Template code. + +**/ +UINTN +EFIAPI +AsmGetVectorTemplatInfo ( + OUT VOID **TemplateBase + ); + + +#endif -- 2.39.2