Reviewed-by: Ray Ni <ray...@intel.com> > -----Original Message----- > From: Tan, Dun <dun....@intel.com> > Sent: Friday, March 31, 2023 5:34 PM > To: devel@edk2.groups.io > Cc: Bi, Dandan <dandan...@intel.com>; Gao, Liming > <gaolim...@byosoft.com.cn>; Ni, Ray <ray...@intel.com>; Wang, Jian J > <jian.j.w...@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....@intel.com> > Cc: Dandan Bi <dandan...@intel.com> > Cc: Liming Gao <gaolim...@byosoft.com.cn> > Cc: Ray Ni <ray...@intel.com> > Cc: Jian J Wang <jian.j.w...@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
-=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#102291): https://edk2.groups.io/g/devel/message/102291 Mute This Topic: https://groups.io/mt/97969865/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/leave/9847357/21656/1706620634/xyzzy [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-