public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
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


  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