From nobody Fri Oct 18 04:21:28 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+101999+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+101999+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1679971463; cv=none; d=zohomail.com; s=zohoarc; b=N27CghZVdR3Wl3zw4uXOyh6YGdahoA09iQBMJjcHGWQBpuBCgAoPi6qHatLLHh2B6FLrhrDk7GyvD7h17sykgjDA74jD45XJgttqd4GaxRzOLIdwgWuqfPFo7GzsVgsREqJRJ+oo9ONGZNl/nHXU+xk/SRGsbs7qLD0A3hAGMXY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1679971463; 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=X9vu7YoEqkIUOoXjNls8oqEQIxpVYimc8ELkbINPsRE=; b=JFPFuDs/BRnUAwQqPtk6hV3lAoQ5KjmAkFy85XETg0q0DWbkOI6wlvNq4tt3VY5na6vJSAszTPm/ITxz+VE9kYCOtWUV7iPpjX3upoXTbtUW+yaXWr9LScrEhjT8TqL+e8sL4oNwej4aAL0D0f1q2FKc71HM01OPcooKio0yfSM= 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+101999+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 1679971463396921.3097646139311; Mon, 27 Mar 2023 19:44:23 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id DwnZYY1788612xJogenUqrDv; Mon, 27 Mar 2023 19:44:23 -0700 X-Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by mx.groups.io with SMTP id smtpd.web11.57515.1679971455383645096 for ; Mon, 27 Mar 2023 19:44:22 -0700 X-IronPort-AV: E=McAfee;i="6600,9927,10662"; a="320852750" X-IronPort-AV: E=Sophos;i="5.98,296,1673942400"; d="scan'208";a="320852750" X-Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2023 19:44:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10662"; a="807700397" X-IronPort-AV: E=Sophos;i="5.98,296,1673942400"; d="scan'208";a="807700397" X-Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.55.92]) by orsmga004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2023 19:44:20 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Dandan Bi , Liming Gao , Ray Ni , Jian J Wang Subject: [edk2-devel] [PATCH 9/9] MdeModulePkg/DxeIpl: Refinement to the code to set PageTable as RO Date: Tue, 28 Mar 2023 10:43:02 +0800 Message-Id: <20230328024302.2085-10-dun.tan@intel.com> In-Reply-To: <20230328024302.2085-1-dun.tan@intel.com> References: <20230328024302.2085-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: 1yA7t6Vz5M4MGn7e98rvJZgax1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1679971463; bh=BGtFjJAqF5WAYWQ681Y0vG7bFoNaPm2Jtp10Qc4DwnA=; h=Cc:Date:From:Reply-To:Subject:To; b=nvcH005S0iofqIH2mtjyjmrlVBxZX69SdkLcb9lsXZgyJwaHUl+A6YY8LpHKGk7o7wI QUE3buLewlnSBgfpa9skAe7HzaSeiP3VzRHJzMC7DOzDu6iUdRCkMUqq1A0OD2ZLltZcg FbFMsdgt1LrpanUTvJLPf/l/LKMbHgid0nM= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1679971465039100002 Content-Type: text/plain; charset="utf-8" Code refinement to the code to set page table as RO in DxeIpl module. Set all page table pools as ReadOnly by calling PageTableMap() in CpuPageTableLib multiple times instead of searching each page table pool address in page table layer by layer. Also, this commit solve the issue that original SetPageTablePoolReadOnly() code in DxeIpl doesn't handle the Level5Paging case. Bugzila: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4176 Signed-off-by: Dun Tan Cc: Dandan Bi Cc: Liming Gao Cc: Ray Ni Cc: Jian J Wang --- MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 154 ++++++++++++++-----= ---------------------------------------------------------------------------= ------------------------------------------------------------ MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h | 15 --------------- 2 files changed, 14 insertions(+), 155 deletions(-) diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePk= g/Core/DxeIplPeim/X64/VirtualMemory.c index ac3a2b2dc4..c88ff7cf0a 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c @@ -330,154 +330,36 @@ CreateOrUpdatePageTable ( ASSERT (PageTableBufferSize =3D=3D 0); } =20 -/** - Set one page of page table pool memory to be read-only. - - @param[in] PageTableBase Base address of page table (CR3). - @param[in] Address Start address of a page to be set as read-on= ly. - @param[in] Level4Paging Level 4 paging flag. - -**/ -VOID -SetPageTablePoolReadOnly ( - IN UINTN PageTableBase, - IN EFI_PHYSICAL_ADDRESS Address, - IN BOOLEAN Level4Paging - ) -{ - UINTN Index; - UINTN EntryIndex; - UINT64 AddressEncMask; - EFI_PHYSICAL_ADDRESS PhysicalAddress; - UINT64 *PageTable; - UINT64 *NewPageTable; - UINT64 PageAttr; - UINT64 LevelSize[5]; - UINT64 LevelMask[5]; - UINTN LevelShift[5]; - UINTN Level; - UINT64 PoolUnitSize; - - ASSERT (PageTableBase !=3D 0); - - // - // Since the page table is always from page table pool, which is always - // located at the boundary of PcdPageTablePoolAlignment, we just need to - // set the whole pool unit to be read-only. - // - Address =3D Address & PAGE_TABLE_POOL_ALIGN_MASK; - - LevelShift[1] =3D PAGING_L1_ADDRESS_SHIFT; - LevelShift[2] =3D PAGING_L2_ADDRESS_SHIFT; - LevelShift[3] =3D PAGING_L3_ADDRESS_SHIFT; - LevelShift[4] =3D PAGING_L4_ADDRESS_SHIFT; - - LevelMask[1] =3D PAGING_4K_ADDRESS_MASK_64; - LevelMask[2] =3D PAGING_2M_ADDRESS_MASK_64; - LevelMask[3] =3D PAGING_1G_ADDRESS_MASK_64; - LevelMask[4] =3D PAGING_1G_ADDRESS_MASK_64; - - LevelSize[1] =3D SIZE_4KB; - LevelSize[2] =3D SIZE_2MB; - LevelSize[3] =3D SIZE_1GB; - LevelSize[4] =3D SIZE_512GB; - - AddressEncMask =3D PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & - PAGING_1G_ADDRESS_MASK_64; - PageTable =3D (UINT64 *)(UINTN)PageTableBase; - PoolUnitSize =3D PAGE_TABLE_POOL_UNIT_SIZE; - - for (Level =3D (Level4Paging) ? 4 : 3; Level > 0; --Level) { - Index =3D ((UINTN)RShiftU64 (Address, LevelShift[Level])); - Index &=3D PAGING_PAE_INDEX_MASK; - - PageAttr =3D PageTable[Index]; - if ((PageAttr & IA32_PG_PS) =3D=3D 0) { - // - // Go to next level of table. - // - PageTable =3D (UINT64 *)(UINTN)(PageAttr & ~AddressEncMask & - PAGING_4K_ADDRESS_MASK_64); - continue; - } - - if (PoolUnitSize >=3D LevelSize[Level]) { - // - // Clear R/W bit if current page granularity is not larger than pool= unit - // size. - // - if ((PageAttr & IA32_PG_RW) !=3D 0) { - while (PoolUnitSize > 0) { - // - // PAGE_TABLE_POOL_UNIT_SIZE and PAGE_TABLE_POOL_ALIGNMENT are f= it in - // one page (2MB). Then we don't need to update attributes for p= ages - // crossing page directory. ASSERT below is for that purpose. - // - ASSERT (Index < EFI_PAGE_SIZE/sizeof (UINT64)); - - PageTable[Index] &=3D ~(UINT64)IA32_PG_RW; - PoolUnitSize -=3D LevelSize[Level]; - - ++Index; - } - } - - break; - } else { - // - // The smaller granularity of page must be needed. - // - ASSERT (Level > 1); - - NewPageTable =3D AllocatePageTableMemory (1); - ASSERT (NewPageTable !=3D NULL); - - PhysicalAddress =3D PageAttr & LevelMask[Level]; - for (EntryIndex =3D 0; - EntryIndex < EFI_PAGE_SIZE/sizeof (UINT64); - ++EntryIndex) - { - NewPageTable[EntryIndex] =3D PhysicalAddress | AddressEncMask | - IA32_PG_P | IA32_PG_RW; - if (Level > 2) { - NewPageTable[EntryIndex] |=3D IA32_PG_PS; - } - - PhysicalAddress +=3D LevelSize[Level - 1]; - } - - PageTable[Index] =3D (UINT64)(UINTN)NewPageTable | AddressEncMask | - IA32_PG_P | IA32_PG_RW; - PageTable =3D NewPageTable; - } - } -} - /** Prevent the memory pages used for page table from been overwritten. =20 - @param[in] PageTableBase Base address of page table (CR3). - @param[in] Level4Paging Level 4 paging flag. + @param[in] PageTableBase Base address of page table (CR3). + @param[in] PagingMode The paging mode. =20 **/ VOID EnablePageTableProtection ( - IN UINTN PageTableBase, - IN BOOLEAN Level4Paging + IN UINTN PageTableBase, + IN PAGING_MODE PagingMode ) { PAGE_TABLE_POOL *HeadPool; PAGE_TABLE_POOL *Pool; UINT64 PoolSize; EFI_PHYSICAL_ADDRESS Address; + IA32_MAP_ATTRIBUTE MapAttribute; + IA32_MAP_ATTRIBUTE MapMask; =20 if (mPageTablePool =3D=3D NULL) { return; } =20 + MapAttribute.Uint64 =3D 0; + MapMask.Uint64 =3D 0; + MapMask.Bits.ReadWrite =3D 1; + // - // No need to clear CR0.WP since PageTableBase has't been written to CR3= yet. - // SetPageTablePoolReadOnly might update mPageTablePool. It's safer to + // CreateOrUpdatePageTable might update mPageTablePool. It's safer to // remember original one in advance. // HeadPool =3D mPageTablePool; @@ -485,18 +367,10 @@ EnablePageTableProtection ( do { Address =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Pool; PoolSize =3D Pool->Offset + EFI_PAGES_TO_SIZE (Pool->FreePages); - // - // The size of one pool must be multiple of PAGE_TABLE_POOL_UNIT_SIZE,= which - // is one of page size of the processor (2MB by default). Let's apply = the - // protection to them one by one. + // Set entire pool including header, used-memory and left free-memory = as ReadOnly. // - while (PoolSize > 0) { - SetPageTablePoolReadOnly (PageTableBase, Address, Level4Paging); - Address +=3D PAGE_TABLE_POOL_UNIT_SIZE; - PoolSize -=3D PAGE_TABLE_POOL_UNIT_SIZE; - } - + CreateOrUpdatePageTable (&PageTableBase, PagingMode, Address, PoolSize= , &MapAttribute, &MapMask); Pool =3D Pool->NextPool; } while (Pool !=3D HeadPool); =20 @@ -678,7 +552,7 @@ CreateIdentityMappingPageTables ( // Protect the page table by marking the memory used for page table to be // read-only. // - EnablePageTableProtection ((UINTN)PageTable, TRUE); + EnablePageTableProtection (PageTable, PagingMode); =20 // // Set IA32_EFER.NXE if necessary. diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h b/MdeModulePk= g/Core/DxeIplPeim/X64/VirtualMemory.h index 7d4bc4e4ba..174a2245c0 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h @@ -50,23 +50,8 @@ typedef struct { =20 #define CR0_WP BIT16 =20 -#define IA32_PG_P BIT0 -#define IA32_PG_RW BIT1 -#define IA32_PG_PS BIT7 - -#define PAGING_PAE_INDEX_MASK 0x1FF - -#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull -#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull #define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull =20 -#define PAGING_L1_ADDRESS_SHIFT 12 -#define PAGING_L2_ADDRESS_SHIFT 21 -#define PAGING_L3_ADDRESS_SHIFT 30 -#define PAGING_L4_ADDRESS_SHIFT 39 - -#define PAGING_PML4E_NUMBER 4 - #define PAGE_TABLE_POOL_ALIGNMENT BASE_2MB #define PAGE_TABLE_POOL_UNIT_SIZE SIZE_2MB #define PAGE_TABLE_POOL_UNIT_PAGES EFI_SIZE_TO_PAGES (PAGE_TABLE_POOL_UNI= T_SIZE) --=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 (#101999): https://edk2.groups.io/g/devel/message/101999 Mute This Topic: https://groups.io/mt/97897987/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-