mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-25 22:54:51 +02:00
Use CPU_HOB to detect max address support from platform, and added 1G page table support.
Sign-off-by: jyao1 Reviewed-by: li-elvin git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12332 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
81b7a60989
commit
c56b65665d
@ -20,6 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include <Library/BaseMemoryLib.h>
|
#include <Library/BaseMemoryLib.h>
|
||||||
#include <Library/UefiBootServicesTableLib.h>
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||||
|
#include <Library/HobLib.h>
|
||||||
#include <Library/LockBoxLib.h>
|
#include <Library/LockBoxLib.h>
|
||||||
#include <Library/PcdLib.h>
|
#include <Library/PcdLib.h>
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
@ -201,46 +202,76 @@ S3CreateIdentityMappingPageTables (
|
|||||||
{
|
{
|
||||||
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
|
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
|
||||||
UINT32 RegEax;
|
UINT32 RegEax;
|
||||||
|
UINT32 RegEdx;
|
||||||
UINT8 PhysicalAddressBits;
|
UINT8 PhysicalAddressBits;
|
||||||
EFI_PHYSICAL_ADDRESS PageAddress;
|
EFI_PHYSICAL_ADDRESS PageAddress;
|
||||||
UINTN IndexOfPml4Entries;
|
UINTN IndexOfPml4Entries;
|
||||||
UINTN IndexOfPdpEntries;
|
UINTN IndexOfPdpEntries;
|
||||||
UINTN IndexOfPageDirectoryEntries;
|
UINTN IndexOfPageDirectoryEntries;
|
||||||
UINTN NumberOfPml4EntriesNeeded;
|
UINT32 NumberOfPml4EntriesNeeded;
|
||||||
UINTN NumberOfPdpEntriesNeeded;
|
UINT32 NumberOfPdpEntriesNeeded;
|
||||||
PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
|
PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
|
||||||
PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
|
PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
|
||||||
PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
|
PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
|
||||||
PAGE_TABLE_ENTRY *PageDirectoryEntry;
|
PAGE_TABLE_ENTRY *PageDirectoryEntry;
|
||||||
EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress;
|
EFI_PHYSICAL_ADDRESS S3NvsPageTableAddress;
|
||||||
UINTN TotalPageTableSize;
|
UINTN TotalPageTableSize;
|
||||||
|
VOID *Hob;
|
||||||
|
BOOLEAN Page1GSupport;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get physical address bits supported.
|
// Get physical address bits supported.
|
||||||
//
|
//
|
||||||
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
|
||||||
if (RegEax >= 0x80000008) {
|
if (Hob != NULL) {
|
||||||
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
|
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
|
||||||
PhysicalAddressBits = (UINT8) RegEax;
|
|
||||||
} else {
|
} else {
|
||||||
PhysicalAddressBits = 36;
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x80000008) {
|
||||||
|
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
|
||||||
|
PhysicalAddressBits = (UINT8) RegEax;
|
||||||
|
} else {
|
||||||
|
PhysicalAddressBits = 36;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
|
||||||
|
//
|
||||||
|
ASSERT (PhysicalAddressBits <= 52);
|
||||||
|
if (PhysicalAddressBits > 48) {
|
||||||
|
PhysicalAddressBits = 48;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate the table entries needed.
|
// Calculate the table entries needed.
|
||||||
//
|
//
|
||||||
if (PhysicalAddressBits <= 39 ) {
|
if (PhysicalAddressBits <= 39 ) {
|
||||||
NumberOfPml4EntriesNeeded = 1;
|
NumberOfPml4EntriesNeeded = 1;
|
||||||
NumberOfPdpEntriesNeeded = (UINTN)LShiftU64 (1, (PhysicalAddressBits - 30));
|
NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
|
||||||
} else {
|
} else {
|
||||||
NumberOfPml4EntriesNeeded = (UINTN)LShiftU64 (1, (PhysicalAddressBits - 39));
|
NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
|
||||||
NumberOfPdpEntriesNeeded = 512;
|
NumberOfPdpEntriesNeeded = 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs.
|
// We need calculate whole page size then allocate once, because S3 restore page table does not know each page in Nvs.
|
||||||
//
|
//
|
||||||
TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded);
|
if (!Page1GSupport) {
|
||||||
|
TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded + NumberOfPml4EntriesNeeded * NumberOfPdpEntriesNeeded);
|
||||||
|
} else {
|
||||||
|
TotalPageTableSize = (UINTN)(1 + NumberOfPml4EntriesNeeded);
|
||||||
|
}
|
||||||
DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %x pages\n", TotalPageTableSize));
|
DEBUG ((EFI_D_ERROR, "TotalPageTableSize - %x pages\n", TotalPageTableSize));
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -267,29 +298,44 @@ S3CreateIdentityMappingPageTables (
|
|||||||
PageMapLevel4Entry->Bits.ReadWrite = 1;
|
PageMapLevel4Entry->Bits.ReadWrite = 1;
|
||||||
PageMapLevel4Entry->Bits.Present = 1;
|
PageMapLevel4Entry->Bits.Present = 1;
|
||||||
|
|
||||||
for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
|
if (Page1GSupport) {
|
||||||
//
|
PageDirectory1GEntry = (VOID *) S3NvsPageTableAddress;
|
||||||
// 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 = (PAGE_TABLE_ENTRY *)(UINTN)S3NvsPageTableAddress;
|
|
||||||
S3NvsPageTableAddress += SIZE_4KB;
|
S3NvsPageTableAddress += SIZE_4KB;
|
||||||
|
|
||||||
//
|
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
|
||||||
// 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
|
// Fill in the Page Directory entries
|
||||||
//
|
//
|
||||||
PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
|
PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
|
||||||
PageDirectoryEntry->Bits.ReadWrite = 1;
|
PageDirectory1GEntry->Bits.ReadWrite = 1;
|
||||||
PageDirectoryEntry->Bits.Present = 1;
|
PageDirectory1GEntry->Bits.Present = 1;
|
||||||
PageDirectoryEntry->Bits.MustBe1 = 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 = (PAGE_TABLE_ENTRY *)(UINTN)S3NvsPageTableAddress;
|
||||||
|
S3NvsPageTableAddress += 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
This is an implementation of the ACPI S3 Save protocol. This is defined in
|
This is an implementation of the ACPI S3 Save protocol. This is defined in
|
||||||
S3 boot path specification 0.9.
|
S3 boot path specification 0.9.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions
|
are licensed and made available under the terms and conditions
|
||||||
@ -18,7 +18,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#ifndef _ACPI_S3_SAVE_H_
|
#ifndef _ACPI_S3_SAVE_H_
|
||||||
#define _ACPI_S3_SAVE_H_
|
#define _ACPI_S3_SAVE_H_
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(1)
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
struct {
|
struct {
|
||||||
@ -92,6 +92,30 @@ typedef union {
|
|||||||
UINT64 Uint64;
|
UINT64 Uint64;
|
||||||
} PAGE_TABLE_ENTRY;
|
} PAGE_TABLE_ENTRY;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Page Table Entry 1GB
|
||||||
|
//
|
||||||
|
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:17; // Must be zero;
|
||||||
|
UINT64 PageTableBaseAddress:22; // 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_1G_ENTRY;
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
2) IA-32 Intel(R) Architecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
|
2) IA-32 Intel(R) Architecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
|
||||||
3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
|
3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
|
||||||
|
|
||||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -46,6 +46,8 @@ CreateIdentityMappingPageTables (
|
|||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
UINT32 RegEax;
|
||||||
|
UINT32 RegEdx;
|
||||||
UINT8 PhysicalAddressBits;
|
UINT8 PhysicalAddressBits;
|
||||||
EFI_PHYSICAL_ADDRESS PageAddress;
|
EFI_PHYSICAL_ADDRESS PageAddress;
|
||||||
UINTN IndexOfPml4Entries;
|
UINTN IndexOfPml4Entries;
|
||||||
@ -60,15 +62,32 @@ CreateIdentityMappingPageTables (
|
|||||||
UINTN TotalPagesNum;
|
UINTN TotalPagesNum;
|
||||||
UINTN BigPageAddress;
|
UINTN BigPageAddress;
|
||||||
VOID *Hob;
|
VOID *Hob;
|
||||||
|
BOOLEAN Page1GSupport;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get physical address bits supported from CPU HOB.
|
// Get physical address bits supported.
|
||||||
//
|
//
|
||||||
PhysicalAddressBits = 36;
|
|
||||||
|
|
||||||
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
|
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
|
||||||
if (Hob != NULL) {
|
if (Hob != NULL) {
|
||||||
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
|
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
|
||||||
|
} else {
|
||||||
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x80000008) {
|
||||||
|
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
|
||||||
|
PhysicalAddressBits = (UINT8) RegEax;
|
||||||
|
} else {
|
||||||
|
PhysicalAddressBits = 36;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -84,16 +103,20 @@ CreateIdentityMappingPageTables (
|
|||||||
//
|
//
|
||||||
if (PhysicalAddressBits <= 39 ) {
|
if (PhysicalAddressBits <= 39 ) {
|
||||||
NumberOfPml4EntriesNeeded = 1;
|
NumberOfPml4EntriesNeeded = 1;
|
||||||
NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30);
|
NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
|
||||||
} else {
|
} else {
|
||||||
NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39);
|
NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
|
||||||
NumberOfPdpEntriesNeeded = 512;
|
NumberOfPdpEntriesNeeded = 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Pre-allocate big pages to avoid later allocations.
|
// Pre-allocate big pages to avoid later allocations.
|
||||||
//
|
//
|
||||||
TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1;
|
if (!Page1GSupport) {
|
||||||
|
TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1;
|
||||||
|
} else {
|
||||||
|
TotalPagesNum = NumberOfPml4EntriesNeeded + 1;
|
||||||
|
}
|
||||||
BigPageAddress = (UINTN) AllocatePages (TotalPagesNum);
|
BigPageAddress = (UINTN) AllocatePages (TotalPagesNum);
|
||||||
ASSERT (BigPageAddress != 0);
|
ASSERT (BigPageAddress != 0);
|
||||||
|
|
||||||
@ -101,7 +124,7 @@ CreateIdentityMappingPageTables (
|
|||||||
// By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
|
// By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
|
||||||
//
|
//
|
||||||
PageMap = (VOID *) BigPageAddress;
|
PageMap = (VOID *) BigPageAddress;
|
||||||
BigPageAddress += EFI_PAGE_SIZE;
|
BigPageAddress += SIZE_4KB;
|
||||||
|
|
||||||
PageMapLevel4Entry = PageMap;
|
PageMapLevel4Entry = PageMap;
|
||||||
PageAddress = 0;
|
PageAddress = 0;
|
||||||
@ -111,7 +134,7 @@ CreateIdentityMappingPageTables (
|
|||||||
// So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
|
// So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
|
||||||
//
|
//
|
||||||
PageDirectoryPointerEntry = (VOID *) BigPageAddress;
|
PageDirectoryPointerEntry = (VOID *) BigPageAddress;
|
||||||
BigPageAddress += EFI_PAGE_SIZE;
|
BigPageAddress += SIZE_4KB;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make a PML4 Entry
|
// Make a PML4 Entry
|
||||||
@ -120,44 +143,63 @@ CreateIdentityMappingPageTables (
|
|||||||
PageMapLevel4Entry->Bits.ReadWrite = 1;
|
PageMapLevel4Entry->Bits.ReadWrite = 1;
|
||||||
PageMapLevel4Entry->Bits.Present = 1;
|
PageMapLevel4Entry->Bits.Present = 1;
|
||||||
|
|
||||||
for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
|
if (Page1GSupport) {
|
||||||
//
|
PageDirectory1GEntry = (VOID *) BigPageAddress;
|
||||||
// Each Directory Pointer entries points to a page of Page Directory entires.
|
BigPageAddress += SIZE_4KB;
|
||||||
// So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
|
|
||||||
//
|
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
|
||||||
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
|
// Fill in the Page Directory entries
|
||||||
//
|
//
|
||||||
PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
|
PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
|
||||||
PageDirectoryEntry->Bits.ReadWrite = 1;
|
PageDirectory1GEntry->Bits.ReadWrite = 1;
|
||||||
PageDirectoryEntry->Bits.Present = 1;
|
PageDirectory1GEntry->Bits.Present = 1;
|
||||||
PageDirectoryEntry->Bits.MustBe1 = 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(PAGE_MAP_AND_DIRECTORY_POINTER)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// For the PML4 entries we are not using fill in a null entry.
|
// 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++) {
|
for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) {
|
||||||
CopyMem (
|
ZeroMem (
|
||||||
PageMapLevel4Entry,
|
PageMapLevel4Entry,
|
||||||
PageMap,
|
sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
|
||||||
sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (UINTN)PageMap;
|
return (UINTN)PageMap;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
|
3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
|
||||||
4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
|
4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
|
||||||
|
|
||||||
Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -97,6 +97,30 @@ typedef union {
|
|||||||
UINT64 Uint64;
|
UINT64 Uint64;
|
||||||
} PAGE_TABLE_ENTRY;
|
} PAGE_TABLE_ENTRY;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Page Table Entry 1GB
|
||||||
|
//
|
||||||
|
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:17; // Must be zero;
|
||||||
|
UINT64 PageTableBaseAddress:22; // 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_1G_ENTRY;
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,6 +89,30 @@ typedef union {
|
|||||||
UINT64 Uint64;
|
UINT64 Uint64;
|
||||||
} PAGE_TABLE_ENTRY;
|
} PAGE_TABLE_ENTRY;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Page Table Entry 1GB
|
||||||
|
//
|
||||||
|
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:17; // Must be zero;
|
||||||
|
UINT64 PageTableBaseAddress:22; // 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_1G_ENTRY;
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
|
@ -53,20 +53,38 @@ CalculatePageTableSize (
|
|||||||
VOID
|
VOID
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
UINT32 RegEax;
|
||||||
|
UINT32 RegEdx;
|
||||||
UINTN TotalPagesNum;
|
UINTN TotalPagesNum;
|
||||||
UINT8 PhysicalAddressBits;
|
UINT8 PhysicalAddressBits;
|
||||||
VOID *Hob;
|
VOID *Hob;
|
||||||
UINT32 NumberOfPml4EntriesNeeded;
|
UINT32 NumberOfPml4EntriesNeeded;
|
||||||
UINT32 NumberOfPdpEntriesNeeded;
|
UINT32 NumberOfPdpEntriesNeeded;
|
||||||
|
BOOLEAN Page1GSupport;
|
||||||
|
|
||||||
|
Page1GSupport = FALSE;
|
||||||
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x80000001) {
|
||||||
|
AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
|
||||||
|
if ((RegEdx & BIT26) != 0) {
|
||||||
|
Page1GSupport = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get physical address bits supported from CPU HOB.
|
// Get physical address bits supported.
|
||||||
//
|
//
|
||||||
PhysicalAddressBits = 36;
|
|
||||||
|
|
||||||
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
|
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
|
||||||
if (Hob != NULL) {
|
if (Hob != NULL) {
|
||||||
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
|
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
|
||||||
|
} else {
|
||||||
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x80000008) {
|
||||||
|
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
|
||||||
|
PhysicalAddressBits = (UINT8) RegEax;
|
||||||
|
} else {
|
||||||
|
PhysicalAddressBits = 36;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -82,13 +100,17 @@ CalculatePageTableSize (
|
|||||||
//
|
//
|
||||||
if (PhysicalAddressBits <= 39 ) {
|
if (PhysicalAddressBits <= 39 ) {
|
||||||
NumberOfPml4EntriesNeeded = 1;
|
NumberOfPml4EntriesNeeded = 1;
|
||||||
NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30);
|
NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
|
||||||
} else {
|
} else {
|
||||||
NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39);
|
NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
|
||||||
NumberOfPdpEntriesNeeded = 512;
|
NumberOfPdpEntriesNeeded = 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1;
|
if (!Page1GSupport) {
|
||||||
|
TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1;
|
||||||
|
} else {
|
||||||
|
TotalPagesNum = NumberOfPml4EntriesNeeded + 1;
|
||||||
|
}
|
||||||
|
|
||||||
return EFI_PAGES_TO_SIZE (TotalPagesNum);
|
return EFI_PAGES_TO_SIZE (TotalPagesNum);
|
||||||
}
|
}
|
||||||
@ -118,15 +140,32 @@ CreateIdentityMappingPageTables (
|
|||||||
PAGE_TABLE_ENTRY *PageDirectoryEntry;
|
PAGE_TABLE_ENTRY *PageDirectoryEntry;
|
||||||
UINTN BigPageAddress;
|
UINTN BigPageAddress;
|
||||||
VOID *Hob;
|
VOID *Hob;
|
||||||
|
BOOLEAN Page1GSupport;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get physical address bits supported from CPU HOB.
|
// Get physical address bits supported.
|
||||||
//
|
//
|
||||||
PhysicalAddressBits = 36;
|
|
||||||
|
|
||||||
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
|
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
|
||||||
if (Hob != NULL) {
|
if (Hob != NULL) {
|
||||||
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
|
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
|
||||||
|
} else {
|
||||||
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x80000008) {
|
||||||
|
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
|
||||||
|
PhysicalAddressBits = (UINT8) RegEax;
|
||||||
|
} else {
|
||||||
|
PhysicalAddressBits = 36;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -142,9 +181,9 @@ CreateIdentityMappingPageTables (
|
|||||||
//
|
//
|
||||||
if (PhysicalAddressBits <= 39 ) {
|
if (PhysicalAddressBits <= 39 ) {
|
||||||
NumberOfPml4EntriesNeeded = 1;
|
NumberOfPml4EntriesNeeded = 1;
|
||||||
NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30);
|
NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
|
||||||
} else {
|
} else {
|
||||||
NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39);
|
NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
|
||||||
NumberOfPdpEntriesNeeded = 512;
|
NumberOfPdpEntriesNeeded = 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +196,7 @@ CreateIdentityMappingPageTables (
|
|||||||
// By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
|
// By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
|
||||||
//
|
//
|
||||||
PageMap = (VOID *) BigPageAddress;
|
PageMap = (VOID *) BigPageAddress;
|
||||||
BigPageAddress += EFI_PAGE_SIZE;
|
BigPageAddress += SIZE_4KB;
|
||||||
|
|
||||||
PageMapLevel4Entry = PageMap;
|
PageMapLevel4Entry = PageMap;
|
||||||
PageAddress = 0;
|
PageAddress = 0;
|
||||||
@ -167,7 +206,7 @@ CreateIdentityMappingPageTables (
|
|||||||
// So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
|
// So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
|
||||||
//
|
//
|
||||||
PageDirectoryPointerEntry = (VOID *) BigPageAddress;
|
PageDirectoryPointerEntry = (VOID *) BigPageAddress;
|
||||||
BigPageAddress += EFI_PAGE_SIZE;
|
BigPageAddress += SIZE_4KB;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make a PML4 Entry
|
// Make a PML4 Entry
|
||||||
@ -176,44 +215,63 @@ CreateIdentityMappingPageTables (
|
|||||||
PageMapLevel4Entry->Bits.ReadWrite = 1;
|
PageMapLevel4Entry->Bits.ReadWrite = 1;
|
||||||
PageMapLevel4Entry->Bits.Present = 1;
|
PageMapLevel4Entry->Bits.Present = 1;
|
||||||
|
|
||||||
for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
|
if (Page1GSupport) {
|
||||||
//
|
PageDirectory1GEntry = (VOID *) BigPageAddress;
|
||||||
// Each Directory Pointer entries points to a page of Page Directory entires.
|
BigPageAddress += SIZE_4KB;
|
||||||
// So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
|
|
||||||
//
|
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
|
||||||
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
|
// Fill in the Page Directory entries
|
||||||
//
|
//
|
||||||
PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
|
PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
|
||||||
PageDirectoryEntry->Bits.ReadWrite = 1;
|
PageDirectory1GEntry->Bits.ReadWrite = 1;
|
||||||
PageDirectoryEntry->Bits.Present = 1;
|
PageDirectory1GEntry->Bits.Present = 1;
|
||||||
PageDirectoryEntry->Bits.MustBe1 = 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(PAGE_MAP_AND_DIRECTORY_POINTER)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// For the PML4 entries we are not using fill in a null entry.
|
// 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++) {
|
for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) {
|
||||||
CopyMem (
|
ZeroMem (
|
||||||
PageMapLevel4Entry,
|
PageMapLevel4Entry,
|
||||||
PageMap,
|
sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
|
||||||
sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include <Library/LocalApicLib.h>
|
#include <Library/LocalApicLib.h>
|
||||||
#include <Library/ReportStatusCodeLib.h>
|
#include <Library/ReportStatusCodeLib.h>
|
||||||
#include <Library/PrintLib.h>
|
#include <Library/PrintLib.h>
|
||||||
|
#include <Library/HobLib.h>
|
||||||
#include <Library/LockBoxLib.h>
|
#include <Library/LockBoxLib.h>
|
||||||
#include <IndustryStandard/Acpi.h>
|
#include <IndustryStandard/Acpi.h>
|
||||||
|
|
||||||
@ -113,6 +114,30 @@ typedef union {
|
|||||||
UINT64 Uint64;
|
UINT64 Uint64;
|
||||||
} PAGE_TABLE_ENTRY;
|
} PAGE_TABLE_ENTRY;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Page Table Entry 1GB
|
||||||
|
//
|
||||||
|
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:17; // Must be zero;
|
||||||
|
UINT64 PageTableBaseAddress:22; // 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_1G_ENTRY;
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -462,17 +487,21 @@ RestoreS3PageTables (
|
|||||||
{
|
{
|
||||||
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
|
if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
|
||||||
UINT32 RegEax;
|
UINT32 RegEax;
|
||||||
|
UINT32 RegEdx;
|
||||||
UINT8 PhysicalAddressBits;
|
UINT8 PhysicalAddressBits;
|
||||||
EFI_PHYSICAL_ADDRESS PageAddress;
|
EFI_PHYSICAL_ADDRESS PageAddress;
|
||||||
UINTN IndexOfPml4Entries;
|
UINTN IndexOfPml4Entries;
|
||||||
UINTN IndexOfPdpEntries;
|
UINTN IndexOfPdpEntries;
|
||||||
UINTN IndexOfPageDirectoryEntries;
|
UINTN IndexOfPageDirectoryEntries;
|
||||||
UINT64 NumberOfPml4EntriesNeeded;
|
UINT32 NumberOfPml4EntriesNeeded;
|
||||||
UINT64 NumberOfPdpEntriesNeeded;
|
UINT32 NumberOfPdpEntriesNeeded;
|
||||||
PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
|
PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
|
||||||
PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
|
PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
|
||||||
PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
|
PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
|
||||||
PAGE_TABLE_ENTRY *PageDirectoryEntry;
|
PAGE_TABLE_ENTRY *PageDirectoryEntry;
|
||||||
|
VOID *Hob;
|
||||||
|
BOOLEAN Page1GSupport;
|
||||||
|
PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
|
||||||
|
|
||||||
//
|
//
|
||||||
// NOTE: We have to ASSUME the page table generation format, because we do not know whole page table information.
|
// NOTE: We have to ASSUME the page table generation format, because we do not know whole page table information.
|
||||||
@ -488,25 +517,47 @@ RestoreS3PageTables (
|
|||||||
PageMap = (PAGE_MAP_AND_DIRECTORY_POINTER *)S3NvsPageTableAddress;
|
PageMap = (PAGE_MAP_AND_DIRECTORY_POINTER *)S3NvsPageTableAddress;
|
||||||
S3NvsPageTableAddress += SIZE_4KB;
|
S3NvsPageTableAddress += SIZE_4KB;
|
||||||
|
|
||||||
|
Page1GSupport = FALSE;
|
||||||
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x80000001) {
|
||||||
|
AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
|
||||||
|
if ((RegEdx & BIT26) != 0) {
|
||||||
|
Page1GSupport = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get physical address bits supported.
|
// Get physical address bits supported.
|
||||||
//
|
//
|
||||||
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
|
||||||
if (RegEax >= 0x80000008) {
|
if (Hob != NULL) {
|
||||||
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
|
PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
|
||||||
PhysicalAddressBits = (UINT8) RegEax;
|
|
||||||
} else {
|
} else {
|
||||||
PhysicalAddressBits = 36;
|
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||||
|
if (RegEax >= 0x80000008) {
|
||||||
|
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
|
||||||
|
PhysicalAddressBits = (UINT8) RegEax;
|
||||||
|
} else {
|
||||||
|
PhysicalAddressBits = 36;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
|
||||||
|
//
|
||||||
|
ASSERT (PhysicalAddressBits <= 52);
|
||||||
|
if (PhysicalAddressBits > 48) {
|
||||||
|
PhysicalAddressBits = 48;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate the table entries needed.
|
// Calculate the table entries needed.
|
||||||
//
|
//
|
||||||
if (PhysicalAddressBits <= 39) {
|
if (PhysicalAddressBits <= 39) {
|
||||||
NumberOfPml4EntriesNeeded = 1;
|
NumberOfPml4EntriesNeeded = 1;
|
||||||
NumberOfPdpEntriesNeeded = LShiftU64 (1, (PhysicalAddressBits - 30));
|
NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
|
||||||
} else {
|
} else {
|
||||||
NumberOfPml4EntriesNeeded = LShiftU64 (1, (PhysicalAddressBits - 39));
|
NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39));
|
||||||
NumberOfPdpEntriesNeeded = 512;
|
NumberOfPdpEntriesNeeded = 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,30 +577,45 @@ RestoreS3PageTables (
|
|||||||
PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
|
PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;
|
||||||
PageMapLevel4Entry->Bits.ReadWrite = 1;
|
PageMapLevel4Entry->Bits.ReadWrite = 1;
|
||||||
PageMapLevel4Entry->Bits.Present = 1;
|
PageMapLevel4Entry->Bits.Present = 1;
|
||||||
|
|
||||||
for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
|
if (Page1GSupport) {
|
||||||
//
|
PageDirectory1GEntry = (VOID *) S3NvsPageTableAddress;
|
||||||
// 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 = (PAGE_TABLE_ENTRY *)S3NvsPageTableAddress;
|
|
||||||
S3NvsPageTableAddress += SIZE_4KB;
|
S3NvsPageTableAddress += SIZE_4KB;
|
||||||
|
|
||||||
//
|
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
|
||||||
// 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
|
// Fill in the Page Directory entries
|
||||||
//
|
//
|
||||||
PageDirectoryEntry->Uint64 = (UINT64)PageAddress;
|
PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;
|
||||||
PageDirectoryEntry->Bits.ReadWrite = 1;
|
PageDirectory1GEntry->Bits.ReadWrite = 1;
|
||||||
PageDirectoryEntry->Bits.Present = 1;
|
PageDirectory1GEntry->Bits.Present = 1;
|
||||||
PageDirectoryEntry->Bits.MustBe1 = 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 = (PAGE_TABLE_ENTRY *)S3NvsPageTableAddress;
|
||||||
|
S3NvsPageTableAddress += 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user