From: "Ni, Ray" <ray.ni@intel.com>
To: "Wu, Jiaxin" <jiaxin.wu@intel.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: Laszlo Ersek <lersek@redhat.com>,
"Dong, Eric" <eric.dong@intel.com>,
"Zeng, Star" <star.zeng@intel.com>,
Gerd Hoffmann <kraxel@redhat.com>,
"Kumar, Rahul R" <rahul.r.kumar@intel.com>
Subject: Re: [edk2-devel] [PATCH v5 4/8] UefiCpuPkg: Implements SmmCpuSyncLib library instance
Date: Tue, 19 Dec 2023 09:34:28 +0000 [thread overview]
Message-ID: <MN6PR11MB8244EA26A1646E8F86D4945C8C97A@MN6PR11MB8244.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20231219071839.4248-5-jiaxin.wu@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Thanks,
Ray
> -----Original Message-----
> From: Wu, Jiaxin <jiaxin.wu@intel.com>
> Sent: Tuesday, December 19, 2023 3:19 PM
> To: devel@edk2.groups.io
> Cc: Laszlo Ersek <lersek@redhat.com>; Dong, Eric <eric.dong@intel.com>; Ni,
> Ray <ray.ni@intel.com>; Zeng, Star <star.zeng@intel.com>; Gerd Hoffmann
> <kraxel@redhat.com>; Kumar, Rahul R <rahul.r.kumar@intel.com>
> Subject: [PATCH v5 4/8] UefiCpuPkg: Implements SmmCpuSyncLib library
> instance
>
> Implements SmmCpuSyncLib Library instance. The instance refers the
> existing SMM CPU driver (PiSmmCpuDxeSmm) sync implementation
> and behavior:
> 1.Abstract Counter and Run semaphores into SmmCpuSyncCtx.
> 2.Abstract CPU arrival count operation to
> SmmCpuSyncGetArrivedCpuCount(), SmmCpuSyncCheckInCpu(),
> SmmCpuSyncCheckOutCpu(), SmmCpuSyncLockDoor().
> Implementation is aligned with existing SMM CPU driver.
> 3. Abstract SMM CPU Sync flow to:
> BSP: SmmCpuSyncReleaseOneAp --> AP: SmmCpuSyncWaitForBsp
> BSP: SmmCpuSyncWaitForAPs <-- AP: SmmCpuSyncReleaseBsp
> Semaphores release & wait during sync flow is same as existing SMM
> CPU driver.
> 4.Same operation to Counter and Run semaphores by leverage the atomic
> compare exchange.
>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Zeng Star <star.zeng@intel.com>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Cc: Rahul Kumar <rahul1.kumar@intel.com>
> Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
> ---
> UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c | 652
> +++++++++++++++++++++
> UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.inf | 34 ++
> UefiCpuPkg/UefiCpuPkg.dsc | 2 +
> 3 files changed, 688 insertions(+)
> create mode 100644
> UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> create mode 100644
> UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.inf
>
> diff --git a/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> b/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> new file mode 100644
> index 0000000000..d517d4b706
> --- /dev/null
> +++ b/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.c
> @@ -0,0 +1,652 @@
> +/** @file
> + SMM CPU Sync lib implementation.
> +
> + 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
> +
> +**/
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/SafeIntLib.h>
> +#include <Library/SmmCpuSyncLib.h>
> +#include <Library/SynchronizationLib.h>
> +#include <Uefi.h>
> +
> +///
> +/// The implementation shall place one semaphore on exclusive cache line
> for good performance.
> +///
> +typedef volatile UINT32 SMM_CPU_SYNC_SEMAPHORE;
> +
> +typedef struct {
> + ///
> + /// Used for control each CPU continue run or wait for signal
> + ///
> + SMM_CPU_SYNC_SEMAPHORE *Run;
> +} SMM_CPU_SYNC_SEMAPHORE_FOR_EACH_CPU;
> +
> +struct SMM_CPU_SYNC_CONTEXT {
> + ///
> + /// Indicate all CPUs in the system.
> + ///
> + UINTN NumberOfCpus;
> + ///
> + /// Address of semaphores.
> + ///
> + VOID *SemBuffer;
> + ///
> + /// Size of semaphores.
> + ///
> + UINTN SemBufferPages;
> + ///
> + /// Before the door is locked, CpuCount stores the arrived CPU count.
> + /// After the door is locked, CpuCount is set to -1 indicating the door is
> locked.
> + /// ArrivedCpuCountUponLock stores the arrived CPU count then.
> + ///
> + UINTN
> ArrivedCpuCountUponLock;
> + ///
> + /// Indicate CPUs entered SMM before lock door.
> + ///
> + SMM_CPU_SYNC_SEMAPHORE *CpuCount;
> + ///
> + /// Define an array of structure for each CPU semaphore due to the size
> alignment
> + /// requirement. With the array of structure for each CPU semaphore, it's
> easy to
> + /// reach the specific CPU with CPU Index for its own semaphore access:
> CpuSem[CpuIndex].
> + ///
> + SMM_CPU_SYNC_SEMAPHORE_FOR_EACH_CPU CpuSem[];
> +};
> +
> +/**
> + Performs an atomic compare exchange operation to get semaphore.
> + The compare exchange operation must be performed using MP safe
> + mechanisms.
> +
> + @param[in,out] Sem IN: 32-bit unsigned integer
> + OUT: original integer - 1 if Sem is not locked.
> + OUT: MAX_UINT32 if Sem is locked.
> +
> + @retval Original integer - 1 if Sem is not locked.
> + MAX_UINT32 if Sem is locked.
> +
> +**/
> +STATIC
> +UINT32
> +InternalWaitForSemaphore (
> + IN OUT volatile UINT32 *Sem
> + )
> +{
> + UINT32 Value;
> +
> + for ( ; ;) {
> + Value = *Sem;
> + if (Value == MAX_UINT32) {
> + return Value;
> + }
> +
> + if ((Value != 0) &&
> + (InterlockedCompareExchange32 (
> + (UINT32 *)Sem,
> + Value,
> + Value - 1
> + ) == Value))
> + {
> + break;
> + }
> +
> + CpuPause ();
> + }
> +
> + return Value - 1;
> +}
> +
> +/**
> + Performs an atomic compare exchange operation to release semaphore.
> + The compare exchange operation must be performed using MP safe
> + mechanisms.
> +
> + @param[in,out] Sem IN: 32-bit unsigned integer
> + OUT: original integer + 1 if Sem is not locked.
> + OUT: MAX_UINT32 if Sem is locked.
> +
> + @retval Original integer + 1 if Sem is not locked.
> + MAX_UINT32 if Sem is locked.
> +
> +**/
> +STATIC
> +UINT32
> +InternalReleaseSemaphore (
> + IN OUT volatile UINT32 *Sem
> + )
> +{
> + UINT32 Value;
> +
> + do {
> + Value = *Sem;
> + } while (Value + 1 != 0 &&
> + InterlockedCompareExchange32 (
> + (UINT32 *)Sem,
> + Value,
> + Value + 1
> + ) != Value);
> +
> + if (Value == MAX_UINT32) {
> + return Value;
> + }
> +
> + return Value + 1;
> +}
> +
> +/**
> + Performs an atomic compare exchange operation to lock semaphore.
> + The compare exchange operation must be performed using MP safe
> + mechanisms.
> +
> + @param[in,out] Sem IN: 32-bit unsigned integer
> + OUT: -1
> +
> + @retval Original integer
> +
> +**/
> +STATIC
> +UINT32
> +InternalLockdownSemaphore (
> + IN OUT volatile UINT32 *Sem
> + )
> +{
> + UINT32 Value;
> +
> + do {
> + Value = *Sem;
> + } while (InterlockedCompareExchange32 (
> + (UINT32 *)Sem,
> + Value,
> + (UINT32)-1
> + ) != Value);
> +
> + return Value;
> +}
> +
> +/**
> + 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
> + )
> +{
> + RETURN_STATUS Status;
> + UINTN ContextSize;
> + UINTN OneSemSize;
> + UINTN NumSem;
> + UINTN TotalSemSize;
> + UINTN SemAddr;
> + UINTN CpuIndex;
> + SMM_CPU_SYNC_SEMAPHORE_FOR_EACH_CPU *CpuSem;
> +
> + ASSERT (Context != NULL);
> +
> + //
> + // Calculate ContextSize
> + //
> + Status = SafeUintnMult (NumberOfCpus, sizeof
> (SMM_CPU_SYNC_SEMAPHORE_FOR_EACH_CPU), &ContextSize);
> + if (RETURN_ERROR (Status)) {
> + return Status;
> + }
> +
> + Status = SafeUintnAdd (ContextSize, sizeof (SMM_CPU_SYNC_CONTEXT),
> &ContextSize);
> + if (RETURN_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Allocate Buffer for Context
> + //
> + *Context = AllocatePool (ContextSize);
> + if (*Context == NULL) {
> + return RETURN_OUT_OF_RESOURCES;
> + }
> +
> + (*Context)->ArrivedCpuCountUponLock = 0;
> +
> + //
> + // Save NumberOfCpus
> + //
> + (*Context)->NumberOfCpus = NumberOfCpus;
> +
> + //
> + // Calculate total semaphore size
> + //
> + OneSemSize = GetSpinLockProperties ();
> + ASSERT (sizeof (SMM_CPU_SYNC_SEMAPHORE) <= OneSemSize);
> +
> + Status = SafeUintnAdd (1, NumberOfCpus, &NumSem);
> + if (RETURN_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> +
> + Status = SafeUintnMult (NumSem, OneSemSize, &TotalSemSize);
> + if (RETURN_ERROR (Status)) {
> + goto ON_ERROR;
> + }
> +
> + //
> + // Allocate for Semaphores in the *Context
> + //
> + (*Context)->SemBufferPages = EFI_SIZE_TO_PAGES (TotalSemSize);
> + (*Context)->SemBuffer = AllocatePages
> ((*Context)->SemBufferPages);
> + if ((*Context)->SemBuffer == NULL) {
> + Status = RETURN_OUT_OF_RESOURCES;
> + goto ON_ERROR;
> + }
> +
> + //
> + // Assign Global Semaphore pointer
> + //
> + SemAddr = (UINTN)(*Context)->SemBuffer;
> + (*Context)->CpuCount = (SMM_CPU_SYNC_SEMAPHORE *)SemAddr;
> + *(*Context)->CpuCount = 0;
> +
> + SemAddr += OneSemSize;
> +
> + //
> + // Assign CPU Semaphore pointer
> + //
> + CpuSem = (*Context)->CpuSem;
> + for (CpuIndex = 0; CpuIndex < NumberOfCpus; CpuIndex++) {
> + CpuSem->Run = (SMM_CPU_SYNC_SEMAPHORE *)SemAddr;
> + *CpuSem->Run = 0;
> +
> + CpuSem++;
> + SemAddr += OneSemSize;
> + }
> +
> + return RETURN_SUCCESS;
> +
> +ON_ERROR:
> + FreePool (*Context);
> + return Status;
> +}
> +
> +/**
> + 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
> + )
> +{
> + ASSERT (Context != NULL);
> +
> + FreePages (Context->SemBuffer, Context->SemBufferPages);
> +
> + FreePool (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
> + )
> +{
> + ASSERT (Context != NULL);
> +
> + Context->ArrivedCpuCountUponLock = 0;
> + *Context->CpuCount = 0;
> +}
> +
> +/**
> + 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
> + )
> +{
> + UINT32 Value;
> +
> + ASSERT (Context != NULL);
> +
> + Value = *Context->CpuCount;
> +
> + if (Value == (UINT32)-1) {
> + return Context->ArrivedCpuCountUponLock;
> + }
> +
> + return Value;
> +}
> +
> +/**
> + 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
> + )
> +{
> + ASSERT (Context != NULL);
> +
> + ASSERT (CpuIndex < Context->NumberOfCpus);
> +
> + //
> + // Check to return if CpuCount has already been locked.
> + //
> + if (InternalReleaseSemaphore (Context->CpuCount) == MAX_UINT32) {
> + return RETURN_ABORTED;
> + }
> +
> + return RETURN_SUCCESS;
> +}
> +
> +/**
> + 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
> + )
> +{
> + ASSERT (Context != NULL);
> +
> + ASSERT (CpuIndex < Context->NumberOfCpus);
> +
> + if (InternalWaitForSemaphore (Context->CpuCount) == MAX_UINT32) {
> + return RETURN_ABORTED;
> + }
> +
> + return RETURN_SUCCESS;
> +}
> +
> +/**
> + 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
> + )
> +{
> + ASSERT (Context != NULL);
> +
> + ASSERT (CpuCount != NULL);
> +
> + ASSERT (CpuIndex < Context->NumberOfCpus);
> +
> + //
> + // Temporarily record the CpuCount into the ArrivedCpuCountUponLock
> before lock door.
> + // Recording before lock door is to avoid the Context->CpuCount is locked
> but possible
> + // Context->ArrivedCpuCountUponLock is not updated.
> + //
> + Context->ArrivedCpuCountUponLock = *Context->CpuCount;
> +
> + //
> + // Lock door operation
> + //
> + *CpuCount = InternalLockdownSemaphore (Context->CpuCount);
> +
> + //
> + // Update the ArrivedCpuCountUponLock
> + //
> + Context->ArrivedCpuCountUponLock = *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
> + )
> +{
> + UINTN Arrived;
> +
> + ASSERT (Context != NULL);
> +
> + ASSERT (NumberOfAPs < Context->NumberOfCpus);
> +
> + ASSERT (BspIndex < Context->NumberOfCpus);
> +
> + for (Arrived = 0; Arrived < NumberOfAPs; Arrived++) {
> + InternalWaitForSemaphore (Context->CpuSem[BspIndex].Run);
> + }
> +}
> +
> +/**
> + 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
> + )
> +{
> + ASSERT (Context != NULL);
> +
> + ASSERT (BspIndex != CpuIndex);
> +
> + ASSERT (CpuIndex < Context->NumberOfCpus);
> +
> + ASSERT (BspIndex < Context->NumberOfCpus);
> +
> + InternalReleaseSemaphore (Context->CpuSem[CpuIndex].Run);
> +}
> +
> +/**
> + 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
> + )
> +{
> + ASSERT (Context != NULL);
> +
> + ASSERT (BspIndex != CpuIndex);
> +
> + ASSERT (CpuIndex < Context->NumberOfCpus);
> +
> + ASSERT (BspIndex < Context->NumberOfCpus);
> +
> + InternalWaitForSemaphore (Context->CpuSem[CpuIndex].Run);
> +}
> +
> +/**
> + 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
> + )
> +{
> + ASSERT (Context != NULL);
> +
> + ASSERT (BspIndex != CpuIndex);
> +
> + ASSERT (CpuIndex < Context->NumberOfCpus);
> +
> + ASSERT (BspIndex < Context->NumberOfCpus);
> +
> + InternalReleaseSemaphore (Context->CpuSem[BspIndex].Run);
> +}
> diff --git a/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.inf
> b/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.inf
> new file mode 100644
> index 0000000000..6b0d49c30a
> --- /dev/null
> +++ b/UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.inf
> @@ -0,0 +1,34 @@
> +## @file
> +# SMM CPU Synchronization lib.
> +#
> +# This is SMM CPU Synchronization lib used for SMM CPU sync operations.
> +#
> +# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = SmmCpuSyncLib
> + FILE_GUID =
> 1ca1bc1a-16a4-46ef-956a-ca500fd3381f
> + MODULE_TYPE = DXE_SMM_DRIVER
> + LIBRARY_CLASS =
> SmmCpuSyncLib|DXE_SMM_DRIVER
> +
> +[Sources]
> + SmmCpuSyncLib.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + UefiCpuPkg/UefiCpuPkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> + DebugLib
> + MemoryAllocationLib
> + SafeIntLib
> + SynchronizationLib
> +
> +[Pcd]
> +
> +[Protocols]
> diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
> index 074fd77461..28eed85bce 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dsc
> +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> @@ -54,10 +54,11 @@
>
> CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCac
> heMaintenanceLib.inf
> PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
> PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
>
> SmmCpuPlatformHookLib|UefiCpuPkg/Library/SmmCpuPlatformHookLibNull/
> SmmCpuPlatformHookLibNull.inf
>
> SmmCpuFeaturesLib|UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeat
> uresLib.inf
> +
> SmmCpuSyncLib|UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.inf
>
> PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BaseP
> eCoffGetEntryPointLib.inf
>
> PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePe
> CoffExtraActionLibNull.inf
>
> TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/Tpm
> MeasurementLibNull.inf
> CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
> MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
> @@ -154,10 +155,11 @@
>
> UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.inf
>
> UefiCpuPkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLib
> Null.inf
> UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
> UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
>
> UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf
> + UefiCpuPkg/Library/SmmCpuSyncLib/SmmCpuSyncLib.inf
> UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
> UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
> UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
> UefiCpuPkg/SecCore/SecCore.inf
> UefiCpuPkg/SecCore/SecCoreNative.inf
> --
> 2.16.2.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#112716): https://edk2.groups.io/g/devel/message/112716
Mute This Topic: https://groups.io/mt/103259036/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/12367111/7686176/1913456212/xyzzy [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2023-12-19 9:34 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-19 7:18 [edk2-devel] [PATCH v5 0/8] Refine SMM CPU Sync flow and abstract SmmCpuSyncLib Wu, Jiaxin
2023-12-19 7:18 ` [edk2-devel] [PATCH v5 1/8] UefiCpuPkg/PiSmmCpuDxeSmm: Optimize Semaphore Sync between BSP and AP Wu, Jiaxin
2023-12-19 7:18 ` [edk2-devel] [PATCH v5 2/8] UefiCpuPkg: Adds SmmCpuSyncLib library class Wu, Jiaxin
2023-12-19 7:18 ` [edk2-devel] [PATCH v5 3/8] MdePkg/MdeLibs.dsc.inc: Add SafeIntLib instance Wu, Jiaxin
2023-12-19 7:18 ` [edk2-devel] [PATCH v5 4/8] UefiCpuPkg: Implements SmmCpuSyncLib library instance Wu, Jiaxin
2023-12-19 9:34 ` Ni, Ray [this message]
2023-12-19 10:11 ` Wu, Jiaxin
2023-12-19 7:18 ` [edk2-devel] [PATCH v5 5/8] OvmfPkg: Specifies SmmCpuSyncLib instance Wu, Jiaxin
2023-12-19 7:18 ` [edk2-devel] [PATCH v5 6/8] UefiPayloadPkg: " Wu, Jiaxin
2023-12-19 7:18 ` [edk2-devel] [PATCH v5 7/8] UefiCpuPkg/PiSmmCpuDxeSmm: Simplify RunningApCount decrement Wu, Jiaxin
2023-12-19 7:18 ` [edk2-devel] [PATCH v5 8/8] UefiCpuPkg/PiSmmCpuDxeSmm: Consume SmmCpuSyncLib Wu, Jiaxin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MN6PR11MB8244EA26A1646E8F86D4945C8C97A@MN6PR11MB8244.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox