From nobody Mon Sep 16 18:53:31 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+104925+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+104925+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1684231225; cv=none; d=zohomail.com; s=zohoarc; b=MhU/oTVwbiSlZk8Qo8C7++WIPAcBV8MfjcyyEd1bz2XHGTp9d9oRh/zTuWyVWfZ/w6JktzRuUVHGHSW+9LL+XM3zAw+mX7dCm04+eI1IUNs65Qhh/3A9x9YyYV7CgGARrXPgzdT4jcxfm3GGaU+kNpMw9RU7p7ednDhHGbXrb+c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1684231225; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=UUJfPqsmoQV3VwAkfVcNq3Xv9JGxmE6CJOTOaMcDdYY=; b=N7HYaxjV67XnX7El/VdrSr4x9h9Jd37U6yFiW8ZcD3np9zukXbph6KuzMVBgTQDlFVoOxf44dpxVt34wUVfM1IYV07kPJvT0E8LDFIFXtBQgDwYkmugHeMjzfv987GXa5XXnJjoJMwKaagpYnmlJVqxNlPb8PrczNATGyOPqWDg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+104925+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1684231225266444.5356059938225; Tue, 16 May 2023 03:00:25 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 3YRhYY1788612xULN8e2gZaf; Tue, 16 May 2023 03:00:24 -0700 X-Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by mx.groups.io with SMTP id smtpd.web11.17915.1684231210780691710 for ; Tue, 16 May 2023 03:00:24 -0700 X-IronPort-AV: E=McAfee;i="6600,9927,10711"; a="417093228" X-IronPort-AV: E=Sophos;i="5.99,278,1677571200"; d="scan'208";a="417093228" X-Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2023 03:00:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10711"; a="791019530" X-IronPort-AV: E=Sophos;i="5.99,278,1677571200"; d="scan'208";a="791019530" X-Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.55.158]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 May 2023 03:00:22 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar , Gerd Hoffmann Subject: [edk2-devel] [Patch V4 05/15] UefiCpuPkg: Use CpuPageTableLib to convert SMM paging attribute. Date: Tue, 16 May 2023 17:59:22 +0800 Message-Id: <20230516095932.1525-6-dun.tan@intel.com> In-Reply-To: <20230516095932.1525-1-dun.tan@intel.com> References: <20230516095932.1525-1-dun.tan@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: 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,dun.tan@intel.com X-Gm-Message-State: Xzkeroc3jR0NbcBTzON9GwVSx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1684231224; bh=InLGH8lCgJo4ReNTDRAyZ5yJJTC6xA43Uu4rFNbTlkY=; h=Cc:Date:From:Reply-To:Subject:To; b=myuZguT6NkRnS2O2YxtaKQTOod5jegKdJOFFB2pCC9ZtLYG7uAp0TRCeiKSkv11sWb3 +jt7xjvOcF0TDVuujhfDYCOxijvH79OpT3K2CeYSsAIPn2LHXjlMEIvhG3rPoULLRjmJD 9HaJPx2fjKWjgFLOVQ1BPzr0YxnHcWACAaE= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1684231226841100007 Content-Type: text/plain; charset="utf-8" Simplify the ConvertMemoryPageAttributes API to convert paging attribute by CpuPageTableLib. In the new API, it calls PageTableMap() to update the page attributes of a memory range. With the PageTableMap() API in CpuPageTableLib, we can remove the complicated page table manipulating code. Signed-off-by: Dun Tan Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Cc: Gerd Hoffmann --- UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c | 3 ++- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h | 28 +++++++++++++----= ----------- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf | 1 + UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 443 +++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++----------------------------------= ---------------------------------------------------------------------------= ---------------------------------------------------------------------------= ---------------------------------------------------------------------------= --------------------------------------------------- UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c | 9 +++++++-- 5 files changed, 156 insertions(+), 328 deletions(-) diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpu= DxeSmm/Ia32/PageTbl.c index 34bf6e1a25..9c8107080a 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c @@ -1,7 +1,7 @@ /** @file Page table manipulation functions for IA-32 processors =20 -Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.
Copyright (c) 2017, AMD Incorporated. All rights reserved.
=20 SPDX-License-Identifier: BSD-2-Clause-Patent @@ -31,6 +31,7 @@ SmmInitPageTable ( InitializeSpinLock (mPFLock); =20 mPhysicalAddressBits =3D 32; + mPagingMode =3D PagingPae; =20 if (FeaturePcdGet (PcdCpuSmmProfileEnable) || HEAP_GUARD_NONSTOP_MODE || diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/UefiCpuPkg/PiSmmC= puDxeSmm/PiSmmCpuDxeSmm.h index a5c2bdd971..ba341cadc6 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h @@ -50,6 +50,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include =20 #include #include @@ -260,6 +261,7 @@ extern UINTN mNumberOfCpus; extern EFI_SMM_CPU_PROTOCOL mSmmCpu; extern EFI_MM_MP_PROTOCOL mSmmMp; extern BOOLEAN m5LevelPagingNeeded; +extern PAGING_MODE mPagingMode; =20 /// /// The mode of the CPU at the time an SMI occurs @@ -1008,11 +1010,10 @@ SetPageTableAttributes ( Length from their current attributes to the attributes specified by Attr= ibutes. =20 @param[in] PageTableBase The page table base. - @param[in] EnablePML5Paging If PML5 paging is enabled. + @param[in] PagingMode The paging mode. @param[in] BaseAddress The physical address that is the start add= ress of a memory region. @param[in] Length The size in bytes of the memory region. @param[in] Attributes The bit mask of attributes to set for the = memory region. - @param[out] IsSplitted TRUE means page table splitted. FALSE mean= s page table not splitted. =20 @retval EFI_SUCCESS The attributes were set for the memory reg= ion. @retval EFI_ACCESS_DENIED The attributes for the memory resource ran= ge specified by @@ -1030,12 +1031,11 @@ SetPageTableAttributes ( **/ EFI_STATUS SmmSetMemoryAttributesEx ( - IN UINTN PageTableBase, - IN BOOLEAN EnablePML5Paging, - IN EFI_PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 Attributes, - OUT BOOLEAN *IsSplitted OPTIONAL + IN UINTN PageTableBase, + IN PAGING_MODE PagingMode, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes ); =20 /** @@ -1043,34 +1043,32 @@ SmmSetMemoryAttributesEx ( Length from their current attributes to the attributes specified by Attr= ibutes. =20 @param[in] PageTableBase The page table base. - @param[in] EnablePML5Paging If PML5 paging is enabled. + @param[in] PagingMode The paging mode. @param[in] BaseAddress The physical address that is the start add= ress of a memory region. @param[in] Length The size in bytes of the memory region. @param[in] Attributes The bit mask of attributes to clear for th= e memory region. - @param[out] IsSplitted TRUE means page table splitted. FALSE mean= s page table not splitted. =20 @retval EFI_SUCCESS The attributes were cleared for the memory= region. @retval EFI_ACCESS_DENIED The attributes for the memory resource ran= ge specified by BaseAddress and Length cannot be modified. @retval EFI_INVALID_PARAMETER Length is zero. Attributes specified an illegal combinatio= n of attributes that - cannot be set together. + cannot be cleared together. @retval EFI_OUT_OF_RESOURCES There are not enough system resources to m= odify the attributes of the memory resource range. @retval EFI_UNSUPPORTED The processor does not support one or more= bytes of the memory resource range specified by BaseAddress an= d Length. - The bit mask of attributes is not support = for the memory resource + The bit mask of attributes is not supporte= d for the memory resource range specified by BaseAddress and Length. =20 **/ EFI_STATUS SmmClearMemoryAttributesEx ( IN UINTN PageTableBase, - IN BOOLEAN EnablePML5Paging, + IN PAGING_MODE PagingMode, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, - IN UINT64 Attributes, - OUT BOOLEAN *IsSplitted OPTIONAL + IN UINT64 Attributes ); =20 /** diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSm= mCpuDxeSmm/PiSmmCpuDxeSmm.inf index 158e05e264..38d4e950a4 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf @@ -97,6 +97,7 @@ ReportStatusCodeLib SmmCpuFeaturesLib PeCoffGetEntryPointLib + CpuPageTableLib =20 [Protocols] gEfiSmmAccess2ProtocolGuid ## CONSUMES diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPk= g/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c index 834a756061..73ad9fb017 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c @@ -1,6 +1,6 @@ /** @file =20 -Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
+Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ @@ -26,14 +26,9 @@ UINTN mGcdMemNumberOfDesc =3D= 0; =20 EFI_MEMORY_ATTRIBUTES_TABLE *mUefiMemoryAttributesTable =3D NULL; =20 -PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] =3D { - { Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64 }, - { Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64 }, - { Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64 }, -}; - -BOOLEAN mIsShadowStack =3D FALSE; -BOOLEAN m5LevelPagingNeeded =3D FALSE; +BOOLEAN mIsShadowStack =3D FALSE; +BOOLEAN m5LevelPagingNeeded =3D FALSE; +PAGING_MODE mPagingMode =3D PagingModeMax; =20 // // Global variable to keep track current available memory used as page tab= le. @@ -185,52 +180,6 @@ AllocatePageTableMemory ( return Buffer; } =20 -/** - Return length according to page attributes. - - @param[in] PageAttributes The page attribute of the page entry. - - @return The length of page entry. -**/ -UINTN -PageAttributeToLength ( - IN PAGE_ATTRIBUTE PageAttribute - ) -{ - UINTN Index; - - for (Index =3D 0; Index < sizeof (mPageAttributeTable)/sizeof (mPageAttr= ibuteTable[0]); Index++) { - if (PageAttribute =3D=3D mPageAttributeTable[Index].Attribute) { - return (UINTN)mPageAttributeTable[Index].Length; - } - } - - return 0; -} - -/** - Return address mask according to page attributes. - - @param[in] PageAttributes The page attribute of the page entry. - - @return The address mask of page entry. -**/ -UINTN -PageAttributeToMask ( - IN PAGE_ATTRIBUTE PageAttribute - ) -{ - UINTN Index; - - for (Index =3D 0; Index < sizeof (mPageAttributeTable)/sizeof (mPageAttr= ibuteTable[0]); Index++) { - if (PageAttribute =3D=3D mPageAttributeTable[Index].Attribute) { - return (UINTN)mPageAttributeTable[Index].AddressMask; - } - } - - return 0; -} - /** Return page table entry to match the address. =20 @@ -353,181 +302,6 @@ GetAttributesFromPageEntry ( return Attributes; } =20 -/** - Modify memory attributes of page entry. - - @param[in] PageEntry The page entry. - @param[in] Attributes The bit mask of attributes to modify for t= he memory region. - @param[in] IsSet TRUE means to set attributes. FALSE means = to clear attributes. - @param[out] IsModified TRUE means page table modified. FALSE mean= s page table not modified. -**/ -VOID -ConvertPageEntryAttribute ( - IN UINT64 *PageEntry, - IN UINT64 Attributes, - IN BOOLEAN IsSet, - OUT BOOLEAN *IsModified - ) -{ - UINT64 CurrentPageEntry; - UINT64 NewPageEntry; - - CurrentPageEntry =3D *PageEntry; - NewPageEntry =3D CurrentPageEntry; - if ((Attributes & EFI_MEMORY_RP) !=3D 0) { - if (IsSet) { - NewPageEntry &=3D ~(UINT64)IA32_PG_P; - } else { - NewPageEntry |=3D IA32_PG_P; - } - } - - if ((Attributes & EFI_MEMORY_RO) !=3D 0) { - if (IsSet) { - NewPageEntry &=3D ~(UINT64)IA32_PG_RW; - if (mIsShadowStack) { - // Environment setup - // ReadOnly page need set Dirty bit for shadow stack - NewPageEntry |=3D IA32_PG_D; - // Clear user bit for supervisor shadow stack - NewPageEntry &=3D ~(UINT64)IA32_PG_U; - } else { - // Runtime update - // Clear dirty bit for non shadow stack, to protect RO page. - NewPageEntry &=3D ~(UINT64)IA32_PG_D; - } - } else { - NewPageEntry |=3D IA32_PG_RW; - } - } - - if ((Attributes & EFI_MEMORY_XP) !=3D 0) { - if (mXdSupported) { - if (IsSet) { - NewPageEntry |=3D IA32_PG_NX; - } else { - NewPageEntry &=3D ~IA32_PG_NX; - } - } - } - - *PageEntry =3D NewPageEntry; - if (CurrentPageEntry !=3D NewPageEntry) { - *IsModified =3D TRUE; - DEBUG ((DEBUG_VERBOSE, "ConvertPageEntryAttribute 0x%lx", CurrentPageE= ntry)); - DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry)); - } else { - *IsModified =3D FALSE; - } -} - -/** - This function returns if there is need to split page entry. - - @param[in] BaseAddress The base address to be checked. - @param[in] Length The length to be checked. - @param[in] PageEntry The page entry to be checked. - @param[in] PageAttribute The page attribute of the page entry. - - @retval SplitAttributes on if there is need to split page entry. -**/ -PAGE_ATTRIBUTE -NeedSplitPage ( - IN PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 *PageEntry, - IN PAGE_ATTRIBUTE PageAttribute - ) -{ - UINT64 PageEntryLength; - - PageEntryLength =3D PageAttributeToLength (PageAttribute); - - if (((BaseAddress & (PageEntryLength - 1)) =3D=3D 0) && (Length >=3D Pag= eEntryLength)) { - return PageNone; - } - - if (((BaseAddress & PAGING_2M_MASK) !=3D 0) || (Length < SIZE_2MB)) { - return Page4K; - } - - return Page2M; -} - -/** - This function splits one page entry to small page entries. - - @param[in] PageEntry The page entry to be splitted. - @param[in] PageAttribute The page attribute of the page entry. - @param[in] SplitAttribute How to split the page entry. - - @retval RETURN_SUCCESS The page entry is splitted. - @retval RETURN_UNSUPPORTED The page entry does not support to be = splitted. - @retval RETURN_OUT_OF_RESOURCES No resource to split page entry. -**/ -RETURN_STATUS -SplitPage ( - IN UINT64 *PageEntry, - IN PAGE_ATTRIBUTE PageAttribute, - IN PAGE_ATTRIBUTE SplitAttribute - ) -{ - UINT64 BaseAddress; - UINT64 *NewPageEntry; - UINTN Index; - - ASSERT (PageAttribute =3D=3D Page2M || PageAttribute =3D=3D Page1G); - - if (PageAttribute =3D=3D Page2M) { - // - // Split 2M to 4K - // - ASSERT (SplitAttribute =3D=3D Page4K); - if (SplitAttribute =3D=3D Page4K) { - NewPageEntry =3D AllocatePageTableMemory (1); - DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry)); - if (NewPageEntry =3D=3D NULL) { - return RETURN_OUT_OF_RESOURCES; - } - - BaseAddress =3D *PageEntry & PAGING_2M_ADDRESS_MASK_64; - for (Index =3D 0; Index < SIZE_4KB / sizeof (UINT64); Index++) { - NewPageEntry[Index] =3D (BaseAddress + SIZE_4KB * Index) | mAddres= sEncMask | ((*PageEntry) & PAGE_PROGATE_BITS); - } - - (*PageEntry) =3D (UINT64)(UINTN)NewPageEntry | mAddressEncMask | PAG= E_ATTRIBUTE_BITS; - return RETURN_SUCCESS; - } else { - return RETURN_UNSUPPORTED; - } - } else if (PageAttribute =3D=3D Page1G) { - // - // Split 1G to 2M - // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K = to get more compact page table. - // - ASSERT (SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K); - if (((SplitAttribute =3D=3D Page2M) || (SplitAttribute =3D=3D Page4K))= ) { - NewPageEntry =3D AllocatePageTableMemory (1); - DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry)); - if (NewPageEntry =3D=3D NULL) { - return RETURN_OUT_OF_RESOURCES; - } - - BaseAddress =3D *PageEntry & PAGING_1G_ADDRESS_MASK_64; - for (Index =3D 0; Index < SIZE_4KB / sizeof (UINT64); Index++) { - NewPageEntry[Index] =3D (BaseAddress + SIZE_2MB * Index) | mAddres= sEncMask | IA32_PG_PS | ((*PageEntry) & PAGE_PROGATE_BITS); - } - - (*PageEntry) =3D (UINT64)(UINTN)NewPageEntry | mAddressEncMask | PAG= E_ATTRIBUTE_BITS; - return RETURN_SUCCESS; - } else { - return RETURN_UNSUPPORTED; - } - } else { - return RETURN_UNSUPPORTED; - } -} - /** This function modifies the page attributes for the memory region specifi= ed by BaseAddress and Length from their current attributes to the attributes specified by Attr= ibutes. @@ -535,12 +309,11 @@ SplitPage ( Caller should make sure BaseAddress and Length is at page boundary. =20 @param[in] PageTableBase The page table base. - @param[in] EnablePML5Paging If PML5 paging is enabled. + @param[in] PagingMode The paging mode. @param[in] BaseAddress The physical address that is the start add= ress of a memory region. @param[in] Length The size in bytes of the memory region. @param[in] Attributes The bit mask of attributes to modify for t= he memory region. @param[in] IsSet TRUE means to set attributes. FALSE means = to clear attributes. - @param[out] IsSplitted TRUE means page table splitted. FALSE mean= s page table not splitted. @param[out] IsModified TRUE means page table modified. FALSE mean= s page table not modified. =20 @retval RETURN_SUCCESS The attributes were modified for the me= mory region. @@ -559,28 +332,30 @@ SplitPage ( RETURN_STATUS ConvertMemoryPageAttributes ( IN UINTN PageTableBase, - IN BOOLEAN EnablePML5Paging, + IN PAGING_MODE PagingMode, IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, IN BOOLEAN IsSet, - OUT BOOLEAN *IsSplitted OPTIONAL, OUT BOOLEAN *IsModified OPTIONAL ) { - UINT64 *PageEntry; - PAGE_ATTRIBUTE PageAttribute; - UINTN PageEntryLength; - PAGE_ATTRIBUTE SplitAttribute; RETURN_STATUS Status; - BOOLEAN IsEntryModified; + IA32_MAP_ATTRIBUTE PagingAttribute; + IA32_MAP_ATTRIBUTE PagingAttrMask; + UINTN PageTableBufferSize; + VOID *PageTableBuffer; EFI_PHYSICAL_ADDRESS MaximumSupportMemAddress; + IA32_MAP_ENTRY *Map; + UINTN Count; + UINTN Index; =20 ASSERT (Attributes !=3D 0); ASSERT ((Attributes & ~EFI_MEMORY_ATTRIBUTE_MASK) =3D=3D 0); =20 ASSERT ((BaseAddress & (SIZE_4KB - 1)) =3D=3D 0); ASSERT ((Length & (SIZE_4KB - 1)) =3D=3D 0); + ASSERT (PageTableBase !=3D 0); =20 if (Length =3D=3D 0) { return RETURN_INVALID_PARAMETER; @@ -599,61 +374,121 @@ ConvertMemoryPageAttributes ( return RETURN_UNSUPPORTED; } =20 - // DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016= lx, %02lx\n", IsSet, BaseAddress, Length, Attributes)); + PagingAttribute.Uint64 =3D 0; + PagingAttribute.Uint64 =3D mAddressEncMask | BaseAddress; + PagingAttrMask.Uint64 =3D 0; =20 - if (IsSplitted !=3D NULL) { - *IsSplitted =3D FALSE; - } - - if (IsModified !=3D NULL) { - *IsModified =3D FALSE; + if ((Attributes & EFI_MEMORY_RO) !=3D 0) { + PagingAttrMask.Bits.ReadWrite =3D 1; + if (IsSet) { + PagingAttribute.Bits.ReadWrite =3D 0; + PagingAttrMask.Bits.Dirty =3D 1; + if (mIsShadowStack) { + // Environment setup + // ReadOnly page need set Dirty bit for shadow stack + PagingAttribute.Bits.Dirty =3D 1; + // Clear user bit for supervisor shadow stack + PagingAttribute.Bits.UserSupervisor =3D 0; + PagingAttrMask.Bits.UserSupervisor =3D 1; + } else { + // Runtime update + // Clear dirty bit for non shadow stack, to protect RO page. + PagingAttribute.Bits.Dirty =3D 0; + } + } else { + PagingAttribute.Bits.ReadWrite =3D 1; + } } =20 - // - // Below logic is to check 2M/4K page to make sure we do not waste memor= y. - // - while (Length !=3D 0) { - PageEntry =3D GetPageTableEntry (PageTableBase, EnablePML5Paging, Base= Address, &PageAttribute); - if (PageEntry =3D=3D NULL) { - return RETURN_UNSUPPORTED; + if ((Attributes & EFI_MEMORY_XP) !=3D 0) { + if (mXdSupported) { + PagingAttribute.Bits.Nx =3D IsSet ? 1 : 0; + PagingAttrMask.Bits.Nx =3D 1; } + } =20 - PageEntryLength =3D PageAttributeToLength (PageAttribute); - SplitAttribute =3D NeedSplitPage (BaseAddress, Length, PageEntry, Pag= eAttribute); - if (SplitAttribute =3D=3D PageNone) { - ConvertPageEntryAttribute (PageEntry, Attributes, IsSet, &IsEntryMod= ified); - if (IsEntryModified) { - if (IsModified !=3D NULL) { - *IsModified =3D TRUE; - } - } - + if ((Attributes & EFI_MEMORY_RP) !=3D 0) { + if (IsSet) { + PagingAttribute.Bits.Present =3D 0; // - // Convert success, move to next + // When map a range to non-present, all attributes except Present sh= ould not be provided. // - BaseAddress +=3D PageEntryLength; - Length -=3D PageEntryLength; + PagingAttrMask.Uint64 =3D 0; + PagingAttrMask.Bits.Present =3D 1; } else { - Status =3D SplitPage (PageEntry, PageAttribute, SplitAttribute); - if (RETURN_ERROR (Status)) { - return RETURN_UNSUPPORTED; - } + // + // When map range to present range, provide all attributes. + // + PagingAttribute.Bits.Present =3D 1; + PagingAttrMask.Uint64 =3D MAX_UINT64; =20 - if (IsSplitted !=3D NULL) { - *IsSplitted =3D TRUE; - } + // + // By default memory is Ring 3 accessble. + // + PagingAttribute.Bits.UserSupervisor =3D 1; + + DEBUG_CODE ( + if (((Attributes & EFI_MEMORY_RO) =3D=3D 0) || (((Attributes & EFI= _MEMORY_XP) =3D=3D 0) && (mXdSupported))) { + // + // When mapping a range to present and EFI_MEMORY_RO or EFI_MEMORY= _XP is not specificed, + // check if [BaseAddress, BaseAddress + Length] contains present r= ange. + // Existing Present range in [BaseAddress, BaseAddress + Length] i= s set to NX disable and ReadOnly. + // + Count =3D 0; + Map =3D NULL; + Status =3D PageTableParse (PageTableBase, mPagingMode, NULL, &Coun= t); + while (Status =3D=3D RETURN_BUFFER_TOO_SMALL) { + if (Map !=3D NULL) { + FreePool (Map); + } =20 - if (IsModified !=3D NULL) { - *IsModified =3D TRUE; + Map =3D AllocatePool (Count * sizeof (IA32_MAP_ENTRY)); + ASSERT (Map !=3D NULL); + Status =3D PageTableParse (PageTableBase, mPagingMode, Map, &Cou= nt); + } + + ASSERT_RETURN_ERROR (Status); + + for (Index =3D 0; Index < Count; Index++) { + if ((BaseAddress < Map[Index].LinearAddress + + Map[Index].Length) && (BaseAddress + Length > Map[Index].Li= nearAddress)) + { + DEBUG ((DEBUG_ERROR, "SMM ConvertMemoryPageAttributes: Existin= g Present range in [0x%lx, 0x%lx] is set to NX disable and ReadOnly\n", Bas= eAddress, BaseAddress + Length)); + break; + } + } + + FreePool (Map); } =20 - // - // Just split current page - // Convert success in next around - // + ); } } =20 + if (PagingAttrMask.Uint64 =3D=3D 0) { + return RETURN_SUCCESS; + } + + PageTableBufferSize =3D 0; + Status =3D PageTableMap (&PageTableBase, PagingMode, NULL, = &PageTableBufferSize, BaseAddress, Length, &PagingAttribute, &PagingAttrMas= k, IsModified); + + if (Status =3D=3D RETURN_BUFFER_TOO_SMALL) { + PageTableBuffer =3D AllocatePageTableMemory (EFI_SIZE_TO_PAGES (PageTa= bleBufferSize)); + ASSERT (PageTableBuffer !=3D NULL); + Status =3D PageTableMap (&PageTableBase, PagingMode, PageTableBuffer, = &PageTableBufferSize, BaseAddress, Length, &PagingAttribute, &PagingAttrMas= k, IsModified); + } + + if (Status =3D=3D RETURN_INVALID_PARAMETER) { + // + // The only reason that PageTableMap returns RETURN_INVALID_PARAMETER = here is to modify other attributes + // of a non-present range but remains the non-present range still as n= on-present. + // + DEBUG ((DEBUG_ERROR, "SMM ConvertMemoryPageAttributes: Non-present ran= ge in [0x%lx, 0x%lx] needs to be removed\n", BaseAddress, BaseAddress + Len= gth)); + } + + ASSERT_RETURN_ERROR (Status); + ASSERT (PageTableBufferSize =3D=3D 0); + return RETURN_SUCCESS; } =20 @@ -697,11 +532,10 @@ FlushTlbForAll ( Length from their current attributes to the attributes specified by Attr= ibutes. =20 @param[in] PageTableBase The page table base. - @param[in] EnablePML5Paging If PML5 paging is enabled. + @param[in] PagingMode The paging mode. @param[in] BaseAddress The physical address that is the start add= ress of a memory region. @param[in] Length The size in bytes of the memory region. @param[in] Attributes The bit mask of attributes to set for the = memory region. - @param[out] IsSplitted TRUE means page table splitted. FALSE mean= s page table not splitted. =20 @retval EFI_SUCCESS The attributes were set for the memory reg= ion. @retval EFI_ACCESS_DENIED The attributes for the memory resource ran= ge specified by @@ -720,17 +554,16 @@ FlushTlbForAll ( EFI_STATUS SmmSetMemoryAttributesEx ( IN UINTN PageTableBase, - IN BOOLEAN EnablePML5Paging, + IN PAGING_MODE PagingMode, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, - IN UINT64 Attributes, - OUT BOOLEAN *IsSplitted OPTIONAL + IN UINT64 Attributes ) { EFI_STATUS Status; BOOLEAN IsModified; =20 - Status =3D ConvertMemoryPageAttributes (PageTableBase, EnablePML5Paging,= BaseAddress, Length, Attributes, TRUE, IsSplitted, &IsModified); + Status =3D ConvertMemoryPageAttributes (PageTableBase, PagingMode, BaseA= ddress, Length, Attributes, TRUE, &IsModified); if (!EFI_ERROR (Status)) { if (IsModified) { // @@ -748,11 +581,10 @@ SmmSetMemoryAttributesEx ( Length from their current attributes to the attributes specified by Attr= ibutes. =20 @param[in] PageTableBase The page table base. - @param[in] EnablePML5Paging If PML5 paging is enabled. + @param[in] PagingMode The paging mode. @param[in] BaseAddress The physical address that is the start add= ress of a memory region. @param[in] Length The size in bytes of the memory region. @param[in] Attributes The bit mask of attributes to clear for th= e memory region. - @param[out] IsSplitted TRUE means page table splitted. FALSE mean= s page table not splitted. =20 @retval EFI_SUCCESS The attributes were cleared for the memory= region. @retval EFI_ACCESS_DENIED The attributes for the memory resource ran= ge specified by @@ -771,17 +603,16 @@ SmmSetMemoryAttributesEx ( EFI_STATUS SmmClearMemoryAttributesEx ( IN UINTN PageTableBase, - IN BOOLEAN EnablePML5Paging, + IN PAGING_MODE PagingMode, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, - IN UINT64 Attributes, - OUT BOOLEAN *IsSplitted OPTIONAL + IN UINT64 Attributes ) { EFI_STATUS Status; BOOLEAN IsModified; =20 - Status =3D ConvertMemoryPageAttributes (PageTableBase, EnablePML5Paging,= BaseAddress, Length, Attributes, FALSE, IsSplitted, &IsModified); + Status =3D ConvertMemoryPageAttributes (PageTableBase, PagingMode, BaseA= ddress, Length, Attributes, FALSE, &IsModified); if (!EFI_ERROR (Status)) { if (IsModified) { // @@ -823,14 +654,10 @@ SmmSetMemoryAttributes ( IN UINT64 Attributes ) { - IA32_CR4 Cr4; - UINTN PageTableBase; - BOOLEAN Enable5LevelPaging; - - PageTableBase =3D AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; - Cr4.UintN =3D AsmReadCr4 (); - Enable5LevelPaging =3D (BOOLEAN)(Cr4.Bits.LA57 =3D=3D 1); - return SmmSetMemoryAttributesEx (PageTableBase, Enable5LevelPaging, Base= Address, Length, Attributes, NULL); + UINTN PageTableBase; + + PageTableBase =3D AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; + return SmmSetMemoryAttributesEx (PageTableBase, mPagingMode, BaseAddress= , Length, Attributes); } =20 /** @@ -862,14 +689,10 @@ SmmClearMemoryAttributes ( IN UINT64 Attributes ) { - IA32_CR4 Cr4; - UINTN PageTableBase; - BOOLEAN Enable5LevelPaging; - - PageTableBase =3D AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; - Cr4.UintN =3D AsmReadCr4 (); - Enable5LevelPaging =3D (BOOLEAN)(Cr4.Bits.LA57 =3D=3D 1); - return SmmClearMemoryAttributesEx (PageTableBase, Enable5LevelPaging, Ba= seAddress, Length, Attributes, NULL); + UINTN PageTableBase; + + PageTableBase =3D AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; + return SmmClearMemoryAttributesEx (PageTableBase, mPagingMode, BaseAddre= ss, Length, Attributes); } =20 /** @@ -891,7 +714,7 @@ SetShadowStack ( EFI_STATUS Status; =20 mIsShadowStack =3D TRUE; - Status =3D SmmSetMemoryAttributesEx (Cr3, m5LevelPagingNeeded, B= aseAddress, Length, EFI_MEMORY_RO, NULL); + Status =3D SmmSetMemoryAttributesEx (Cr3, mPagingMode, BaseAddre= ss, Length, EFI_MEMORY_RO); mIsShadowStack =3D FALSE; =20 return Status; @@ -915,7 +738,7 @@ SetNotPresentPage ( { EFI_STATUS Status; =20 - Status =3D SmmSetMemoryAttributesEx (Cr3, m5LevelPagingNeeded, BaseAddre= ss, Length, EFI_MEMORY_RP, NULL); + Status =3D SmmSetMemoryAttributesEx (Cr3, mPagingMode, BaseAddress, Leng= th, EFI_MEMORY_RP); return Status; } =20 @@ -1799,7 +1622,7 @@ EnablePageTableProtection ( // // Set entire pool including header, used-memory and left free-memory = as ReadOnly in SMM page table. // - ConvertMemoryPageAttributes (PageTableBase, m5LevelPagingNeeded, Addre= ss, PoolSize, EFI_MEMORY_RO, TRUE, NULL, NULL); + ConvertMemoryPageAttributes (PageTableBase, mPagingMode, Address, Pool= Size, EFI_MEMORY_RO, TRUE, NULL); Pool =3D Pool->NextPool; } while (Pool !=3D HeadPool); } diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c b/UefiCpuPkg/PiSmmCpuD= xeSmm/X64/PageTbl.c index 3deb1ffd67..a25a96f68c 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c @@ -1,7 +1,7 @@ /** @file Page Fault (#PF) handler for X64 processors =20 -Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.
Copyright (c) 2017, AMD Incorporated. All rights reserved.
=20 SPDX-License-Identifier: BSD-2-Clause-Patent @@ -353,7 +353,12 @@ SmmInitPageTable ( m1GPageTableSupport =3D Is1GPageSupport (); m5LevelPagingNeeded =3D Is5LevelPagingNeeded (); mPhysicalAddressBits =3D CalculateMaximumSupportAddress (); - PatchInstructionX86 (gPatch5LevelPagingNeeded, m5LevelPagingNeeded, 1); + if (m5LevelPagingNeeded) { + mPagingMode =3D m1GPageTableSupport ? Paging5Level1GB : Paging5Level; + PatchInstructionX86 (gPatch5LevelPagingNeeded, TRUE, 1); + } else { + mPagingMode =3D m1GPageTableSupport ? Paging4Level1GB : Paging4Level; + } DEBUG ((DEBUG_INFO, "5LevelPaging Needed - %d\n", m5LevelPag= ingNeeded)); DEBUG ((DEBUG_INFO, "1GPageTable Support - %d\n", m1GPageTab= leSupport)); DEBUG ((DEBUG_INFO, "PcdCpuSmmRestrictedMemoryAccess - %d\n", mCpuSmmRes= trictedMemoryAccess)); --=20 2.31.1.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 (#104925): https://edk2.groups.io/g/devel/message/104925 Mute This Topic: https://groups.io/mt/98922930/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-