summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg/PiSmmCpuDxeSmm
diff options
context:
space:
mode:
authorDun Tan <dun.tan@intel.com>2024-07-31 15:20:14 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2024-08-05 06:59:09 +0000
commit8b8ac5d986dd78ee729a3fd32c833ff2235feeb9 (patch)
tree08d4453bd69b056486335c6c5e171adec685f343 /UefiCpuPkg/PiSmmCpuDxeSmm
parentcae90a83907d5f9e10c45cd2985bab1fafc47f56 (diff)
downloadedk2-8b8ac5d986dd78ee729a3fd32c833ff2235feeb9.tar.gz
edk2-8b8ac5d986dd78ee729a3fd32c833ff2235feeb9.tar.bz2
edk2-8b8ac5d986dd78ee729a3fd32c833ff2235feeb9.zip
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 <dun.tan@intel.com>
Diffstat (limited to 'UefiCpuPkg/PiSmmCpuDxeSmm')
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c12
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmProfileArch.c12
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c2
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h4
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c150
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.c152
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmProfileArch.h55
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
@@ -83,18 +83,6 @@ AllocPage (
}
/**
- Page Fault handler for SMM use.
-
-**/
-VOID
-SmiDefaultPFHandler (
- VOID
- )
-{
- CpuDeadLoop ();
-}
-
-/**
ThePage Fault handler wrapper for SMM use.
@param InterruptType Defines the type of interrupt or exception that
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
@@ -701,156 +701,6 @@ AllocPage (
}
/**
- 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.
@param InterruptType Defines the type of interrupt or exception that
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
@@ -110,6 +110,156 @@ AcquirePage (
}
/**
+ 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
table to be restored in single-step exception.
@@ -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_