diff options
author | Jiaxin Wu <jiaxin.wu@intel.com> | 2024-06-26 14:49:01 +0800 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2024-08-28 15:25:27 +0000 |
commit | 1c19ccd5103b918efef9c4076e92d175cfba8d81 (patch) | |
tree | fd06434cd0b8388d522436e9b1583f98a0401914 /UefiCpuPkg | |
parent | 14cb36685bdc260d67c119a81f55e49a1f8e0ca3 (diff) | |
download | edk2-1c19ccd5103b918efef9c4076e92d175cfba8d81.tar.gz |
UefiCpuPkg/PiSmmCpuDxeSmm: Refactor code to create default Page Table
For MM:
Since all accessible NON-MMRAM memory and attribute shall be in
ResourceDescriptor HOBs for MM, the page table for MM can be finalized
and created in the default Page.
For SMM:
There are still 2 steps for the finalized default Page:
1. Create default Page
2. update the page table in the first SMI when SMM ready to lock
happen
This patch to refactor the GenSmmPageTable() function to create the
default Page Table for Both SMM and MM:
1. Create NonMmram MemoryRegion
2. Gen NonMmram MemoryRegion PageTable
3. Gen MMRAM Range PageTable
4. Consider PcdCpuSmmStackGuard & PcdNullPointerDetectionPropertyMask
cases.
Meanwhile, mXdSupported needs to be initialized before GenSmmPageTable since
it's required by GenSmmPageTable function. So, move the mXdSupported init
from CheckFeatureSupported to the common EntryPoint function.
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Dun Tan <dun.tan@intel.com>
Cc: Hongbin1 Zhang <hongbin1.zhang@intel.com>
Cc: Wei6 Xu <wei6.xu@intel.com>
Cc: Yuanhao Xie <yuanhao.xie@intel.com>
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r-- | UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c | 67 | ||||
-rw-r--r-- | UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapStandaloneMm.c | 20 | ||||
-rw-r--r-- | UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c | 57 | ||||
-rw-r--r-- | UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h | 21 | ||||
-rw-r--r-- | UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 166 | ||||
-rw-r--r-- | UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c | 27 | ||||
-rw-r--r-- | UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h | 5 |
7 files changed, 289 insertions, 74 deletions
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c index be5b333cd1..8dbcd8d950 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c @@ -601,3 +601,70 @@ CreateExtendedProtectionRange ( return;
}
+
+/**
+ Create the Non-Mmram Memory Region.
+ Build MemoryRegion to cover [0, 2^PhysicalAddressBits) by excluding all Smram range.
+ The memory attribute is all-allowed (read/write/executable).
+
+ The caller is responsible for freeing MemoryRegion via FreePool().
+
+ @param[in] PhysicalAddressBits The bits of physical address to map.
+ @param[out] MemoryRegion Returned Non-Mmram Memory regions.
+ @param[out] MemoryRegionCount A pointer to the number of Memory regions.
+**/
+VOID
+CreateNonMmramMemMap (
+ IN UINT8 PhysicalAddressBits,
+ OUT MM_CPU_MEMORY_REGION **MemoryRegion,
+ OUT UINTN *MemoryRegionCount
+ )
+{
+ UINT64 MaxLength;
+ UINTN Count;
+ UINTN Index;
+ UINT64 PreviousAddress;
+ UINT64 Base;
+ UINT64 Length;
+
+ ASSERT (MemoryRegion != NULL && MemoryRegionCount != NULL);
+
+ *MemoryRegion = NULL;
+ *MemoryRegionCount = 0;
+
+ MaxLength = LShiftU64 (1, PhysicalAddressBits);
+
+ //
+ // Build MemoryRegion to cover [0, 2^PhysicalAddressBits) by excluding all Smram range
+ //
+ Count = mSmmCpuSmramRangeCount + 1;
+
+ *MemoryRegionCount = Count;
+
+ *MemoryRegion = (MM_CPU_MEMORY_REGION *)AllocateZeroPool (sizeof (MM_CPU_MEMORY_REGION) * Count);
+ ASSERT (*MemoryRegion != NULL);
+
+ PreviousAddress = 0;
+ for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {
+ Base = mSmmCpuSmramRanges[Index].CpuStart;
+ Length = mSmmCpuSmramRanges[Index].PhysicalSize;
+
+ ASSERT (MaxLength > Base + Length);
+
+ if (Base > PreviousAddress) {
+ (*MemoryRegion)[Index].Base = PreviousAddress;
+ (*MemoryRegion)[Index].Length = Base - PreviousAddress;
+ (*MemoryRegion)[Index].Attribute = 0;
+ }
+
+ PreviousAddress = Base + Length;
+ }
+
+ //
+ // Set the last remaining range
+ //
+ if (PreviousAddress < MaxLength) {
+ (*MemoryRegion)[Index].Base = PreviousAddress;
+ (*MemoryRegion)[Index].Length = MaxLength - PreviousAddress;
+ }
+}
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapStandaloneMm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapStandaloneMm.c index 3ae074c63d..8c5286b744 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapStandaloneMm.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapStandaloneMm.c @@ -156,3 +156,23 @@ CreateExtendedProtectionRange ( {
BuildMemoryMapFromResDescHobs (MemoryRegion, MemoryRegionCount);
}
+
+/**
+ Create the Non-Mmram Memory Region within the ResourceDescriptor HOBs
+ without Logging attribute.
+
+ The caller is responsible for freeing MemoryRegion via FreePool().
+
+ @param[in] PhysicalAddressBits The bits of physical address to map.
+ @param[out] MemoryRegion Returned Non-Mmram Memory regions.
+ @param[out] MemoryRegionCount A pointer to the number of Memory regions.
+**/
+VOID
+CreateNonMmramMemMap (
+ IN UINT8 PhysicalAddressBits,
+ OUT MM_CPU_MEMORY_REGION **MemoryRegion,
+ OUT UINTN *MemoryRegionCount
+ )
+{
+ BuildMemoryMapFromResDescHobs (MemoryRegion, MemoryRegionCount);
+}
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c index ecb16454ca..ba559afae6 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c @@ -728,19 +728,20 @@ PiSmmCpuEntryCommon ( VOID
)
{
- EFI_STATUS Status;
- UINTN Index;
- UINTN TileCodeSize;
- UINTN TileDataSize;
- UINTN TileSize;
- UINT8 *Stacks;
- UINT32 RegEax;
- UINT32 RegEbx;
- UINT32 RegEcx;
- UINT32 RegEdx;
- UINTN FamilyId;
- UINTN ModelId;
- UINT32 Cr3;
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN TileCodeSize;
+ UINTN TileDataSize;
+ UINTN TileSize;
+ UINT8 *Stacks;
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+ CPUID_EXTENDED_CPU_SIG_EDX ExtendedRegEdx;
+ UINTN FamilyId;
+ UINTN ModelId;
+ UINT32 Cr3;
PERF_FUNCTION_BEGIN ();
@@ -929,6 +930,36 @@ PiSmmCpuEntryCommon ( }
//
+ // Check XD supported or not.
+ //
+ RegEax = 0;
+ ExtendedRegEdx.Uint32 = 0;
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax <= CPUID_EXTENDED_FUNCTION) {
+ //
+ // Extended CPUID functions are not supported on this processor.
+ //
+ mXdSupported = FALSE;
+ PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);
+ }
+
+ AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &ExtendedRegEdx.Uint32);
+ if (ExtendedRegEdx.Bits.NX == 0) {
+ //
+ // Execute Disable Bit feature is not supported on this processor.
+ //
+ mXdSupported = FALSE;
+ PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);
+ }
+
+ if (StandardSignatureIsAuthenticAMD ()) {
+ //
+ // AMD processors do not support MSR_IA32_MISC_ENABLE
+ //
+ PatchInstructionX86 (gPatchMsrIa32MiscEnableSupported, FALSE, 1);
+ }
+
+ //
// Compute tile size of buffer required to hold the CPU SMRAM Save State Map, extra CPU
// specific context start starts at SMBASE + SMM_PSD_OFFSET, and the SMI entry point.
// This size is rounded up to nearest power of 2.
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h index 475da8f1d7..5b2202490e 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h @@ -959,7 +959,7 @@ IsSmmCommBufferForbiddenAddress ( IN UINT64 Address
);
-/*
+/**
Build extended protection MemoryRegion.
The caller is responsible for freeing MemoryRegion via FreePool().
@@ -967,7 +967,7 @@ IsSmmCommBufferForbiddenAddress ( @param[out] MemoryRegion Returned Non-Mmram Memory regions.
@param[out] MemoryRegionCount A pointer to the number of Memory regions.
-*/
+**/
VOID
CreateExtendedProtectionRange (
OUT MM_CPU_MEMORY_REGION **MemoryRegion,
@@ -975,6 +975,23 @@ CreateExtendedProtectionRange ( );
/**
+ Create the Non-Mmram Memory Region.
+
+ The caller is responsible for freeing MemoryRegion via FreePool().
+
+ @param[in] PhysicalAddressBits The bits of physical address to map.
+ @param[out] MemoryRegion Returned Non-Mmram Memory regions.
+ @param[out] MemoryRegionCount A pointer to the number of Memory regions.
+
+**/
+VOID
+CreateNonMmramMemMap (
+ IN UINT8 PhysicalAddressBits,
+ OUT MM_CPU_MEMORY_REGION **MemoryRegion,
+ OUT UINTN *MemoryRegionCount
+ );
+
+/**
This function caches the UEFI memory map information.
**/
VOID
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c index 76eaaec981..cf1e49d89b 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c @@ -1170,6 +1170,64 @@ EdkiiSmmClearMemoryAttributes ( }
/**
+ Create page table based on input PagingMode, LinearAddress and Length.
+
+ @param[in, out] PageTable The pointer to the page table.
+ @param[in] PagingMode The paging mode.
+ @param[in] LinearAddress The start of the linear address range.
+ @param[in] Length The length of the linear address range.
+ @param[in] MapAttribute The MapAttribute of the linear address range
+ @param[in] MapMask The MapMask used for attribute. The corresponding field in Attribute is ignored if that in MapMask is 0.
+
+**/
+VOID
+GenPageTable (
+ IN OUT UINTN *PageTable,
+ IN PAGING_MODE PagingMode,
+ IN UINT64 LinearAddress,
+ IN UINT64 Length,
+ IN IA32_MAP_ATTRIBUTE MapAttribute,
+ IN IA32_MAP_ATTRIBUTE MapMask
+ )
+{
+ RETURN_STATUS Status;
+ UINTN PageTableBufferSize;
+ VOID *PageTableBuffer;
+
+ PageTableBufferSize = 0;
+
+ Status = PageTableMap (
+ PageTable,
+ PagingMode,
+ NULL,
+ &PageTableBufferSize,
+ LinearAddress,
+ Length,
+ &MapAttribute,
+ &MapMask,
+ NULL
+ );
+ if (Status == RETURN_BUFFER_TOO_SMALL) {
+ PageTableBuffer = AllocatePageTableMemory (EFI_SIZE_TO_PAGES (PageTableBufferSize));
+ ASSERT (PageTableBuffer != NULL);
+ Status = PageTableMap (
+ PageTable,
+ PagingMode,
+ PageTableBuffer,
+ &PageTableBufferSize,
+ LinearAddress,
+ Length,
+ &MapAttribute,
+ &MapMask,
+ NULL
+ );
+ }
+
+ ASSERT (Status == RETURN_SUCCESS);
+ ASSERT (PageTableBufferSize == 0);
+}
+
+/**
Create page table based on input PagingMode and PhysicalAddressBits in smm.
@param[in] PagingMode The paging mode.
@@ -1184,35 +1242,85 @@ GenSmmPageTable ( IN UINT8 PhysicalAddressBits
)
{
- UINTN PageTableBufferSize;
- UINTN PageTable;
- VOID *PageTableBuffer;
- IA32_MAP_ATTRIBUTE MapAttribute;
- IA32_MAP_ATTRIBUTE MapMask;
- RETURN_STATUS Status;
- UINTN GuardPage;
- UINTN Index;
- UINT64 Length;
-
- Length = LShiftU64 (1, PhysicalAddressBits);
- PageTable = 0;
- PageTableBufferSize = 0;
- MapMask.Uint64 = MAX_UINT64;
- MapAttribute.Uint64 = mAddressEncMask;
- MapAttribute.Bits.Present = 1;
- MapAttribute.Bits.ReadWrite = 1;
- MapAttribute.Bits.UserSupervisor = 1;
- MapAttribute.Bits.Accessed = 1;
- MapAttribute.Bits.Dirty = 1;
-
- Status = PageTableMap (&PageTable, PagingMode, NULL, &PageTableBufferSize, 0, Length, &MapAttribute, &MapMask, NULL);
- ASSERT (Status == RETURN_BUFFER_TOO_SMALL);
- DEBUG ((DEBUG_INFO, "GenSMMPageTable: 0x%x bytes needed for initial SMM page table\n", PageTableBufferSize));
- PageTableBuffer = AllocatePageTableMemory (EFI_SIZE_TO_PAGES (PageTableBufferSize));
- ASSERT (PageTableBuffer != NULL);
- Status = PageTableMap (&PageTable, PagingMode, PageTableBuffer, &PageTableBufferSize, 0, Length, &MapAttribute, &MapMask, NULL);
- ASSERT (Status == RETURN_SUCCESS);
- ASSERT (PageTableBufferSize == 0);
+ UINTN PageTable;
+ UINTN Index;
+ MM_CPU_MEMORY_REGION *MemoryRegion;
+ UINTN MemoryRegionCount;
+ IA32_MAP_ATTRIBUTE MapAttribute;
+ IA32_MAP_ATTRIBUTE MapMask;
+ RETURN_STATUS Status;
+ UINTN GuardPage;
+
+ PageTable = 0;
+ MemoryRegion = NULL;
+ MemoryRegionCount = 0;
+ MapMask.Uint64 = MAX_UINT64;
+
+ //
+ // 1. Create NonMmram MemoryRegion
+ //
+ CreateNonMmramMemMap (PhysicalAddressBits, &MemoryRegion, &MemoryRegionCount);
+ ASSERT (MemoryRegion != NULL && MemoryRegionCount != 0);
+
+ //
+ // 2. Gen NonMmram MemoryRegion PageTable
+ //
+ for (Index = 0; Index < MemoryRegionCount; Index++) {
+ ASSERT (MemoryRegion[Index].Base % SIZE_4KB == 0);
+ ASSERT (MemoryRegion[Index].Length % EFI_PAGE_SIZE == 0);
+
+ //
+ // Set the MapAttribute
+ //
+ MapAttribute.Uint64 = mAddressEncMask|MemoryRegion[Index].Base;
+ MapAttribute.Bits.Present = 1;
+ MapAttribute.Bits.ReadWrite = 1;
+ MapAttribute.Bits.UserSupervisor = 1;
+ MapAttribute.Bits.Accessed = 1;
+ MapAttribute.Bits.Dirty = 1;
+
+ //
+ // Update the MapAttribute according MemoryRegion[Index].Attribute
+ //
+ if ((MemoryRegion[Index].Attribute & EFI_MEMORY_RO) != 0) {
+ MapAttribute.Bits.ReadWrite = 0;
+ }
+
+ if ((MemoryRegion[Index].Attribute & EFI_MEMORY_XP) != 0) {
+ if (mXdSupported) {
+ MapAttribute.Bits.Nx = 1;
+ }
+ }
+
+ GenPageTable (&PageTable, PagingMode, MemoryRegion[Index].Base, (UINTN)MemoryRegion[Index].Length, MapAttribute, MapMask);
+ }
+
+ //
+ // Free the MemoryRegion after usage
+ //
+ if (MemoryRegion != NULL) {
+ FreePool (MemoryRegion);
+ }
+
+ //
+ // 3. Gen MMRAM Range PageTable
+ //
+ for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {
+ ASSERT (mSmmCpuSmramRanges[Index].CpuStart % SIZE_4KB == 0);
+ ASSERT (mSmmCpuSmramRanges[Index].PhysicalSize % EFI_PAGE_SIZE == 0);
+
+ //
+ // Set the MapAttribute
+ //
+ MapAttribute.Uint64 = mAddressEncMask|mSmmCpuSmramRanges[Index].CpuStart;
+ MapAttribute.Bits.Present = 1;
+ MapAttribute.Bits.ReadWrite = 1;
+ MapAttribute.Bits.UserSupervisor = 1;
+ MapAttribute.Bits.Accessed = 1;
+ MapAttribute.Bits.Dirty = 1;
+
+ GenPageTable (&PageTable, PagingMode, mSmmCpuSmramRanges[Index].CpuStart, mSmmCpuSmramRanges[Index].PhysicalSize, MapAttribute, MapMask);
+ }
if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
//
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c index f3ef4df0b0..ba83c37cbf 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c @@ -884,33 +884,6 @@ CheckFeatureSupported ( }
}
- if (mXdSupported) {
- AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
- if (RegEax <= CPUID_EXTENDED_FUNCTION) {
- //
- // Extended CPUID functions are not supported on this processor.
- //
- mXdSupported = FALSE;
- PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);
- }
-
- AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & CPUID1_EDX_XD_SUPPORT) == 0) {
- //
- // Execute Disable Bit feature is not supported on this processor.
- //
- mXdSupported = FALSE;
- PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);
- }
-
- if (StandardSignatureIsAuthenticAMD ()) {
- //
- // AMD processors do not support MSR_IA32_MISC_ENABLE
- //
- PatchInstructionX86 (gPatchMsrIa32MiscEnableSupported, FALSE, 1);
- }
- }
-
if (mBtsSupported) {
AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
if ((RegEdx & CPUID1_EDX_BTS_AVAILABLE) != 0) {
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h index 2edfd7a8b2..e8f3f6492f 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h @@ -39,9 +39,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent //
// CPU generic definition
//
-#define CPUID1_EDX_XD_SUPPORT 0x100000
-#define MSR_EFER 0xc0000080
-#define MSR_EFER_XD 0x800
+#define MSR_EFER 0xc0000080
+#define MSR_EFER_XD 0x800
#define CPUID1_EDX_BTS_AVAILABLE 0x200000
|