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>
This commit is contained in:
Dun Tan 2024-07-31 15:20:14 +08:00 committed by mergify[bot]
parent cae90a8390
commit 8b8ac5d986
7 changed files with 221 additions and 166 deletions

View File

@ -82,18 +82,6 @@ AllocPage (
return 0; return 0;
} }
/**
Page Fault handler for SMM use.
**/
VOID
SmiDefaultPFHandler (
VOID
)
{
CpuDeadLoop ();
}
/** /**
ThePage Fault handler wrapper for SMM use. ThePage Fault handler wrapper for SMM use.

View File

@ -76,3 +76,15 @@ ClearTrapFlag (
{ {
SystemContext.SystemContextIa32->Eflags &= (UINTN) ~BIT8; SystemContext.SystemContextIa32->Eflags &= (UINTN) ~BIT8;
} }
/**
Create new entry in page table for page fault address in SmmProfilePFHandler.
**/
VOID
SmmProfileMapPFAddress (
VOID
)
{
CpuDeadLoop ();
}

View File

@ -1337,7 +1337,7 @@ SmmProfilePFHandler (
// //
// If SMM profile does not start, call original page fault handler. // If SMM profile does not start, call original page fault handler.
// //
SmiDefaultPFHandler (); SmmProfileMapPFAddress ();
return; return;
} }

View File

@ -153,11 +153,11 @@ AllocPage (
); );
/** /**
Page Fault handler for SMM use. Create new entry in page table for page fault address in SmmProfilePFHandler.
**/ **/
VOID VOID
SmiDefaultPFHandler ( SmmProfileMapPFAddress (
VOID VOID
); );

View File

@ -700,156 +700,6 @@ AllocPage (
return RetVal; 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. ThePage Fault handler wrapper for SMM use.

View File

@ -109,6 +109,156 @@ AcquirePage (
mPFPageIndex = (mPFPageIndex + 1) % MAX_PF_PAGE_COUNT; 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 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 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. // Create one entry in page table for page fault address.
// //
SmiDefaultPFHandler (); SmmProfileMapPFAddress ();
// //
// Find the page table entry created just now. // Find the page table entry created just now.
// //

View File

@ -55,6 +55,8 @@ typedef struct _PEBS_RECORD {
#pragma pack () #pragma pack ()
extern BOOLEAN m1GPageTableSupport;
#define PHYSICAL_ADDRESS_MASK ((1ull << 52) - SIZE_4KB) #define PHYSICAL_ADDRESS_MASK ((1ull << 52) - SIZE_4KB)
/** /**
@ -98,4 +100,57 @@ InitPagesForPFHandler (
VOID 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_ #endif // _SMM_PROFILE_ARCH_H_