UefiCpuPkg/PiSmmCpuDxeSmm: Enable MM MP Protocol
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1937 Add MM Mp Protocol in PiSmmCpuDxeSmm driver. Cc: Ray Ni <ray.ni@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Signed-off-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
@@ -20,6 +20,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#include <Protocol/SmmReadyToLock.h>
|
||||
#include <Protocol/SmmCpuService.h>
|
||||
#include <Protocol/SmmMemoryAttribute.h>
|
||||
#include <Protocol/MmMp.h>
|
||||
|
||||
#include <Guid/AcpiS3Context.h>
|
||||
#include <Guid/MemoryAttributesTable.h>
|
||||
@@ -197,6 +198,25 @@ typedef UINT32 SMM_CPU_ARRIVAL_EXCEPTIONS;
|
||||
#define ARRIVAL_EXCEPTION_DELAYED 0x2
|
||||
#define ARRIVAL_EXCEPTION_SMI_DISABLED 0x4
|
||||
|
||||
//
|
||||
// Wrapper used to convert EFI_AP_PROCEDURE2 and EFI_AP_PROCEDURE.
|
||||
//
|
||||
typedef struct {
|
||||
EFI_AP_PROCEDURE Procedure;
|
||||
VOID *ProcedureArgument;
|
||||
} PROCEDURE_WRAPPER;
|
||||
|
||||
#define PROCEDURE_TOKEN_SIGNATURE SIGNATURE_32 ('P', 'R', 'T', 'S')
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
SPIN_LOCK *ProcedureToken;
|
||||
} PROCEDURE_TOKEN;
|
||||
|
||||
#define PROCEDURE_TOKEN_FROM_LINK(a) CR (a, PROCEDURE_TOKEN, Link, PROCEDURE_TOKEN_SIGNATURE)
|
||||
|
||||
//
|
||||
// Private structure for the SMM CPU module that is stored in DXE Runtime memory
|
||||
// Contains the SMM Configuration Protocols that is produced.
|
||||
@@ -219,6 +239,10 @@ typedef struct {
|
||||
EFI_SMM_ENTRY_POINT SmmCoreEntry;
|
||||
|
||||
EFI_SMM_CONFIGURATION_PROTOCOL SmmConfiguration;
|
||||
|
||||
PROCEDURE_WRAPPER *ApWrapperFunc;
|
||||
LIST_ENTRY TokenList;
|
||||
|
||||
} SMM_CPU_PRIVATE_DATA;
|
||||
|
||||
extern SMM_CPU_PRIVATE_DATA *gSmmCpuPrivate;
|
||||
@@ -226,6 +250,7 @@ extern CPU_HOT_PLUG_DATA mCpuHotPlugData;
|
||||
extern UINTN mMaxNumberOfCpus;
|
||||
extern UINTN mNumberOfCpus;
|
||||
extern EFI_SMM_CPU_PROTOCOL mSmmCpu;
|
||||
extern EFI_MM_MP_PROTOCOL mSmmMp;
|
||||
|
||||
///
|
||||
/// The mode of the CPU at the time an SMI occurs
|
||||
@@ -363,10 +388,12 @@ SmmRelocationSemaphoreComplete (
|
||||
///
|
||||
typedef struct {
|
||||
SPIN_LOCK *Busy;
|
||||
volatile EFI_AP_PROCEDURE Procedure;
|
||||
volatile EFI_AP_PROCEDURE2 Procedure;
|
||||
volatile VOID *Parameter;
|
||||
volatile UINT32 *Run;
|
||||
volatile BOOLEAN *Present;
|
||||
SPIN_LOCK *Token;
|
||||
EFI_STATUS *Status;
|
||||
} SMM_CPU_DATA_BLOCK;
|
||||
|
||||
typedef enum {
|
||||
@@ -388,6 +415,8 @@ typedef struct {
|
||||
volatile SMM_CPU_SYNC_MODE EffectiveSyncMode;
|
||||
volatile BOOLEAN SwitchBsp;
|
||||
volatile BOOLEAN *CandidateBsp;
|
||||
EFI_AP_PROCEDURE StartupProcedure;
|
||||
VOID *StartupProcArgs;
|
||||
} SMM_DISPATCHER_MP_SYNC_DATA;
|
||||
|
||||
#define SMM_PSD_OFFSET 0xfb00
|
||||
@@ -410,6 +439,7 @@ typedef struct {
|
||||
SPIN_LOCK *Busy;
|
||||
volatile UINT32 *Run;
|
||||
volatile BOOLEAN *Present;
|
||||
SPIN_LOCK *Token;
|
||||
} SMM_CPU_SEMAPHORE_CPU;
|
||||
|
||||
///
|
||||
@@ -1259,4 +1289,165 @@ RestoreCr2 (
|
||||
IN UINTN Cr2
|
||||
);
|
||||
|
||||
/**
|
||||
Schedule a procedure to run on the specified CPU.
|
||||
|
||||
@param[in] Procedure The address of the procedure to run
|
||||
@param[in] CpuIndex Target CPU Index
|
||||
@param[in,out] ProcArguments The parameter to pass to the procedure
|
||||
@param[in,out] Token This is an optional parameter that allows the caller to execute the
|
||||
procedure in a blocking or non-blocking fashion. If it is NULL the
|
||||
call is blocking, and the call will not return until the AP has
|
||||
completed the procedure. If the token is not NULL, the call will
|
||||
return immediately. The caller can check whether the procedure has
|
||||
completed with CheckOnProcedure or WaitForProcedure.
|
||||
@param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for the APs to finish
|
||||
execution of Procedure, either for blocking or non-blocking mode.
|
||||
Zero means infinity. If the timeout expires before all APs return
|
||||
from Procedure, then Procedure on the failed APs is terminated. If
|
||||
the timeout expires in blocking mode, the call returns EFI_TIMEOUT.
|
||||
If the timeout expires in non-blocking mode, the timeout determined
|
||||
can be through CheckOnProcedure or WaitForProcedure.
|
||||
Note that timeout support is optional. Whether an implementation
|
||||
supports this feature can be determined via the Attributes data
|
||||
member.
|
||||
@param[in,out] CPUStatus This optional pointer may be used to get the status code returned
|
||||
by Procedure when it completes execution on the target AP, or with
|
||||
EFI_TIMEOUT if the Procedure fails to complete within the optional
|
||||
timeout. The implementation will update this variable with
|
||||
EFI_NOT_READY prior to starting Procedure on the target AP.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER CpuNumber not valid
|
||||
@retval EFI_INVALID_PARAMETER CpuNumber specifying BSP
|
||||
@retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM
|
||||
@retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy
|
||||
@retval EFI_SUCCESS The procedure has been successfully scheduled
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
InternalSmmStartupThisAp (
|
||||
IN EFI_AP_PROCEDURE2 Procedure,
|
||||
IN UINTN CpuIndex,
|
||||
IN OUT VOID *ProcArguments OPTIONAL,
|
||||
IN MM_COMPLETION *Token,
|
||||
IN UINTN TimeoutInMicroseconds,
|
||||
IN OUT EFI_STATUS *CpuStatus
|
||||
);
|
||||
|
||||
/**
|
||||
Checks whether the input token is the current used token.
|
||||
|
||||
@param[in] Token This parameter describes the token that was passed into DispatchProcedure or
|
||||
BroadcastProcedure.
|
||||
|
||||
@retval TRUE The input token is the current used token.
|
||||
@retval FALSE The input token is not the current used token.
|
||||
**/
|
||||
BOOLEAN
|
||||
IsTokenInUse (
|
||||
IN SPIN_LOCK *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Checks status of specified AP.
|
||||
|
||||
This function checks whether the specified AP has finished the task assigned
|
||||
by StartupThisAP(), and whether timeout expires.
|
||||
|
||||
@param[in] Token This parameter describes the token that was passed into DispatchProcedure or
|
||||
BroadcastProcedure.
|
||||
|
||||
@retval EFI_SUCCESS Specified AP has finished task assigned by StartupThisAPs().
|
||||
@retval EFI_NOT_READY Specified AP has not finished task and timeout has not expired.
|
||||
**/
|
||||
EFI_STATUS
|
||||
IsApReady (
|
||||
IN SPIN_LOCK *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether it is an present AP.
|
||||
|
||||
@param CpuIndex The AP index which calls this function.
|
||||
|
||||
@retval TRUE It's a present AP.
|
||||
@retval TRUE This is not an AP or it is not present.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsPresentAp (
|
||||
IN UINTN CpuIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Worker function to execute a caller provided function on all enabled APs.
|
||||
|
||||
@param[in] Procedure A pointer to the function to be run on
|
||||
enabled APs of the system.
|
||||
@param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
|
||||
APs to return from Procedure, either for
|
||||
blocking or non-blocking mode.
|
||||
@param[in,out] ProcedureArgument The parameter passed into Procedure for
|
||||
all APs.
|
||||
@param[in,out] Token This is an optional parameter that allows the caller to execute the
|
||||
procedure in a blocking or non-blocking fashion. If it is NULL the
|
||||
call is blocking, and the call will not return until the AP has
|
||||
completed the procedure. If the token is not NULL, the call will
|
||||
return immediately. The caller can check whether the procedure has
|
||||
completed with CheckOnProcedure or WaitForProcedure.
|
||||
@param[in,out] CPUStatus This optional pointer may be used to get the status code returned
|
||||
by Procedure when it completes execution on the target AP, or with
|
||||
EFI_TIMEOUT if the Procedure fails to complete within the optional
|
||||
timeout. The implementation will update this variable with
|
||||
EFI_NOT_READY prior to starting Procedure on the target AP.
|
||||
|
||||
@retval EFI_SUCCESS In blocking mode, all APs have finished before
|
||||
the timeout expired.
|
||||
@retval EFI_SUCCESS In non-blocking mode, function has been dispatched
|
||||
to all enabled APs.
|
||||
@retval others Failed to Startup all APs.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
InternalSmmStartupAllAPs (
|
||||
IN EFI_AP_PROCEDURE2 Procedure,
|
||||
IN UINTN TimeoutInMicroseconds,
|
||||
IN OUT VOID *ProcedureArguments OPTIONAL,
|
||||
IN OUT MM_COMPLETION *Token,
|
||||
IN OUT EFI_STATUS *CPUStatus
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Register the SMM Foundation entry point.
|
||||
|
||||
@param[in] Procedure A pointer to the code stream to be run on the designated target AP
|
||||
of the system. Type EFI_AP_PROCEDURE is defined below in Volume 2
|
||||
with the related definitions of
|
||||
EFI_MP_SERVICES_PROTOCOL.StartupAllAPs.
|
||||
If caller may pass a value of NULL to deregister any existing
|
||||
startup procedure.
|
||||
@param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code that is
|
||||
run by the AP. It is an optional common mailbox between APs and
|
||||
the caller to share information
|
||||
|
||||
@retval EFI_SUCCESS The Procedure has been set successfully.
|
||||
@retval EFI_INVALID_PARAMETER The Procedure is NULL but ProcedureArguments not NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
RegisterStartupProcedure (
|
||||
IN EFI_AP_PROCEDURE Procedure,
|
||||
IN VOID *ProcedureArguments OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate buffer for SpinLock and Wrapper function buffer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeDataForMmMp (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user