UefiCpuPkg: Simplify the code to set smm page table as RO

Simplify the code to set memory used by smm page table as RO.
Since memory used by smm page table are in PageTablePool list,
we only need to set all PageTablePool as ReadOnly in smm page
table itself. Also, we only need to flush tlb once after
setting all page table pool as Read Only.

Signed-off-by: Dun Tan <dun.tan@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
This commit is contained in:
Tan, Dun
2022-12-21 12:21:56 +08:00
committed by mergify[bot]
parent 0426115b67
commit 72a9386f67
4 changed files with 136 additions and 259 deletions

View File

@@ -1139,159 +1139,6 @@ Exit:
ReleaseSpinLock (mPFLock);
}
/**
This function sets memory attribute for page table.
**/
VOID
SetPageTableAttributes (
VOID
)
{
UINTN Index2;
UINTN Index3;
UINTN Index4;
UINTN Index5;
UINT64 *L1PageTable;
UINT64 *L2PageTable;
UINT64 *L3PageTable;
UINT64 *L4PageTable;
UINT64 *L5PageTable;
UINTN PageTableBase;
BOOLEAN IsSplitted;
BOOLEAN PageTableSplitted;
BOOLEAN CetEnabled;
BOOLEAN Enable5LevelPaging;
IA32_CR4 Cr4;
//
// Don't mark page table memory as read-only if
// - no restriction on access to non-SMRAM memory; or
// - SMM heap guard feature enabled; or
// BIT2: SMM page guard enabled
// BIT3: SMM pool guard enabled
// - SMM profile feature enabled
//
if (!mCpuSmmRestrictedMemoryAccess ||
((PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) != 0) ||
FeaturePcdGet (PcdCpuSmmProfileEnable))
{
//
// Restriction on access to non-SMRAM memory and heap guard could not be enabled at the same time.
//
ASSERT (
!(mCpuSmmRestrictedMemoryAccess &&
(PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) != 0)
);
//
// Restriction on access to non-SMRAM memory and SMM profile could not be enabled at the same time.
//
ASSERT (!(mCpuSmmRestrictedMemoryAccess && FeaturePcdGet (PcdCpuSmmProfileEnable)));
return;
}
DEBUG ((DEBUG_INFO, "SetPageTableAttributes\n"));
//
// Disable write protection, because we need mark page table to be write protected.
// We need *write* page table memory, to mark itself to be *read only*.
//
CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
if (CetEnabled) {
//
// CET must be disabled if WP is disabled.
//
DisableCet ();
}
AsmWriteCr0 (AsmReadCr0 () & ~CR0_WP);
do {
DEBUG ((DEBUG_INFO, "Start...\n"));
PageTableSplitted = FALSE;
L5PageTable = NULL;
PageTableBase = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64;
Cr4.UintN = AsmReadCr4 ();
Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);
if (Enable5LevelPaging) {
L5PageTable = (UINT64 *)PageTableBase;
SmmSetMemoryAttributesEx (PageTableBase, Enable5LevelPaging, (EFI_PHYSICAL_ADDRESS)PageTableBase, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
PageTableSplitted = (PageTableSplitted || IsSplitted);
}
for (Index5 = 0; Index5 < (Enable5LevelPaging ? SIZE_4KB/sizeof (UINT64) : 1); Index5++) {
if (Enable5LevelPaging) {
L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);
if (L4PageTable == NULL) {
continue;
}
} else {
L4PageTable = (UINT64 *)PageTableBase;
}
SmmSetMemoryAttributesEx (PageTableBase, Enable5LevelPaging, (EFI_PHYSICAL_ADDRESS)(UINTN)L4PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
PageTableSplitted = (PageTableSplitted || IsSplitted);
for (Index4 = 0; Index4 < SIZE_4KB/sizeof (UINT64); Index4++) {
L3PageTable = (UINT64 *)(UINTN)(L4PageTable[Index4] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);
if (L3PageTable == NULL) {
continue;
}
SmmSetMemoryAttributesEx (PageTableBase, Enable5LevelPaging, (EFI_PHYSICAL_ADDRESS)(UINTN)L3PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
PageTableSplitted = (PageTableSplitted || IsSplitted);
for (Index3 = 0; Index3 < SIZE_4KB/sizeof (UINT64); Index3++) {
if ((L3PageTable[Index3] & IA32_PG_PS) != 0) {
// 1G
continue;
}
L2PageTable = (UINT64 *)(UINTN)(L3PageTable[Index3] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);
if (L2PageTable == NULL) {
continue;
}
SmmSetMemoryAttributesEx (PageTableBase, Enable5LevelPaging, (EFI_PHYSICAL_ADDRESS)(UINTN)L2PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
PageTableSplitted = (PageTableSplitted || IsSplitted);
for (Index2 = 0; Index2 < SIZE_4KB/sizeof (UINT64); Index2++) {
if ((L2PageTable[Index2] & IA32_PG_PS) != 0) {
// 2M
continue;
}
L1PageTable = (UINT64 *)(UINTN)(L2PageTable[Index2] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);
if (L1PageTable == NULL) {
continue;
}
SmmSetMemoryAttributesEx (PageTableBase, Enable5LevelPaging, (EFI_PHYSICAL_ADDRESS)(UINTN)L1PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
PageTableSplitted = (PageTableSplitted || IsSplitted);
}
}
}
}
} while (PageTableSplitted);
//
// Enable write protection, after page table updated.
//
AsmWriteCr0 (AsmReadCr0 () | CR0_WP);
if (CetEnabled) {
//
// re-enable CET.
//
EnableCet ();
}
mIsReadOnlyPageTable = TRUE;
return;
}
/**
This function reads CR2 register when on-demand paging is enabled.