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:
Eric Dong
2019-07-10 15:49:11 +08:00
parent 18f169a95c
commit 51dd408ae1
6 changed files with 1391 additions and 25 deletions

View File

@@ -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