UefiCpuPkg/PiSmmCpu: Enable 5L paging only when phy addr line > 48

Today's behavior is to enable 5l paging when CPU supports it
(CPUID[7,0].ECX.BIT[16] is set).

The patch changes the behavior to enable 5l paging when two
conditions are both met:
1. CPU supports it;
2. The max physical address bits is bigger than 48.

Because 4-level paging can support to address physical address up to
2^48 - 1, there is no need to enable 5-level paging with max
physical address bits <= 48.

Signed-off-by: Ray Ni <ray.ni@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Ray Ni 2019-09-06 06:18:47 +08:00
parent 5a9db85880
commit 86ad762fa7
2 changed files with 39 additions and 22 deletions

View File

@ -16,8 +16,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
LIST_ENTRY mPagePool = INITIALIZE_LIST_HEAD_VARIABLE (mPagePool); LIST_ENTRY mPagePool = INITIALIZE_LIST_HEAD_VARIABLE (mPagePool);
BOOLEAN m1GPageTableSupport = FALSE; BOOLEAN m1GPageTableSupport = FALSE;
BOOLEAN mCpuSmmRestrictedMemoryAccess; BOOLEAN mCpuSmmRestrictedMemoryAccess;
BOOLEAN m5LevelPagingSupport; BOOLEAN m5LevelPagingNeeded;
X86_ASSEMBLY_PATCH_LABEL gPatch5LevelPagingSupport; X86_ASSEMBLY_PATCH_LABEL gPatch5LevelPagingNeeded;
/** /**
Disable CET. Disable CET.
@ -63,28 +63,45 @@ Is1GPageSupport (
} }
/** /**
Check if 5-level paging is supported by processor or not. The routine returns TRUE when CPU supports it (CPUID[7,0].ECX.BIT[16] is set) and
the max physical address bits is bigger than 48. Because 4-level paging can support
@retval TRUE 5-level paging is supported. to address physical address up to 2^48 - 1, there is no need to enable 5-level paging
@retval FALSE 5-level paging is not supported. with max physical address bits <= 48.
@retval TRUE 5-level paging enabling is needed.
@retval FALSE 5-level paging enabling is not needed.
**/ **/
BOOLEAN BOOLEAN
Is5LevelPagingSupport ( Is5LevelPagingNeeded (
VOID VOID
) )
{ {
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX EcxFlags; CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize;
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX ExtFeatureEcx;
UINT32 MaxExtendedFunctionId;
AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunctionId, NULL, NULL, NULL);
if (MaxExtendedFunctionId >= CPUID_VIR_PHY_ADDRESS_SIZE) {
AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &VirPhyAddressSize.Uint32, NULL, NULL, NULL);
} else {
VirPhyAddressSize.Bits.PhysicalAddressBits = 36;
}
AsmCpuidEx ( AsmCpuidEx (
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO,
NULL, NULL, NULL, &ExtFeatureEcx.Uint32, NULL
NULL,
&EcxFlags.Uint32,
NULL
); );
return (BOOLEAN) (EcxFlags.Bits.FiveLevelPage != 0); DEBUG ((
DEBUG_INFO, "PhysicalAddressBits = %d, 5LPageTable = %d.\n",
VirPhyAddressSize.Bits.PhysicalAddressBits, ExtFeatureEcx.Bits.FiveLevelPage
));
if (VirPhyAddressSize.Bits.PhysicalAddressBits > 4 * 9 + 12) {
ASSERT (ExtFeatureEcx.Bits.FiveLevelPage == 1);
return TRUE;
} else {
return FALSE;
}
} }
/** /**
@ -190,7 +207,7 @@ SetStaticPageTable (
// when 5-Level Paging is disabled. // when 5-Level Paging is disabled.
// //
ASSERT (mPhysicalAddressBits <= 52); ASSERT (mPhysicalAddressBits <= 52);
if (!m5LevelPagingSupport && mPhysicalAddressBits > 48) { if (!m5LevelPagingNeeded && mPhysicalAddressBits > 48) {
mPhysicalAddressBits = 48; mPhysicalAddressBits = 48;
} }
@ -217,7 +234,7 @@ SetStaticPageTable (
PageMapLevel4Entry = PageMap; PageMapLevel4Entry = PageMap;
PageMapLevel5Entry = NULL; PageMapLevel5Entry = NULL;
if (m5LevelPagingSupport) { if (m5LevelPagingNeeded) {
// //
// By architecture only one PageMapLevel5 exists - so lets allocate storage for it. // By architecture only one PageMapLevel5 exists - so lets allocate storage for it.
// //
@ -233,7 +250,7 @@ SetStaticPageTable (
// So lets allocate space for them and fill them in in the IndexOfPml4Entries loop. // So lets allocate space for them and fill them in in the IndexOfPml4Entries loop.
// When 5-Level Paging is disabled, below allocation happens only once. // When 5-Level Paging is disabled, below allocation happens only once.
// //
if (m5LevelPagingSupport) { if (m5LevelPagingNeeded) {
PageMapLevel4Entry = (UINT64 *) ((*PageMapLevel5Entry) & ~mAddressEncMask & gPhyMask); PageMapLevel4Entry = (UINT64 *) ((*PageMapLevel5Entry) & ~mAddressEncMask & gPhyMask);
if (PageMapLevel4Entry == NULL) { if (PageMapLevel4Entry == NULL) {
PageMapLevel4Entry = AllocatePageTableMemory (1); PageMapLevel4Entry = AllocatePageTableMemory (1);
@ -336,10 +353,10 @@ SmmInitPageTable (
mCpuSmmRestrictedMemoryAccess = PcdGetBool (PcdCpuSmmRestrictedMemoryAccess); mCpuSmmRestrictedMemoryAccess = PcdGetBool (PcdCpuSmmRestrictedMemoryAccess);
m1GPageTableSupport = Is1GPageSupport (); m1GPageTableSupport = Is1GPageSupport ();
m5LevelPagingSupport = Is5LevelPagingSupport (); m5LevelPagingNeeded = Is5LevelPagingNeeded ();
mPhysicalAddressBits = CalculateMaximumSupportAddress (); mPhysicalAddressBits = CalculateMaximumSupportAddress ();
PatchInstructionX86 (gPatch5LevelPagingSupport, m5LevelPagingSupport, 1); PatchInstructionX86 (gPatch5LevelPagingNeeded, m5LevelPagingNeeded, 1);
DEBUG ((DEBUG_INFO, "5LevelPaging Support - %d\n", m5LevelPagingSupport)); DEBUG ((DEBUG_INFO, "5LevelPaging Needed - %d\n", m5LevelPagingNeeded));
DEBUG ((DEBUG_INFO, "1GPageTable Support - %d\n", m1GPageTableSupport)); DEBUG ((DEBUG_INFO, "1GPageTable Support - %d\n", m1GPageTableSupport));
DEBUG ((DEBUG_INFO, "PcdCpuSmmRestrictedMemoryAccess - %d\n", mCpuSmmRestrictedMemoryAccess)); DEBUG ((DEBUG_INFO, "PcdCpuSmmRestrictedMemoryAccess - %d\n", mCpuSmmRestrictedMemoryAccess));
DEBUG ((DEBUG_INFO, "PhysicalAddressBits - %d\n", mPhysicalAddressBits)); DEBUG ((DEBUG_INFO, "PhysicalAddressBits - %d\n", mPhysicalAddressBits));
@ -370,7 +387,7 @@ SmmInitPageTable (
SetSubEntriesNum (Pml4Entry, 3); SetSubEntriesNum (Pml4Entry, 3);
PTEntry = Pml4Entry; PTEntry = Pml4Entry;
if (m5LevelPagingSupport) { if (m5LevelPagingNeeded) {
// //
// Fill PML5 entry // Fill PML5 entry
// //

View File

@ -69,7 +69,7 @@ extern ASM_PFX(mXdSupported)
global ASM_PFX(gPatchXdSupported) global ASM_PFX(gPatchXdSupported)
global ASM_PFX(gPatchSmiStack) global ASM_PFX(gPatchSmiStack)
global ASM_PFX(gPatchSmiCr3) global ASM_PFX(gPatchSmiCr3)
global ASM_PFX(gPatch5LevelPagingSupport) global ASM_PFX(gPatch5LevelPagingNeeded)
global ASM_PFX(gcSmiHandlerTemplate) global ASM_PFX(gcSmiHandlerTemplate)
global ASM_PFX(gcSmiHandlerSize) global ASM_PFX(gcSmiHandlerSize)
@ -127,7 +127,7 @@ ASM_PFX(gPatchSmiCr3):
mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3 mov eax, 0x668 ; as cr4.PGE is not set here, refresh cr3
mov cl, strict byte 0 ; source operand will be patched mov cl, strict byte 0 ; source operand will be patched
ASM_PFX(gPatch5LevelPagingSupport): ASM_PFX(gPatch5LevelPagingNeeded):
cmp cl, 0 cmp cl, 0
je SkipEnable5LevelPaging je SkipEnable5LevelPaging
; ;