From: "Ni, Ray" <ray.ni@intel.com>
To: "Tan, Dun" <dun.tan@intel.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Bi, Dandan" <dandan.bi@intel.com>,
"Gao, Liming" <gaoliming@byosoft.com.cn>,
"Wang, Jian J" <jian.j.wang@intel.com>
Subject: Re: [Patch V2 8/8] MdeModulePkg/DxeIpl: Refinement to the code to set PageTable as RO
Date: Fri, 31 Mar 2023 10:25:17 +0000 [thread overview]
Message-ID: <MN6PR11MB8244E0E813A07EB457917CB08C8F9@MN6PR11MB8244.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20230331093344.2609-9-dun.tan@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
> -----Original Message-----
> From: Tan, Dun <dun.tan@intel.com>
> Sent: Friday, March 31, 2023 5:34 PM
> To: devel@edk2.groups.io
> Cc: Bi, Dandan <dandan.bi@intel.com>; Gao, Liming
> <gaoliming@byosoft.com.cn>; Ni, Ray <ray.ni@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>
> Subject: [Patch V2 8/8] MdeModulePkg/DxeIpl: Refinement to the code to
> set PageTable as RO
>
> 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=4176
> Signed-off-by: Dun Tan <dun.tan@intel.com>
> Cc: Dandan Bi <dandan.bi@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> ---
> MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 155
> +++++++++++++++----------------------------------------------------------------------
> ----------------------------------------------------------------------
> MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h | 15 ---------------
> 2 files changed, 15 insertions(+), 155 deletions(-)
>
> diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> index ecdbd2ca24..a9edf4de32 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
> @@ -330,154 +330,37 @@ CreateOrUpdatePageTable (
> ASSERT (PageTableBufferSize == 0);
> }
>
> -/**
> - 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-only.
> - @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 != 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 = Address & PAGE_TABLE_POOL_ALIGN_MASK;
> -
> - LevelShift[1] = PAGING_L1_ADDRESS_SHIFT;
> - LevelShift[2] = PAGING_L2_ADDRESS_SHIFT;
> - LevelShift[3] = PAGING_L3_ADDRESS_SHIFT;
> - LevelShift[4] = PAGING_L4_ADDRESS_SHIFT;
> -
> - LevelMask[1] = PAGING_4K_ADDRESS_MASK_64;
> - LevelMask[2] = PAGING_2M_ADDRESS_MASK_64;
> - LevelMask[3] = PAGING_1G_ADDRESS_MASK_64;
> - LevelMask[4] = PAGING_1G_ADDRESS_MASK_64;
> -
> - LevelSize[1] = SIZE_4KB;
> - LevelSize[2] = SIZE_2MB;
> - LevelSize[3] = SIZE_1GB;
> - LevelSize[4] = SIZE_512GB;
> -
> - AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask)
> &
> - PAGING_1G_ADDRESS_MASK_64;
> - PageTable = (UINT64 *)(UINTN)PageTableBase;
> - PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE;
> -
> - for (Level = (Level4Paging) ? 4 : 3; Level > 0; --Level) {
> - Index = ((UINTN)RShiftU64 (Address, LevelShift[Level]));
> - Index &= PAGING_PAE_INDEX_MASK;
> -
> - PageAttr = PageTable[Index];
> - if ((PageAttr & IA32_PG_PS) == 0) {
> - //
> - // Go to next level of table.
> - //
> - PageTable = (UINT64 *)(UINTN)(PageAttr & ~AddressEncMask &
> - PAGING_4K_ADDRESS_MASK_64);
> - continue;
> - }
> -
> - if (PoolUnitSize >= LevelSize[Level]) {
> - //
> - // Clear R/W bit if current page granularity is not larger than pool unit
> - // size.
> - //
> - if ((PageAttr & IA32_PG_RW) != 0) {
> - while (PoolUnitSize > 0) {
> - //
> - // PAGE_TABLE_POOL_UNIT_SIZE and
> PAGE_TABLE_POOL_ALIGNMENT are fit in
> - // one page (2MB). Then we don't need to update attributes for pages
> - // crossing page directory. ASSERT below is for that purpose.
> - //
> - ASSERT (Index < EFI_PAGE_SIZE/sizeof (UINT64));
> -
> - PageTable[Index] &= ~(UINT64)IA32_PG_RW;
> - PoolUnitSize -= LevelSize[Level];
> -
> - ++Index;
> - }
> - }
> -
> - break;
> - } else {
> - //
> - // The smaller granularity of page must be needed.
> - //
> - ASSERT (Level > 1);
> -
> - NewPageTable = AllocatePageTableMemory (1);
> - ASSERT (NewPageTable != NULL);
> -
> - PhysicalAddress = PageAttr & LevelMask[Level];
> - for (EntryIndex = 0;
> - EntryIndex < EFI_PAGE_SIZE/sizeof (UINT64);
> - ++EntryIndex)
> - {
> - NewPageTable[EntryIndex] = PhysicalAddress | AddressEncMask |
> - IA32_PG_P | IA32_PG_RW;
> - if (Level > 2) {
> - NewPageTable[EntryIndex] |= IA32_PG_PS;
> - }
> -
> - PhysicalAddress += LevelSize[Level - 1];
> - }
> -
> - PageTable[Index] = (UINT64)(UINTN)NewPageTable | AddressEncMask |
> - IA32_PG_P | IA32_PG_RW;
> - PageTable = NewPageTable;
> - }
> - }
> -}
> -
> /**
> Prevent the memory pages used for page table from been overwritten.
>
> - @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.
>
> **/
> 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;
>
> if (mPageTablePool == NULL) {
> return;
> }
>
> + MapAttribute.Uint64 = 0;
> + MapAttribute.Bits.ReadWrite = 0;
> + MapMask.Uint64 = 0;
> + MapMask.Bits.ReadWrite = 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 = mPageTablePool;
> @@ -485,18 +368,10 @@ EnablePageTableProtection (
> do {
> Address = (EFI_PHYSICAL_ADDRESS)(UINTN)Pool;
> PoolSize = 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 += PAGE_TABLE_POOL_UNIT_SIZE;
> - PoolSize -= PAGE_TABLE_POOL_UNIT_SIZE;
> - }
> -
> + CreateOrUpdatePageTable (&PageTableBase, PagingMode, Address,
> PoolSize, &MapAttribute, &MapMask);
> Pool = Pool->NextPool;
> } while (Pool != HeadPool);
>
> @@ -679,7 +554,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);
>
> //
> // Set IA32_EFER.NXE if necessary.
> diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
> b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
> index a6cf31811d..034c4249d4 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
> +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
> @@ -50,23 +50,8 @@ typedef struct {
>
> #define CR0_WP BIT16
>
> -#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
>
> -#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_UNIT_SIZE)
> --
> 2.31.1.windows.1
next prev parent reply other threads:[~2023-03-31 10:25 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-31 9:33 [Patch V2 0/8] Create page table by CpuPageTableLib in DxeIpl duntan
2023-03-31 9:33 ` [Patch V2 1/8] EmulatorPkg: Add CpuPageTableLib required by DxeIpl in DSC duntan
2023-03-31 10:21 ` Ni, Ray
2023-03-31 9:33 ` [Patch V2 2/8] IntelFsp2Pkg: " duntan
2023-03-31 9:33 ` [Patch V2 3/8] MdeModulePkg: " duntan
2023-04-14 9:09 ` Wang, Jian J
2023-04-24 10:11 ` duntan
2023-03-31 9:33 ` [Patch V2 4/8] OvmfPkg: Add CpuPageTableLib required by DxeIpl in DSC file duntan
2023-03-31 11:50 ` [edk2-devel] " Gerd Hoffmann
2023-03-31 9:33 ` [Patch V2 5/8] MdeModulePkg: Add UefiCpuPkg.dec to pass DependencyCheck duntan
2023-04-14 9:03 ` Wang, Jian J
2023-04-14 15:16 ` [edk2-devel] " Michael D Kinney
2023-04-14 16:07 ` Ni, Ray
2023-04-15 15:50 ` Michael D Kinney
2023-04-15 15:57 ` Michael D Kinney
2023-04-16 5:21 ` Ni, Ray
2023-04-18 19:06 ` Michael D Kinney
2023-04-19 6:00 ` Ni, Ray
2023-04-19 15:02 ` Michael D Kinney
2023-04-21 8:10 ` Ni, Ray
2023-04-21 15:42 ` Michael D Kinney
2023-04-24 10:27 ` duntan
2023-04-24 15:59 ` Ard Biesheuvel
2023-03-31 9:33 ` [Patch V2 6/8] MdeModulePkg/DxeIpl: Create page table by CpuPageTableLib duntan
2023-03-31 10:24 ` Ni, Ray
2023-03-31 9:33 ` [Patch V2 7/8] MdeModulePkg/DxeIpl: Remove duplicated code to enable NX duntan
2023-03-31 9:33 ` [Patch V2 8/8] MdeModulePkg/DxeIpl: Refinement to the code to set PageTable as RO duntan
2023-03-31 10:25 ` Ni, Ray [this message]
[not found] ` <1751776493F12DAB.27612@groups.io>
2023-04-11 6:51 ` [edk2-devel] [Patch V2 4/8] OvmfPkg: Add CpuPageTableLib required by DxeIpl in DSC file duntan
2023-04-11 8:56 ` Gerd Hoffmann
[not found] ` <1751776BEEE9C9E8.27612@groups.io>
2023-04-11 6:51 ` [edk2-devel] [Patch V2 5/8] MdeModulePkg: Add UefiCpuPkg.dec to pass DependencyCheck duntan
[not found] ` <1751776458C20361.12651@groups.io>
2023-04-11 6:53 ` [edk2-devel] [Patch V2 3/8] MdeModulePkg: Add CpuPageTableLib required by DxeIpl in DSC duntan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MN6PR11MB8244E0E813A07EB457917CB08C8F9@MN6PR11MB8244.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox