Reviewed-by: Ray Ni <ray...@intel.com> Thanks, Ray > -----Original Message----- > From: Wu, Jiaxin <jiaxin...@intel.com> > Sent: Friday, December 15, 2023 5:55 PM > To: devel@edk2.groups.io > Cc: Laszlo Ersek <ler...@redhat.com>; Dong, Eric <eric.d...@intel.com>; Ni, > Ray <ray...@intel.com>; Zeng, Star <star.z...@intel.com>; Gerd Hoffmann > <kra...@redhat.com>; Kumar, Rahul R <rahul.r.ku...@intel.com> > Subject: [PATCH v4 2/8] UefiCpuPkg: Adds SmmCpuSyncLib library class > > Intel is planning to provide different SMM CPU Sync implementation > along with some specific registers to improve the SMI performance, > hence need SmmCpuSyncLib Library for Intel. > > This patch is to: > 1.Adds SmmCpuSyncLib Library class in UefiCpuPkg.dec. > 2.Adds SmmCpuSyncLib.h function declaration header file. > > For the new SmmCpuSyncLib, it provides 3 sets of APIs: > > 1. ContextInit/ContextDeinit/ContextReset: > ContextInit() is called in driver's entrypoint to allocate and > initialize the SMM CPU Sync context. ContextDeinit() is called in > driver's unload function to deinitialize SMM CPU Sync context. > ContextReset() is called before CPU exist SMI, which allows CPU to > check into the next SMI from this point. > > 2. GetArrivedCpuCount/CheckInCpu/CheckOutCpu/LockDoor: > When SMI happens, all processors including BSP enter to SMM mode by > calling CheckInCpu(). The elected BSP calls LockDoor() so that > CheckInCpu() will return the error code after that. CheckOutCpu() can > be called in error handling flow for the CPU who calls CheckInCpu() > earlier. GetArrivedCpuCount() returns the number of checked-in CPUs. > > 3. WaitForAPs/ReleaseOneAp/WaitForBsp/ReleaseBsp > WaitForAPs() & ReleaseOneAp() are called from BSP to wait the number > of APs and release one specific AP. WaitForBsp() & ReleaseBsp() are > called from APs to wait and release BSP. The 4 APIs are used to > synchronize the running flow among BSP and APs. BSP and AP Sync flow > can be easy understand as below: > BSP: ReleaseOneAp --> AP: WaitForBsp > BSP: WaitForAPs <-- AP: ReleaseBsp > > Cc: Laszlo Ersek <ler...@redhat.com> > Cc: Eric Dong <eric.d...@intel.com> > Cc: Ray Ni <ray...@intel.com> > Cc: Zeng Star <star.z...@intel.com> > Cc: Gerd Hoffmann <kra...@redhat.com> > Cc: Rahul Kumar <rahul1.ku...@intel.com> > Signed-off-by: Jiaxin Wu <jiaxin...@intel.com> > --- > UefiCpuPkg/Include/Library/SmmCpuSyncLib.h | 290 > +++++++++++++++++++++++++++++ > UefiCpuPkg/UefiCpuPkg.dec | 3 + > 2 files changed, 293 insertions(+) > create mode 100644 UefiCpuPkg/Include/Library/SmmCpuSyncLib.h > > diff --git a/UefiCpuPkg/Include/Library/SmmCpuSyncLib.h > b/UefiCpuPkg/Include/Library/SmmCpuSyncLib.h > new file mode 100644 > index 0000000000..4d273095c9 > --- /dev/null > +++ b/UefiCpuPkg/Include/Library/SmmCpuSyncLib.h > @@ -0,0 +1,290 @@ > +/** @file > + Library that provides SMM CPU Sync related operations. > + > + The lib provides 3 sets of APIs: > + 1. ContextInit/ContextDeinit/ContextReset: > + > + ContextInit() is called in driver's entrypoint to allocate and > initialize the > SMM CPU Sync context. > + ContextDeinit() is called in driver's unload function to deinitialize the > SMM CPU Sync context. > + ContextReset() is called by one of CPUs after all CPUs are ready to exit > SMI, which allows CPU to > + check into the next SMI from this point. > + > + 2. GetArrivedCpuCount/CheckInCpu/CheckOutCpu/LockDoor: > + When SMI happens, all processors including BSP enter to SMM mode by > calling CheckInCpu(). > + CheckOutCpu() can be called in error handling flow for the CPU who > calls CheckInCpu() earlier. > + The elected BSP calls LockDoor() so that CheckInCpu() and > CheckOutCpu() will return the error code after that. > + GetArrivedCpuCount() returns the number of checked-in CPUs. > + > + 3. WaitForAPs/ReleaseOneAp/WaitForBsp/ReleaseBsp > + WaitForAPs() & ReleaseOneAp() are called from BSP to wait the number > of APs and release one specific AP. > + WaitForBsp() & ReleaseBsp() are called from APs to wait and release > BSP. > + The 4 APIs are used to synchronize the running flow among BSP and > APs. > + BSP and AP Sync flow can be easy understand as below: > + BSP: ReleaseOneAp --> AP: WaitForBsp > + BSP: WaitForAPs <-- AP: ReleaseBsp > + > + Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef SMM_CPU_SYNC_LIB_H_ > +#define SMM_CPU_SYNC_LIB_H_ > + > +#include <Uefi/UefiBaseType.h> > + > +// > +// Opaque structure for SMM CPU Sync context. > +// > +typedef struct SMM_CPU_SYNC_CONTEXT SMM_CPU_SYNC_CONTEXT; > + > +/** > + Create and initialize the SMM CPU Sync context. It is to allocate and > initialize the > + SMM CPU Sync context. > + > + If Context is NULL, then ASSERT(). > + > + @param[in] NumberOfCpus The number of Logical > Processors in the system. > + @param[out] Context Pointer to the new created and > initialized SMM CPU Sync context object. > + NULL will be returned if any > error happen during init. > + > + @retval RETURN_SUCCESS The SMM CPU Sync context > was successful created and initialized. > + @retval RETURN_OUT_OF_RESOURCES There are not enough > resources available to create and initialize SMM CPU Sync context. > + @retval RETURN_BUFFER_TOO_SMALL Overflow happen > + > +**/ > +RETURN_STATUS > +EFIAPI > +SmmCpuSyncContextInit ( > + IN UINTN NumberOfCpus, > + OUT SMM_CPU_SYNC_CONTEXT **Context > + ); > + > +/** > + Deinit an allocated SMM CPU Sync context. The resources allocated in > SmmCpuSyncContextInit() will > + be freed. > + > + If Context is NULL, then ASSERT(). > + > + @param[in,out] Context Pointer to the SMM CPU Sync context > object to be deinitialized. > + > +**/ > +VOID > +EFIAPI > +SmmCpuSyncContextDeinit ( > + IN OUT SMM_CPU_SYNC_CONTEXT *Context > + ); > + > +/** > + Reset SMM CPU Sync context. SMM CPU Sync context will be reset to the > initialized state. > + > + This function is called by one of CPUs after all CPUs are ready to exit > SMI, > which allows CPU to > + check into the next SMI from this point. > + > + If Context is NULL, then ASSERT(). > + > + @param[in,out] Context Pointer to the SMM CPU Sync context > object to be reset. > + > +**/ > +VOID > +EFIAPI > +SmmCpuSyncContextReset ( > + IN OUT SMM_CPU_SYNC_CONTEXT *Context > + ); > + > +/** > + Get current number of arrived CPU in SMI. > + > + BSP might need to know the current number of arrived CPU in SMI to > make sure all APs > + in SMI. This API can be for that purpose. > + > + If Context is NULL, then ASSERT(). > + > + @param[in] Context Pointer to the SMM CPU Sync context > object. > + > + @retval Current number of arrived CPU in SMI. > + > +**/ > +UINTN > +EFIAPI > +SmmCpuSyncGetArrivedCpuCount ( > + IN SMM_CPU_SYNC_CONTEXT *Context > + ); > + > +/** > + Performs an atomic operation to check in CPU. > + > + When SMI happens, all processors including BSP enter to SMM mode by > calling SmmCpuSyncCheckInCpu(). > + > + If Context is NULL, then ASSERT(). > + If CpuIndex exceeds the range of all CPUs in the system, then ASSERT(). > + > + @param[in,out] Context Pointer to the SMM CPU Sync > context object. > + @param[in] CpuIndex Check in CPU index. > + > + @retval RETURN_SUCCESS Check in CPU (CpuIndex) > successfully. > + @retval RETURN_ABORTED Check in CPU failed due to > SmmCpuSyncLockDoor() has been called by one elected CPU. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SmmCpuSyncCheckInCpu ( > + IN OUT SMM_CPU_SYNC_CONTEXT *Context, > + IN UINTN CpuIndex > + ); > + > +/** > + Performs an atomic operation to check out CPU. > + > + This function can be called in error handling flow for the CPU who calls > CheckInCpu() earlier. > + The caller shall make sure the CPU specified by CpuIndex has already > checked-in. > + > + If Context is NULL, then ASSERT(). > + If CpuIndex exceeds the range of all CPUs in the system, then ASSERT(). > + > + @param[in,out] Context Pointer to the SMM CPU Sync > context object. > + @param[in] CpuIndex Check out CPU index. > + > + @retval RETURN_SUCCESS Check out CPU (CpuIndex) > successfully. > + @retval RETURN_ABORTED Check out CPU failed due to > SmmCpuSyncLockDoor() has been called by one elected CPU. > + > +**/ > +RETURN_STATUS > +EFIAPI > +SmmCpuSyncCheckOutCpu ( > + IN OUT SMM_CPU_SYNC_CONTEXT *Context, > + IN UINTN CpuIndex > + ); > + > +/** > + Performs an atomic operation lock door for CPU checkin and checkout. > After this function: > + CPU can not check in via SmmCpuSyncCheckInCpu(). > + CPU can not check out via SmmCpuSyncCheckOutCpu(). > + > + The CPU specified by CpuIndex is elected to lock door. The caller shall > make sure the CpuIndex > + is the actual CPU calling this function to avoid the undefined behavior. > + > + If Context is NULL, then ASSERT(). > + If CpuCount is NULL, then ASSERT(). > + If CpuIndex exceeds the range of all CPUs in the system, then ASSERT(). > + > + @param[in,out] Context Pointer to the SMM CPU Sync > context object. > + @param[in] CpuIndex Indicate which CPU to lock door. > + @param[out] CpuCount Number of arrived CPU in SMI > after look door. > + > +**/ > +VOID > +EFIAPI > +SmmCpuSyncLockDoor ( > + IN OUT SMM_CPU_SYNC_CONTEXT *Context, > + IN UINTN CpuIndex, > + OUT UINTN *CpuCount > + ); > + > +/** > + Used by the BSP to wait for APs. > + > + The number of APs need to be waited is specified by NumberOfAPs. The > BSP is specified by BspIndex. > + The caller shall make sure the BspIndex is the actual CPU calling this > function to avoid the undefined behavior. > + The caller shall make sure the NumberOfAPs have already checked-in to > avoid the undefined behavior. > + > + If Context is NULL, then ASSERT(). > + If NumberOfAPs >= All CPUs in system, then ASSERT(). > + If BspIndex exceeds the range of all CPUs in the system, then ASSERT(). > + > + Note: > + This function is blocking mode, and it will return only after the number of > APs released by > + calling SmmCpuSyncReleaseBsp(): > + BSP: WaitForAPs <-- AP: ReleaseBsp > + > + @param[in,out] Context Pointer to the SMM CPU Sync > context object. > + @param[in] NumberOfAPs Number of APs need to be > waited by BSP. > + @param[in] BspIndex The BSP Index to wait for APs. > + > +**/ > +VOID > +EFIAPI > +SmmCpuSyncWaitForAPs ( > + IN OUT SMM_CPU_SYNC_CONTEXT *Context, > + IN UINTN NumberOfAPs, > + IN UINTN BspIndex > + ); > + > +/** > + Used by the BSP to release one AP. > + > + The AP is specified by CpuIndex. The BSP is specified by BspIndex. > + The caller shall make sure the BspIndex is the actual CPU calling this > function to avoid the undefined behavior. > + The caller shall make sure the CpuIndex has already checked-in to avoid > the undefined behavior. > + > + If Context is NULL, then ASSERT(). > + If CpuIndex == BspIndex, then ASSERT(). > + If BspIndex or CpuIndex exceed the range of all CPUs in the system, then > ASSERT(). > + > + @param[in,out] Context Pointer to the SMM CPU Sync > context object. > + @param[in] CpuIndex Indicate which AP need to be > released. > + @param[in] BspIndex The BSP Index to release AP. > + > +**/ > +VOID > +EFIAPI > +SmmCpuSyncReleaseOneAp ( > + IN OUT SMM_CPU_SYNC_CONTEXT *Context, > + IN UINTN CpuIndex, > + IN UINTN BspIndex > + ); > + > +/** > + Used by the AP to wait BSP. > + > + The AP is specified by CpuIndex. > + The caller shall make sure the CpuIndex is the actual CPU calling this > function to avoid the undefined behavior. > + The BSP is specified by BspIndex. > + > + If Context is NULL, then ASSERT(). > + If CpuIndex == BspIndex, then ASSERT(). > + If BspIndex or CpuIndex exceed the range of all CPUs in the system, then > ASSERT(). > + > + Note: > + This function is blocking mode, and it will return only after the AP > released > by > + calling SmmCpuSyncReleaseOneAp(): > + BSP: ReleaseOneAp --> AP: WaitForBsp > + > + @param[in,out] Context Pointer to the SMM CPU Sync > context object. > + @param[in] CpuIndex Indicate which AP wait BSP. > + @param[in] BspIndex The BSP Index to be waited. > + > +**/ > +VOID > +EFIAPI > +SmmCpuSyncWaitForBsp ( > + IN OUT SMM_CPU_SYNC_CONTEXT *Context, > + IN UINTN CpuIndex, > + IN UINTN BspIndex > + ); > + > +/** > + Used by the AP to release BSP. > + > + The AP is specified by CpuIndex. > + The caller shall make sure the CpuIndex is the actual CPU calling this > function to avoid the undefined behavior. > + The BSP is specified by BspIndex. > + > + If Context is NULL, then ASSERT(). > + If CpuIndex == BspIndex, then ASSERT(). > + If BspIndex or CpuIndex exceed the range of all CPUs in the system, then > ASSERT(). > + > + @param[in,out] Context Pointer to the SMM CPU Sync > context object. > + @param[in] CpuIndex Indicate which AP release BSP. > + @param[in] BspIndex The BSP Index to be released. > + > +**/ > +VOID > +EFIAPI > +SmmCpuSyncReleaseBsp ( > + IN OUT SMM_CPU_SYNC_CONTEXT *Context, > + IN UINTN CpuIndex, > + IN UINTN BspIndex > + ); > + > +#endif > diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec > index 61bd34ef17..cc785a3222 100644 > --- a/UefiCpuPkg/UefiCpuPkg.dec > +++ b/UefiCpuPkg/UefiCpuPkg.dec > @@ -62,10 +62,13 @@ > CpuPageTableLib|Include/Library/CpuPageTableLib.h > > ## @libraryclass Provides functions for manipulating smram savestate > registers. > MmSaveStateLib|Include/Library/MmSaveStateLib.h > > + ## @libraryclass Provides functions for SMM CPU Sync Operation. > + SmmCpuSyncLib|Include/Library/SmmCpuSyncLib.h > + > [LibraryClasses.RISCV64] > ## @libraryclass Provides functions to manage MMU features on > RISCV64 CPUs. > ## > RiscVMmuLib|Include/Library/BaseRiscVMmuLib.h > > -- > 2.16.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112681): https://edk2.groups.io/g/devel/message/112681 Mute This Topic: https://groups.io/mt/103187892/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/leave/9847357/21656/1706620634/xyzzy [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-