From ec07fd0e35d90dbcc36be300a9ceeac29c5de2ad Mon Sep 17 00:00:00 2001 From: "Wu, Jiaxin" Date: Thu, 16 Feb 2023 14:16:31 +0800 Subject: UefiCpuPkg/PiSmmCpuDxeSmm: Consume SMM Base Hob for SmBase info REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4337 Existing SMBASE Relocation is in the PiSmmCpuDxeSmm driver, which will relocate the SMBASE of each processor by setting the SMBASE field in the saved state map (at offset 7EF8h) to a new value. The RSM instruction reloads the internal SMBASE register with the value in SMBASE field when each time it exits SMM. All subsequent SMI requests will use the new SMBASE to find the starting address for the SMI handler (at SMBASE + 8000h). Due to the default SMBASE for all x86 processors is 0x30000, the APs' 1st SMI for rebase has to be executed one by one to avoid the processors over-writing each other's SMM Save State Area (see existing SmmRelocateBases() function), which means the next AP has to wait for the previous AP to finish its 1st SMI, then it can call into its 1st SMI for rebase via Smi Ipi command, thus leading the existing SMBASE Relocation has to be running in series. Besides, it needs very complex code to handle the AP exit semaphore (mRebased[Index]), which will hook return address of SMM Save State so that semaphore code can be executed immediately after AP exits SMM for SMBASE relocation (see existing SemaphoreHook() function). With SMM Base Hob support, PiSmmCpuDxeSmm does not need the RSM instruction to do the SMBASE Relocation. SMBASE Register for each processors have already been programmed and all SMBASE address have recorded in SMM Base Hob. So the same default SMBASE Address (0x30000) will not be used, thus the processors over-writing each other's SMM Save State Area will not happen in PiSmmCpuDxeSmm driver. This way makes the first SMI init can be executed in parallel and save boot time on multi-core system. Besides, Semaphore Hook code logic is also not required, which will greatly simplify the SMBASE Relocation flow. Mainly changes as below: * Assume the biggest possibility of tile size is 8k. * Combine 2 SMIs (gcSmmInitTemplate & gcSmiHandlerTemplate) into one (gcSmiHandlerTemplate), the new SMI handler needs to run to 2 paths: one to SmmCpuFeaturesInitializeProcessor(), the other to SMM Core Entry Point. * Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) for first SMI init before normal SMI sources happen. * Call SmmCpuFeaturesInitializeProcessor() in parallel. Cc: Eric Dong Cc: Ray Ni Cc: Zeng Star Cc: Laszlo Ersek Acked-by: Gerd Hoffmann Cc: Rahul Kumar Signed-off-by: Jiaxin Wu Reviewed-by: Ray Ni --- UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c') diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c index fb4a44eab6..d408b3f9f7 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c @@ -1,7 +1,7 @@ /** @file Code for Processor S3 restoration -Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -824,9 +824,34 @@ SmmRestoreCpu ( } // - // Restore SMBASE for BSP and all APs + // Make sure the gSmmBaseHobGuid existence status is the same between normal and S3 boot. // - SmmRelocateBases (); + ASSERT (mSmmRelocated == (BOOLEAN)(GetFirstGuidHob (&gSmmBaseHobGuid) != NULL)); + if (mSmmRelocated != (BOOLEAN)(GetFirstGuidHob (&gSmmBaseHobGuid) != NULL)) { + DEBUG (( + DEBUG_ERROR, + "gSmmBaseHobGuid %a produced in normal boot but %a in S3 boot!", + mSmmRelocated ? "is" : "is not", + mSmmRelocated ? "is not" : "is" + )); + CpuDeadLoop (); + } + + // + // Check whether Smm Relocation is done or not. + // If not, will do the SmmBases Relocation here!!! + // + if (!mSmmRelocated) { + // + // Restore SMBASE for BSP and all APs + // + SmmRelocateBases (); + } else { + // + // Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init. + // + ExecuteFirstSmiInit (); + } // // Skip initialization if mAcpiCpuData is not valid -- cgit