summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--UefiCpuPkg/Include/Library/SmmCpuSyncLib.h290
-rw-r--r--UefiCpuPkg/UefiCpuPkg.dec3
2 files changed, 293 insertions, 0 deletions
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
@@ -64,6 +64,9 @@
## @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.
##