Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>\r
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <Protocol/SmmReadyToLock.h>\r
#include <Protocol/SmmCpuService.h>\r
#include <Protocol/SmmMemoryAttribute.h>\r
+#include <Protocol/MmMp.h>\r
\r
#include <Guid/AcpiS3Context.h>\r
#include <Guid/MemoryAttributesTable.h>\r
#include <AcpiCpuData.h>\r
#include <CpuHotPlugData.h>\r
\r
-#include <Register/Cpuid.h>\r
-#include <Register/Msr.h>\r
+#include <Register/Intel/Cpuid.h>\r
+#include <Register/Intel/Msr.h>\r
\r
#include "CpuService.h"\r
#include "SmmProfile.h"\r
#define ARRIVAL_EXCEPTION_DELAYED 0x2\r
#define ARRIVAL_EXCEPTION_SMI_DISABLED 0x4\r
\r
+//\r
+// Wrapper used to convert EFI_AP_PROCEDURE2 and EFI_AP_PROCEDURE.\r
+//\r
+typedef struct {\r
+ EFI_AP_PROCEDURE Procedure;\r
+ VOID *ProcedureArgument;\r
+} PROCEDURE_WRAPPER;\r
+\r
+#define PROCEDURE_TOKEN_SIGNATURE SIGNATURE_32 ('P', 'R', 'T', 'S')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ SPIN_LOCK *ProcedureToken;\r
+} PROCEDURE_TOKEN;\r
+\r
+#define PROCEDURE_TOKEN_FROM_LINK(a) CR (a, PROCEDURE_TOKEN, Link, PROCEDURE_TOKEN_SIGNATURE)\r
+\r
//\r
// Private structure for the SMM CPU module that is stored in DXE Runtime memory\r
// Contains the SMM Configuration Protocols that is produced.\r
EFI_SMM_ENTRY_POINT SmmCoreEntry;\r
\r
EFI_SMM_CONFIGURATION_PROTOCOL SmmConfiguration;\r
+\r
+ PROCEDURE_WRAPPER *ApWrapperFunc;\r
+ LIST_ENTRY TokenList;\r
+\r
} SMM_CPU_PRIVATE_DATA;\r
\r
extern SMM_CPU_PRIVATE_DATA *gSmmCpuPrivate;\r
extern UINTN mMaxNumberOfCpus;\r
extern UINTN mNumberOfCpus;\r
extern EFI_SMM_CPU_PROTOCOL mSmmCpu;\r
+extern EFI_MM_MP_PROTOCOL mSmmMp;\r
\r
///\r
/// The mode of the CPU at the time an SMI occurs\r
///\r
typedef struct {\r
SPIN_LOCK *Busy;\r
- volatile EFI_AP_PROCEDURE Procedure;\r
+ volatile EFI_AP_PROCEDURE2 Procedure;\r
volatile VOID *Parameter;\r
volatile UINT32 *Run;\r
volatile BOOLEAN *Present;\r
+ SPIN_LOCK *Token;\r
+ EFI_STATUS *Status;\r
} SMM_CPU_DATA_BLOCK;\r
\r
typedef enum {\r
volatile SMM_CPU_SYNC_MODE EffectiveSyncMode;\r
volatile BOOLEAN SwitchBsp;\r
volatile BOOLEAN *CandidateBsp;\r
+ EFI_AP_PROCEDURE StartupProcedure;\r
+ VOID *StartupProcArgs;\r
} SMM_DISPATCHER_MP_SYNC_DATA;\r
\r
#define SMM_PSD_OFFSET 0xfb00\r
SPIN_LOCK *Busy;\r
volatile UINT32 *Run;\r
volatile BOOLEAN *Present;\r
+ SPIN_LOCK *Token;\r
} SMM_CPU_SEMAPHORE_CPU;\r
\r
///\r
PiSmmCpuSmiEntryFixupAddress (\r
);\r
\r
+/**\r
+ This function reads CR2 register when on-demand paging is enabled\r
+ for 64 bit and no action for 32 bit.\r
+\r
+ @param[out] *Cr2 Pointer to variable to hold CR2 register value.\r
+**/\r
+VOID\r
+SaveCr2 (\r
+ OUT UINTN *Cr2\r
+ );\r
+\r
+/**\r
+ This function writes into CR2 register when on-demand paging is enabled\r
+ for 64 bit and no action for 32 bit.\r
+\r
+ @param[in] Cr2 Value to write into CR2 register.\r
+**/\r
+VOID\r
+RestoreCr2 (\r
+ IN UINTN Cr2\r
+ );\r
+\r
+/**\r
+ Schedule a procedure to run on the specified CPU.\r
+\r
+ @param[in] Procedure The address of the procedure to run\r
+ @param[in] CpuIndex Target CPU Index\r
+ @param[in,out] ProcArguments The parameter to pass to the procedure\r
+ @param[in,out] Token This is an optional parameter that allows the caller to execute the\r
+ procedure in a blocking or non-blocking fashion. If it is NULL the\r
+ call is blocking, and the call will not return until the AP has\r
+ completed the procedure. If the token is not NULL, the call will\r
+ return immediately. The caller can check whether the procedure has\r
+ completed with CheckOnProcedure or WaitForProcedure.\r
+ @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for the APs to finish\r
+ execution of Procedure, either for blocking or non-blocking mode.\r
+ Zero means infinity. If the timeout expires before all APs return\r
+ from Procedure, then Procedure on the failed APs is terminated. If\r
+ the timeout expires in blocking mode, the call returns EFI_TIMEOUT.\r
+ If the timeout expires in non-blocking mode, the timeout determined\r
+ can be through CheckOnProcedure or WaitForProcedure.\r
+ Note that timeout support is optional. Whether an implementation\r
+ supports this feature can be determined via the Attributes data\r
+ member.\r
+ @param[in,out] CpuStatus This optional pointer may be used to get the status code returned\r
+ by Procedure when it completes execution on the target AP, or with\r
+ EFI_TIMEOUT if the Procedure fails to complete within the optional\r
+ timeout. The implementation will update this variable with\r
+ EFI_NOT_READY prior to starting Procedure on the target AP.\r
+\r
+ @retval EFI_INVALID_PARAMETER CpuNumber not valid\r
+ @retval EFI_INVALID_PARAMETER CpuNumber specifying BSP\r
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber did not enter SMM\r
+ @retval EFI_INVALID_PARAMETER The AP specified by CpuNumber is busy\r
+ @retval EFI_SUCCESS The procedure has been successfully scheduled\r
+\r
+**/\r
+EFI_STATUS\r
+InternalSmmStartupThisAp (\r
+ IN EFI_AP_PROCEDURE2 Procedure,\r
+ IN UINTN CpuIndex,\r
+ IN OUT VOID *ProcArguments OPTIONAL,\r
+ IN OUT MM_COMPLETION *Token,\r
+ IN UINTN TimeoutInMicroseconds,\r
+ IN OUT EFI_STATUS *CpuStatus\r
+ );\r
+\r
+/**\r
+ Checks whether the input token is the current used token.\r
+\r
+ @param[in] Token This parameter describes the token that was passed into DispatchProcedure or\r
+ BroadcastProcedure.\r
+\r
+ @retval TRUE The input token is the current used token.\r
+ @retval FALSE The input token is not the current used token.\r
+**/\r
+BOOLEAN\r
+IsTokenInUse (\r
+ IN SPIN_LOCK *Token\r
+ );\r
+\r
+/**\r
+ Checks status of specified AP.\r
+\r
+ This function checks whether the specified AP has finished the task assigned\r
+ by StartupThisAP(), and whether timeout expires.\r
+\r
+ @param[in] Token This parameter describes the token that was passed into DispatchProcedure or\r
+ BroadcastProcedure.\r
+\r
+ @retval EFI_SUCCESS Specified AP has finished task assigned by StartupThisAPs().\r
+ @retval EFI_NOT_READY Specified AP has not finished task and timeout has not expired.\r
+**/\r
+EFI_STATUS\r
+IsApReady (\r
+ IN SPIN_LOCK *Token\r
+ );\r
+\r
+/**\r
+ Check whether it is an present AP.\r
+\r
+ @param CpuIndex The AP index which calls this function.\r
+\r
+ @retval TRUE It's a present AP.\r
+ @retval TRUE This is not an AP or it is not present.\r
+\r
+**/\r
+BOOLEAN\r
+IsPresentAp (\r
+ IN UINTN CpuIndex\r
+ );\r
+\r
+/**\r
+ Worker function to execute a caller provided function on all enabled APs.\r
+\r
+ @param[in] Procedure A pointer to the function to be run on\r
+ enabled APs of the system.\r
+ @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
+ APs to return from Procedure, either for\r
+ blocking or non-blocking mode.\r
+ @param[in,out] ProcedureArguments The parameter passed into Procedure for\r
+ all APs.\r
+ @param[in,out] Token This is an optional parameter that allows the caller to execute the\r
+ procedure in a blocking or non-blocking fashion. If it is NULL the\r
+ call is blocking, and the call will not return until the AP has\r
+ completed the procedure. If the token is not NULL, the call will\r
+ return immediately. The caller can check whether the procedure has\r
+ completed with CheckOnProcedure or WaitForProcedure.\r
+ @param[in,out] CPUStatus This optional pointer may be used to get the status code returned\r
+ by Procedure when it completes execution on the target AP, or with\r
+ EFI_TIMEOUT if the Procedure fails to complete within the optional\r
+ timeout. The implementation will update this variable with\r
+ EFI_NOT_READY prior to starting Procedure on the target AP.\r
+\r
+ @retval EFI_SUCCESS In blocking mode, all APs have finished before\r
+ the timeout expired.\r
+ @retval EFI_SUCCESS In non-blocking mode, function has been dispatched\r
+ to all enabled APs.\r
+ @retval others Failed to Startup all APs.\r
+\r
+**/\r
+EFI_STATUS\r
+InternalSmmStartupAllAPs (\r
+ IN EFI_AP_PROCEDURE2 Procedure,\r
+ IN UINTN TimeoutInMicroseconds,\r
+ IN OUT VOID *ProcedureArguments OPTIONAL,\r
+ IN OUT MM_COMPLETION *Token,\r
+ IN OUT EFI_STATUS *CPUStatus\r
+ );\r
+\r
+/**\r
+\r
+ Register the SMM Foundation entry point.\r
+\r
+ @param[in] Procedure A pointer to the code stream to be run on the designated target AP\r
+ of the system. Type EFI_AP_PROCEDURE is defined below in Volume 2\r
+ with the related definitions of\r
+ EFI_MP_SERVICES_PROTOCOL.StartupAllAPs.\r
+ If caller may pass a value of NULL to deregister any existing\r
+ startup procedure.\r
+ @param[in,out] ProcedureArguments Allows the caller to pass a list of parameters to the code that is\r
+ run by the AP. It is an optional common mailbox between APs and\r
+ the caller to share information\r
+\r
+ @retval EFI_SUCCESS The Procedure has been set successfully.\r
+ @retval EFI_INVALID_PARAMETER The Procedure is NULL but ProcedureArguments not NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterStartupProcedure (\r
+ IN EFI_AP_PROCEDURE Procedure,\r
+ IN OUT VOID *ProcedureArguments OPTIONAL\r
+ );\r
+\r
+/**\r
+ Allocate buffer for SpinLock and Wrapper function buffer.\r
+\r
+**/\r
+VOID\r
+InitializeDataForMmMp (\r
+ VOID\r
+ );\r
+\r
#endif\r