From 79468b58c31e9fcbc6bd7aa1955876fc516bebc4 Mon Sep 17 00:00:00 2001 From: Jiaxin Wu Date: Wed, 26 Jun 2024 15:43:52 +0800 Subject: [PATCH] UefiCpuPkg/PiSmmCpuDxeSmm: Differentiate PerformRemainingTasks For MM: SMRAM & PageTable itself & SMM Paging State shall be configured once the gEdkiiPiMmMemoryAttributesTableGuid is installed by SMM core. It will happen after MmIpl.Entrypoint. PerformRemainingTasks will be called before MmIpl.Entrypoint exit. For SMM: SMRAM & PageTable itself & SMM Paging State are still configured in the first SMI when SMM ready to lock happen. So, this patch is to differentiate PerformRemainingTasks for MM and SMM. Signed-off-by: Jiaxin Wu Cc: Ray Ni Cc: Rahul Kumar Cc: Gerd Hoffmann Cc: Star Zeng Cc: Dun Tan Cc: Hongbin1 Zhang Cc: Wei6 Xu Cc: Yuanhao Xie --- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c | 81 ---------------- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h | 24 ++++- UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c | 92 +++++++++++++++++++ .../PiSmmCpuDxeSmm/PiSmmCpuStandaloneMm.c | 57 ++++++++++++ .../PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 36 ++++---- 5 files changed, 188 insertions(+), 102 deletions(-) diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c index cd43619d17..c5921a6de8 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.c @@ -96,11 +96,6 @@ BOOLEAN mCetSupported = TRUE; UINTN mMaxNumberOfCpus = 0; UINTN mNumberOfCpus = 0; -// -// SMM ready to lock flag -// -BOOLEAN mSmmReadyToLock = FALSE; - // // Global used to cache PCD for SMM Code Access Check enable // @@ -1525,82 +1520,6 @@ AllocateCodePages ( return (VOID *)(UINTN)Memory; } -/** - Perform the remaining tasks. - -**/ -VOID -PerformRemainingTasks ( - VOID - ) -{ - if (mSmmReadyToLock) { - PERF_FUNCTION_BEGIN (); - - // - // Check if all Aps enter SMM. In Relaxed-AP Sync Mode, BSP will not wait for - // all Aps arrive. However,PerformRemainingTasks() needs to wait all Aps arrive before calling - // SetMemMapAttributes() and ConfigSmmCodeAccessCheck() when mSmmReadyToLock - // is true. In SetMemMapAttributes(), SmmSetMemoryAttributesEx() will call - // FlushTlbForAll() that need to start up the aps. So it need to let all - // aps arrive. Same as SetMemMapAttributes(), ConfigSmmCodeAccessCheck() - // also will start up the aps. - // - if (EFI_ERROR (SmmCpuRendezvous (NULL, TRUE))) { - DEBUG ((DEBUG_ERROR, "PerformRemainingTasks: fail to wait for all AP check in SMM!\n")); - } - - // - // Start SMM Profile feature - // - if (FeaturePcdGet (PcdCpuSmmProfileEnable)) { - SmmProfileStart (); - } - - // - // Create a mix of 2MB and 4KB page table. Update some memory ranges absent and execute-disable. - // - InitPaging (); - - // - // Mark critical region to be read-only in page table - // - SetMemMapAttributes (); - - if (IsRestrictedMemoryAccess ()) { - // - // For outside SMRAM, we only map SMM communication buffer or MMIO. - // - SetUefiMemMapAttributes (); - - // - // Set page table itself to be read-only - // - SetPageTableAttributes (); - } - - // - // Configure SMM Code Access Check feature if available. - // - ConfigSmmCodeAccessCheck (); - - // - // Measure performance of SmmCpuFeaturesCompleteSmmReadyToLock() from caller side - // as the implementation is provided by platform. - // - PERF_START (NULL, "SmmCompleteReadyToLock", NULL, 0); - SmmCpuFeaturesCompleteSmmReadyToLock (); - PERF_END (NULL, "SmmCompleteReadyToLock", NULL, 0); - - // - // Clean SMM ready to lock flag - // - mSmmReadyToLock = FALSE; - - PERF_FUNCTION_END (); - } -} - /** Perform the pre tasks. diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h index a0b5e6fafb..44bf3f3aba 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuCommon.h @@ -273,7 +273,6 @@ extern UINT8 mSmmSaveStateRegisterLma; extern BOOLEAN mBtsSupported; extern UINTN mMsrDsAreaSize; extern BOOLEAN mAcpiS3Enable; -extern BOOLEAN mSmmReadyToLock; #define PAGE_TABLE_POOL_ALIGNMENT BASE_128KB #define PAGE_TABLE_POOL_UNIT_SIZE BASE_128KB @@ -780,6 +779,24 @@ SmmClearMemoryAttributes ( IN UINT64 Attributes ); +/** + Retrieves a pointer to the system configuration table from the SMM System Table + based on a specified GUID. + + @param[in] TableGuid The pointer to table's GUID type. + @param[out] Table The pointer to the table associated with TableGuid in the EFI System Table. + + @retval EFI_SUCCESS A configuration table matching TableGuid was found. + @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found. + +**/ +EFI_STATUS +EFIAPI +SmmGetSystemConfigurationTable ( + IN EFI_GUID *TableGuid, + OUT VOID **Table + ); + /** Initialize MP synchronization data. @@ -932,10 +949,13 @@ DumpModuleInfoByIp ( /** This function sets memory attribute according to MemoryAttributesTable. + + @param MemoryAttributesTable A pointer to the buffer of SmmMemoryAttributesTable. + **/ VOID SetMemMapAttributes ( - VOID + EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable ); /** diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c index c5e7f4363b..959e993bda 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c @@ -18,6 +18,98 @@ SPDX-License-Identifier: BSD-2-Clause-Patent // const BOOLEAN mIsStandaloneMm = FALSE; +// +// SMM ready to lock flag +// +BOOLEAN mSmmReadyToLock = FALSE; + +/** + Perform the remaining tasks. + +**/ +VOID +PerformRemainingTasks ( + VOID + ) +{ + EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable; + + if (mSmmReadyToLock) { + PERF_FUNCTION_BEGIN (); + + // + // Start SMM Profile feature + // + if (FeaturePcdGet (PcdCpuSmmProfileEnable)) { + SmmProfileStart (); + } + + // + // Check if all Aps enter SMM. In Relaxed-AP Sync Mode, BSP will not wait for + // all Aps arrive. However,PerformRemainingTasks() needs to wait all Aps arrive before calling + // SetMemMapAttributes() and ConfigSmmCodeAccessCheck() when mSmmReadyToLock + // is true. In SetMemMapAttributes(), SmmSetMemoryAttributesEx() will call + // FlushTlbForAll() that need to start up the aps. So it need to let all + // aps arrive. Same as SetMemMapAttributes(), ConfigSmmCodeAccessCheck() + // also will start up the aps. + // + if (EFI_ERROR (SmmCpuRendezvous (NULL, TRUE))) { + DEBUG ((DEBUG_ERROR, "PerformRemainingTasks: fail to wait for all AP check in SMM!\n")); + } + + // + // Create a mix of 2MB and 4KB page table. Update some memory ranges absent and execute-disable. + // + InitPaging (); + + // + // gEdkiiPiSmmMemoryAttributesTableGuid should have been published at EndOfDxe by SmmCore + // Note: gEdkiiPiSmmMemoryAttributesTableGuid is not always installed since it depends on + // the memory protection attribute setting in MM Core. + // + SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable); + + // + // Set critical region attribute in page table according to the MemoryAttributesTable + // + if (MemoryAttributesTable != NULL) { + SetMemMapAttributes (MemoryAttributesTable); + } + + if (IsRestrictedMemoryAccess ()) { + // + // For outside SMRAM, we only map SMM communication buffer or MMIO. + // + SetUefiMemMapAttributes (); + + // + // Set page table itself to be read-only + // + SetPageTableAttributes (); + } + + // + // Configure SMM Code Access Check feature if available. + // + ConfigSmmCodeAccessCheck (); + + // + // Measure performance of SmmCpuFeaturesCompleteSmmReadyToLock() from caller side + // as the implementation is provided by platform. + // + PERF_START (NULL, "SmmCompleteReadyToLock", NULL, 0); + SmmCpuFeaturesCompleteSmmReadyToLock (); + PERF_END (NULL, "SmmCompleteReadyToLock", NULL, 0); + + // + // Clean SMM ready to lock flag + // + mSmmReadyToLock = FALSE; + + PERF_FUNCTION_END (); + } +} + /** To get system port address of the SMI Command Port in FADT table. diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuStandaloneMm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuStandaloneMm.c index 7d143e78eb..005fbcd968 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuStandaloneMm.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuStandaloneMm.c @@ -15,6 +15,63 @@ SPDX-License-Identifier: BSD-2-Clause-Patent // const BOOLEAN mIsStandaloneMm = TRUE; +// +// RemainingTasks Done flag +// +BOOLEAN mRemainingTasksDone = FALSE; + +/** + Perform the remaining tasks. + +**/ +VOID +PerformRemainingTasks ( + VOID + ) +{ + EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable; + + if (!mRemainingTasksDone) { + PERF_FUNCTION_BEGIN (); + + // + // gEdkiiPiSmmMemoryAttributesTableGuid should have been published after SmmCore dispatched all MM drivers (MmDriverDispatchHandler). + // Note: gEdkiiPiSmmMemoryAttributesTableGuid is not always installed since it depends on + // the memory protection attribute setting in MM Core. + // + SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable); + + // + // Set critical region attribute in page table according to the MemoryAttributesTable + // + if (MemoryAttributesTable != NULL) { + SetMemMapAttributes (MemoryAttributesTable); + } + + if (IsRestrictedMemoryAccess ()) { + // + // Set page table itself to be read-only + // + SetPageTableAttributes (); + } + + // + // Measure performance of SmmCpuFeaturesCompleteSmmReadyToLock() from caller side + // as the implementation is provided by platform. + // + PERF_START (NULL, "SmmCompleteReadyToLock", NULL, 0); + SmmCpuFeaturesCompleteSmmReadyToLock (); + PERF_END (NULL, "SmmCompleteReadyToLock", NULL, 0); + + // + // Mark RemainingTasks Done flag to TRUE + // + mRemainingTasksDone = TRUE; + + PERF_FUNCTION_END (); + } +} + /** To get system port address of the SMI Command Port. diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c index cf1e49d89b..4022c45065 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c @@ -993,31 +993,29 @@ SetMemMapWithNonPresentRange ( /** This function sets memory attribute according to MemoryAttributesTable. + + @param MemoryAttributesTable A pointer to the buffer of SmmMemoryAttributesTable. + **/ VOID SetMemMapAttributes ( - VOID + EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable ) { - EFI_MEMORY_DESCRIPTOR *MemoryMap; - EFI_MEMORY_DESCRIPTOR *MemoryMapStart; - UINTN MemoryMapEntryCount; - UINTN DescriptorSize; - UINTN Index; - EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable; - UINTN PageTable; - EFI_STATUS Status; - IA32_MAP_ENTRY *Map; - UINTN Count; - UINT64 MemoryAttribute; - BOOLEAN WriteProtect; - BOOLEAN CetEnabled; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + EFI_MEMORY_DESCRIPTOR *MemoryMapStart; + UINTN MemoryMapEntryCount; + UINTN DescriptorSize; + UINTN Index; + UINTN PageTable; + EFI_STATUS Status; + IA32_MAP_ENTRY *Map; + UINTN Count; + UINT64 MemoryAttribute; + BOOLEAN WriteProtect; + BOOLEAN CetEnabled; - SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable); - if (MemoryAttributesTable == NULL) { - DEBUG ((DEBUG_INFO, "MemoryAttributesTable - NULL\n")); - return; - } + ASSERT (MemoryAttributesTable != NULL); PERF_FUNCTION_BEGIN ();