UefiCpuPkg/PiSmmCpuDxeSmm: Create extended protection MemRegion in func

MM can not use the gDS service, so move the extended protection
MemRegion creation into function. This can make InitProtectedMemRange()
to be a common function for both SMM and MM.

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>
This commit is contained in:
Jiaxin Wu 2024-06-24 23:53:34 +08:00 committed by mergify[bot]
parent d480f106a6
commit 0c037b5fa7
3 changed files with 191 additions and 99 deletions

View File

@ -523,3 +523,81 @@ IsSmmCommBufferForbiddenAddress (
return FALSE; return FALSE;
} }
/**
Create extended protection MemoryRegion.
Return all MMIO ranges that are reported in GCD service at EndOfDxe.
The caller is responsible for freeing MemoryRegion via FreePool().
@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,
OUT UINTN *MemoryRegionCount
)
{
UINTN Index;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
UINTN NumberOfSpaceDescriptors;
UINTN MemoryRegionIndex;
UINTN Count;
MemorySpaceMap = NULL;
NumberOfSpaceDescriptors = 0;
Count = 0;
ASSERT (MemoryRegion != NULL && MemoryRegionCount != NULL);
*MemoryRegion = NULL;
*MemoryRegionCount = 0;
//
// Get MMIO ranges from GCD.
//
gDS->GetMemorySpaceMap (
&NumberOfSpaceDescriptors,
&MemorySpaceMap
);
for (Index = 0; Index < NumberOfSpaceDescriptors; Index++) {
if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) {
if (ADDRESS_IS_ALIGNED (MemorySpaceMap[Index].BaseAddress, SIZE_4KB) &&
(MemorySpaceMap[Index].Length % SIZE_4KB == 0))
{
Count++;
} else {
//
// Skip the MMIO range that BaseAddress and Length are not 4k aligned since
// the minimum granularity of the page table is 4k
//
DEBUG ((
DEBUG_WARN,
"MMIO range [0x%lx, 0x%lx] is skipped since it is not 4k aligned.\n",
MemorySpaceMap[Index].BaseAddress,
MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length
));
}
}
}
*MemoryRegionCount = Count;
*MemoryRegion = (MM_CPU_MEMORY_REGION *)AllocateZeroPool (sizeof (MM_CPU_MEMORY_REGION) * Count);
ASSERT (*MemoryRegion != NULL);
MemoryRegionIndex = 0;
for (Index = 0; Index < NumberOfSpaceDescriptors; Index++) {
if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&
ADDRESS_IS_ALIGNED (MemorySpaceMap[Index].BaseAddress, SIZE_4KB) &&
(MemorySpaceMap[Index].Length % SIZE_4KB == 0))
{
(*MemoryRegion)[MemoryRegionIndex].Base = MemorySpaceMap[Index].BaseAddress;
(*MemoryRegion)[MemoryRegionIndex].Length = MemorySpaceMap[Index].Length;
MemoryRegionIndex++;
}
}
return;
}

View File

@ -479,6 +479,21 @@ extern UINT64 mAddressEncMask;
extern UINT64 mTimeoutTicker; extern UINT64 mTimeoutTicker;
extern UINT64 mTimeoutTicker2; extern UINT64 mTimeoutTicker2;
typedef struct {
///
/// Address of the first byte in the memory region.
///
EFI_PHYSICAL_ADDRESS Base;
///
/// Length in bytes of the memory region.
///
UINT64 Length;
///
/// Attributes of the memory region
///
UINT64 Attribute;
} MM_CPU_MEMORY_REGION;
/** /**
Create 4G PageTable in SMRAM. Create 4G PageTable in SMRAM.
@ -940,6 +955,21 @@ IsSmmCommBufferForbiddenAddress (
IN UINT64 Address IN UINT64 Address
); );
/*
Build extended protection MemoryRegion.
The caller is responsible for freeing MemoryRegion via FreePool().
@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,
OUT UINTN *MemoryRegionCount
);
/** /**
This function caches the UEFI memory map information. This function caches the UEFI memory map information.
**/ **/

View File

@ -405,11 +405,11 @@ InitProtectedMemRange (
) )
{ {
UINTN Index; UINTN Index;
UINTN NumberOfDescriptors; MM_CPU_MEMORY_REGION *MemoryRegion;
UINTN MemoryRegionCount;
UINTN NumberOfAddedDescriptors; UINTN NumberOfAddedDescriptors;
UINTN NumberOfProtectRange; UINTN NumberOfProtectRange;
UINTN NumberOfSpliteRange; UINTN NumberOfSpliteRange;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
UINTN TotalSize; UINTN TotalSize;
EFI_PHYSICAL_ADDRESS ProtectBaseAddress; EFI_PHYSICAL_ADDRESS ProtectBaseAddress;
EFI_PHYSICAL_ADDRESS ProtectEndAddress; EFI_PHYSICAL_ADDRESS ProtectEndAddress;
@ -419,40 +419,23 @@ InitProtectedMemRange (
UINT64 Low4KBPageSize; UINT64 Low4KBPageSize;
MEMORY_PROTECTION_RANGE MemProtectionRange; MEMORY_PROTECTION_RANGE MemProtectionRange;
NumberOfDescriptors = 0; MemoryRegion = NULL;
MemoryRegionCount = 0;
NumberOfAddedDescriptors = mSmmCpuSmramRangeCount; NumberOfAddedDescriptors = mSmmCpuSmramRangeCount;
NumberOfSpliteRange = 0; NumberOfSpliteRange = 0;
MemorySpaceMap = NULL;
// //
// Get MMIO ranges from GCD and add them into protected memory ranges. // Create extended protection MemoryRegion and add them into protected memory ranges.
// Retrieve the accessible regions when SMM profile is enabled.
// In SMM: only MMIO is accessible.
// //
gDS->GetMemorySpaceMap ( CreateExtendedProtectionRange (&MemoryRegion, &MemoryRegionCount);
&NumberOfDescriptors, ASSERT (MemoryRegion != NULL);
&MemorySpaceMap
); NumberOfAddedDescriptors += MemoryRegionCount;
for (Index = 0; Index < NumberOfDescriptors; Index++) {
if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) { ASSERT (NumberOfAddedDescriptors != 0);
if (ADDRESS_IS_ALIGNED (MemorySpaceMap[Index].BaseAddress, SIZE_4KB) &&
(MemorySpaceMap[Index].Length % SIZE_4KB == 0))
{
NumberOfAddedDescriptors++;
} else {
//
// Skip the MMIO range that BaseAddress and Length are not 4k aligned since
// the minimum granularity of the page table is 4k
//
DEBUG ((
DEBUG_WARN,
"MMIO range [0x%lx, 0x%lx] is skipped since it is not 4k aligned.\n",
MemorySpaceMap[Index].BaseAddress,
MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length
));
}
}
}
if (NumberOfAddedDescriptors != 0) {
TotalSize = NumberOfAddedDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate); TotalSize = NumberOfAddedDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate);
mProtectionMemRange = (MEMORY_PROTECTION_RANGE *)AllocateZeroPool (TotalSize); mProtectionMemRange = (MEMORY_PROTECTION_RANGE *)AllocateZeroPool (TotalSize);
ASSERT (mProtectionMemRange != NULL); ASSERT (mProtectionMemRange != NULL);
@ -494,17 +477,19 @@ InitProtectedMemRange (
// //
// Create MMIO ranges which are set to present and execution-disable. // Create MMIO ranges which are set to present and execution-disable.
// //
for (Index = 0; Index < NumberOfDescriptors; Index++) { for (Index = 0; Index < MemoryRegionCount; Index++) {
if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && mProtectionMemRange[NumberOfProtectRange].Range.Base = MemoryRegion[Index].Base;
ADDRESS_IS_ALIGNED (MemorySpaceMap[Index].BaseAddress, SIZE_4KB) && mProtectionMemRange[NumberOfProtectRange].Range.Top = MemoryRegion[Index].Base + MemoryRegion[Index].Length;
(MemorySpaceMap[Index].Length % SIZE_4KB == 0))
{
mProtectionMemRange[NumberOfProtectRange].Range.Base = MemorySpaceMap[Index].BaseAddress;
mProtectionMemRange[NumberOfProtectRange].Range.Top = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length;
mProtectionMemRange[NumberOfProtectRange].Present = TRUE; mProtectionMemRange[NumberOfProtectRange].Present = TRUE;
mProtectionMemRange[NumberOfProtectRange].Nx = TRUE; mProtectionMemRange[NumberOfProtectRange].Nx = TRUE;
NumberOfProtectRange++; NumberOfProtectRange++;
} }
//
// Free the MemoryRegion
//
if (MemoryRegion != NULL) {
FreePool (MemoryRegion);
} }
// //
@ -512,7 +497,6 @@ InitProtectedMemRange (
// //
ASSERT (NumberOfProtectRange <= mProtectionMemRangeCount); ASSERT (NumberOfProtectRange <= mProtectionMemRangeCount);
mProtectionMemRangeCount = NumberOfProtectRange; mProtectionMemRangeCount = NumberOfProtectRange;
}
// //
// According to protected ranges, create the ranges which will be mapped by 2KB page. // According to protected ranges, create the ranges which will be mapped by 2KB page.