From nobody Sat Feb 7 10:16:20 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+42979+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+42979+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1561704451; cv=none; d=zoho.com; s=zohoarc; b=CXJpDpwrvBJbFH1ZmFliXzxpfAOvs1Km9yhnm9eXzoYDChHbtzyMc28ZS86Q7higNphL33AQYJbwQcT5jGg+WqeE6e3njjEWeDzLxQKqCLdEcWjN4EWUSHsRrgKJLu7gcAXgcTMeC6bcvgpqWrEMDQTdPtRlH3uZ5oL74KDaU74= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1561704451; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=vsSLROJ4eJHtyP6yLHFophsrk5XO1OEYSE87eZhl+TY=; b=Ww0Sob051oRinRiJwu8AiGQdS9pf5HLccsh5OOxIjPxSJSZkmdfRwhm/MFUActzV1mESoUVqnS5oxCssOUr1nWyhamhtzhf6FtLISRmDA9iTCgJ6RBzRsDup3M4mvD10ZcVkNA1sezl7qrm7yFrViZ+UsH3/E6Pz1gdir3CjXa4= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+42979+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1561704451173983.3890121306091; Thu, 27 Jun 2019 23:47:31 -0700 (PDT) Return-Path: X-Received: from mga14.intel.com (mga14.intel.com []) by groups.io with SMTP; Thu, 27 Jun 2019 23:47:29 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Jun 2019 23:47:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,426,1557212400"; d="scan'208";a="189342998" X-Received: from ray-dev.ccr.corp.intel.com ([10.239.9.16]) by fmsmga002.fm.intel.com with ESMTP; 27 Jun 2019 23:47:28 -0700 From: "Ni, Ray" To: devel@edk2.groups.io Cc: Eric Dong Subject: [edk2-devel] [PATCH 3/3] UefiCpuPkg/PiSmmCpu: Enable 5 level paging when CPU supports Date: Fri, 28 Jun 2019 14:47:00 +0800 Message-Id: <20190628064700.549472-4-ray.ni@intel.com> In-Reply-To: <20190628064700.549472-1-ray.ni@intel.com> References: <20190628064700.549472-1-ray.ni@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ray.ni@intel.com Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1561704450; bh=KsPJvDHLJarISLOClAu1jFfonKFm0NmU9PuEJ8q/oqA=; h=Cc:Date:From:Reply-To:Subject:To; b=oGiR61Sq9X17JDkv+BlAVpJStzyasrlFgWevGu3LzzcfbgdRB9WPkvG0jGylq7IcBJs PBIeCWpnTVfEabocOhYGmdpQDVNqKW4PF4o28Dh7uEjptf11+HsoqdDUWLLJKqvT7pf0d q9kafOc7plw6dMaHuclEqyuufMRYsOGNkkE= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1946 The patch changes SMM environment to use 5 level paging when CPU supports it. Signed-off-by: Ray Ni Cc: Eric Dong --- .../PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 20 +- UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c | 272 ++++++---- UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c | 483 ++++++++++++------ UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm | 12 + .../PiSmmCpuDxeSmm/X64/SmmProfileArch.c | 72 ++- 5 files changed, 559 insertions(+), 300 deletions(-) diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPk= g/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] & ~mAddressEnc= Mask & 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/PiSmmCpuDx= eSmm/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 - 3= 0)); - } else { - NumberOfPml4Entries =3D (UINT32)LShiftU64 (1, (SizeOfMemorySpace - 3= 9)); - 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 & PHYS= ICAL_ADDRESS_MASK); - } else { - Pdpt =3D (UINT64*)(UINTN)mSmmProfileCr3; - } - for (PdptIndex =3D 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pd= pt++) { - 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_ADDRE= SS_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 split = 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 spli= t 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_BIT= S; - } // end if IsAddressSplit - } // end for PD - } // end for PDPT - } // end for PML4 + // Split it + for (PtIndex =3D 0; PtIndex < SIZE_4KB / sizeof(*Pt); PtIndex+= +, Pt++) { + *Pt =3D Address + ((PtIndex << 12) | mAddressEncMask | PAGE_= ATTRIBUTE_BITS); + } // end for PT + *Pd =3D (UINT64)(UINTN)Pt | mAddressEncMask | PAGE_ATTRIBUTE_B= ITS; + } // 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 & PHYS= ICAL_ADDRESS_MASK); - } else { - Pdpt =3D (UINT64*)(UINTN)mSmmProfileCr3; - } - for (PdptIndex =3D 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pd= pt++) { - 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_ADDRE= SS_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_ADDRE= SS_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_ADD= RESS_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); PtIndex+= +, 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_M= ASK); + } =20 // // PML4 diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c b/UefiCpuPkg/PiSmmCpuD= xeSmm/X64/PageTbl.c index 3d5d663d99..c088010327 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c @@ -16,6 +16,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent LIST_ENTRY mPagePool =3D INITIALIZE_LIST_HEAD_VAR= IABLE (mPagePool); BOOLEAN m1GPageTableSupport =3D FALSE; BOOLEAN mCpuSmmStaticPageTable; +BOOLEAN m5LevelPagingSupport; =20 /** Disable CET. @@ -60,6 +61,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 +156,6 @@ CalculateMaximumSupportAddress ( PhysicalAddressBits =3D 36; } } - - // - // IA-32e paging translates 48-bit linear addresses to 52-bit physical a= ddresses. - // - ASSERT (PhysicalAddressBits <=3D 52); - if (PhysicalAddressBits > 48) { - PhysicalAddressBits =3D 48; - } return PhysicalAddressBits; } =20 @@ -152,89 +170,137 @@ SetStaticPageTable ( ) { UINT64 PageAddress; + UINTN NumberOfPml5EntriesNeeded; UINTN NumberOfPml4EntriesNeeded; UINTN NumberOfPdpEntriesNeeded; + UINTN IndexOfPml5Entries; UINTN IndexOfPml4Entries; UINTN IndexOfPdpEntries; UINTN IndexOfPageDirectoryEntrie= s; + UINT64 *PageMapLevel5Entry; UINT64 *PageMapLevel4Entry; UINT64 *PageMap; UINT64 *PageDirectoryPointerEntry; UINT64 *PageDirectory1GEntry; UINT64 *PageDirectoryEntry; =20 - if (mPhysicalAddressBits <=3D 39 ) { - NumberOfPml4EntriesNeeded =3D 1; - NumberOfPdpEntriesNeeded =3D (UINT32)LShiftU64 (1, (mPhysicalAddressBi= ts - 30)); - } else { - NumberOfPml4EntriesNeeded =3D (UINT32)LShiftU64 (1, (mPhysicalAddressB= its - 39)); - NumberOfPdpEntriesNeeded =3D 512; + // + // IA-32e paging translates 48-bit linear addresses to 52-bit physical a= ddresses + // 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, mPhysicalAddressBi= ts - 48); + mPhysicalAddressBits =3D 48; + } + + NumberOfPml4EntriesNeeded =3D 1; + if (mPhysicalAddressBits > 39) { + NumberOfPml4EntriesNeeded =3D (UINTN) LShiftU64 (1, mPhysicalAddressBi= ts - 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 stor= age for it. // PageMap =3D (VOID *) PageTable; =20 PageMapLevel4Entry =3D PageMap; - PageAddress =3D 0; - for (IndexOfPml4Entries =3D 0; IndexOfPml4Entries < NumberOfPml4EntriesN= eeded; IndexOfPml4Entries++, PageMapLevel4Entry++) { + PageMapLevel5Entry =3D NULL; + if (m5LevelPagingSupport) { // - // Each PML4 entry points to a page of Page Directory Pointer entries. + // By architecture only one PageMapLevel5 exists - so lets allocate st= orage for it. // - PageDirectoryPointerEntry =3D (UINT64 *) ((*PageMapLevel4Entry) & ~mAd= dressEncMask & 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 | m= AddressEncMask | 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 IndexOfPml4= Entries loop. + // When 5-Level Paging is disabled, below allocation happens only once. + // + if (m5LevelPagingSupport) { + PageMapLevel4Entry =3D (UINT64 *) ((*PageMapLevel5Entry) & ~mAddress= EncMask & 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 | mAddre= ssEncMask | PAGE_ATTRIBUTE_BITS; + } } =20 - if (m1GPageTableSupport) { - PageDirectory1GEntry =3D PageDirectoryPointerEntry; - for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntries = < 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 < (NumberOfPml5Entri= esNeeded =3D=3D 1 ? NumberOfPml4EntriesNeeded : 512); IndexOfPml4Entries++,= PageMapLevel4Entry++) { + // + // Each PML4 entry points to a page of Page Directory Pointer entrie= s. + // + PageDirectoryPointerEntry =3D (UINT64 *) ((*PageMapLevel4Entry) & ~m= AddressEncMask & 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 < NumberOfPdpEntries= Needed; IndexOfPdpEntries++, PageDirectoryPointerEntry++) { - if (IndexOfPml4Entries =3D=3D 0 && IndexOfPdpEntries < 4) { - // - // Skip the < 4G entries - // - continue; - } - // - // Each Directory Pointer entries points to a page of Page Directo= ry entires. - // So allocate space for them and fill them in in the IndexOfPageD= irectoryEntries 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; IndexOfPageDirectoryEntrie= s < 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)PageDirectoryEntry= | mAddressEncMask | PAGE_ATTRIBUTE_BITS; + *PageDirectory1GEntry =3D PageAddress | mAddressEncMask | IA32_P= G_PS | PAGE_ATTRIBUTE_BITS; } - - for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntrie= s < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += =3D SIZE_2MB) { + } else { + PageAddress =3D BASE_4GB; + for (IndexOfPdpEntries =3D 0; IndexOfPdpEntries < (NumberOfPml4Ent= riesNeeded =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 Direc= tory entires. + // So allocate space for them and fill them in in the IndexOfPag= eDirectoryEntries 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)PageDirectoryEnt= ry | mAddressEncMask | PAGE_ATTRIBUTE_BITS; + } + + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntr= ies < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress= +=3D SIZE_2MB) { + // + // Fill in the Page Directory entries + // + *PageDirectoryEntry =3D PageAddress | mAddressEncMask | IA32_P= G_PS | PAGE_ATTRIBUTE_BITS; + } } } } @@ -259,6 +325,8 @@ SmmInitPageTable ( UINTN PageFaultHandlerHookAddress; IA32_IDT_GATE_DESCRIPTOR *IdtEntry; EFI_STATUS Status; + UINT64 *Pml4Entry; + UINT64 *Pml5Entry; =20 // // Initialize spin lock @@ -266,12 +334,13 @@ 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", mCpuSmmStaticPa= geTable)); - - mPhysicalAddressBits =3D CalculateMaximumSupportAddress (); - DEBUG ((DEBUG_INFO, "PhysicalAddressBits - 0x%x\n", mPhysicalAddressBits= )); + m1GPageTableSupport =3D Is1GPageSupport (); + m5LevelPagingSupport =3D Is5LevelPagingSupport (); + mPhysicalAddressBits =3D CalculateMaximumSupportAddress (); + DEBUG ((DEBUG_INFO, "5LevelPaging Support - %d\n", m5LevelPagingSupp= ort)); + DEBUG ((DEBUG_INFO, "1GPageTable Support - %d\n", m1GPageTableSuppo= rt)); + DEBUG ((DEBUG_INFO, "PcdCpuSmmStaticPageTable - %d\n", mCpuSmmStaticPage= Table)); + DEBUG ((DEBUG_INFO, "PhysicalAddressBits - %d\n", mPhysicalAddressB= its)); // // Generate PAE page table for the first 4GB memory space // @@ -288,15 +357,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_BI= TS; + 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 +428,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 +520,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 +539,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 stru= cture. + // + 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); Pml4In= dex++) { - 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 & gPhyMas= k); - PML4EIgnore =3D FALSE; - for (PdptIndex =3D 0; PdptIndex < EFI_PAGE_SIZE / sizeof (*Pdpt); Pdpt= Index++) { - if ((Pdpt[PdptIndex] & IA32_PG_P) =3D=3D 0 || (Pdpt[PdptIndex] & IA3= 2_PG_PMNT) !=3D 0) { + Pml4 =3D (UINT64*)(UINTN)(Pml5[Pml5Index] & gPhyMask); + for (Pml4Index =3D 0; Pml4Index < EFI_PAGE_SIZE / sizeof (*Pml4); Pml4= Index++) { + if ((Pml4[Pml4Index] & IA32_PG_P) =3D=3D 0 || (Pml4[Pml4Index] & IA3= 2_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 PML4= 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 & gPh= yMask); - PDPTEIgnore =3D FALSE; - for (PdtIndex =3D 0; PdtIndex < EFI_PAGE_SIZE / sizeof(*Pdt); PdtI= ndex++) { - if ((Pdt[PdtIndex] & IA32_PG_P) =3D=3D 0 || (Pdt[PdtIndex] & IA3= 2_PG_PMNT) !=3D 0) { + Pdpt =3D (UINT64*)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & gPhyM= ask); + PML4EIgnore =3D FALSE; + for (PdptIndex =3D 0; PdptIndex < EFI_PAGE_SIZE / sizeof (*Pdpt); Pd= ptIndex++) { + if ((Pdpt[PdptIndex] & IA32_PG_P) =3D=3D 0 || (Pdpt[PdptIndex] & I= A32_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 PM= L4 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 & gP= hyMask); + 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] & I= A32_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 more + // + 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 entry + // we will find the entry has the smallest access record val= ue // 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 value + // 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 // - 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 page= s, - // 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 +703,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 & gPhyMas= k); SubEntriesNum =3D GetSubEntriesNum(Pdpt + MinPdpt); if (SubEntriesNum =3D=3D 0) { @@ -679,7 +795,7 @@ SmiDefaultPFHandler ( ) { UINT64 *PageTable; - UINT64 *Pml4; + UINT64 *PageTableTop; UINT64 PFAddress; UINTN StartBit; UINTN EndBit; @@ -690,6 +806,8 @@ SmiDefaultPFHandler ( UINTN PageAttribute; EFI_STATUS Status; UINT64 *UpperEntry; + BOOLEAN Enable5LevelPaging; + IA32_CR4 Cr4; =20 // // Set default SMM page attribute @@ -699,9 +817,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, &NumOfPa= ges, &PageAttribute); // // If platform not support page table attribute, set default SMM page at= tribute @@ -755,9 +876,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; Sta= rtBit -=3D 9) { PTIndex =3D BitFieldRead64 (PFAddress, StartBit, StartBit + 8); if ((PageTable[PTIndex] & IA32_PG_P) =3D=3D 0) { // @@ -941,13 +1062,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 +1119,59 @@ SetPageTableAttributes ( do { DEBUG ((DEBUG_INFO, "Start...\n")); PageTableSplitted =3D FALSE; - - L4PageTable =3D (UINT64 *)GetPageTableBase (); - SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L4PageTable, SI= ZE_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] & ~mAddressEnc= Mask & 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(UINT= 64) : 1); Index5++) { + if (Enable5LevelPaging) { + L4PageTable =3D (UINT64 *)(UINTN)(L5PageTable[Index5] & ~mAddressE= ncMask & PAGING_4K_ADDRESS_MASK_64); + if (L4PageTable =3D=3D NULL) { continue; } - L2PageTable =3D (UINT64 *)(UINTN)(L3PageTable[Index3] & ~mAddressE= ncMask & 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] & ~mAddressE= ncMask & 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] & ~mAddres= sEncMask & PAGING_4K_ADDRESS_MASK_64); - if (L1PageTable =3D=3D NULL) { + L2PageTable =3D (UINT64 *)(UINTN)(L3PageTable[Index3] & ~mAddres= sEncMask & PAGING_4K_ADDRESS_MASK_64); + if (L2PageTable =3D=3D NULL) { continue; } - SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L1PageTab= le, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); + + SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L2PageTab= le, 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] & ~mAddr= essEncMask & PAGING_4K_ADDRESS_MASK_64); + if (L1PageTable =3D=3D NULL) { + continue; + } + SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L1PageT= able, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); + PageTableSplitted =3D (PageTableSplitted || IsSplitted); + } } } } diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm b/UefiCpuPkg/PiSmm= CpuDxeSmm/X64/SmiEntry.nasm index 741e4b7da2..b5e0405b3b 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(m5LevelPagingSupport) 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, ref= resh cr3 + + DB 0xb1 ; mov cl, m5LevelPagingSupport +ASM_PFX(m5LevelPagingSupport): DB 0 + 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 TLB. ; Load TSS sub esp, 8 ; reserve room in stack diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c b/UefiCpuPkg/Pi= SmmCpuDxeSmm/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 & PHYSI= CAL_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] & ~mAddressEncMa= sk& 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] & ~mAddressEncMa= sk & 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 crea= te a new entry to map 2MB. + // 2MB page // - PTIndex =3D BitFieldRead64 (PFAddress, 12, 20); Address =3D (UINT64)(PageTable[PTIndex] & ~mAddressEncMask & PHY= SICAL_ADDRESS_MASK); - if ((Address & ~((1ull << 12) - 1)) =3D=3D (PFAddress & PHYSICAL= _ADDRESS_MASK & ~((1ull << 12) - 1))) { + if ((Address & ~((1ull << 21) - 1)) =3D=3D ((PFAddress & PHYSICA= L_ADDRESS_MASK & ~((1ull << 21) - 1)))) { Existed =3D TRUE; } + } else { + // + // 4KB page + // + PageTable =3D (UINT64*)(UINTN)(PageTable[PTIndex] & ~mAddressEnc= Mask& PHYSICAL_ADDRESS_MASK); + if (PageTable !=3D 0) { + // + // When there is a valid entry to map to 4KB page, need not cr= eate a new entry to map 2MB. + // + PTIndex =3D BitFieldRead64 (PFAddress, 12, 20); + Address =3D (UINT64)(PageTable[PTIndex] & ~mAddressEncMask & P= HYSICAL_ADDRESS_MASK); + if ((Address & ~((1ull << 12) - 1)) =3D=3D (PFAddress & PHYSIC= AL_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); --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#42979): https://edk2.groups.io/g/devel/message/42979 Mute This Topic: https://groups.io/mt/32239521/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-