summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhang Hongbin <hongbin1.zhang@intel.com>2024-07-02 18:57:28 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2024-08-28 15:25:27 +0000
commit6855567d52246d6fb31a2eccc6add3e12fa9b3df (patch)
treea5f5b4bb286e225ee64169e389d9e67570d404b5
parent378aff173c3e57374a4df2765b9b971236bb03bd (diff)
downloadedk2-6855567d52246d6fb31a2eccc6add3e12fa9b3df.zip
edk2-6855567d52246d6fb31a2eccc6add3e12fa9b3df.tar.gz
edk2-6855567d52246d6fb31a2eccc6add3e12fa9b3df.tar.bz2
StandaloneMmPkg/MmIpl: Create memory resource HOBs
If PcdCpuSmmRestrictedMemoryAccess is TRUE, only unblocked memory Regions are available, if FALSE, all system memory is available. Signed-off-by: Hongbin1 Zhang <hongbin1.zhang@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Jiaxin Wu <jiaxin.wu@intel.com> Cc: Wei6 Xu <wei6.xu@intel.com> Cc: Sami Mujawar <sami.mujawar@arm.com> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Supreeth Venkatesh <supreeth.venkatesh@arm.com>
-rw-r--r--StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c305
-rw-r--r--StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c2
-rw-r--r--StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h2
-rw-r--r--StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf4
4 files changed, 313 insertions, 0 deletions
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c
index f3f4363..b13d4f6 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/MmFoundationHob.c
@@ -12,9 +12,15 @@
#include <Guid/MmAcpiS3Enable.h>
#include <Guid/MmCpuSyncConfig.h>
#include <Guid/MmProfileData.h>
+#include <Guid/MmUnblockRegion.h>
#include <Register/Intel/Cpuid.h>
#include <Register/Intel/ArchitecturalMsr.h>
+typedef struct {
+ EFI_PHYSICAL_ADDRESS Base;
+ UINT64 Length;
+} MM_IPL_MEMORY_REGION;
+
/**
Add a new HOB to the HOB List.
@@ -402,6 +408,275 @@ MmIplBuildMmProfileHobs (
}
/**
+
+ Build resource Hobs from unblocked memory regions
+
+ This function builds resource HOBs for all unblocked memory regions.
+
+ @param[in] HobBuffer The pointer of new HOB buffer.
+ @param[in, out] HobBufferSize The total size of the same GUID HOBs when as output.
+
+**/
+VOID
+MmIplBuildResourceHobForUnblockedRegion (
+ IN UINT8 *HobBuffer,
+ IN OUT UINTN *HobBufferSize
+ )
+{
+ MM_UNBLOCK_REGION *UnblockRegion;
+ EFI_HOB_GENERIC_HEADER *GuidHob;
+ UINTN UsedSize;
+
+ UsedSize = 0;
+
+ GuidHob = GetFirstGuidHob (&gMmUnblockRegionHobGuid);
+ while (GuidHob != NULL) {
+ if (*HobBufferSize >= UsedSize + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)) {
+ UnblockRegion = GET_GUID_HOB_DATA (GuidHob);
+ MmIplBuildMemoryResourceHob (
+ (EFI_HOB_RESOURCE_DESCRIPTOR *)(HobBuffer + UsedSize),
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ 0,
+ UnblockRegion->PhysicalStart,
+ EFI_PAGES_TO_SIZE (UnblockRegion->NumberOfPages),
+ &UnblockRegion->IdentifierGuid
+ );
+ }
+
+ UsedSize += sizeof (EFI_HOB_RESOURCE_DESCRIPTOR);
+ GuidHob = GetNextGuidHob (&gMmUnblockRegionHobGuid, GET_NEXT_HOB (GuidHob));
+ }
+
+ *HobBufferSize = UsedSize;
+}
+
+/**
+ Create MMIO memory map according to platform HOB.
+
+ @param[in] PlatformHobList Platform HOB list.
+ @param[in] PlatformHobSize Platform HOB size.
+ @param[in, out] MemoryRegion Memory regions.
+ @param[in, out] MemoryRegionCount Count of MMIO regions
+**/
+VOID
+CollectPlatformMemoryRegions (
+ IN UINT8 *PlatformHobList,
+ IN UINTN PlatformHobSize,
+ IN OUT MM_IPL_MEMORY_REGION *MemoryRegion,
+ IN OUT UINTN *MemoryRegionCount
+ )
+{
+ UINTN Index;
+ EFI_PEI_HOB_POINTERS Hob;
+
+ ASSERT (MemoryRegionCount != NULL);
+ ASSERT (*MemoryRegionCount == 0 || MemoryRegion != NULL);
+
+ Index = 0;
+ //
+ // Get the HOB list for processing
+ //
+ Hob.Raw = PlatformHobList;
+
+ //
+ // Collect memory ranges
+ //
+ while (Hob.Raw < PlatformHobList + PlatformHobSize) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ if ( (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_MAPPED_IO)
+ || (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY)
+ || (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_FIRMWARE_DEVICE)
+ || (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED))
+ {
+ if (Index < *MemoryRegionCount) {
+ MemoryRegion[Index].Base = Hob.ResourceDescriptor->PhysicalStart;
+ MemoryRegion[Index].Length = Hob.ResourceDescriptor->ResourceLength;
+ }
+
+ Index++;
+ }
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+
+ *MemoryRegionCount = Index;
+}
+
+/**
+ Function to compare 2 MM_IPL_MEMORY_REGION pointer based on Base.
+
+ @param[in] Buffer1 pointer to MM_IPL_MEMORY_REGION pointer to compare
+ @param[in] Buffer2 pointer to second MM_IPL_MEMORY_REGION pointer to compare
+
+ @retval 0 Buffer1 equal to Buffer2
+ @retval <0 Buffer1 is less than Buffer2
+ @retval >0 Buffer1 is greater than Buffer2
+**/
+INTN
+EFIAPI
+MemoryRegionBaseAddressCompare (
+ IN CONST VOID *Buffer1,
+ IN CONST VOID *Buffer2
+ )
+{
+ if (((MM_IPL_MEMORY_REGION *)Buffer1)->Base > ((MM_IPL_MEMORY_REGION *)Buffer2)->Base) {
+ return 1;
+ } else if (((MM_IPL_MEMORY_REGION *)Buffer1)->Base < ((MM_IPL_MEMORY_REGION *)Buffer2)->Base) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ Calculate the maximum support address.
+
+ @return the maximum support address.
+**/
+UINT8
+MmIplCalculateMaximumSupportAddress (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+ VOID *Hob;
+
+ //
+ // Get physical address bits supported.
+ //
+ Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
+ if (Hob != NULL) {
+ PhysicalAddressBits = ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;
+ } else {
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
+ AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8)RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+ }
+
+ return PhysicalAddressBits;
+}
+
+/**
+ Build resource HOB to cover [0, PhysicalAddressBits length] by excluding
+ all Mmram ranges, MM Profile data and MMIO ranges.
+
+ @param[in] HobBuffer The pointer of new HOB buffer.
+ @param[in, out] HobBufferSize The available size of the HOB buffer when as input.
+ The used size of when as output.
+ @param[in] PlatformHobList Platform HOB list.
+ @param[in] PlatformHobSize Platform HOB size.
+ @param[in] Block Pointer of MMRAM descriptor block.
+ @param[in] MmProfileDataHob Pointer to MM profile data HOB.
+
+**/
+VOID
+MmIplBuildResourceHobForAllSystemMemory (
+ IN UINT8 *HobBuffer,
+ IN OUT UINTN *HobBufferSize,
+ IN VOID *PlatformHobList,
+ IN UINTN PlatformHobSize,
+ IN EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *Block,
+ IN EFI_HOB_MEMORY_ALLOCATION *MmProfileDataHob
+ )
+{
+ UINTN Index;
+ UINTN Count;
+ UINTN PlatformRegionCount;
+ UINTN UsedSize;
+ UINT64 PreviousAddress;
+ UINT64 MaxAddress;
+ MM_IPL_MEMORY_REGION *MemoryRegions;
+ MM_IPL_MEMORY_REGION SortBuffer;
+
+ MaxAddress = LShiftU64 (1, MmIplCalculateMaximumSupportAddress ());
+
+ //
+ // Get the count of platform memory regions
+ //
+ PlatformRegionCount = 0;
+ if ((PlatformHobList != NULL) && (PlatformHobSize != 0)) {
+ CollectPlatformMemoryRegions (PlatformHobList, PlatformHobSize, NULL, &PlatformRegionCount);
+ }
+
+ //
+ // Allocate buffer for platform memory regions, MM Profile data, MMRam ranges, an extra terminator.
+ //
+ Count = PlatformRegionCount + Block->NumberOfMmReservedRegions + ((MmProfileDataHob != NULL) ? 1 : 0) + 1;
+ MemoryRegions = AllocatePages (EFI_SIZE_TO_PAGES (Count * sizeof (*MemoryRegions)));
+ ASSERT (MemoryRegions != NULL);
+ if (MemoryRegions == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a:%d - No enough memory\n", __func__, __LINE__));
+ CpuDeadLoop ();
+ return;
+ }
+
+ //
+ // The very last region is the terminator
+ //
+ MemoryRegions[Count - 1].Base = MaxAddress;
+ MemoryRegions[Count - 1].Length = 0;
+
+ //
+ // Collect platform memory regions
+ //
+ if (PlatformRegionCount != 0) {
+ CollectPlatformMemoryRegions (PlatformHobList, PlatformHobSize, MemoryRegions, &PlatformRegionCount);
+ }
+
+ //
+ // Collect SMRAM regions
+ //
+ for (Index = 0; Index < Block->NumberOfMmReservedRegions; Index++) {
+ MemoryRegions[PlatformRegionCount + Index].Base = Block->Descriptor[Index].CpuStart;
+ MemoryRegions[PlatformRegionCount + Index].Length = Block->Descriptor[Index].PhysicalSize;
+ }
+
+ //
+ // Collect MM profile database region
+ //
+ if (MmProfileDataHob != NULL) {
+ MemoryRegions[PlatformRegionCount + Block->NumberOfMmReservedRegions].Base = MmProfileDataHob->AllocDescriptor.MemoryBaseAddress;
+ MemoryRegions[PlatformRegionCount + Block->NumberOfMmReservedRegions].Length = MmProfileDataHob->AllocDescriptor.MemoryLength;
+ }
+
+ //
+ // Build system memory resource HOBs excluding platform memory regions, SMRAM regions, MmProfile database.
+ //
+ QuickSort (MemoryRegions, Count, sizeof (*MemoryRegions), MemoryRegionBaseAddressCompare, &SortBuffer);
+ UsedSize = 0;
+ PreviousAddress = 0;
+ for (Index = 0; Index < Count; Index++) {
+ ASSERT (MaxAddress >= MemoryRegions[Index].Base + MemoryRegions[Index].Length);
+
+ if (MemoryRegions[Index].Base > PreviousAddress) {
+ if (*HobBufferSize >= UsedSize + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)) {
+ MmIplBuildMemoryResourceHob (
+ (EFI_HOB_RESOURCE_DESCRIPTOR *)(HobBuffer + UsedSize),
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ FeaturePcdGet (PcdCpuSmmProfileEnable) ? MM_RESOURCE_ATTRIBUTE_LOGGING : 0,
+ PreviousAddress,
+ MemoryRegions[Index].Base - PreviousAddress,
+ &gEfiCallerIdGuid
+ );
+ }
+
+ UsedSize += sizeof (EFI_HOB_RESOURCE_DESCRIPTOR);
+ }
+
+ PreviousAddress = MemoryRegions[Index].Base + MemoryRegions[Index].Length;
+ }
+
+ *HobBufferSize = UsedSize;
+ FreePages (MemoryRegions, EFI_SIZE_TO_PAGES (Count * sizeof (EFI_MEMORY_DESCRIPTOR)));
+}
+
+/**
Get remaining size for building HOBs.
@param[in] TotalHobSize Total size of foundation HOBs.
@@ -439,6 +714,7 @@ GetRemainingHobSize (
@param[in] MmCoreImageAddress Image address of MM core dirver.
@param[in] MmCoreImageSize Image size of MM core dirver.
@param[in] MmCoreEntryPoint Entry pinter of MM core dirver.
+ @param[in] MmProfileDataHob Pointer to Mm profile data HOB.
@param[in] Block Pointer of MMRAM descriptor block.
@retval RETURN_BUFFER_TOO_SMALL The buffer is too small for HOB creation.
@@ -460,6 +736,7 @@ CreateMmFoundationHobList (
IN EFI_PHYSICAL_ADDRESS MmCoreImageAddress,
IN UINT64 MmCoreImageSize,
IN EFI_PHYSICAL_ADDRESS MmCoreEntryPoint,
+ IN EFI_HOB_MEMORY_ALLOCATION *MmProfileDataHob,
IN EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *Block
)
{
@@ -474,6 +751,16 @@ CreateMmFoundationHobList (
((*FoundationHobSize == 0) && (FoundationHobList == NULL))
);
+ if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
+ //
+ // When SmmProfile is enabled, all DRAM is accessible from SMM drivers' perspective.
+ // However, underline Cpu SMM driver does not map the DRAM so that every access to it triggers #PF.
+ // #PF handler records the access then sets up the mapping in the page table to allow the temporary access by current instruction.
+ // The mapping is revoked before next instruction runs.
+ //
+ ASSERT (!PcdGetBool (PcdCpuSmmRestrictedMemoryAccess));
+ }
+
UsedSize = 0;
//
@@ -556,6 +843,24 @@ CreateMmFoundationHobList (
UsedSize += HobLength;
}
+ HobLength = GetRemainingHobSize (*FoundationHobSize, UsedSize);
+ if (PcdGetBool (PcdCpuSmmRestrictedMemoryAccess)) {
+ //
+ // Only unblocked memory regions are accessible
+ //
+ MmIplBuildResourceHobForUnblockedRegion (FoundationHobList + UsedSize, &HobLength);
+ } else {
+ //
+ // All system memory (DRAM) is accessible.
+ // When SMM Profile is enabled:
+ // * Access to regions reported from MmPlatformHobProducerLib do not require logging.
+ // * Access to other system memory requires logging.
+ //
+ MmIplBuildResourceHobForAllSystemMemory (FoundationHobList + UsedSize, &HobLength, PlatformHobList, PlatformHobSize, Block, MmProfileDataHob);
+ }
+
+ UsedSize += HobLength;
+
if (*FoundationHobSize < UsedSize) {
Status = RETURN_BUFFER_TOO_SMALL;
} else {
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
index b6525b2..b1cd3c1 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
@@ -294,6 +294,7 @@ CreatMmHobList (
MmCoreImageAddress,
MmCoreImageSize,
MmCoreEntryPoint,
+ MmProfileDataHob,
Block
);
FreePages (PlatformHobList, EFI_SIZE_TO_PAGES (PlatformHobSize));
@@ -331,6 +332,7 @@ CreatMmHobList (
MmCoreImageAddress,
MmCoreImageSize,
MmCoreEntryPoint,
+ MmProfileDataHob,
Block
);
ASSERT_EFI_ERROR (Status);
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
index e167a0d..9301b8f 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
@@ -102,6 +102,7 @@ MmIplCreateHob (
@param[in] MmCoreImageAddress Image address of MM core dirver.
@param[in] MmCoreImageSize Image size of MM core dirver.
@param[in] MmCoreEntryPoint Entry pinter of MM core dirver.
+ @param[in] MmProfileDataHob Pointer to MM profile data HOB.
@param[in] Block Pointer of MMRAM descriptor block.
@retval RETURN_BUFFER_TOO_SMALL The buffer is too small for HOB creation.
@@ -123,6 +124,7 @@ CreateMmFoundationHobList (
IN EFI_PHYSICAL_ADDRESS MmCoreImageAddress,
IN UINT64 MmCoreImageSize,
IN EFI_PHYSICAL_ADDRESS MmCoreEntryPoint,
+ IN EFI_HOB_MEMORY_ALLOCATION *MmProfileDataHob,
IN EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *Block
);
diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
index 325a373..dfc1812 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
@@ -55,6 +55,7 @@
gMmAcpiS3EnableHobGuid
gMmCpuSyncConfigHobGuid
gMmProfileDataHobGuid
+ gMmUnblockRegionHobGuid
[Ppis]
gEfiPeiMmControlPpiGuid
@@ -73,5 +74,8 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileSize ## CONSUMES
+[Pcd.X64]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmRestrictedMemoryAccess ## CONSUMES
+
[Depex]
gEfiPeiMmControlPpiGuid AND gEfiPeiMpServicesPpiGuid