From c56b65665de7a665e29107ee9c377c1e2e84d343 Mon Sep 17 00:00:00 2001 From: jyao1 Date: Tue, 13 Sep 2011 05:48:57 +0000 Subject: 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 --- MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 112 +++++++++++++------ MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h | 26 ++++- MdeModulePkg/Universal/CapsulePei/Capsule.h | 24 ++++ MdeModulePkg/Universal/CapsulePei/UefiCapsule.c | 136 ++++++++++++++++------- 4 files changed, 223 insertions(+), 75 deletions(-) (limited to 'MdeModulePkg') diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c index 0e95989faa..6666a02c3d 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c @@ -15,7 +15,7 @@ 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 -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2011, 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 @@ -46,6 +46,8 @@ CreateIdentityMappingPageTables ( VOID ) { + UINT32 RegEax; + UINT32 RegEdx; UINT8 PhysicalAddressBits; EFI_PHYSICAL_ADDRESS PageAddress; UINTN IndexOfPml4Entries; @@ -60,15 +62,32 @@ CreateIdentityMappingPageTables ( UINTN TotalPagesNum; UINTN BigPageAddress; 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); if (Hob != NULL) { 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 ) { NumberOfPml4EntriesNeeded = 1; - NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30); + NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); } else { - NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39); + NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39)); NumberOfPdpEntriesNeeded = 512; } // // 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); ASSERT (BigPageAddress != 0); @@ -101,7 +124,7 @@ CreateIdentityMappingPageTables ( // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. // PageMap = (VOID *) BigPageAddress; - BigPageAddress += EFI_PAGE_SIZE; + BigPageAddress += SIZE_4KB; PageMapLevel4Entry = PageMap; PageAddress = 0; @@ -111,7 +134,7 @@ CreateIdentityMappingPageTables ( // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop. // PageDirectoryPointerEntry = (VOID *) BigPageAddress; - BigPageAddress += EFI_PAGE_SIZE; + BigPageAddress += SIZE_4KB; // // Make a PML4 Entry @@ -120,44 +143,63 @@ CreateIdentityMappingPageTables ( 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) { + if (Page1GSupport) { + PageDirectory1GEntry = (VOID *) BigPageAddress; + BigPageAddress += SIZE_4KB; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) { // // Fill in the Page Directory entries // - PageDirectoryEntry->Uint64 = (UINT64)PageAddress; - PageDirectoryEntry->Bits.ReadWrite = 1; - PageDirectoryEntry->Bits.Present = 1; - PageDirectoryEntry->Bits.MustBe1 = 1; + 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 *) 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 now we just copy the first entry. // for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) { - CopyMem ( - PageMapLevel4Entry, - PageMap, - sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) - ); + ZeroMem ( + PageMapLevel4Entry, + 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 index b1de665f76..87a27b0824 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h @@ -7,7 +7,7 @@ 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 -Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2011, 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 @@ -97,6 +97,30 @@ typedef union { UINT64 Uint64; } 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() diff --git a/MdeModulePkg/Universal/CapsulePei/Capsule.h b/MdeModulePkg/Universal/CapsulePei/Capsule.h index 5b7caae674..57af114c40 100644 --- a/MdeModulePkg/Universal/CapsulePei/Capsule.h +++ b/MdeModulePkg/Universal/CapsulePei/Capsule.h @@ -89,6 +89,30 @@ typedef union { UINT64 Uint64; } 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() typedef diff --git a/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c b/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c index da37e671fe..a6a6f57aba 100644 --- a/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c +++ b/MdeModulePkg/Universal/CapsulePei/UefiCapsule.c @@ -53,20 +53,38 @@ CalculatePageTableSize ( VOID ) { + UINT32 RegEax; + UINT32 RegEdx; UINTN TotalPagesNum; UINT8 PhysicalAddressBits; VOID *Hob; UINT32 NumberOfPml4EntriesNeeded; 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); if (Hob != NULL) { 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 ) { NumberOfPml4EntriesNeeded = 1; - NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30); + NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); } else { - NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39); + NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39)); NumberOfPdpEntriesNeeded = 512; } - TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1; + if (!Page1GSupport) { + TotalPagesNum = (NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1; + } else { + TotalPagesNum = NumberOfPml4EntriesNeeded + 1; + } return EFI_PAGES_TO_SIZE (TotalPagesNum); } @@ -118,15 +140,32 @@ CreateIdentityMappingPageTables ( PAGE_TABLE_ENTRY *PageDirectoryEntry; UINTN BigPageAddress; 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); if (Hob != NULL) { 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 ) { NumberOfPml4EntriesNeeded = 1; - NumberOfPdpEntriesNeeded = 1 << (PhysicalAddressBits - 30); + NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30)); } else { - NumberOfPml4EntriesNeeded = 1 << (PhysicalAddressBits - 39); + NumberOfPml4EntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 39)); NumberOfPdpEntriesNeeded = 512; } @@ -157,7 +196,7 @@ CreateIdentityMappingPageTables ( // By architecture only one PageMapLevel4 exists - so lets allocate storage for it. // PageMap = (VOID *) BigPageAddress; - BigPageAddress += EFI_PAGE_SIZE; + BigPageAddress += SIZE_4KB; PageMapLevel4Entry = PageMap; PageAddress = 0; @@ -167,7 +206,7 @@ CreateIdentityMappingPageTables ( // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop. // PageDirectoryPointerEntry = (VOID *) BigPageAddress; - BigPageAddress += EFI_PAGE_SIZE; + BigPageAddress += SIZE_4KB; // // Make a PML4 Entry @@ -176,44 +215,63 @@ CreateIdentityMappingPageTables ( 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) { + if (Page1GSupport) { + PageDirectory1GEntry = (VOID *) BigPageAddress; + BigPageAddress += SIZE_4KB; + + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) { // // Fill in the Page Directory entries // - PageDirectoryEntry->Uint64 = (UINT64)PageAddress; - PageDirectoryEntry->Bits.ReadWrite = 1; - PageDirectoryEntry->Bits.Present = 1; - PageDirectoryEntry->Bits.MustBe1 = 1; + 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 *) 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 now we just copy the first entry. // for (; IndexOfPml4Entries < 512; IndexOfPml4Entries++, PageMapLevel4Entry++) { - CopyMem ( - PageMapLevel4Entry, - PageMap, - sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) - ); + ZeroMem ( + PageMapLevel4Entry, + sizeof (PAGE_MAP_AND_DIRECTORY_POINTER) + ); } } -- cgit v1.2.3