diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c index 8ec8790c05..97058a2810 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c @@ -28,26 +28,6 @@ EnableCet ( VOID ); -/** - Get page table base address and the depth of the page table. - - @param[out] Base Page table base address. - @param[out] FiveLevels TRUE means 5 level paging. FALSE means 4 level paging. -**/ -VOID -GetPageTable ( - OUT UINTN *Base, - OUT BOOLEAN *FiveLevels OPTIONAL - ) -{ - *Base = ((mInternalCr3 == 0) ? - (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64) : - mInternalCr3); - if (FiveLevels != NULL) { - *FiveLevels = FALSE; - } -} - /** Create PageTable for SMM use. @@ -297,10 +277,10 @@ SetPageTableAttributes ( DEBUG ((DEBUG_INFO, "Start...\n")); PageTableSplitted = FALSE; - GetPageTable (&PageTableBase, NULL); - L3PageTable = (UINT64 *)PageTableBase; + PageTableBase = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; + L3PageTable = (UINT64 *)PageTableBase; - SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)PageTableBase, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); + SmmSetMemoryAttributesEx (PageTableBase, FALSE, (EFI_PHYSICAL_ADDRESS)PageTableBase, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); PageTableSplitted = (PageTableSplitted || IsSplitted); for (Index3 = 0; Index3 < 4; Index3++) { @@ -309,7 +289,7 @@ SetPageTableAttributes ( continue; } - SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L2PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); + SmmSetMemoryAttributesEx (PageTableBase, FALSE, (EFI_PHYSICAL_ADDRESS)(UINTN)L2PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); PageTableSplitted = (PageTableSplitted || IsSplitted); for (Index2 = 0; Index2 < SIZE_4KB/sizeof (UINT64); Index2++) { @@ -323,7 +303,7 @@ SetPageTableAttributes ( continue; } - SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L1PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); + SmmSetMemoryAttributesEx (PageTableBase, FALSE, (EFI_PHYSICAL_ADDRESS)(UINTN)L1PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); PageTableSplitted = (PageTableSplitted || IsSplitted); } } diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h index dfeceec2aa..ef8bf5947d 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h @@ -264,7 +264,7 @@ extern UINTN mMaxNumberOfCpus; extern UINTN mNumberOfCpus; extern EFI_SMM_CPU_PROTOCOL mSmmCpu; extern EFI_MM_MP_PROTOCOL mSmmMp; -extern UINTN mInternalCr3; +extern BOOLEAN m5LevelPagingNeeded; /// /// The mode of the CPU at the time an SMI occurs @@ -682,7 +682,6 @@ SmmBlockingStartupThisAp ( **/ EFI_STATUS -EFIAPI SmmSetMemoryAttributes ( IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, @@ -712,7 +711,6 @@ SmmSetMemoryAttributes ( **/ EFI_STATUS -EFIAPI SmmClearMemoryAttributes ( IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, @@ -957,22 +955,12 @@ SetPageTableAttributes ( VOID ); -/** - Get page table base address and the depth of the page table. - - @param[out] Base Page table base address. - @param[out] FiveLevels TRUE means 5 level paging. FALSE means 4 level paging. -**/ -VOID -GetPageTable ( - OUT UINTN *Base, - OUT BOOLEAN *FiveLevels OPTIONAL - ); - /** This function sets the attributes for the memory region specified by BaseAddress and Length from their current attributes to the attributes specified by Attributes. + @param[in] PageTableBase The page table base. + @param[in] EnablePML5Paging If PML5 paging is enabled. @param[in] BaseAddress The physical address that is the start address of a memory region. @param[in] Length The size in bytes of the memory region. @param[in] Attributes The bit mask of attributes to set for the memory region. @@ -993,8 +981,9 @@ GetPageTable ( **/ EFI_STATUS -EFIAPI SmmSetMemoryAttributesEx ( + IN UINTN PageTableBase, + IN BOOLEAN EnablePML5Paging, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, @@ -1005,6 +994,8 @@ SmmSetMemoryAttributesEx ( This function clears the attributes for the memory region specified by BaseAddress and Length from their current attributes to the attributes specified by Attributes. + @param[in] PageTableBase The page table base. + @param[in] EnablePML5Paging If PML5 paging is enabled. @param[in] BaseAddress The physical address that is the start address of a memory region. @param[in] Length The size in bytes of the memory region. @param[in] Attributes The bit mask of attributes to clear for the memory region. @@ -1025,8 +1016,9 @@ SmmSetMemoryAttributesEx ( **/ EFI_STATUS -EFIAPI SmmClearMemoryAttributesEx ( + IN UINTN PageTableBase, + IN BOOLEAN EnablePML5Paging, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c index 10de8dd8e4..773ab927e6 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c @@ -32,23 +32,8 @@ PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = { { Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64 }, }; -UINTN mInternalCr3; -BOOLEAN mIsShadowStack = FALSE; - -/** - Set the internal page table base address. - If it is non zero, further MemoryAttribute modification will be on this page table. - If it is zero, further MemoryAttribute modification will be on real page table. - - @param Cr3 page table base. -**/ -VOID -SetPageTableBase ( - IN UINTN Cr3 - ) -{ - mInternalCr3 = Cr3; -} +BOOLEAN mIsShadowStack = FALSE; +BOOLEAN m5LevelPagingNeeded = FALSE; /** Return length according to page attributes. @@ -99,31 +84,31 @@ PageAttributeToMask ( /** Return page table entry to match the address. - @param[in] Address The address to be checked. - @param[out] PageAttributes The page attribute of the page entry. + @param[in] PageTableBase The page table base. + @param[in] Enable5LevelPaging If PML5 paging is enabled. + @param[in] Address The address to be checked. + @param[out] PageAttributes The page attribute of the page entry. @return The page entry. **/ VOID * GetPageTableEntry ( + IN UINTN PageTableBase, + IN BOOLEAN Enable5LevelPaging, IN PHYSICAL_ADDRESS Address, OUT PAGE_ATTRIBUTE *PageAttribute ) { - UINTN Index1; - UINTN Index2; - UINTN Index3; - UINTN Index4; - UINTN Index5; - UINT64 *L1PageTable; - UINT64 *L2PageTable; - UINT64 *L3PageTable; - UINT64 *L4PageTable; - UINT64 *L5PageTable; - UINTN PageTableBase; - BOOLEAN Enable5LevelPaging; - - GetPageTable (&PageTableBase, &Enable5LevelPaging); + UINTN Index1; + UINTN Index2; + UINTN Index3; + UINTN Index4; + UINTN Index5; + UINT64 *L1PageTable; + UINT64 *L2PageTable; + UINT64 *L3PageTable; + UINT64 *L4PageTable; + UINT64 *L5PageTable; Index5 = ((UINTN)RShiftU64 (Address, 48)) & PAGING_PAE_INDEX_MASK; Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_PAE_INDEX_MASK; @@ -399,6 +384,8 @@ SplitPage ( Caller should make sure BaseAddress and Length is at page boundary. + @param[in] PageTableBase The page table base. + @param[in] EnablePML5Paging If PML5 paging is enabled. @param[in] BaseAddress The physical address that is the start address of a memory region. @param[in] Length The size in bytes of the memory region. @param[in] Attributes The bit mask of attributes to modify for the memory region. @@ -420,8 +407,9 @@ SplitPage ( range specified by BaseAddress and Length. **/ RETURN_STATUS -EFIAPI ConvertMemoryPageAttributes ( + IN UINTN PageTableBase, + IN BOOLEAN EnablePML5Paging, IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, @@ -475,7 +463,7 @@ ConvertMemoryPageAttributes ( // Below logic is to check 2M/4K page to make sure we do not waste memory. // while (Length != 0) { - PageEntry = GetPageTableEntry (BaseAddress, &PageAttribute); + PageEntry = GetPageTableEntry (PageTableBase, EnablePML5Paging, BaseAddress, &PageAttribute); if (PageEntry == NULL) { return RETURN_UNSUPPORTED; } @@ -558,6 +546,8 @@ FlushTlbForAll ( This function sets the attributes for the memory region specified by BaseAddress and Length from their current attributes to the attributes specified by Attributes. + @param[in] PageTableBase The page table base. + @param[in] EnablePML5Paging If PML5 paging is enabled. @param[in] BaseAddress The physical address that is the start address of a memory region. @param[in] Length The size in bytes of the memory region. @param[in] Attributes The bit mask of attributes to set for the memory region. @@ -578,8 +568,9 @@ FlushTlbForAll ( **/ EFI_STATUS -EFIAPI SmmSetMemoryAttributesEx ( + IN UINTN PageTableBase, + IN BOOLEAN EnablePML5Paging, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, @@ -589,7 +580,7 @@ SmmSetMemoryAttributesEx ( EFI_STATUS Status; BOOLEAN IsModified; - Status = ConvertMemoryPageAttributes (BaseAddress, Length, Attributes, TRUE, IsSplitted, &IsModified); + Status = ConvertMemoryPageAttributes (PageTableBase, EnablePML5Paging, BaseAddress, Length, Attributes, TRUE, IsSplitted, &IsModified); if (!EFI_ERROR (Status)) { if (IsModified) { // @@ -606,6 +597,8 @@ SmmSetMemoryAttributesEx ( This function clears the attributes for the memory region specified by BaseAddress and Length from their current attributes to the attributes specified by Attributes. + @param[in] PageTableBase The page table base. + @param[in] EnablePML5Paging If PML5 paging is enabled. @param[in] BaseAddress The physical address that is the start address of a memory region. @param[in] Length The size in bytes of the memory region. @param[in] Attributes The bit mask of attributes to clear for the memory region. @@ -626,8 +619,9 @@ SmmSetMemoryAttributesEx ( **/ EFI_STATUS -EFIAPI SmmClearMemoryAttributesEx ( + IN UINTN PageTableBase, + IN BOOLEAN EnablePML5Paging, IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, @@ -637,7 +631,7 @@ SmmClearMemoryAttributesEx ( EFI_STATUS Status; BOOLEAN IsModified; - Status = ConvertMemoryPageAttributes (BaseAddress, Length, Attributes, FALSE, IsSplitted, &IsModified); + Status = ConvertMemoryPageAttributes (PageTableBase, EnablePML5Paging, BaseAddress, Length, Attributes, FALSE, IsSplitted, &IsModified); if (!EFI_ERROR (Status)) { if (IsModified) { // @@ -673,14 +667,20 @@ SmmClearMemoryAttributesEx ( **/ EFI_STATUS -EFIAPI SmmSetMemoryAttributes ( IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes ) { - return SmmSetMemoryAttributesEx (BaseAddress, Length, Attributes, NULL); + IA32_CR4 Cr4; + UINTN PageTableBase; + BOOLEAN Enable5LevelPaging; + + PageTableBase = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; + Cr4.UintN = AsmReadCr4 (); + Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1); + return SmmSetMemoryAttributesEx (PageTableBase, Enable5LevelPaging, BaseAddress, Length, Attributes, NULL); } /** @@ -706,14 +706,20 @@ SmmSetMemoryAttributes ( **/ EFI_STATUS -EFIAPI SmmClearMemoryAttributes ( IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes ) { - return SmmClearMemoryAttributesEx (BaseAddress, Length, Attributes, NULL); + IA32_CR4 Cr4; + UINTN PageTableBase; + BOOLEAN Enable5LevelPaging; + + PageTableBase = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; + Cr4.UintN = AsmReadCr4 (); + Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1); + return SmmClearMemoryAttributesEx (PageTableBase, Enable5LevelPaging, BaseAddress, Length, Attributes, NULL); } /** @@ -734,11 +740,8 @@ SetShadowStack ( { EFI_STATUS Status; - SetPageTableBase (Cr3); mIsShadowStack = TRUE; - Status = SmmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RO); - - SetPageTableBase (0); + Status = SmmSetMemoryAttributesEx (Cr3, m5LevelPagingNeeded, BaseAddress, Length, EFI_MEMORY_RO, NULL); mIsShadowStack = FALSE; return Status; @@ -762,12 +765,7 @@ SetNotPresentPage ( { EFI_STATUS Status; - SetPageTableBase (Cr3); - - Status = SmmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RP); - - SetPageTableBase (0); - + Status = SmmSetMemoryAttributesEx (Cr3, m5LevelPagingNeeded, BaseAddress, Length, EFI_MEMORY_RP, NULL); return Status; } @@ -1560,6 +1558,9 @@ EdkiiSmmGetMemoryAttributes ( UINT64 MemAttr; PAGE_ATTRIBUTE PageAttr; INT64 Size; + UINTN PageTableBase; + BOOLEAN EnablePML5Paging; + IA32_CR4 Cr4; if ((Length < SIZE_4KB) || (Attributes == NULL)) { return EFI_INVALID_PARAMETER; @@ -1568,8 +1569,12 @@ EdkiiSmmGetMemoryAttributes ( Size = (INT64)Length; MemAttr = (UINT64)-1; + PageTableBase = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; + Cr4.UintN = AsmReadCr4 (); + EnablePML5Paging = (BOOLEAN)(Cr4.Bits.LA57 == 1); + do { - PageEntry = GetPageTableEntry (BaseAddress, &PageAttr); + PageEntry = GetPageTableEntry (PageTableBase, EnablePML5Paging, BaseAddress, &PageAttr); if ((PageEntry == NULL) || (PageAttr == PageNone)) { return EFI_UNSUPPORTED; } diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c index 538394f239..6587212f4e 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c @@ -18,7 +18,6 @@ extern UINTN mSmmShadowStackSize; LIST_ENTRY mPagePool = INITIALIZE_LIST_HEAD_VARIABLE (mPagePool); BOOLEAN m1GPageTableSupport = FALSE; BOOLEAN mCpuSmmRestrictedMemoryAccess; -BOOLEAN m5LevelPagingNeeded; X86_ASSEMBLY_PATCH_LABEL gPatch5LevelPagingNeeded; /** @@ -113,36 +112,6 @@ Is5LevelPagingNeeded ( } } -/** - Get page table base address and the depth of the page table. - - @param[out] Base Page table base address. - @param[out] FiveLevels TRUE means 5 level paging. FALSE means 4 level paging. -**/ -VOID -GetPageTable ( - OUT UINTN *Base, - OUT BOOLEAN *FiveLevels OPTIONAL - ) -{ - IA32_CR4 Cr4; - - if (mInternalCr3 == 0) { - *Base = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; - if (FiveLevels != NULL) { - Cr4.UintN = AsmReadCr4 (); - *FiveLevels = (BOOLEAN)(Cr4.Bits.LA57 == 1); - } - - return; - } - - *Base = mInternalCr3; - if (FiveLevels != NULL) { - *FiveLevels = m5LevelPagingNeeded; - } -} - /** Set sub-entries number in entry. @@ -1195,20 +1164,21 @@ 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; + 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 @@ -1258,11 +1228,13 @@ SetPageTableAttributes ( PageTableSplitted = FALSE; L5PageTable = NULL; - GetPageTable (&PageTableBase, &Enable5LevelPaging); + PageTableBase = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64; + Cr4.UintN = AsmReadCr4 (); + Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1); if (Enable5LevelPaging) { L5PageTable = (UINT64 *)PageTableBase; - SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)PageTableBase, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); + SmmSetMemoryAttributesEx (PageTableBase, Enable5LevelPaging, (EFI_PHYSICAL_ADDRESS)PageTableBase, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); PageTableSplitted = (PageTableSplitted || IsSplitted); } @@ -1276,7 +1248,7 @@ SetPageTableAttributes ( L4PageTable = (UINT64 *)PageTableBase; } - SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L4PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); + 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++) { @@ -1285,7 +1257,7 @@ SetPageTableAttributes ( continue; } - SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L3PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); + 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++) { @@ -1299,7 +1271,7 @@ SetPageTableAttributes ( continue; } - SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L2PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); + 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++) { @@ -1313,7 +1285,7 @@ SetPageTableAttributes ( continue; } - SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L1PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); + SmmSetMemoryAttributesEx (PageTableBase, Enable5LevelPaging, (EFI_PHYSICAL_ADDRESS)(UINTN)L1PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted); PageTableSplitted = (PageTableSplitted || IsSplitted); } }