From: "duntan" <dun.tan@intel.com>
To: devel@edk2.groups.io
Cc: Eric Dong <eric.dong@intel.com>, Ray Ni <ray.ni@intel.com>,
Rahul Kumar <rahul1.kumar@intel.com>,
Gerd Hoffmann <kraxel@redhat.com>
Subject: [Patch V5 13/14] UefiCpuPkg: Refinement to smm runtime InitPaging() code
Date: Thu, 8 Jun 2023 10:27:41 +0800 [thread overview]
Message-ID: <20230608022742.1292-14-dun.tan@intel.com> (raw)
In-Reply-To: <20230608022742.1292-1-dun.tan@intel.com>
This commit is code refinement to current smm runtime InitPaging()
page table update code. In InitPaging(), if PcdCpuSmmProfileEnable
is TRUE, use ConvertMemoryPageAttributes() API to map the range in
mProtectionMemRange to the attrbute recorded in the attribute field
of mProtectionMemRange, map the range outside mProtectionMemRange
as non-present. If PcdCpuSmmProfileEnable is FALSE, only need to
set the ranges not in mSmmCpuSmramRanges as NX.
Signed-off-by: Dun Tan <dun.tan@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
---
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h | 37 +++++++++++++++++++++++++++++++++++++
UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c | 293 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2 files changed, 101 insertions(+), 229 deletions(-)
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
index 5399659bc0..12ad86028e 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -725,6 +725,43 @@ SmmBlockingStartupThisAp (
IN OUT VOID *ProcArguments OPTIONAL
);
+/**
+ This function modifies the page attributes for the memory region specified by BaseAddress and
+ Length from their current attributes to the attributes specified by Attributes.
+
+ Caller should make sure BaseAddress and Length is at page boundary.
+
+ @param[in] PageTableBase The page table base.
+ @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.
+ @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.
+ @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
+
+ @retval RETURN_SUCCESS The attributes were modified for the memory region.
+ @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ @retval RETURN_INVALID_PARAMETER Length is zero.
+ Attributes specified an illegal combination of attributes that
+ cannot be set together.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
+ the memory resource range.
+ @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+**/
+RETURN_STATUS
+ConvertMemoryPageAttributes (
+ IN UINTN PageTableBase,
+ IN PAGING_MODE PagingMode,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes,
+ IN BOOLEAN IsSet,
+ OUT BOOLEAN *IsModified 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.
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
index 2a1f132b29..ab6b79ddf4 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
@@ -586,254 +586,89 @@ InitPaging (
VOID
)
{
- UINT64 Pml5Entry;
- UINT64 Pml4Entry;
- UINT64 *Pml5;
- UINT64 *Pml4;
- UINT64 *Pdpt;
- UINT64 *Pd;
- UINT64 *Pt;
- UINTN Address;
- UINTN Pml5Index;
- UINTN Pml4Index;
- UINTN PdptIndex;
- UINTN PdIndex;
- UINTN PtIndex;
- UINTN NumberOfPdptEntries;
- UINTN NumberOfPml4Entries;
- UINTN NumberOfPml5Entries;
- UINTN SizeOfMemorySpace;
- BOOLEAN Nx;
- IA32_CR4 Cr4;
- BOOLEAN Enable5LevelPaging;
- BOOLEAN WpEnabled;
- BOOLEAN CetEnabled;
-
- Cr4.UintN = AsmReadCr4 ();
- Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);
-
- if (sizeof (UINTN) == sizeof (UINT64)) {
- if (!Enable5LevelPaging) {
- Pml5Entry = (UINTN)mSmmProfileCr3 | IA32_PG_P;
- Pml5 = &Pml5Entry;
- } else {
- Pml5 = (UINT64 *)(UINTN)mSmmProfileCr3;
- }
-
- SizeOfMemorySpace = HighBitSet64 (gPhyMask) + 1;
- ASSERT (SizeOfMemorySpace <= 52);
-
- //
- // Calculate the table entries of PML5E, PML4E and PDPTE.
- //
- NumberOfPml5Entries = 1;
- if (SizeOfMemorySpace > 48) {
- if (Enable5LevelPaging) {
- NumberOfPml5Entries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 48);
- }
-
- SizeOfMemorySpace = 48;
- }
-
- NumberOfPml4Entries = 1;
- if (SizeOfMemorySpace > 39) {
- NumberOfPml4Entries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 39);
- SizeOfMemorySpace = 39;
- }
-
- NumberOfPdptEntries = 1;
- ASSERT (SizeOfMemorySpace > 30);
- NumberOfPdptEntries = (UINTN)LShiftU64 (1, SizeOfMemorySpace - 30);
+ RETURN_STATUS Status;
+ UINTN Index;
+ UINTN PageTable;
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Limit;
+ UINT64 PreviousAddress;
+ UINT64 MemoryAttrMask;
+ BOOLEAN WpEnabled;
+ BOOLEAN CetEnabled;
+
+ PageTable = AsmReadCr3 ();
+ if (sizeof (UINTN) == sizeof (UINT32)) {
+ Limit = BASE_4GB;
} else {
- Pml4Entry = (UINTN)mSmmProfileCr3 | IA32_PG_P;
- Pml4 = &Pml4Entry;
- Pml5Entry = (UINTN)Pml4 | IA32_PG_P;
- Pml5 = &Pml5Entry;
- NumberOfPml5Entries = 1;
- NumberOfPml4Entries = 1;
- NumberOfPdptEntries = 4;
+ Limit = (IsRestrictedMemoryAccess ()) ? LShiftU64 (1, mPhysicalAddressBits) : BASE_4GB;
}
DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
//
- // Go through page table and change 2MB-page into 4KB-page.
+ // [0, 4k] may be non-present.
//
- for (Pml5Index = 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) {
- if ((Pml5[Pml5Index] & IA32_PG_P) == 0) {
- //
- // If PML5 entry does not exist, skip it
- //
- continue;
- }
+ PreviousAddress = ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) ? BASE_4KB : 0;
- Pml4 = (UINT64 *)(UINTN)(Pml5[Pml5Index] & PHYSICAL_ADDRESS_MASK);
- for (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) {
- if ((Pml4[Pml4Index] & IA32_PG_P) == 0) {
- //
- // If PML4 entry does not exist, skip it
- //
- continue;
+ DEBUG ((DEBUG_INFO, "Patch page table start ...\n"));
+ if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
+ for (Index = 0; Index < mProtectionMemRangeCount; Index++) {
+ MemoryAttrMask = 0;
+ if (mProtectionMemRange[Index].Nx == TRUE) {
+ MemoryAttrMask |= EFI_MEMORY_XP;
}
- Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
- for (PdptIndex = 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pdpt++) {
- if ((*Pdpt & IA32_PG_P) == 0) {
- //
- // If PDPT entry does not exist, skip it
- //
- continue;
- }
-
- if ((*Pdpt & IA32_PG_PS) != 0) {
- //
- // This is 1G entry, skip it
- //
- continue;
- }
-
- Pd = (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
- if (Pd == 0) {
- continue;
- }
-
- for (PdIndex = 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, Pd++) {
- if ((*Pd & IA32_PG_P) == 0) {
- //
- // If PD entry does not exist, skip it
- //
- continue;
- }
-
- Address = (UINTN)LShiftU64 (
- LShiftU64 (
- LShiftU64 ((Pml5Index << 9) + Pml4Index, 9) + PdptIndex,
- 9
- ) + PdIndex,
- 21
- );
-
- //
- // If it is 2M page, check IsAddressSplit()
- //
- if (((*Pd & IA32_PG_PS) != 0) && IsAddressSplit (Address)) {
- //
- // Based on current page table, create 4KB page table for split area.
- //
- ASSERT (Address == (*Pd & PHYSICAL_ADDRESS_MASK));
-
- Pt = AllocatePageTableMemory (1);
- ASSERT (Pt != NULL);
+ if (mProtectionMemRange[Index].Present == FALSE) {
+ MemoryAttrMask = EFI_MEMORY_RP;
+ }
- // Split it
- for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof (*Pt); PtIndex++) {
- Pt[PtIndex] = Address + ((PtIndex << 12) | mAddressEncMask | PAGE_ATTRIBUTE_BITS);
- } // end for PT
+ Base = mProtectionMemRange[Index].Range.Base;
+ Length = mProtectionMemRange[Index].Range.Top - Base;
+ if (MemoryAttrMask != 0) {
+ Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, Base, Length, MemoryAttrMask, TRUE, NULL);
+ ASSERT_RETURN_ERROR (Status);
+ }
- *Pd = (UINT64)(UINTN)Pt | mAddressEncMask | PAGE_ATTRIBUTE_BITS;
- } // end if IsAddressSplit
- } // end for PD
- } // end for PDPT
- } // end for PML4
- } // end for PML5
+ if (Base > PreviousAddress) {
+ //
+ // Mark the ranges not in mProtectionMemRange as non-present.
+ //
+ MemoryAttrMask = EFI_MEMORY_RP;
+ Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Base - PreviousAddress, MemoryAttrMask, TRUE, NULL);
+ ASSERT_RETURN_ERROR (Status);
+ }
- //
- // Go through page table and set several page table entries to absent or execute-disable.
- //
- DEBUG ((DEBUG_INFO, "Patch page table start ...\n"));
- for (Pml5Index = 0; Pml5Index < NumberOfPml5Entries; Pml5Index++) {
- if ((Pml5[Pml5Index] & IA32_PG_P) == 0) {
- //
- // If PML5 entry does not exist, skip it
- //
- continue;
+ PreviousAddress = Base + Length;
}
- Pml4 = (UINT64 *)(UINTN)(Pml5[Pml5Index] & PHYSICAL_ADDRESS_MASK);
- for (Pml4Index = 0; Pml4Index < NumberOfPml4Entries; Pml4Index++) {
- if ((Pml4[Pml4Index] & IA32_PG_P) == 0) {
+ //
+ // This assignment is for setting the last remaining range
+ //
+ MemoryAttrMask = EFI_MEMORY_RP;
+ } else {
+ MemoryAttrMask = EFI_MEMORY_XP;
+ for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {
+ Base = mSmmCpuSmramRanges[Index].CpuStart;
+ if (Base > PreviousAddress) {
//
- // If PML4 entry does not exist, skip it
+ // Mark the ranges not in mSmmCpuSmramRanges as NX.
//
- continue;
+ Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Base - PreviousAddress, MemoryAttrMask, TRUE, NULL);
+ ASSERT_RETURN_ERROR (Status);
}
- Pdpt = (UINT64 *)(UINTN)(Pml4[Pml4Index] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
- for (PdptIndex = 0; PdptIndex < NumberOfPdptEntries; PdptIndex++, Pdpt++) {
- if ((*Pdpt & IA32_PG_P) == 0) {
- //
- // If PDPT entry does not exist, skip it
- //
- continue;
- }
-
- if ((*Pdpt & IA32_PG_PS) != 0) {
- //
- // This is 1G entry, set NX bit and skip it
- //
- if (mXdSupported) {
- *Pdpt = *Pdpt | IA32_PG_NX;
- }
-
- continue;
- }
-
- Pd = (UINT64 *)(UINTN)(*Pdpt & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
- if (Pd == 0) {
- continue;
- }
+ PreviousAddress = mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize;
+ }
+ }
- for (PdIndex = 0; PdIndex < SIZE_4KB / sizeof (*Pd); PdIndex++, Pd++) {
- if ((*Pd & IA32_PG_P) == 0) {
- //
- // If PD entry does not exist, skip it
- //
- continue;
- }
-
- Address = (UINTN)LShiftU64 (
- LShiftU64 (
- LShiftU64 ((Pml5Index << 9) + Pml4Index, 9) + PdptIndex,
- 9
- ) + PdIndex,
- 21
- );
-
- if ((*Pd & IA32_PG_PS) != 0) {
- // 2MB page
-
- if (!IsAddressValid (Address, &Nx)) {
- //
- // Patch to remove Present flag and RW flag
- //
- *Pd = *Pd & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);
- }
-
- if (Nx && mXdSupported) {
- *Pd = *Pd | IA32_PG_NX;
- }
- } else {
- // 4KB page
- Pt = (UINT64 *)(UINTN)(*Pd & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);
- if (Pt == 0) {
- continue;
- }
-
- for (PtIndex = 0; PtIndex < SIZE_4KB / sizeof (*Pt); PtIndex++, Pt++) {
- if (!IsAddressValid (Address, &Nx)) {
- *Pt = *Pt & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);
- }
-
- if (Nx && mXdSupported) {
- *Pt = *Pt | IA32_PG_NX;
- }
-
- Address += SIZE_4KB;
- } // end for PT
- } // end if PS
- } // end for PD
- } // end for PDPT
- } // end for PML4
- } // end for PML5
+ if (PreviousAddress < Limit) {
+ //
+ // Set the last remaining range to EFI_MEMORY_RP/EFI_MEMORY_XP.
+ // This path applies to both SmmProfile enable/disable case.
+ //
+ Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Limit - PreviousAddress, MemoryAttrMask, TRUE, NULL);
+ ASSERT_RETURN_ERROR (Status);
+ }
EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
--
2.31.1.windows.1
next prev parent reply other threads:[~2023-06-08 2:29 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-08 2:27 [Patch V5 00/14] Use CpuPageTableLib to create and update smm page table duntan
2023-06-08 2:27 ` [Patch V5 01/14] OvmfPkg:Remove code that apply AddressEncMask to non-leaf entry duntan
2023-06-08 10:33 ` Ni, Ray
2023-06-19 10:26 ` [edk2-devel] " Gerd Hoffmann
2023-06-08 2:27 ` [Patch V5 02/14] MdeModulePkg: Remove RO and NX protection when unset guard page duntan
2023-06-08 10:08 ` Ni, Ray
2023-06-08 12:18 ` [edk2-devel] " Ard Biesheuvel
2023-06-09 9:10 ` duntan
2023-06-08 2:27 ` [Patch V5 03/14] UefiCpuPkg: Use CpuPageTableLib to convert SMM paging attribute duntan
2023-06-08 10:24 ` Ni, Ray
2023-06-08 2:27 ` [Patch V5 04/14] UefiCpuPkg: Add DEBUG_CODE for special case when clear RP duntan
2023-06-08 10:33 ` Ni, Ray
2023-06-08 2:27 ` [Patch V5 05/14] UefiCpuPkg/PiSmmCpuDxeSmm: Avoid setting non-present range to RO/NX duntan
2023-06-08 10:32 ` [edk2-devel] " Ni, Ray
2023-06-08 2:27 ` [Patch V5 06/14] UefiCpuPkg/PiSmmCpuDxeSmm: Add 2 function to disable/enable CR0.WP duntan
2023-06-08 2:27 ` [Patch V5 07/14] UefiCpuPkg/PiSmmCpuDxeSmm: Clear CR0.WP before modify page table duntan
2023-06-08 2:27 ` [Patch V5 08/14] UefiCpuPkg: Extern mSmmShadowStackSize in PiSmmCpuDxeSmm.h duntan
2023-06-08 10:21 ` Ni, Ray
2023-06-08 2:27 ` [Patch V5 09/14] UefiCpuPkg: Add GenSmmPageTable() to create smm page table duntan
2023-06-08 10:16 ` Ni, Ray
2023-06-08 2:27 ` [Patch V5 10/14] UefiCpuPkg: Use GenSmmPageTable() to create Smm S3 " duntan
2023-06-08 2:27 ` [Patch V5 11/14] UefiCpuPkg: Sort mSmmCpuSmramRanges in FindSmramInfo duntan
2023-06-08 10:16 ` Ni, Ray
2023-06-08 2:27 ` [Patch V5 12/14] UefiCpuPkg: Sort mProtectionMemRange when ReadyToLock duntan
2023-06-08 10:17 ` Ni, Ray
2023-06-08 2:27 ` duntan [this message]
2023-06-08 10:18 ` [Patch V5 13/14] UefiCpuPkg: Refinement to smm runtime InitPaging() code Ni, Ray
2023-06-08 2:27 ` [Patch V5 14/14] UefiCpuPkg/PiSmmCpuDxeSmm: Remove unnecessary function duntan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230608022742.1292-14-dun.tan@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox