From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.65, mailfrom: eric.dong@intel.com) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by groups.io with SMTP; Tue, 09 Jul 2019 06:33:59 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 09 Jul 2019 06:33:58 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,470,1557212400"; d="scan'208";a="156180821" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by orsmga007.jf.intel.com with ESMTP; 09 Jul 2019 06:33:58 -0700 Received: from fmsmsx113.amr.corp.intel.com (10.18.116.7) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.439.0; Tue, 9 Jul 2019 06:33:58 -0700 Received: from shsmsx153.ccr.corp.intel.com (10.239.6.53) by FMSMSX113.amr.corp.intel.com (10.18.116.7) with Microsoft SMTP Server (TLS) id 14.3.439.0; Tue, 9 Jul 2019 06:33:57 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.3]) by SHSMSX153.ccr.corp.intel.com ([169.254.12.60]) with mapi id 14.03.0439.000; Tue, 9 Jul 2019 21:33:55 +0800 From: "Dong, Eric" To: "Ni, Ray" , "devel@edk2.groups.io" CC: Laszlo Ersek Subject: Re: [PATCH v2 3/3] UefiCpuPkg/PiSmmCpu: Enable 5 level paging when CPU supports Thread-Topic: [PATCH v2 3/3] UefiCpuPkg/PiSmmCpu: Enable 5 level paging when CPU supports Thread-Index: AQHVMWw8iOV0jzTRLUGzmnIdxRfvfabBoZww Date: Tue, 9 Jul 2019 13:33:54 +0000 Message-ID: References: <20190703065416.116816-1-ray.ni@intel.com> <20190703065416.116816-4-ray.ni@intel.com> In-Reply-To: <20190703065416.116816-4-ray.ni@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiNmYyYzk5N2ItM2U2NC00ZGYxLThjMjUtODE5NzM1ODBlOGY2IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiNUV0N2lwVmNPUEpuZjdscyt6NEZiUVJlbzNOWVM0b3dNNHZUR3NHMzNGSUF3YkNES1lIRzJFaGNuNlZOU0RlRiJ9 x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.0.600.7 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: eric.dong@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Eric Dong > -----Original Message----- > From: Ni, Ray > Sent: Wednesday, July 3, 2019 2:54 PM > To: devel@edk2.groups.io > Cc: Dong, Eric ; Laszlo Ersek > Subject: [PATCH v2 3/3] UefiCpuPkg/PiSmmCpu: Enable 5 level paging when > CPU supports >=20 > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1946 >=20 > The patch changes SMM environment to use 5 level paging when CPU > supports it. >=20 > Signed-off-by: Ray Ni > Cc: Eric Dong > Regression-tested-by: Laszlo Ersek > --- > .../PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 20 +- > UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c | 272 ++++++---- > UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c | 485 ++++++++++++----- > - > UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm | 12 + > .../PiSmmCpuDxeSmm/X64/SmmProfileArch.c | 72 ++- > 5 files changed, 561 insertions(+), 300 deletions(-) >=20 > diff --git > a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c > b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c > index 069be3aaa5..55090e9c3e 100644 > --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c > +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c > @@ -125,18 +125,36 @@ GetPageTableEntry ( > UINTN Index2; > UINTN Index3; > UINTN Index4; > + UINTN Index5; > UINT64 *L1PageTable; > UINT64 *L2PageTable; > UINT64 *L3PageTable; > UINT64 *L4PageTable; > + UINT64 *L5PageTable; > + IA32_CR4 Cr4; > + BOOLEAN Enable5LevelPaging; >=20 > + Index5 =3D ((UINTN)RShiftU64 (Address, 48)) & PAGING_PAE_INDEX_MASK; > Index4 =3D ((UINTN)RShiftU64 (Address, 39)) & PAGING_PAE_INDEX_MASK; > Index3 =3D ((UINTN)Address >> 30) & PAGING_PAE_INDEX_MASK; > Index2 =3D ((UINTN)Address >> 21) & PAGING_PAE_INDEX_MASK; > Index1 =3D ((UINTN)Address >> 12) & PAGING_PAE_INDEX_MASK; >=20 > + Cr4.UintN =3D AsmReadCr4 (); > + Enable5LevelPaging =3D (BOOLEAN) (Cr4.Bits.LA57 =3D=3D 1); > + > if (sizeof(UINTN) =3D=3D sizeof(UINT64)) { > - L4PageTable =3D (UINT64 *)GetPageTableBase (); > + if (Enable5LevelPaging) { > + L5PageTable =3D (UINT64 *)GetPageTableBase (); > + if (L5PageTable[Index5] =3D=3D 0) { > + *PageAttribute =3D PageNone; > + return NULL; > + } > + > + L4PageTable =3D (UINT64 *)(UINTN)(L5PageTable[Index5] & > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > + } else { > + L4PageTable =3D (UINT64 *)GetPageTableBase (); > + } > if (L4PageTable[Index4] =3D=3D 0) { > *PageAttribute =3D PageNone; > return NULL; > diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c > b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c > index e2b6a2d9b2..c5131526f0 100644 > --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c > +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c > @@ -534,43 +534,78 @@ InitPaging ( > VOID > ) > { > + UINT64 Pml5Entry; > + UINT64 Pml4Entry; > + UINT64 *Pml5; > UINT64 *Pml4; > UINT64 *Pdpt; > UINT64 *Pd; > UINT64 *Pt; > UINTN Address; > + UINTN Pml5Index; > UINTN Pml4Index; > UINTN PdptIndex; > UINTN PdIndex; > UINTN PtIndex; > UINTN NumberOfPdptEntries; > UINTN NumberOfPml4Entries; > + UINTN NumberOfPml5Entries; > UINTN SizeOfMemorySpace; > BOOLEAN Nx; > + IA32_CR4 Cr4; > + BOOLEAN Enable5LevelPaging; > + > + Cr4.UintN =3D AsmReadCr4 (); > + Enable5LevelPaging =3D (BOOLEAN) (Cr4.Bits.LA57 =3D=3D 1); >=20 > if (sizeof (UINTN) =3D=3D sizeof (UINT64)) { > - Pml4 =3D (UINT64*)(UINTN)mSmmProfileCr3; > + if (!Enable5LevelPaging) { > + Pml5Entry =3D (UINTN) mSmmProfileCr3 | IA32_PG_P; > + Pml5 =3D &Pml5Entry; > + } else { > + Pml5 =3D (UINT64*) (UINTN) mSmmProfileCr3; > + } > SizeOfMemorySpace =3D HighBitSet64 (gPhyMask) + 1; > // > // Calculate the table entries of PML4E and PDPTE. > // > - if (SizeOfMemorySpace <=3D 39 ) { > - NumberOfPml4Entries =3D 1; > - NumberOfPdptEntries =3D (UINT32)LShiftU64 (1, (SizeOfMemorySpace - > 30)); > - } else { > - NumberOfPml4Entries =3D (UINT32)LShiftU64 (1, (SizeOfMemorySpace - > 39)); > - NumberOfPdptEntries =3D 512; > + NumberOfPml5Entries =3D 1; > + if (SizeOfMemorySpace > 48) { > + NumberOfPml5Entries =3D (UINTN) LShiftU64 (1, SizeOfMemorySpace - = 48); > + SizeOfMemorySpace =3D 48; > } > - } else { > + > NumberOfPml4Entries =3D 1; > + if (SizeOfMemorySpace > 39) { > + NumberOfPml4Entries =3D (UINTN) LShiftU64 (1, SizeOfMemorySpace - = 39); > + SizeOfMemorySpace =3D 39; > + } > + > + NumberOfPdptEntries =3D 1; > + ASSERT (SizeOfMemorySpace > 30); > + NumberOfPdptEntries =3D (UINTN) LShiftU64 (1, SizeOfMemorySpace - > + 30); } else { > + Pml4Entry =3D (UINTN) mSmmProfileCr3 | IA32_PG_P; > + Pml4 =3D &Pml4Entry; > + Pml5Entry =3D (UINTN) Pml4 | IA32_PG_P; > + Pml5 =3D &Pml5Entry; > + NumberOfPml5Entries =3D 1; > + NumberOfPml4Entries =3D 1; > NumberOfPdptEntries =3D 4; > } >=20 > // > // Go through page table and change 2MB-page into 4KB-page. > // > - for (Pml4Index =3D 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) { > - if (sizeof (UINTN) =3D=3D sizeof (UINT64)) { > + for (Pml5Index =3D 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) { > + if ((Pml5[Pml5Index] & IA32_PG_P) =3D=3D 0) { > + // > + // If PML5 entry does not exist, skip it > + // > + continue; > + } > + Pml4 =3D (UINT64 *) (UINTN) (Pml5[Pml5Index] & > PHYSICAL_ADDRESS_MASK); > + for (Pml4Index =3D 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) = { > if ((Pml4[Pml4Index] & IA32_PG_P) =3D=3D 0) { > // > // If PML4 entry does not exist, skip it @@ -578,63 +613,76 @@ > InitPaging ( > continue; > } > Pdpt =3D (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > - } else { > - Pdpt =3D (UINT64*)(UINTN)mSmmProfileCr3; > - } > - for (PdptIndex =3D 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, > Pdpt++) { > - if ((*Pdpt & IA32_PG_P) =3D=3D 0) { > - // > - // If PDPT entry does not exist, skip it > - // > - continue; > - } > - if ((*Pdpt & IA32_PG_PS) !=3D 0) { > - // > - // This is 1G entry, skip it > - // > - continue; > - } > - Pd =3D (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > - if (Pd =3D=3D 0) { > - continue; > - } > - for (PdIndex =3D 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, = Pd++) { > - if ((*Pd & IA32_PG_P) =3D=3D 0) { > + for (PdptIndex =3D 0; PdptIndex < NumberOfPdptEntries; PdptIndex++= , > Pdpt++) { > + if ((*Pdpt & IA32_PG_P) =3D=3D 0) { > + // > + // If PDPT entry does not exist, skip it > + // > + continue; > + } > + if ((*Pdpt & IA32_PG_PS) !=3D 0) { > // > - // If PD entry does not exist, skip it > + // This is 1G entry, skip it > // > continue; > } > - Address =3D (((PdptIndex << 9) + PdIndex) << 21); > + Pd =3D (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > + if (Pd =3D=3D 0) { > + continue; > + } > + for (PdIndex =3D 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++= , Pd++) { > + if ((*Pd & IA32_PG_P) =3D=3D 0) { > + // > + // If PD entry does not exist, skip it > + // > + continue; > + } > + Address =3D (UINTN) LShiftU64 ( > + LShiftU64 ( > + LShiftU64 ((Pml5Index << 9) + Pml4Index,= 9) + PdptIndex, > + 9 > + ) + PdIndex, > + 21 > + ); >=20 > - // > - // If it is 2M page, check IsAddressSplit() > - // > - if (((*Pd & IA32_PG_PS) !=3D 0) && IsAddressSplit (Address)) { > // > - // Based on current page table, create 4KB page table for spli= t area. > + // If it is 2M page, check IsAddressSplit() > // > - ASSERT (Address =3D=3D (*Pd & PHYSICAL_ADDRESS_MASK)); > + if (((*Pd & IA32_PG_PS) !=3D 0) && IsAddressSplit (Address)) { > + // > + // Based on current page table, create 4KB page table for sp= lit area. > + // > + ASSERT (Address =3D=3D (*Pd & PHYSICAL_ADDRESS_MASK)); > + > + Pt =3D AllocatePageTableMemory (1); > + ASSERT (Pt !=3D NULL); >=20 > - Pt =3D AllocatePageTableMemory (1); > - ASSERT (Pt !=3D NULL); > + *Pd =3D (UINTN) Pt | IA32_PG_RW | IA32_PG_P; >=20 > - // Split it > - for (PtIndex =3D 0; PtIndex < SIZE_4KB / sizeof(*Pt); PtIndex+= +) { > - Pt[PtIndex] =3D Address + ((PtIndex << 12) | mAddressEncMask= | > PAGE_ATTRIBUTE_BITS); > - } // end for PT > - *Pd =3D (UINT64)(UINTN)Pt | mAddressEncMask | > PAGE_ATTRIBUTE_BITS; > - } // end if IsAddressSplit > - } // end for PD > - } // end for PDPT > - } // end for PML4 > + // Split it > + for (PtIndex =3D 0; PtIndex < SIZE_4KB / sizeof(*Pt); PtInde= x++, Pt++) { > + *Pt =3D Address + ((PtIndex << 12) | mAddressEncMask | > PAGE_ATTRIBUTE_BITS); > + } // end for PT > + *Pd =3D (UINT64)(UINTN)Pt | mAddressEncMask | > PAGE_ATTRIBUTE_BITS; > + } // end if IsAddressSplit > + } // end for PD > + } // end for PDPT > + } // end for PML4 > + } // end for PML5 >=20 > // > // Go through page table and set several page table entries to absent = or > execute-disable. > // > DEBUG ((EFI_D_INFO, "Patch page table start ...\n")); > - for (Pml4Index =3D 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) { > - if (sizeof (UINTN) =3D=3D sizeof (UINT64)) { > + for (Pml5Index =3D 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) { > + if ((Pml5[Pml5Index] & IA32_PG_P) =3D=3D 0) { > + // > + // If PML5 entry does not exist, skip it > + // > + continue; > + } > + Pml4 =3D (UINT64 *) (UINTN) (Pml5[Pml5Index] & > PHYSICAL_ADDRESS_MASK); > + for (Pml4Index =3D 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) = { > if ((Pml4[Pml4Index] & IA32_PG_P) =3D=3D 0) { > // > // If PML4 entry does not exist, skip it @@ -642,69 +690,73 @@ > InitPaging ( > continue; > } > Pdpt =3D (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > - } else { > - Pdpt =3D (UINT64*)(UINTN)mSmmProfileCr3; > - } > - for (PdptIndex =3D 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, > Pdpt++) { > - if ((*Pdpt & IA32_PG_P) =3D=3D 0) { > - // > - // If PDPT entry does not exist, skip it > - // > - continue; > - } > - if ((*Pdpt & IA32_PG_PS) !=3D 0) { > - // > - // This is 1G entry, set NX bit and skip it > - // > - if (mXdSupported) { > - *Pdpt =3D *Pdpt | IA32_PG_NX; > + for (PdptIndex =3D 0; PdptIndex < NumberOfPdptEntries; PdptIndex++= , > Pdpt++) { > + if ((*Pdpt & IA32_PG_P) =3D=3D 0) { > + // > + // If PDPT entry does not exist, skip it > + // > + continue; > } > - continue; > - } > - Pd =3D (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > - if (Pd =3D=3D 0) { > - continue; > - } > - for (PdIndex =3D 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, = Pd++) { > - if ((*Pd & IA32_PG_P) =3D=3D 0) { > + if ((*Pdpt & IA32_PG_PS) !=3D 0) { > // > - // If PD entry does not exist, skip it > + // This is 1G entry, set NX bit and skip it > // > + if (mXdSupported) { > + *Pdpt =3D *Pdpt | IA32_PG_NX; > + } > continue; > } > - Address =3D (((PdptIndex << 9) + PdIndex) << 21); > - > - if ((*Pd & IA32_PG_PS) !=3D 0) { > - // 2MB page > - > - if (!IsAddressValid (Address, &Nx)) { > + Pd =3D (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > + if (Pd =3D=3D 0) { > + continue; > + } > + for (PdIndex =3D 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++= , Pd++) { > + if ((*Pd & IA32_PG_P) =3D=3D 0) { > // > - // Patch to remove Present flag and RW flag > + // If PD entry does not exist, skip it > // > - *Pd =3D *Pd & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS); > - } > - if (Nx && mXdSupported) { > - *Pd =3D *Pd | IA32_PG_NX; > - } > - } else { > - // 4KB page > - Pt =3D (UINT64 *)(UINTN)(*Pd & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > - if (Pt =3D=3D 0) { > continue; > } > - for (PtIndex =3D 0; PtIndex < SIZE_4KB / sizeof(*Pt); PtIndex+= +, Pt++) { > + Address =3D (UINTN) LShiftU64 ( > + LShiftU64 ( > + LShiftU64 ((Pml5Index << 9) + Pml4Index,= 9) + PdptIndex, > + 9 > + ) + PdIndex, > + 21 > + ); > + > + if ((*Pd & IA32_PG_PS) !=3D 0) { > + // 2MB page > + > if (!IsAddressValid (Address, &Nx)) { > - *Pt =3D *Pt & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS); > + // > + // Patch to remove Present flag and RW flag > + // > + *Pd =3D *Pd & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS); > } > if (Nx && mXdSupported) { > - *Pt =3D *Pt | IA32_PG_NX; > + *Pd =3D *Pd | IA32_PG_NX; > + } > + } else { > + // 4KB page > + Pt =3D (UINT64 *)(UINTN)(*Pd & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > + if (Pt =3D=3D 0) { > + continue; > } > - Address +=3D SIZE_4KB; > - } // end for PT > - } // end if PS > - } // end for PD > - } // end for PDPT > - } // end for PML4 > + for (PtIndex =3D 0; PtIndex < SIZE_4KB / sizeof(*Pt); PtInde= x++, Pt++) { > + if (!IsAddressValid (Address, &Nx)) { > + *Pt =3D *Pt & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS); > + } > + if (Nx && mXdSupported) { > + *Pt =3D *Pt | IA32_PG_NX; > + } > + Address +=3D SIZE_4KB; > + } // end for PT > + } // end if PS > + } // end for PD > + } // end for PDPT > + } // end for PML4 > + } // end for PML5 >=20 > // > // Flush TLB > @@ -1156,6 +1208,20 @@ RestorePageTableBelow4G ( { > UINTN PTIndex; > UINTN PFIndex; > + IA32_CR4 Cr4; > + BOOLEAN Enable5LevelPaging; > + > + Cr4.UintN =3D AsmReadCr4 (); > + Enable5LevelPaging =3D (BOOLEAN) (Cr4.Bits.LA57 =3D=3D 1); > + > + // > + // PML5 > + // > + if (Enable5LevelPaging) { > + PTIndex =3D (UINTN)BitFieldRead64 (PFAddress, 48, 56); > + ASSERT (PageTable[PTIndex] !=3D 0); > + PageTable =3D (UINT64*)(UINTN)(PageTable[PTIndex] & > + PHYSICAL_ADDRESS_MASK); } >=20 > // > // PML4 > diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c > b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c > index 3d5d663d99..c31160735a 100644 > --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c > +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c > @@ -16,6 +16,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > LIST_ENTRY mPagePool =3D INITIALIZE_LIST_HEAD_V= ARIABLE > (mPagePool); > BOOLEAN m1GPageTableSupport =3D FALSE; > BOOLEAN mCpuSmmStaticPageTable; > +BOOLEAN m5LevelPagingSupport; > +X86_ASSEMBLY_PATCH_LABEL gPatch5LevelPagingSupport; >=20 > /** > Disable CET. > @@ -60,6 +62,31 @@ Is1GPageSupport ( > return FALSE; > } >=20 > +/** > + Check if 5-level paging is supported by processor or not. > + > + @retval TRUE 5-level paging is supported. > + @retval FALSE 5-level paging is not supported. > + > +**/ > +BOOLEAN > +Is5LevelPagingSupport ( > + VOID > + ) > +{ > + CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX EcxFlags; > + > + AsmCpuidEx ( > + CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, > + CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, > + NULL, > + NULL, > + &EcxFlags.Uint32, > + NULL > + ); > + return (BOOLEAN) (EcxFlags.Bits.FiveLevelPage !=3D 0); } > + > /** > Set sub-entries number in entry. >=20 > @@ -130,14 +157,6 @@ CalculateMaximumSupportAddress ( > PhysicalAddressBits =3D 36; > } > } > - > - // > - // IA-32e paging translates 48-bit linear addresses to 52-bit physical > addresses. > - // > - ASSERT (PhysicalAddressBits <=3D 52); > - if (PhysicalAddressBits > 48) { > - PhysicalAddressBits =3D 48; > - } > return PhysicalAddressBits; > } >=20 > @@ -152,89 +171,137 @@ SetStaticPageTable ( > ) > { > UINT64 PageAddress; > + UINTN NumberOfPml5EntriesNeede= d; > UINTN NumberOfPml4EntriesNeede= d; > UINTN NumberOfPdpEntriesNeeded= ; > + UINTN IndexOfPml5Entries; > UINTN IndexOfPml4Entries; > UINTN IndexOfPdpEntries; > UINTN IndexOfPageDirectoryEntr= ies; > + UINT64 *PageMapLevel5Entry; > UINT64 *PageMapLevel4Entry; > UINT64 *PageMap; > UINT64 *PageDirectoryPointerEnt= ry; > UINT64 *PageDirectory1GEntry; > UINT64 *PageDirectoryEntry; >=20 > - if (mPhysicalAddressBits <=3D 39 ) { > - NumberOfPml4EntriesNeeded =3D 1; > - NumberOfPdpEntriesNeeded =3D (UINT32)LShiftU64 (1, > (mPhysicalAddressBits - 30)); > - } else { > - NumberOfPml4EntriesNeeded =3D (UINT32)LShiftU64 (1, > (mPhysicalAddressBits - 39)); > - NumberOfPdpEntriesNeeded =3D 512; > + // > + // IA-32e paging translates 48-bit linear addresses to 52-bit > + physical addresses // when 5-Level Paging is disabled. > + // > + ASSERT (mPhysicalAddressBits <=3D 52); > + if (!m5LevelPagingSupport && mPhysicalAddressBits > 48) { > + mPhysicalAddressBits =3D 48; > + } > + > + NumberOfPml5EntriesNeeded =3D 1; > + if (mPhysicalAddressBits > 48) { > + NumberOfPml5EntriesNeeded =3D (UINTN) LShiftU64 (1, > mPhysicalAddressBits - 48); > + mPhysicalAddressBits =3D 48; > + } > + > + NumberOfPml4EntriesNeeded =3D 1; > + if (mPhysicalAddressBits > 39) { > + NumberOfPml4EntriesNeeded =3D (UINTN) LShiftU64 (1, > mPhysicalAddressBits - 39); > + mPhysicalAddressBits =3D 39; > } >=20 > + NumberOfPdpEntriesNeeded =3D 1; > + ASSERT (mPhysicalAddressBits > 30); > + NumberOfPdpEntriesNeeded =3D (UINTN) LShiftU64 (1, > mPhysicalAddressBits > + - 30); > + > // > // By architecture only one PageMapLevel4 exists - so lets allocate st= orage > for it. > // > PageMap =3D (VOID *) PageTable; >=20 > PageMapLevel4Entry =3D PageMap; > - PageAddress =3D 0; > - for (IndexOfPml4Entries =3D 0; IndexOfPml4Entries < > NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, > PageMapLevel4Entry++) { > + PageMapLevel5Entry =3D NULL; > + if (m5LevelPagingSupport) { > // > - // Each PML4 entry points to a page of Page Directory Pointer entrie= s. > + // By architecture only one PageMapLevel5 exists - so lets allocate = storage > for it. > // > - PageDirectoryPointerEntry =3D (UINT64 *) ((*PageMapLevel4Entry) & > ~mAddressEncMask & gPhyMask); > - if (PageDirectoryPointerEntry =3D=3D NULL) { > - PageDirectoryPointerEntry =3D AllocatePageTableMemory (1); > - ASSERT(PageDirectoryPointerEntry !=3D NULL); > - ZeroMem (PageDirectoryPointerEntry, EFI_PAGES_TO_SIZE(1)); > + PageMapLevel5Entry =3D PageMap; > + } > + PageAddress =3D 0; >=20 > - *PageMapLevel4Entry =3D (UINT64)(UINTN)PageDirectoryPointerEntry | > mAddressEncMask | PAGE_ATTRIBUTE_BITS; > + for ( IndexOfPml5Entries =3D 0 > + ; IndexOfPml5Entries < NumberOfPml5EntriesNeeded > + ; IndexOfPml5Entries++, PageMapLevel5Entry++) { > + // > + // Each PML5 entry points to a page of PML4 entires. > + // So lets allocate space for them and fill them in in the > IndexOfPml4Entries loop. > + // When 5-Level Paging is disabled, below allocation happens only on= ce. > + // > + if (m5LevelPagingSupport) { > + PageMapLevel4Entry =3D (UINT64 *) ((*PageMapLevel5Entry) & > ~mAddressEncMask & gPhyMask); > + if (PageMapLevel4Entry =3D=3D NULL) { > + PageMapLevel4Entry =3D AllocatePageTableMemory (1); > + ASSERT(PageMapLevel4Entry !=3D NULL); > + ZeroMem (PageMapLevel4Entry, EFI_PAGES_TO_SIZE(1)); > + > + *PageMapLevel5Entry =3D (UINT64)(UINTN)PageMapLevel4Entry | > mAddressEncMask | PAGE_ATTRIBUTE_BITS; > + } > } >=20 > - if (m1GPageTableSupport) { > - PageDirectory1GEntry =3D PageDirectoryPointerEntry; > - for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntrie= s < 512; > IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress +=3D > SIZE_1GB) { > - if (IndexOfPml4Entries =3D=3D 0 && IndexOfPageDirectoryEntries <= 4) { > - // > - // Skip the < 4G entries > - // > - continue; > - } > - // > - // Fill in the Page Directory entries > - // > - *PageDirectory1GEntry =3D PageAddress | mAddressEncMask | > IA32_PG_PS | PAGE_ATTRIBUTE_BITS; > + for (IndexOfPml4Entries =3D 0; IndexOfPml4Entries < > (NumberOfPml5EntriesNeeded =3D=3D 1 ? NumberOfPml4EntriesNeeded : 512); > IndexOfPml4Entries++, PageMapLevel4Entry++) { > + // > + // Each PML4 entry points to a page of Page Directory Pointer entr= ies. > + // > + PageDirectoryPointerEntry =3D (UINT64 *) ((*PageMapLevel4Entry) & > ~mAddressEncMask & gPhyMask); > + if (PageDirectoryPointerEntry =3D=3D NULL) { > + PageDirectoryPointerEntry =3D AllocatePageTableMemory (1); > + ASSERT(PageDirectoryPointerEntry !=3D NULL); > + ZeroMem (PageDirectoryPointerEntry, EFI_PAGES_TO_SIZE(1)); > + > + *PageMapLevel4Entry =3D (UINT64)(UINTN)PageDirectoryPointerEntry > + | mAddressEncMask | PAGE_ATTRIBUTE_BITS; > } > - } else { > - PageAddress =3D BASE_4GB; > - for (IndexOfPdpEntries =3D 0; IndexOfPdpEntries < > NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, > PageDirectoryPointerEntry++) { > - if (IndexOfPml4Entries =3D=3D 0 && IndexOfPdpEntries < 4) { > - // > - // Skip the < 4G entries > - // > - continue; > - } > - // > - // Each Directory Pointer entries points to a page of Page Direc= tory > entires. > - // So allocate space for them and fill them in in the > IndexOfPageDirectoryEntries loop. > - // > - PageDirectoryEntry =3D (UINT64 *) ((*PageDirectoryPointerEntry) = & > ~mAddressEncMask & gPhyMask); > - if (PageDirectoryEntry =3D=3D NULL) { > - PageDirectoryEntry =3D AllocatePageTableMemory (1); > - ASSERT(PageDirectoryEntry !=3D NULL); > - ZeroMem (PageDirectoryEntry, EFI_PAGES_TO_SIZE(1)); >=20 > + if (m1GPageTableSupport) { > + PageDirectory1GEntry =3D PageDirectoryPointerEntry; > + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntr= ies < > 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress > +=3D SIZE_1GB) { > + if (IndexOfPml4Entries =3D=3D 0 && IndexOfPageDirectoryEntries= < 4) { > + // > + // Skip the < 4G entries > + // > + continue; > + } > // > - // Fill in a Page Directory Pointer Entries > + // Fill in the Page Directory entries > // > - *PageDirectoryPointerEntry =3D (UINT64)(UINTN)PageDirectoryEnt= ry | > mAddressEncMask | PAGE_ATTRIBUTE_BITS; > + *PageDirectory1GEntry =3D PageAddress | mAddressEncMask | > + IA32_PG_PS | PAGE_ATTRIBUTE_BITS; > } > - > - for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntr= ies < > 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += =3D > SIZE_2MB) { > + } else { > + PageAddress =3D BASE_4GB; > + for (IndexOfPdpEntries =3D 0; IndexOfPdpEntries < > (NumberOfPml4EntriesNeeded =3D=3D 1 ? NumberOfPdpEntriesNeeded : 512); > IndexOfPdpEntries++, PageDirectoryPointerEntry++) { > + if (IndexOfPml4Entries =3D=3D 0 && IndexOfPdpEntries < 4) { > + // > + // Skip the < 4G entries > + // > + continue; > + } > // > - // Fill in the Page Directory entries > + // Each Directory Pointer entries points to a page of Page Dir= ectory > entires. > + // So allocate space for them and fill them in in the > IndexOfPageDirectoryEntries loop. > // > - *PageDirectoryEntry =3D PageAddress | mAddressEncMask | > IA32_PG_PS | PAGE_ATTRIBUTE_BITS; > + PageDirectoryEntry =3D (UINT64 *) ((*PageDirectoryPointerEntry= ) & > ~mAddressEncMask & gPhyMask); > + if (PageDirectoryEntry =3D=3D NULL) { > + PageDirectoryEntry =3D AllocatePageTableMemory (1); > + ASSERT(PageDirectoryEntry !=3D NULL); > + ZeroMem (PageDirectoryEntry, EFI_PAGES_TO_SIZE(1)); > + > + // > + // Fill in a Page Directory Pointer Entries > + // > + *PageDirectoryPointerEntry =3D (UINT64)(UINTN)PageDirectoryE= ntry | > mAddressEncMask | PAGE_ATTRIBUTE_BITS; > + } > + > + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEn= tries < > 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += =3D > SIZE_2MB) { > + // > + // Fill in the Page Directory entries > + // > + *PageDirectoryEntry =3D PageAddress | mAddressEncMask | > IA32_PG_PS | PAGE_ATTRIBUTE_BITS; > + } > } > } > } > @@ -259,6 +326,8 @@ SmmInitPageTable ( > UINTN PageFaultHandlerHookAddress; > IA32_IDT_GATE_DESCRIPTOR *IdtEntry; > EFI_STATUS Status; > + UINT64 *Pml4Entry; > + UINT64 *Pml5Entry; >=20 > // > // Initialize spin lock > @@ -266,12 +335,14 @@ SmmInitPageTable ( > InitializeSpinLock (mPFLock); >=20 > mCpuSmmStaticPageTable =3D PcdGetBool (PcdCpuSmmStaticPageTable); > - m1GPageTableSupport =3D Is1GPageSupport (); > - DEBUG ((DEBUG_INFO, "1GPageTableSupport - 0x%x\n", > m1GPageTableSupport)); > - DEBUG ((DEBUG_INFO, "PcdCpuSmmStaticPageTable - 0x%x\n", > mCpuSmmStaticPageTable)); > - > - mPhysicalAddressBits =3D CalculateMaximumSupportAddress (); > - DEBUG ((DEBUG_INFO, "PhysicalAddressBits - 0x%x\n", > mPhysicalAddressBits)); > + m1GPageTableSupport =3D Is1GPageSupport (); > + m5LevelPagingSupport =3D Is5LevelPagingSupport (); > + mPhysicalAddressBits =3D CalculateMaximumSupportAddress (); > + PatchInstructionX86 (gPatch5LevelPagingSupport, m5LevelPagingSupport, > 1); > + DEBUG ((DEBUG_INFO, "5LevelPaging Support - %d\n", > m5LevelPagingSupport)); > + DEBUG ((DEBUG_INFO, "1GPageTable Support - %d\n", > m1GPageTableSupport)); > + DEBUG ((DEBUG_INFO, "PcdCpuSmmStaticPageTable - %d\n", > mCpuSmmStaticPageTable)); > + DEBUG ((DEBUG_INFO, "PhysicalAddressBits - %d\n", > mPhysicalAddressBits)); > // > // Generate PAE page table for the first 4GB memory space > // > @@ -288,15 +359,30 @@ SmmInitPageTable ( > // > // Fill Page-Table-Level4 (PML4) entry > // > - PTEntry =3D (UINT64*)AllocatePageTableMemory (1); > - ASSERT (PTEntry !=3D NULL); > - *PTEntry =3D Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS; > - ZeroMem (PTEntry + 1, EFI_PAGE_SIZE - sizeof (*PTEntry)); > + Pml4Entry =3D (UINT64*)AllocatePageTableMemory (1); ASSERT (Pml4Entry > + !=3D NULL); *Pml4Entry =3D Pages | mAddressEncMask | > PAGE_ATTRIBUTE_BITS; > + ZeroMem (Pml4Entry + 1, EFI_PAGE_SIZE - sizeof (*Pml4Entry)); >=20 > // > // Set sub-entries number > // > - SetSubEntriesNum (PTEntry, 3); > + SetSubEntriesNum (Pml4Entry, 3); > + PTEntry =3D Pml4Entry; > + > + if (m5LevelPagingSupport) { > + // > + // Fill PML5 entry > + // > + Pml5Entry =3D (UINT64*)AllocatePageTableMemory (1); > + *Pml5Entry =3D (UINTN) Pml4Entry | mAddressEncMask | > PAGE_ATTRIBUTE_BITS; > + ZeroMem (Pml5Entry + 1, EFI_PAGE_SIZE - sizeof (*Pml5Entry)); > + // > + // Set sub-entries number > + // > + SetSubEntriesNum (Pml5Entry, 1); > + PTEntry =3D Pml5Entry; > + } >=20 > if (mCpuSmmStaticPageTable) { > SetStaticPageTable ((UINTN)PTEntry); @@ -344,7 +430,7 @@ > SmmInitPageTable ( > } >=20 > // > - // Return the address of PML4 (to set CR3) > + // Return the address of PML4/PML5 (to set CR3) > // > return (UINT32)(UINTN)PTEntry; > } > @@ -436,12 +522,16 @@ ReclaimPages ( > VOID > ) > { > + UINT64 Pml5Entry; > + UINT64 *Pml5; > UINT64 *Pml4; > UINT64 *Pdpt; > UINT64 *Pdt; > + UINTN Pml5Index; > UINTN Pml4Index; > UINTN PdptIndex; > UINTN PdtIndex; > + UINTN MinPml5; > UINTN MinPml4; > UINTN MinPdpt; > UINTN MinPdt; > @@ -451,120 +541,147 @@ ReclaimPages ( > BOOLEAN PML4EIgnore; > BOOLEAN PDPTEIgnore; > UINT64 *ReleasePageAddress; > + IA32_CR4 Cr4; > + BOOLEAN Enable5LevelPaging; >=20 > Pml4 =3D NULL; > Pdpt =3D NULL; > Pdt =3D NULL; > MinAcc =3D (UINT64)-1; > MinPml4 =3D (UINTN)-1; > + MinPml5 =3D (UINTN)-1; > MinPdpt =3D (UINTN)-1; > MinPdt =3D (UINTN)-1; > Acc =3D 0; > ReleasePageAddress =3D 0; >=20 > + Cr4.UintN =3D AsmReadCr4 (); > + Enable5LevelPaging =3D (BOOLEAN) (Cr4.Bits.LA57 =3D=3D 1); > + Pml5 =3D (UINT64*)(UINTN)(AsmReadCr3 () & gPhyMask); > + > + if (!Enable5LevelPaging) { > + // > + // Create one fake PML5 entry for 4-Level Paging > + // so that the page table parsing logic only handles 5-Level page st= ructure. > + // > + Pml5Entry =3D (UINTN) Pml5 | IA32_PG_P; > + Pml5 =3D &Pml5Entry; > + } > + > // > // First, find the leaf entry has the smallest access record value > // > - Pml4 =3D (UINT64*)(UINTN)(AsmReadCr3 () & gPhyMask); > - for (Pml4Index =3D 0; Pml4Index < EFI_PAGE_SIZE / sizeof (*Pml4); > Pml4Index++) { > - if ((Pml4[Pml4Index] & IA32_PG_P) =3D=3D 0 || (Pml4[Pml4Index] & > IA32_PG_PMNT) !=3D 0) { > + for (Pml5Index =3D 0; Pml5Index < Enable5LevelPaging ? (EFI_PAGE_SIZE = / > sizeof (*Pml4)) : 1; Pml5Index++) { > + if ((Pml5[Pml5Index] & IA32_PG_P) =3D=3D 0 || (Pml5[Pml5Index] & > + IA32_PG_PMNT) !=3D 0) { > // > - // If the PML4 entry is not present or is masked, skip it > + // If the PML5 entry is not present or is masked, skip it > // > continue; > } > - Pdpt =3D (UINT64*)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & > gPhyMask); > - PML4EIgnore =3D FALSE; > - for (PdptIndex =3D 0; PdptIndex < EFI_PAGE_SIZE / sizeof (*Pdpt); > PdptIndex++) { > - if ((Pdpt[PdptIndex] & IA32_PG_P) =3D=3D 0 || (Pdpt[PdptIndex] & > IA32_PG_PMNT) !=3D 0) { > + Pml4 =3D (UINT64*)(UINTN)(Pml5[Pml5Index] & gPhyMask); > + for (Pml4Index =3D 0; Pml4Index < EFI_PAGE_SIZE / sizeof (*Pml4); > Pml4Index++) { > + if ((Pml4[Pml4Index] & IA32_PG_P) =3D=3D 0 || (Pml4[Pml4Index] & > + IA32_PG_PMNT) !=3D 0) { > // > - // If the PDPT entry is not present or is masked, skip it > + // If the PML4 entry is not present or is masked, skip it > // > - if ((Pdpt[PdptIndex] & IA32_PG_PMNT) !=3D 0) { > - // > - // If the PDPT entry is masked, we will ignore checking the PM= L4 entry > - // > - PML4EIgnore =3D TRUE; > - } > continue; > } > - if ((Pdpt[PdptIndex] & IA32_PG_PS) =3D=3D 0) { > - // > - // It's not 1-GByte pages entry, it should be a PDPT entry, > - // we will not check PML4 entry more > - // > - PML4EIgnore =3D TRUE; > - Pdt =3D (UINT64*)(UINTN)(Pdpt[PdptIndex] & ~mAddressEncMask & > gPhyMask); > - PDPTEIgnore =3D FALSE; > - for (PdtIndex =3D 0; PdtIndex < EFI_PAGE_SIZE / sizeof(*Pdt); Pd= tIndex++) > { > - if ((Pdt[PdtIndex] & IA32_PG_P) =3D=3D 0 || (Pdt[PdtIndex] & > IA32_PG_PMNT) !=3D 0) { > + Pdpt =3D (UINT64*)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & > gPhyMask); > + PML4EIgnore =3D FALSE; > + for (PdptIndex =3D 0; PdptIndex < EFI_PAGE_SIZE / sizeof (*Pdpt); > PdptIndex++) { > + if ((Pdpt[PdptIndex] & IA32_PG_P) =3D=3D 0 || (Pdpt[PdptIndex] & > IA32_PG_PMNT) !=3D 0) { > + // > + // If the PDPT entry is not present or is masked, skip it > + // > + if ((Pdpt[PdptIndex] & IA32_PG_PMNT) !=3D 0) { > // > - // If the PD entry is not present or is masked, skip it > + // If the PDPT entry is masked, we will ignore checking the > + PML4 entry > // > - if ((Pdt[PdtIndex] & IA32_PG_PMNT) !=3D 0) { > + PML4EIgnore =3D TRUE; > + } > + continue; > + } > + if ((Pdpt[PdptIndex] & IA32_PG_PS) =3D=3D 0) { > + // > + // It's not 1-GByte pages entry, it should be a PDPT entry, > + // we will not check PML4 entry more > + // > + PML4EIgnore =3D TRUE; > + Pdt =3D (UINT64*)(UINTN)(Pdpt[PdptIndex] & ~mAddressEncMask & > gPhyMask); > + PDPTEIgnore =3D FALSE; > + for (PdtIndex =3D 0; PdtIndex < EFI_PAGE_SIZE / sizeof(*Pdt); > PdtIndex++) { > + if ((Pdt[PdtIndex] & IA32_PG_P) =3D=3D 0 || (Pdt[PdtIndex] & > IA32_PG_PMNT) !=3D 0) { > + // > + // If the PD entry is not present or is masked, skip it > + // > + if ((Pdt[PdtIndex] & IA32_PG_PMNT) !=3D 0) { > + // > + // If the PD entry is masked, we will not PDPT entry mor= e > + // > + PDPTEIgnore =3D TRUE; > + } > + continue; > + } > + if ((Pdt[PdtIndex] & IA32_PG_PS) =3D=3D 0) { > // > - // If the PD entry is masked, we will not PDPT entry more > + // It's not 2 MByte page table entry, it should be PD entr= y > + // we will find the entry has the smallest access record > + value > // > PDPTEIgnore =3D TRUE; > + Acc =3D GetAndUpdateAccNum (Pdt + PdtIndex); > + if (Acc < MinAcc) { > + // > + // If the PD entry has the smallest access record value, > + // save the Page address to be released > + // > + MinAcc =3D Acc; > + MinPml5 =3D Pml5Index; > + MinPml4 =3D Pml4Index; > + MinPdpt =3D PdptIndex; > + MinPdt =3D PdtIndex; > + ReleasePageAddress =3D Pdt + PdtIndex; > + } > } > - continue; > } > - if ((Pdt[PdtIndex] & IA32_PG_PS) =3D=3D 0) { > + if (!PDPTEIgnore) { > // > - // It's not 2 MByte page table entry, it should be PD entry > - // we will find the entry has the smallest access record val= ue > + // If this PDPT entry has no PDT entries pointer to 4 KByte = pages, > + // it should only has the entries point to 2 MByte Pages > // > - PDPTEIgnore =3D TRUE; > - Acc =3D GetAndUpdateAccNum (Pdt + PdtIndex); > + Acc =3D GetAndUpdateAccNum (Pdpt + PdptIndex); > if (Acc < MinAcc) { > // > - // If the PD entry has the smallest access record value, > + // If the PDPT entry has the smallest access record > + value, > // save the Page address to be released > // > MinAcc =3D Acc; > + MinPml5 =3D Pml5Index; > MinPml4 =3D Pml4Index; > MinPdpt =3D PdptIndex; > - MinPdt =3D PdtIndex; > - ReleasePageAddress =3D Pdt + PdtIndex; > + MinPdt =3D (UINTN)-1; > + ReleasePageAddress =3D Pdpt + PdptIndex; > } > } > } > - if (!PDPTEIgnore) { > - // > - // If this PDPT entry has no PDT entries pointer to 4 KByte pa= ges, > - // it should only has the entries point to 2 MByte Pages > - // > - Acc =3D GetAndUpdateAccNum (Pdpt + PdptIndex); > - if (Acc < MinAcc) { > - // > - // If the PDPT entry has the smallest access record value, > - // save the Page address to be released > - // > - MinAcc =3D Acc; > - MinPml4 =3D Pml4Index; > - MinPdpt =3D PdptIndex; > - MinPdt =3D (UINTN)-1; > - ReleasePageAddress =3D Pdpt + PdptIndex; > - } > - } > } > - } > - if (!PML4EIgnore) { > - // > - // If PML4 entry has no the PDPT entry pointer to 2 MByte pages, > - // it should only has the entries point to 1 GByte Pages > - // > - Acc =3D GetAndUpdateAccNum (Pml4 + Pml4Index); > - if (Acc < MinAcc) { > + if (!PML4EIgnore) { > // > - // If the PML4 entry has the smallest access record value, > - // save the Page address to be released > + // If PML4 entry has no the PDPT entry pointer to 2 MByte pages, > + // it should only has the entries point to 1 GByte Pages > // > - MinAcc =3D Acc; > - MinPml4 =3D Pml4Index; > - MinPdpt =3D (UINTN)-1; > - MinPdt =3D (UINTN)-1; > - ReleasePageAddress =3D Pml4 + Pml4Index; > + Acc =3D GetAndUpdateAccNum (Pml4 + Pml4Index); > + if (Acc < MinAcc) { > + // > + // If the PML4 entry has the smallest access record value, > + // save the Page address to be released > + // > + MinAcc =3D Acc; > + MinPml5 =3D Pml5Index; > + MinPml4 =3D Pml4Index; > + MinPdpt =3D (UINTN)-1; > + MinPdt =3D (UINTN)-1; > + ReleasePageAddress =3D Pml4 + Pml4Index; > + } > } > } > } > @@ -588,6 +705,7 @@ ReclaimPages ( > // > // If 4 KByte Page Table is released, check the PDPT entry > // > + Pml4 =3D (UINT64 *) (UINTN) (Pml5[MinPml5] & gPhyMask); > Pdpt =3D (UINT64*)(UINTN)(Pml4[MinPml4] & ~mAddressEncMask & > gPhyMask); > SubEntriesNum =3D GetSubEntriesNum(Pdpt + MinPdpt); > if (SubEntriesNum =3D=3D 0) { > @@ -679,7 +797,7 @@ SmiDefaultPFHandler ( > ) > { > UINT64 *PageTable; > - UINT64 *Pml4; > + UINT64 *PageTableTop; > UINT64 PFAddress; > UINTN StartBit; > UINTN EndBit; > @@ -690,6 +808,8 @@ SmiDefaultPFHandler ( > UINTN PageAttribute; > EFI_STATUS Status; > UINT64 *UpperEntry; > + BOOLEAN Enable5LevelPaging; > + IA32_CR4 Cr4; >=20 > // > // Set default SMM page attribute > @@ -699,9 +819,12 @@ SmiDefaultPFHandler ( > PageAttribute =3D 0; >=20 > EndBit =3D 0; > - Pml4 =3D (UINT64*)(AsmReadCr3 () & gPhyMask); > + PageTableTop =3D (UINT64*)(AsmReadCr3 () & gPhyMask); > PFAddress =3D AsmReadCr2 (); >=20 > + Cr4.UintN =3D AsmReadCr4 (); > + Enable5LevelPaging =3D (BOOLEAN) (Cr4.Bits.LA57 !=3D 0); > + > Status =3D GetPlatformPageTableAttribute (PFAddress, &PageSize, > &NumOfPages, &PageAttribute); > // > // If platform not support page table attribute, set default SMM page > attribute @@ -755,9 +878,9 @@ SmiDefaultPFHandler ( > } >=20 > for (Index =3D 0; Index < NumOfPages; Index++) { > - PageTable =3D Pml4; > + PageTable =3D PageTableTop; > UpperEntry =3D NULL; > - for (StartBit =3D 39; StartBit > EndBit; StartBit -=3D 9) { > + for (StartBit =3D Enable5LevelPaging ? 48 : 39; StartBit > EndBit; > + StartBit -=3D 9) { > PTIndex =3D BitFieldRead64 (PFAddress, StartBit, StartBit + 8); > if ((PageTable[PTIndex] & IA32_PG_P) =3D=3D 0) { > // > @@ -941,13 +1064,20 @@ SetPageTableAttributes ( > UINTN Index2; > UINTN Index3; > UINTN Index4; > + UINTN Index5; > UINT64 *L1PageTable; > UINT64 *L2PageTable; > UINT64 *L3PageTable; > UINT64 *L4PageTable; > + UINT64 *L5PageTable; > BOOLEAN IsSplitted; > BOOLEAN PageTableSplitted; > BOOLEAN CetEnabled; > + IA32_CR4 Cr4; > + BOOLEAN Enable5LevelPaging; > + > + Cr4.UintN =3D AsmReadCr4 (); > + Enable5LevelPaging =3D (BOOLEAN) (Cr4.Bits.LA57 =3D=3D 1); >=20 > // > // Don't do this if > @@ -991,44 +1121,59 @@ SetPageTableAttributes ( > do { > DEBUG ((DEBUG_INFO, "Start...\n")); > PageTableSplitted =3D FALSE; > - > - L4PageTable =3D (UINT64 *)GetPageTableBase (); > - SmmSetMemoryAttributesEx > ((EFI_PHYSICAL_ADDRESS)(UINTN)L4PageTable, SIZE_4KB, EFI_MEMORY_RO, > &IsSplitted); > - PageTableSplitted =3D (PageTableSplitted || IsSplitted); > - > - for (Index4 =3D 0; Index4 < SIZE_4KB/sizeof(UINT64); Index4++) { > - L3PageTable =3D (UINT64 *)(UINTN)(L4PageTable[Index4] & > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > - if (L3PageTable =3D=3D NULL) { > - continue; > - } > - > - SmmSetMemoryAttributesEx > ((EFI_PHYSICAL_ADDRESS)(UINTN)L3PageTable, SIZE_4KB, EFI_MEMORY_RO, > &IsSplitted); > + L5PageTable =3D NULL; > + if (Enable5LevelPaging) { > + L5PageTable =3D (UINT64 *)GetPageTableBase (); > + SmmSetMemoryAttributesEx > + ((EFI_PHYSICAL_ADDRESS)(UINTN)L5PageTable, SIZE_4KB, > EFI_MEMORY_RO, > + &IsSplitted); > PageTableSplitted =3D (PageTableSplitted || IsSplitted); > + } >=20 > - for (Index3 =3D 0; Index3 < SIZE_4KB/sizeof(UINT64); Index3++) { > - if ((L3PageTable[Index3] & IA32_PG_PS) !=3D 0) { > - // 1G > + for (Index5 =3D 0; Index5 < (Enable5LevelPaging ? SIZE_4KB/sizeof(UI= NT64) : > 1); Index5++) { > + if (Enable5LevelPaging) { > + L4PageTable =3D (UINT64 *)(UINTN)(L5PageTable[Index5] & > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > + if (L4PageTable =3D=3D NULL) { > continue; > } > - L2PageTable =3D (UINT64 *)(UINTN)(L3PageTable[Index3] & > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > - if (L2PageTable =3D=3D NULL) { > + } else { > + L4PageTable =3D (UINT64 *)GetPageTableBase (); > + } > + SmmSetMemoryAttributesEx > ((EFI_PHYSICAL_ADDRESS)(UINTN)L4PageTable, SIZE_4KB, EFI_MEMORY_RO, > &IsSplitted); > + PageTableSplitted =3D (PageTableSplitted || IsSplitted); > + > + for (Index4 =3D 0; Index4 < SIZE_4KB/sizeof(UINT64); Index4++) { > + L3PageTable =3D (UINT64 *)(UINTN)(L4PageTable[Index4] & > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > + if (L3PageTable =3D=3D NULL) { > continue; > } >=20 > - SmmSetMemoryAttributesEx > ((EFI_PHYSICAL_ADDRESS)(UINTN)L2PageTable, SIZE_4KB, EFI_MEMORY_RO, > &IsSplitted); > + SmmSetMemoryAttributesEx > + ((EFI_PHYSICAL_ADDRESS)(UINTN)L3PageTable, SIZE_4KB, > EFI_MEMORY_RO, > + &IsSplitted); > PageTableSplitted =3D (PageTableSplitted || IsSplitted); >=20 > - for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(UINT64); Index2++) { > - if ((L2PageTable[Index2] & IA32_PG_PS) !=3D 0) { > - // 2M > + for (Index3 =3D 0; Index3 < SIZE_4KB/sizeof(UINT64); Index3++) { > + if ((L3PageTable[Index3] & IA32_PG_PS) !=3D 0) { > + // 1G > continue; > } > - L1PageTable =3D (UINT64 *)(UINTN)(L2PageTable[Index2] & > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > - if (L1PageTable =3D=3D NULL) { > + L2PageTable =3D (UINT64 *)(UINTN)(L3PageTable[Index3] & > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > + if (L2PageTable =3D=3D NULL) { > continue; > } > - SmmSetMemoryAttributesEx > ((EFI_PHYSICAL_ADDRESS)(UINTN)L1PageTable, SIZE_4KB, EFI_MEMORY_RO, > &IsSplitted); > + > + SmmSetMemoryAttributesEx > + ((EFI_PHYSICAL_ADDRESS)(UINTN)L2PageTable, SIZE_4KB, > EFI_MEMORY_RO, > + &IsSplitted); > PageTableSplitted =3D (PageTableSplitted || IsSplitted); > + > + for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(UINT64); Index2++)= { > + if ((L2PageTable[Index2] & IA32_PG_PS) !=3D 0) { > + // 2M > + continue; > + } > + L1PageTable =3D (UINT64 *)(UINTN)(L2PageTable[Index2] & > ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64); > + if (L1PageTable =3D=3D NULL) { > + continue; > + } > + SmmSetMemoryAttributesEx > ((EFI_PHYSICAL_ADDRESS)(UINTN)L1PageTable, SIZE_4KB, EFI_MEMORY_RO, > &IsSplitted); > + PageTableSplitted =3D (PageTableSplitted || IsSplitted); > + } > } > } > } > diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm > b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm > index 741e4b7da2..271492a9d7 100644 > --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm > +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm > @@ -69,6 +69,7 @@ extern ASM_PFX(mXdSupported) global > ASM_PFX(gPatchXdSupported) global ASM_PFX(gPatchSmiStack) global > ASM_PFX(gPatchSmiCr3) > +global ASM_PFX(gPatch5LevelPagingSupport) > global ASM_PFX(gcSmiHandlerTemplate) > global ASM_PFX(gcSmiHandlerSize) >=20 > @@ -124,6 +125,17 @@ ProtFlatMode: > ASM_PFX(gPatchSmiCr3): > mov cr3, rax > mov eax, 0x668 ; as cr4.PGE is not set here, r= efresh cr3 > + > + mov cl, strict byte 0 ; source operand will be patche= d > +ASM_PFX(gPatch5LevelPagingSupport): > + cmp cl, 0 > + je SkipEnable5LevelPaging > + ; > + ; Enable 5-Level Paging bit > + ; > + bts eax, 12 ; Set LA57 bit (bit #12) > +SkipEnable5LevelPaging: > + > mov cr4, rax ; in PreModifyMtrrs() to flush T= LB. > ; Load TSS > sub esp, 8 ; reserve room in stack > diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c > b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c > index e7c78d36fc..63bae5a913 100644 > --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c > +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c > @@ -1,7 +1,7 @@ > /** @file > X64 processor specific functions to enable SMM profile. >=20 > -Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.
> +Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.
> Copyright (c) 2017, AMD Incorporated. All rights reserved.
>=20 > SPDX-License-Identifier: BSD-2-Clause-Patent @@ -147,9 +147,14 @@ > RestorePageTableAbove4G ( > BOOLEAN Existed; > UINTN Index; > UINTN PFIndex; > + IA32_CR4 Cr4; > + BOOLEAN Enable5LevelPaging; >=20 > ASSERT ((PageTable !=3D NULL) && (IsValidPFAddress !=3D NULL)); >=20 > + Cr4.UintN =3D AsmReadCr4 (); > + Enable5LevelPaging =3D (BOOLEAN) (Cr4.Bits.LA57 =3D=3D 1); > + > // > // If page fault address is 4GB above. > // > @@ -161,38 +166,48 @@ RestorePageTableAbove4G ( > // > Existed =3D FALSE; > PageTable =3D (UINT64*)(AsmReadCr3 () & PHYSICAL_ADDRESS_MASK); > - PTIndex =3D BitFieldRead64 (PFAddress, 39, 47); > - if ((PageTable[PTIndex] & IA32_PG_P) !=3D 0) { > - // PML4E > - PageTable =3D (UINT64*)(UINTN)(PageTable[PTIndex] & > ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); > - PTIndex =3D BitFieldRead64 (PFAddress, 30, 38); > + PTIndex =3D 0; > + if (Enable5LevelPaging) { > + PTIndex =3D BitFieldRead64 (PFAddress, 48, 56); } if > + ((!Enable5LevelPaging) || ((PageTable[PTIndex] & IA32_PG_P) !=3D 0)) { > + // PML5E > + if (Enable5LevelPaging) { > + PageTable =3D (UINT64*)(UINTN)(PageTable[PTIndex] & > ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); > + } > + PTIndex =3D BitFieldRead64 (PFAddress, 39, 47); > if ((PageTable[PTIndex] & IA32_PG_P) !=3D 0) { > - // PDPTE > + // PML4E > PageTable =3D (UINT64*)(UINTN)(PageTable[PTIndex] & > ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); > - PTIndex =3D BitFieldRead64 (PFAddress, 21, 29); > - // PD > - if ((PageTable[PTIndex] & IA32_PG_PS) !=3D 0) { > - // > - // 2MB page > - // > - Address =3D (UINT64)(PageTable[PTIndex] & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > - if ((Address & ~((1ull << 21) - 1)) =3D=3D ((PFAddress & > PHYSICAL_ADDRESS_MASK & ~((1ull << 21) - 1)))) { > - Existed =3D TRUE; > - } > - } else { > - // > - // 4KB page > - // > - PageTable =3D (UINT64*)(UINTN)(PageTable[PTIndex] & > ~mAddressEncMask& PHYSICAL_ADDRESS_MASK); > - if (PageTable !=3D 0) { > + PTIndex =3D BitFieldRead64 (PFAddress, 30, 38); > + if ((PageTable[PTIndex] & IA32_PG_P) !=3D 0) { > + // PDPTE > + PageTable =3D (UINT64*)(UINTN)(PageTable[PTIndex] & > ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); > + PTIndex =3D BitFieldRead64 (PFAddress, 21, 29); > + // PD > + if ((PageTable[PTIndex] & IA32_PG_PS) !=3D 0) { > // > - // When there is a valid entry to map to 4KB page, need not cr= eate a > new entry to map 2MB. > + // 2MB page > // > - PTIndex =3D BitFieldRead64 (PFAddress, 12, 20); > Address =3D (UINT64)(PageTable[PTIndex] & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > - if ((Address & ~((1ull << 12) - 1)) =3D=3D (PFAddress & > PHYSICAL_ADDRESS_MASK & ~((1ull << 12) - 1))) { > + if ((Address & ~((1ull << 21) - 1)) =3D=3D ((PFAddress & > + PHYSICAL_ADDRESS_MASK & ~((1ull << 21) - 1)))) { > Existed =3D TRUE; > } > + } else { > + // > + // 4KB page > + // > + PageTable =3D (UINT64*)(UINTN)(PageTable[PTIndex] & > ~mAddressEncMask& PHYSICAL_ADDRESS_MASK); > + if (PageTable !=3D 0) { > + // > + // When there is a valid entry to map to 4KB page, need not = create a > new entry to map 2MB. > + // > + PTIndex =3D BitFieldRead64 (PFAddress, 12, 20); > + Address =3D (UINT64)(PageTable[PTIndex] & ~mAddressEncMask & > PHYSICAL_ADDRESS_MASK); > + if ((Address & ~((1ull << 12) - 1)) =3D=3D (PFAddress & > PHYSICAL_ADDRESS_MASK & ~((1ull << 12) - 1))) { > + Existed =3D TRUE; > + } > + } > } > } > } > @@ -221,6 +236,11 @@ RestorePageTableAbove4G ( > // > PageTable =3D (UINT64*)(AsmReadCr3 () & PHYSICAL_ADDRESS_MASK); > PFAddress =3D AsmReadCr2 (); > + // PML5E > + if (Enable5LevelPaging) { > + PTIndex =3D BitFieldRead64 (PFAddress, 48, 56); > + PageTable =3D (UINT64*)(UINTN)(PageTable[PTIndex] & > ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); > + } > // PML4E > PTIndex =3D BitFieldRead64 (PFAddress, 39, 47); > PageTable =3D (UINT64*)(UINTN)(PageTable[PTIndex] & > ~mAddressEncMask & PHYSICAL_ADDRESS_MASK); > -- > 2.21.0.windows.1