summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg
diff options
context:
space:
mode:
authorJiaxin Wu <jiaxin.wu@intel.com>2024-07-08 09:59:03 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2024-08-28 15:25:27 +0000
commit1816c78f43f5d2d309a2a2d91bf5e7412bab19b5 (patch)
treea93bbcb3826d85cb64514dfa1c69be2380a13db9 /UefiCpuPkg
parent5bcf6049f2f09f52f837d9b37607ed52c0153cd3 (diff)
downloadedk2-1816c78f43f5d2d309a2a2d91bf5e7412bab19b5.tar.gz
UefiCpuPkg/PiSmmCpuDxeSmm: Refine DxeSmm PageTable update logic
This patch is to refine the updatePageTable logic for DxeSmm. For DxeSmm, PageTable will be updated in the first SMI when SMM ready to lock happen: IF SMM Profile is TRUE: 1. Mark mProtectionMemRange attribute: SmrrBase:Present, SMM profile base:Present&Nx, MMRAM ranges:Present, MMIO ranges: Present&Nx. 2. Mark the ranges not in mProtectionMemRange as RP (non-present). IF SMM Profile is FALSE: 1. Mark Non-MMRAM ranges as NX. 2. IF RestrictedMemoryAccess is TRUE: Forbidden Address mark as RP (IsUefiPageNotPresent is TRUE). 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.c192
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h17
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c13
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c92
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h4
5 files changed, 174 insertions, 144 deletions
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c
index 27f159b98c..51f0edd296 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c
@@ -311,116 +311,170 @@ GetUefiMemoryMap (
}
/**
- This function sets UEFI memory attribute according to UEFI memory map.
+ This function updates UEFI memory attribute according to UEFI memory map.
- The normal memory region is marked as not present, such as
- EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
- EfiUnusableMemory, EfiACPIReclaimMemory.
**/
VOID
-SetUefiMemMapAttributes (
+UpdateUefiMemMapAttributes (
VOID
)
{
+ BOOLEAN WriteProtect;
+ BOOLEAN CetEnabled;
EFI_STATUS Status;
+ UINTN Index;
+ UINT64 Limit;
+ UINT64 PreviousAddress;
+ UINTN PageTable;
+ UINT64 Base;
EFI_MEMORY_DESCRIPTOR *MemoryMap;
UINTN MemoryMapEntryCount;
- UINTN Index;
EFI_MEMORY_DESCRIPTOR *Entry;
- BOOLEAN WriteProtect;
- BOOLEAN CetEnabled;
- PERF_FUNCTION_BEGIN ();
-
- DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));
+ DEBUG ((DEBUG_INFO, "UpdateUefiMemMapAttributes Start...\n"));
WRITE_UNPROTECT_RO_PAGES (WriteProtect, CetEnabled);
- if (mUefiMemoryMap != NULL) {
- MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;
- MemoryMap = mUefiMemoryMap;
- for (Index = 0; Index < MemoryMapEntryCount; Index++) {
- if (IsUefiPageNotPresent (MemoryMap)) {
- Status = SmmSetMemoryAttributes (
- MemoryMap->PhysicalStart,
- EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
- EFI_MEMORY_RP
- );
- DEBUG ((
- DEBUG_INFO,
- "UefiMemory protection: 0x%lx - 0x%lx %r\n",
- MemoryMap->PhysicalStart,
- MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
- Status
- ));
- }
-
- MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, mUefiDescriptorSize);
- }
- }
+ PageTable = AsmReadCr3 ();
+ Limit = LShiftU64 (1, mPhysicalAddressBits);
//
- // Do not free mUefiMemoryMap, it will be checked in IsSmmCommBufferForbiddenAddress().
+ // [0, 4k] may be non-present.
//
+ PreviousAddress = ((FixedPcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) ? BASE_4KB : 0;
//
- // Set untested memory as not present.
+ // NonMmram shall be non-executable after the SmmReadyToLock event occurs, regardless of whether
+ // RestrictedMemoryAccess is enabled, since all MM drivers located in NonMmram have already been dispatched and executed.
//
- if (mGcdMemSpace != NULL) {
- for (Index = 0; Index < mGcdMemNumberOfDesc; Index++) {
- Status = SmmSetMemoryAttributes (
- mGcdMemSpace[Index].BaseAddress,
- mGcdMemSpace[Index].Length,
- EFI_MEMORY_RP
- );
- DEBUG ((
- DEBUG_INFO,
- "GcdMemory protection: 0x%lx - 0x%lx %r\n",
- mGcdMemSpace[Index].BaseAddress,
- mGcdMemSpace[Index].BaseAddress + mGcdMemSpace[Index].Length,
- Status
- ));
+ for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {
+ Base = mSmmCpuSmramRanges[Index].CpuStart;
+ if (Base > PreviousAddress) {
+ Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Base - PreviousAddress, EFI_MEMORY_XP, TRUE, NULL);
+ ASSERT_RETURN_ERROR (Status);
}
+
+ PreviousAddress = mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize;
}
- //
- // Do not free mGcdMemSpace, it will be checked in IsSmmCommBufferForbiddenAddress().
- //
+ if (PreviousAddress < Limit) {
+ Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Limit - PreviousAddress, EFI_MEMORY_XP, TRUE, NULL);
+ ASSERT_RETURN_ERROR (Status);
+ }
//
- // Set UEFI runtime memory with EFI_MEMORY_RO as not present.
+ // Set NonMmram to not-present by excluding "RT, Reserved and NVS" memory type when RestrictedMemoryAccess is enabled.
//
- if (mUefiMemoryAttributesTable != NULL) {
- Entry = (EFI_MEMORY_DESCRIPTOR *)(mUefiMemoryAttributesTable + 1);
- for (Index = 0; Index < mUefiMemoryAttributesTable->NumberOfEntries; Index++) {
- if ((Entry->Type == EfiRuntimeServicesCode) || (Entry->Type == EfiRuntimeServicesData)) {
- if ((Entry->Attribute & EFI_MEMORY_RO) != 0) {
- Status = SmmSetMemoryAttributes (
- Entry->PhysicalStart,
- EFI_PAGES_TO_SIZE ((UINTN)Entry->NumberOfPages),
- EFI_MEMORY_RP
+ if (IsRestrictedMemoryAccess ()) {
+ if (mUefiMemoryMap != NULL) {
+ MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;
+ MemoryMap = mUefiMemoryMap;
+ for (Index = 0; Index < MemoryMapEntryCount; Index++) {
+ if (IsUefiPageNotPresent (MemoryMap)) {
+ Status = ConvertMemoryPageAttributes (
+ PageTable,
+ mPagingMode,
+ MemoryMap->PhysicalStart,
+ EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
+ EFI_MEMORY_RP,
+ TRUE,
+ NULL
);
DEBUG ((
DEBUG_INFO,
- "UefiMemoryAttribute protection: 0x%lx - 0x%lx %r\n",
- Entry->PhysicalStart,
- Entry->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE ((UINTN)Entry->NumberOfPages),
+ "UefiMemory protection: 0x%lx - 0x%lx %r\n",
+ MemoryMap->PhysicalStart,
+ MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
Status
));
}
+
+ MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, mUefiDescriptorSize);
+ }
+ }
+
+ //
+ // Do not free mUefiMemoryMap, it will be checked in IsSmmCommBufferForbiddenAddress().
+ //
+
+ //
+ // Set untested NonMmram memory as not present.
+ //
+ if (mGcdMemSpace != NULL) {
+ for (Index = 0; Index < mGcdMemNumberOfDesc; Index++) {
+ Status = ConvertMemoryPageAttributes (
+ PageTable,
+ mPagingMode,
+ mGcdMemSpace[Index].BaseAddress,
+ mGcdMemSpace[Index].Length,
+ EFI_MEMORY_RP,
+ TRUE,
+ NULL
+ );
+ DEBUG ((
+ DEBUG_INFO,
+ "GcdMemory protection: 0x%lx - 0x%lx %r\n",
+ mGcdMemSpace[Index].BaseAddress,
+ mGcdMemSpace[Index].BaseAddress + mGcdMemSpace[Index].Length,
+ Status
+ ));
}
+ }
+
+ //
+ // Do not free mGcdMemSpace, it will be checked in IsSmmCommBufferForbiddenAddress().
+ //
+
+ //
+ // Above logic sets the whole RT memory as present.
+ // Below logic is to set the RT code as not present.
+ //
+ if (mUefiMemoryAttributesTable != NULL) {
+ Entry = (EFI_MEMORY_DESCRIPTOR *)(mUefiMemoryAttributesTable + 1);
+ for (Index = 0; Index < mUefiMemoryAttributesTable->NumberOfEntries; Index++) {
+ if ((Entry->Type == EfiRuntimeServicesCode) || (Entry->Type == EfiRuntimeServicesData)) {
+ if ((Entry->Attribute & EFI_MEMORY_RO) != 0) {
+ Status = ConvertMemoryPageAttributes (
+ PageTable,
+ mPagingMode,
+ Entry->PhysicalStart,
+ EFI_PAGES_TO_SIZE ((UINTN)Entry->NumberOfPages),
+ EFI_MEMORY_RP,
+ TRUE,
+ NULL
+ );
+ DEBUG ((
+ DEBUG_INFO,
+ "UefiMemoryAttribute protection: 0x%lx - 0x%lx %r\n",
+ Entry->PhysicalStart,
+ Entry->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE ((UINTN)Entry->NumberOfPages),
+ Status
+ ));
+ }
+ }
- Entry = NEXT_MEMORY_DESCRIPTOR (Entry, mUefiMemoryAttributesTable->DescriptorSize);
+ Entry = NEXT_MEMORY_DESCRIPTOR (Entry, mUefiMemoryAttributesTable->DescriptorSize);
+ }
}
+
+ //
+ // Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress().
+ //
}
- WRITE_PROTECT_RO_PAGES (WriteProtect, CetEnabled);
+ //
+ // Flush TLB
+ //
+ CpuFlushTlb ();
//
- // Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress().
+ // Set execute-disable flag
//
+ mXdEnabled = TRUE;
+
+ WRITE_PROTECT_RO_PAGES (WriteProtect, CetEnabled);
- PERF_FUNCTION_END ();
+ DEBUG ((DEBUG_INFO, "UpdateUefiMemMapAttributes Done.\n"));
}
/**
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h
index 73ace4efa4..ec3f32e381 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h
@@ -959,14 +959,6 @@ SetMemMapAttributes (
);
/**
- This function sets UEFI memory attribute according to UEFI memory map.
-**/
-VOID
-SetUefiMemMapAttributes (
- VOID
- );
-
-/**
Get SmmProfileData.
@param[in, out] Size Return Size of SmmProfileData.
@@ -1038,6 +1030,15 @@ CreateNonMmramMemMap (
);
/**
+ This function updates UEFI memory attribute according to UEFI memory map.
+
+**/
+VOID
+UpdateUefiMemMapAttributes (
+ VOID
+ );
+
+/**
This function caches the UEFI memory map information.
**/
VOID
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
index 93bb67ce7a..579f5bd985 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
@@ -58,9 +58,13 @@ PerformRemainingTasks (
}
//
- // Create a mix of 2MB and 4KB page table. Update some memory ranges absent and execute-disable.
+ // Update Page Table for outside SMRAM.
//
- InitPaging ();
+ if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
+ SmmProfileUpdateMemoryAttributes ();
+ } else {
+ UpdateUefiMemMapAttributes ();
+ }
//
// gEdkiiPiSmmMemoryAttributesTableGuid should have been published at EndOfDxe by SmmCore
@@ -78,11 +82,6 @@ PerformRemainingTasks (
if (IsRestrictedMemoryAccess ()) {
//
- // For outside SMRAM, we only map SMM communication buffer or MMIO.
- //
- SetUefiMemMapAttributes ();
-
- //
// Set page table itself to be read-only
//
SetPageTableAttributes ();
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
index 0e95fc0eb3..44f67cc38b 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
@@ -573,11 +573,11 @@ InitProtectedMemRange (
}
/**
- Update page table according to protected memory ranges and the 4KB-page mapped memory ranges.
+ This function updates memory attribute according to mProtectionMemRangeCount.
**/
VOID
-InitPaging (
+SmmProfileUpdateMemoryAttributes (
VOID
)
{
@@ -592,91 +592,67 @@ InitPaging (
BOOLEAN WriteProtect;
BOOLEAN CetEnabled;
- PERF_FUNCTION_BEGIN ();
+ DEBUG ((DEBUG_INFO, "SmmProfileUpdateMemoryAttributes Start...\n"));
+
+ WRITE_UNPROTECT_RO_PAGES (WriteProtect, CetEnabled);
PageTable = AsmReadCr3 ();
Limit = LShiftU64 (1, mPhysicalAddressBits);
- WRITE_UNPROTECT_RO_PAGES (WriteProtect, CetEnabled);
-
//
// [0, 4k] may be non-present.
//
PreviousAddress = ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) ? BASE_4KB : 0;
- 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;
- }
-
- if (mProtectionMemRange[Index].Present == FALSE) {
- MemoryAttrMask = EFI_MEMORY_RP;
- }
-
- 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);
- }
-
- 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);
- }
+ for (Index = 0; Index < mProtectionMemRangeCount; Index++) {
+ MemoryAttrMask = 0;
+ if (mProtectionMemRange[Index].Nx == TRUE) {
+ MemoryAttrMask = EFI_MEMORY_XP;
+ }
- PreviousAddress = Base + Length;
+ if (mProtectionMemRange[Index].Present == FALSE) {
+ MemoryAttrMask = EFI_MEMORY_RP;
}
- //
- // 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) {
- //
- // Mark the ranges not in mSmmCpuSmramRanges as NX.
- //
- Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Base - PreviousAddress, MemoryAttrMask, TRUE, NULL);
- ASSERT_RETURN_ERROR (Status);
- }
+ 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);
+ }
- PreviousAddress = mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize;
+ if (Base > PreviousAddress) {
+ //
+ // Mark the ranges not in mProtectionMemRange as non-present.
+ //
+ Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Base - PreviousAddress, EFI_MEMORY_RP, TRUE, NULL);
+ ASSERT_RETURN_ERROR (Status);
}
+
+ PreviousAddress = Base + Length;
}
+ //
+ // Set the last remaining range
+ //
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);
+ Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, PreviousAddress, Limit - PreviousAddress, EFI_MEMORY_RP, TRUE, NULL);
ASSERT_RETURN_ERROR (Status);
}
- WRITE_PROTECT_RO_PAGES (WriteProtect, CetEnabled);
-
//
// Flush TLB
//
CpuFlushTlb ();
- DEBUG ((DEBUG_INFO, "Patch page table done!\n"));
+
//
// Set execute-disable flag
//
mXdEnabled = TRUE;
- PERF_FUNCTION_END ();
+ WRITE_PROTECT_RO_PAGES (WriteProtect, CetEnabled);
+
+ DEBUG ((DEBUG_INFO, "SmmProfileUpdateMemoryAttributes Done.\n"));
}
/**
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h
index fc4c2731a0..feddf6eec3 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h
@@ -100,11 +100,11 @@ InitProtectedMemRange (
);
/**
- Update page table according to protected memory ranges and the 4KB-page mapped memory ranges.
+ This function updates memory attribute according to mProtectionMemRangeCount.
**/
VOID
-InitPaging (
+SmmProfileUpdateMemoryAttributes (
VOID
);