UefiCpuPkg/PiSmmCpu: Enable 5 level paging when CPU supports
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1946 The patch changes SMM environment to use 5 level paging when CPU supports it. Signed-off-by: Ray Ni <ray.ni@intel.com> Cc: Eric Dong <eric.dong@intel.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Eric Dong <eric.dong@intel.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
X64 processor specific functions to enable SMM profile.
|
||||
|
||||
Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
@@ -147,9 +147,14 @@ RestorePageTableAbove4G (
|
||||
BOOLEAN Existed;
|
||||
UINTN Index;
|
||||
UINTN PFIndex;
|
||||
IA32_CR4 Cr4;
|
||||
BOOLEAN Enable5LevelPaging;
|
||||
|
||||
ASSERT ((PageTable != NULL) && (IsValidPFAddress != NULL));
|
||||
|
||||
Cr4.UintN = AsmReadCr4 ();
|
||||
Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);
|
||||
|
||||
//
|
||||
// If page fault address is 4GB above.
|
||||
//
|
||||
@@ -161,38 +166,48 @@ RestorePageTableAbove4G (
|
||||
//
|
||||
Existed = FALSE;
|
||||
PageTable = (UINT64*)(AsmReadCr3 () & PHYSICAL_ADDRESS_MASK);
|
||||
PTIndex = BitFieldRead64 (PFAddress, 39, 47);
|
||||
if ((PageTable[PTIndex] & IA32_PG_P) != 0) {
|
||||
// PML4E
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
|
||||
PTIndex = BitFieldRead64 (PFAddress, 30, 38);
|
||||
if ((PageTable[PTIndex] & IA32_PG_P) != 0) {
|
||||
// PDPTE
|
||||
PTIndex = 0;
|
||||
if (Enable5LevelPaging) {
|
||||
PTIndex = BitFieldRead64 (PFAddress, 48, 56);
|
||||
}
|
||||
if ((!Enable5LevelPaging) || ((PageTable[PTIndex] & IA32_PG_P) != 0)) {
|
||||
// PML5E
|
||||
if (Enable5LevelPaging) {
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
|
||||
PTIndex = BitFieldRead64 (PFAddress, 21, 29);
|
||||
// PD
|
||||
if ((PageTable[PTIndex] & IA32_PG_PS) != 0) {
|
||||
//
|
||||
// 2MB page
|
||||
//
|
||||
Address = (UINT64)(PageTable[PTIndex] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
|
||||
if ((Address & ~((1ull << 21) - 1)) == ((PFAddress & PHYSICAL_ADDRESS_MASK & ~((1ull << 21) - 1)))) {
|
||||
Existed = TRUE;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// 4KB page
|
||||
//
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask& PHYSICAL_ADDRESS_MASK);
|
||||
if (PageTable != 0) {
|
||||
}
|
||||
PTIndex = BitFieldRead64 (PFAddress, 39, 47);
|
||||
if ((PageTable[PTIndex] & IA32_PG_P) != 0) {
|
||||
// PML4E
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
|
||||
PTIndex = BitFieldRead64 (PFAddress, 30, 38);
|
||||
if ((PageTable[PTIndex] & IA32_PG_P) != 0) {
|
||||
// PDPTE
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
|
||||
PTIndex = BitFieldRead64 (PFAddress, 21, 29);
|
||||
// PD
|
||||
if ((PageTable[PTIndex] & IA32_PG_PS) != 0) {
|
||||
//
|
||||
// When there is a valid entry to map to 4KB page, need not create a new entry to map 2MB.
|
||||
// 2MB page
|
||||
//
|
||||
PTIndex = BitFieldRead64 (PFAddress, 12, 20);
|
||||
Address = (UINT64)(PageTable[PTIndex] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
|
||||
if ((Address & ~((1ull << 12) - 1)) == (PFAddress & PHYSICAL_ADDRESS_MASK & ~((1ull << 12) - 1))) {
|
||||
if ((Address & ~((1ull << 21) - 1)) == ((PFAddress & PHYSICAL_ADDRESS_MASK & ~((1ull << 21) - 1)))) {
|
||||
Existed = TRUE;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// 4KB page
|
||||
//
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask& PHYSICAL_ADDRESS_MASK);
|
||||
if (PageTable != 0) {
|
||||
//
|
||||
// When there is a valid entry to map to 4KB page, need not create a new entry to map 2MB.
|
||||
//
|
||||
PTIndex = BitFieldRead64 (PFAddress, 12, 20);
|
||||
Address = (UINT64)(PageTable[PTIndex] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
|
||||
if ((Address & ~((1ull << 12) - 1)) == (PFAddress & PHYSICAL_ADDRESS_MASK & ~((1ull << 12) - 1))) {
|
||||
Existed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,6 +236,11 @@ RestorePageTableAbove4G (
|
||||
//
|
||||
PageTable = (UINT64*)(AsmReadCr3 () & PHYSICAL_ADDRESS_MASK);
|
||||
PFAddress = AsmReadCr2 ();
|
||||
// PML5E
|
||||
if (Enable5LevelPaging) {
|
||||
PTIndex = BitFieldRead64 (PFAddress, 48, 56);
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
|
||||
}
|
||||
// PML4E
|
||||
PTIndex = BitFieldRead64 (PFAddress, 39, 47);
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
|
||||
|
Reference in New Issue
Block a user