From 8b8ac5d986dd78ee729a3fd32c833ff2235feeb9 Mon Sep 17 00:00:00 2001 From: Dun Tan Date: Wed, 31 Jul 2024 15:20:14 +0800 Subject: UefiCpuPkg: rename the SmiDefaultPFHandler function Rename SmiDefaultPFHandler to SmiProfileMapPFAddress and move the implementation to SmmProfileArch.c since it only will be used when SMM profile is enabled. Signed-off-by: Dun Tan --- UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c | 12 -- UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c | 12 ++ UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c | 2 +- UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h | 4 +- UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c | 150 ----------------------- UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c | 152 +++++++++++++++++++++++- UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.h | 55 +++++++++ 7 files changed, 221 insertions(+), 166 deletions(-) diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c index a8f0b503c0..dfc9668dbc 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c @@ -82,18 +82,6 @@ AllocPage ( return 0; } -/** - Page Fault handler for SMM use. - -**/ -VOID -SmiDefaultPFHandler ( - VOID - ) -{ - CpuDeadLoop (); -} - /** ThePage Fault handler wrapper for SMM use. diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c index 9021f9cf5d..b279c8a09c 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c @@ -76,3 +76,15 @@ ClearTrapFlag ( { SystemContext.SystemContextIa32->Eflags &= (UINTN) ~BIT8; } + +/** + Create new entry in page table for page fault address in SmmProfilePFHandler. + +**/ +VOID +SmmProfileMapPFAddress ( + VOID + ) +{ + CpuDeadLoop (); +} diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c index 6172c7df34..351afc9638 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c @@ -1337,7 +1337,7 @@ SmmProfilePFHandler ( // // If SMM profile does not start, call original page fault handler. // - SmiDefaultPFHandler (); + SmmProfileMapPFAddress (); return; } diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h index 9b00ea41b3..df6bdae0cc 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h @@ -153,11 +153,11 @@ AllocPage ( ); /** - Page Fault handler for SMM use. + Create new entry in page table for page fault address in SmmProfilePFHandler. **/ VOID -SmiDefaultPFHandler ( +SmmProfileMapPFAddress ( VOID ); diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c index a29bec55ea..abaa3349f4 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c @@ -700,156 +700,6 @@ AllocPage ( return RetVal; } -/** - Page Fault handler for SMM use. - -**/ -VOID -SmiDefaultPFHandler ( - VOID - ) -{ - UINT64 *PageTable; - UINT64 *PageTableTop; - UINT64 PFAddress; - UINTN StartBit; - UINTN EndBit; - UINT64 PTIndex; - UINTN Index; - SMM_PAGE_SIZE_TYPE PageSize; - UINTN NumOfPages; - UINTN PageAttribute; - EFI_STATUS Status; - UINT64 *UpperEntry; - BOOLEAN Enable5LevelPaging; - IA32_CR4 Cr4; - - // - // Set default SMM page attribute - // - PageSize = SmmPageSize2M; - NumOfPages = 1; - PageAttribute = 0; - - EndBit = 0; - PageTableTop = (UINT64 *)(AsmReadCr3 () & gPhyMask); - PFAddress = AsmReadCr2 (); - - Cr4.UintN = AsmReadCr4 (); - Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 != 0); - - Status = GetPlatformPageTableAttribute (PFAddress, &PageSize, &NumOfPages, &PageAttribute); - // - // If platform not support page table attribute, set default SMM page attribute - // - if (Status != EFI_SUCCESS) { - PageSize = SmmPageSize2M; - NumOfPages = 1; - PageAttribute = 0; - } - - if (PageSize >= MaxSmmPageSizeType) { - PageSize = SmmPageSize2M; - } - - if (NumOfPages > 512) { - NumOfPages = 512; - } - - switch (PageSize) { - case SmmPageSize4K: - // - // BIT12 to BIT20 is Page Table index - // - EndBit = 12; - break; - case SmmPageSize2M: - // - // BIT21 to BIT29 is Page Directory index - // - EndBit = 21; - PageAttribute |= (UINTN)IA32_PG_PS; - break; - case SmmPageSize1G: - if (!m1GPageTableSupport) { - DEBUG ((DEBUG_ERROR, "1-GByte pages is not supported!")); - ASSERT (FALSE); - } - - // - // BIT30 to BIT38 is Page Directory Pointer Table index - // - EndBit = 30; - PageAttribute |= (UINTN)IA32_PG_PS; - break; - default: - ASSERT (FALSE); - } - - // - // If execute-disable is enabled, set NX bit - // - if (mXdEnabled) { - PageAttribute |= IA32_PG_NX; - } - - for (Index = 0; Index < NumOfPages; Index++) { - PageTable = PageTableTop; - UpperEntry = NULL; - for (StartBit = Enable5LevelPaging ? 48 : 39; StartBit > 12; StartBit -= 9) { - PTIndex = BitFieldRead64 (PFAddress, StartBit, StartBit + 8); - - // - // Iterate through the page table to find the appropriate page table entry for page creation if one of the following cases is met: - // 1) StartBit > EndBit: The PageSize of current entry is bigger than the platform-specified PageSize granularity. - // 2) IA32_PG_P bit is 0 & IA32_PG_PS bit is not 0: The current entry is present and it's a non-leaf entry. - // - if ((StartBit > EndBit) || ((((PageTable[PTIndex] & IA32_PG_P) != 0) && ((PageTable[PTIndex] & IA32_PG_PS) == 0)))) { - if ((PageTable[PTIndex] & IA32_PG_P) == 0) { - // - // If the entry is not present, allocate one page from page pool for it - // - PageTable[PTIndex] = AllocPage () | mAddressEncMask | PAGE_ATTRIBUTE_BITS; - } else { - // - // Save the upper entry address - // - UpperEntry = PageTable + PTIndex; - } - - // - // BIT9 to BIT11 of entry is used to save access record, - // initialize value is 7 - // - PageTable[PTIndex] |= (UINT64)IA32_PG_A; - SetAccNum (PageTable + PTIndex, 7); - PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & gPhyMask); - } else { - // - // Found the appropriate entry. - // - break; - } - } - - PTIndex = BitFieldRead64 (PFAddress, StartBit, StartBit + 8); - - // - // Fill the new entry - // - PageTable[PTIndex] = ((PFAddress | mAddressEncMask) & gPhyMask & ~((1ull << StartBit) - 1)) | - PageAttribute | IA32_PG_A | PAGE_ATTRIBUTE_BITS; - if (UpperEntry != NULL) { - SetSubEntriesNum (UpperEntry, (GetSubEntriesNum (UpperEntry) + 1) & 0x1FF); - } - - // - // Get the next page address if we need to create more page tables - // - PFAddress += (1ull << StartBit); - } -} - /** ThePage Fault handler wrapper for SMM use. diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c index 8e15c42d99..39dd2c8029 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c @@ -109,6 +109,156 @@ AcquirePage ( mPFPageIndex = (mPFPageIndex + 1) % MAX_PF_PAGE_COUNT; } +/** + Create new entry in page table for page fault address in SmmProfilePFHandler. + +**/ +VOID +SmmProfileMapPFAddress ( + VOID + ) +{ + UINT64 *PageTable; + UINT64 *PageTableTop; + UINT64 PFAddress; + UINTN StartBit; + UINTN EndBit; + UINT64 PTIndex; + UINTN Index; + SMM_PAGE_SIZE_TYPE PageSize; + UINTN NumOfPages; + UINTN PageAttribute; + EFI_STATUS Status; + UINT64 *UpperEntry; + BOOLEAN Enable5LevelPaging; + IA32_CR4 Cr4; + + // + // Set default SMM page attribute + // + PageSize = SmmPageSize2M; + NumOfPages = 1; + PageAttribute = 0; + + EndBit = 0; + PageTableTop = (UINT64 *)(AsmReadCr3 () & gPhyMask); + PFAddress = AsmReadCr2 (); + + Cr4.UintN = AsmReadCr4 (); + Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 != 0); + + Status = GetPlatformPageTableAttribute (PFAddress, &PageSize, &NumOfPages, &PageAttribute); + // + // If platform not support page table attribute, set default SMM page attribute + // + if (Status != EFI_SUCCESS) { + PageSize = SmmPageSize2M; + NumOfPages = 1; + PageAttribute = 0; + } + + if (PageSize >= MaxSmmPageSizeType) { + PageSize = SmmPageSize2M; + } + + if (NumOfPages > 512) { + NumOfPages = 512; + } + + switch (PageSize) { + case SmmPageSize4K: + // + // BIT12 to BIT20 is Page Table index + // + EndBit = 12; + break; + case SmmPageSize2M: + // + // BIT21 to BIT29 is Page Directory index + // + EndBit = 21; + PageAttribute |= (UINTN)IA32_PG_PS; + break; + case SmmPageSize1G: + if (!m1GPageTableSupport) { + DEBUG ((DEBUG_ERROR, "1-GByte pages is not supported!")); + ASSERT (FALSE); + } + + // + // BIT30 to BIT38 is Page Directory Pointer Table index + // + EndBit = 30; + PageAttribute |= (UINTN)IA32_PG_PS; + break; + default: + ASSERT (FALSE); + } + + // + // If execute-disable is enabled, set NX bit + // + if (mXdEnabled) { + PageAttribute |= IA32_PG_NX; + } + + for (Index = 0; Index < NumOfPages; Index++) { + PageTable = PageTableTop; + UpperEntry = NULL; + for (StartBit = Enable5LevelPaging ? 48 : 39; StartBit > 12; StartBit -= 9) { + PTIndex = BitFieldRead64 (PFAddress, StartBit, StartBit + 8); + + // + // Iterate through the page table to find the appropriate page table entry for page creation if one of the following cases is met: + // 1) StartBit > EndBit: The PageSize of current entry is bigger than the platform-specified PageSize granularity. + // 2) IA32_PG_P bit is 0 & IA32_PG_PS bit is not 0: The current entry is present and it's a non-leaf entry. + // + if ((StartBit > EndBit) || ((((PageTable[PTIndex] & IA32_PG_P) != 0) && ((PageTable[PTIndex] & IA32_PG_PS) == 0)))) { + if ((PageTable[PTIndex] & IA32_PG_P) == 0) { + // + // If the entry is not present, allocate one page from page pool for it + // + PageTable[PTIndex] = AllocPage () | mAddressEncMask | PAGE_ATTRIBUTE_BITS; + } else { + // + // Save the upper entry address + // + UpperEntry = PageTable + PTIndex; + } + + // + // BIT9 to BIT11 of entry is used to save access record, + // initialize value is 7 + // + PageTable[PTIndex] |= (UINT64)IA32_PG_A; + SetAccNum (PageTable + PTIndex, 7); + PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & gPhyMask); + } else { + // + // Found the appropriate entry. + // + break; + } + } + + PTIndex = BitFieldRead64 (PFAddress, StartBit, StartBit + 8); + + // + // Fill the new entry + // + PageTable[PTIndex] = ((PFAddress | mAddressEncMask) & gPhyMask & ~((1ull << StartBit) - 1)) | + PageAttribute | IA32_PG_A | PAGE_ATTRIBUTE_BITS; + if (UpperEntry != NULL) { + SetSubEntriesNum (UpperEntry, (GetSubEntriesNum (UpperEntry) + 1) & 0x1FF); + } + + // + // Get the next page address if we need to create more page tables + // + PFAddress += (1ull << StartBit); + } +} + /** Update page table to map the memory correctly in order to make the instruction which caused page fault execute successfully. And it also save the original page @@ -220,7 +370,7 @@ RestorePageTableAbove4G ( // // Create one entry in page table for page fault address. // - SmiDefaultPFHandler (); + SmmProfileMapPFAddress (); // // Find the page table entry created just now. // diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.h b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.h index 993e1dd63a..5249360a1a 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.h @@ -55,6 +55,8 @@ typedef struct _PEBS_RECORD { #pragma pack () +extern BOOLEAN m1GPageTableSupport; + #define PHYSICAL_ADDRESS_MASK ((1ull << 52) - SIZE_4KB) /** @@ -98,4 +100,57 @@ InitPagesForPFHandler ( VOID ); +/** + Set sub-entries number in entry. + + @param[in, out] Entry Pointer to entry + @param[in] SubEntryNum Sub-entries number based on 0: + 0 means there is 1 sub-entry under this entry + 0x1ff means there is 512 sub-entries under this entry + +**/ +VOID +SetSubEntriesNum ( + IN OUT UINT64 *Entry, + IN UINT64 SubEntryNum + ); + +/** + Return sub-entries number in entry. + + @param[in] Entry Pointer to entry + + @return Sub-entries number based on 0: + 0 means there is 1 sub-entry under this entry + 0x1ff means there is 512 sub-entries under this entry +**/ +UINT64 +GetSubEntriesNum ( + IN UINT64 *Entry + ); + +/** + Allocate free Page for PageFault handler use. + + @return Page address. + +**/ +UINT64 +AllocPage ( + VOID + ); + +/** + Set access record in entry. + + @param[in, out] Entry Pointer to entry + @param[in] Acc Access record value + +**/ +VOID +SetAccNum ( + IN OUT UINT64 *Entry, + IN UINT64 Acc + ); + #endif // _SMM_PROFILE_ARCH_H_ -- cgit