UefiCpuPkg: Extend SMM CPU Service with rendezvous support.

REF? https://bugzilla.tianocore.org/show_bug.cgi?id=3815

This patch define a new Protocol with the new services
SmmWaitForAllProcessor(), which can be used by SMI handler
to optionally wait for other APs to complete SMM rendezvous in
relaxed AP mode.

A new library SmmCpuRendezvousLib is provided to abstract the service
into library API to simple SMI handler code.

Cc: Eric Dong <eric.dong@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Cc: Zhihao Li <zhihao.li@intel.com>

Signed-off-by: Zhihao Li <zhihao.li@intel.com>
This commit is contained in:
Li, Zhihao 2022-03-01 19:22:19 +08:00 committed by mergify[bot]
parent b83d0a6438
commit 4a68176cb5
10 changed files with 322 additions and 12 deletions

View File

@ -0,0 +1,27 @@
/** @file
SMM CPU Rendezvous library header file.
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef SMM_CPU_RENDEZVOUS_H_
#define SMM_CPU_RENDEZVOUS_H_
/**
This routine wait for all AP processors to arrive in SMM.
@param[in] BlockingMode Blocking mode or non-blocking mode.
@retval EFI_SUCCESS All processors checked in to SMM.
@retval EFI_TIMEOUT Wait for all APs until timeout.
**/
EFI_STATUS
EFIAPI
SmmWaitForAllProcessor (
IN BOOLEAN BlockingMode
);
#endif

View File

@ -1,7 +1,7 @@
/** @file /** @file
SMM CPU Service protocol definition. SMM CPU Service protocol definition.
Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2013 - 2022, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
@ -200,4 +200,38 @@ struct _EFI_SMM_CPU_SERVICE_PROTOCOL {
extern EFI_GUID gEfiSmmCpuServiceProtocolGuid; extern EFI_GUID gEfiSmmCpuServiceProtocolGuid;
//
// EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL provide SMM CPU
// rendezvous service support.
//
#define EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL_GUID \
{ \
0xaa00d50b, 0x4911, 0x428f, { 0xb9, 0x1a, 0xa5, 0x9d, 0xdb, 0x13, 0xe2, 0x4c } \
}
typedef struct _EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL;
/**
Wait for all APs to arrive SMM mode in given timeout constraint.
@param[in] This A pointer to the EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL instance.
@param[in] BlockingMode Block or non-block mode.
@retval EFI_SUCCESS All APs have arrived SMM mode except SMI disabled APs.
@retval EFI_TIMEOUT There are APs not in SMM mode in given timeout constraint.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_WAIT_FOR_ALL_PROCESSOR)(
IN EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL *This,
IN BOOLEAN BlockingMode
);
struct _EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL {
EDKII_WAIT_FOR_ALL_PROCESSOR WaitForAllProcessor;
};
extern EFI_GUID gEdkiiSmmCpuRendezvousProtocolGuid;
#endif #endif

View File

@ -0,0 +1,103 @@
/** @file
SMM CPU Rendezvous sevice implement.
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Base.h>
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/MmServicesTableLib.h>
#include <Protocol/SmmCpuService.h>
#include <Library/SmmCpuRendezvousLib.h>
STATIC EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL *mSmmCpuRendezvous = NULL;
STATIC VOID *mRegistration = NULL;
/**
Callback function to wait Smm cpu rendezvous service located.
SmmCpuRendezvousLib need to support MM_STANDALONE and DXE_SMM_DRIVER driver.
So do not use library constructor to locate the protocol.
@param[in] Protocol Points to the protocol's unique identifier.
@param[in] Interface Points to the interface instance.
@param[in] Handle The handle on which the interface was installed.
@retval EFI_SUCCESS Notification runs successfully.
**/
EFI_STATUS
EFIAPI
SmmCpuRendezvousProtocolNotify (
IN CONST EFI_GUID *Protocol,
IN VOID *Interface,
IN EFI_HANDLE Handle
)
{
EFI_STATUS Status;
Status = gMmst->MmLocateProtocol (
&gEdkiiSmmCpuRendezvousProtocolGuid,
NULL,
(VOID **)&mSmmCpuRendezvous
);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
/**
This routine wait for all AP processors to arrive in SMM.
@param[in] BlockingMode Blocking mode or non-blocking mode.
@retval EFI_SUCCESS All avaiable APs arrived.
@retval EFI_TIMEOUT Wait for all APs until timeout.
@retval OTHER Fail to register SMM CPU Rendezvous service Protocol.
**/
EFI_STATUS
EFIAPI
SmmWaitForAllProcessor (
IN BOOLEAN BlockingMode
)
{
EFI_STATUS Status;
if ((mRegistration == NULL) && (mSmmCpuRendezvous == NULL)) {
//
// Locate SMM cpu rendezvous protocol for the first time execute the function.
//
Status = gMmst->MmLocateProtocol (
&gEdkiiSmmCpuRendezvousProtocolGuid,
NULL,
(VOID **)&mSmmCpuRendezvous
);
if (EFI_ERROR (Status)) {
Status = gMmst->MmRegisterProtocolNotify (
&gEdkiiSmmCpuRendezvousProtocolGuid,
SmmCpuRendezvousProtocolNotify,
&mRegistration
);
if (EFI_ERROR (Status)) {
return Status;
}
}
}
//
// The platform have not set up. It doesn't need smm cpu rendezvous.
//
if (mSmmCpuRendezvous == NULL) {
return EFI_SUCCESS;
}
Status = mSmmCpuRendezvous->WaitForAllProcessor (
mSmmCpuRendezvous,
BlockingMode
);
return Status;
}

View File

@ -0,0 +1,35 @@
## @file
# SMM CPU Rendezvous service lib.
#
# This is SMM CPU rendezvous service lib that wait for all
# APs to enter SMM mode.
#
# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SmmCpuRendezvousLib
FILE_GUID = 1509Bb36-9Ba4-438B-B195-Ac5914Db14E2
MODULE_TYPE = DXE_SMM_DRIVER
LIBRARY_CLASS = SmmCpuRendezvousLib|MM_STANDALONE DXE_SMM_DRIVER
[Sources]
SmmCpuRendezvousLib.c
[Packages]
MdePkg/MdePkg.dec
UefiCpuPkg/UefiCpuPkg.dec
[LibraryClasses]
BaseLib
DebugLib
MmServicesTableLib
[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmApSyncTimeout ## CONSUMES
[Protocols]
gEdkiiSmmCpuRendezvousProtocolGuid

View File

@ -1,7 +1,7 @@
/** @file /** @file
Implementation of SMM CPU Services Protocol. Implementation of SMM CPU Services Protocol.
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2011 - 2022, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
@ -20,6 +20,13 @@ EFI_SMM_CPU_SERVICE_PROTOCOL mSmmCpuService = {
SmmRegisterExceptionHandler SmmRegisterExceptionHandler
}; };
//
// EDKII SMM CPU Rendezvous Service Protocol instance
//
EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL mSmmCpuRendezvousService = {
SmmCpuRendezvous
};
/** /**
Gets processor information on the requested processor at the instant this call is made. Gets processor information on the requested processor at the instant this call is made.
@ -350,6 +357,7 @@ SmmRegisterExceptionHandler (
@param ImageHandle The firmware allocated handle for the EFI image. @param ImageHandle The firmware allocated handle for the EFI image.
@retval EFI_SUCCESS EFI SMM CPU Services Protocol was installed successfully. @retval EFI_SUCCESS EFI SMM CPU Services Protocol was installed successfully.
@retval OTHER Fail to install Protocol.
**/ **/
EFI_STATUS EFI_STATUS
InitializeSmmCpuServices ( InitializeSmmCpuServices (
@ -365,5 +373,64 @@ InitializeSmmCpuServices (
&mSmmCpuService &mSmmCpuService
); );
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gSmst->SmmInstallProtocolInterface (
&Handle,
&gEdkiiSmmCpuRendezvousProtocolGuid,
EFI_NATIVE_INTERFACE,
&mSmmCpuRendezvousService
);
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
Wait for all processors enterring SMM until all CPUs are already synchronized or not.
If BlockingMode is False, timeout value is zero.
@param This A pointer to the EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL instance.
@param BlockingMode Blocking mode or non-blocking mode.
@retval EFI_SUCCESS All avaiable APs arrived.
@retval EFI_TIMEOUT Wait for all APs until timeout.
**/
EFI_STATUS
EFIAPI
SmmCpuRendezvous (
IN EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL *This,
IN BOOLEAN BlockingMode
)
{
EFI_STATUS Status;
//
// Return success immediately if all CPUs are already synchronized.
//
if (mSmmMpSyncData->AllApArrivedWithException) {
Status = EFI_SUCCESS;
goto ON_EXIT;
}
if (!BlockingMode) {
Status = EFI_TIMEOUT;
goto ON_EXIT;
}
//
// There are some APs outside SMM, Wait for all avaiable APs to arrive.
//
SmmWaitForApArrival ();
Status = mSmmMpSyncData->AllApArrivedWithException ? EFI_SUCCESS : EFI_TIMEOUT;
ON_EXIT:
if (!mSmmMpSyncData->AllApArrivedWithException) {
DEBUG ((DEBUG_INFO, "EdkiiSmmWaitForAllApArrival: Timeout to wait all APs arrival\n"));
}
return Status; return Status;
} }

View File

@ -1,7 +1,7 @@
/** @file /** @file
SMM MP service implementation SMM MP service implementation
Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR> Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
@ -293,10 +293,14 @@ SmmWaitForApArrival (
// Sync with APs 1st timeout // Sync with APs 1st timeout
// //
for (Timer = StartSyncTimer (); for (Timer = StartSyncTimer ();
!IsSyncTimerTimeout (Timer) && !(LmceEn && LmceSignal) && !IsSyncTimerTimeout (Timer) && !(LmceEn && LmceSignal);
!AllCpusInSmmWithExceptions (ARRIVAL_EXCEPTION_BLOCKED | ARRIVAL_EXCEPTION_SMI_DISABLED);
) )
{ {
mSmmMpSyncData->AllApArrivedWithException = AllCpusInSmmWithExceptions (ARRIVAL_EXCEPTION_BLOCKED | ARRIVAL_EXCEPTION_SMI_DISABLED);
if (mSmmMpSyncData->AllApArrivedWithException) {
break;
}
CpuPause (); CpuPause ();
} }
@ -330,10 +334,14 @@ SmmWaitForApArrival (
// Sync with APs 2nd timeout. // Sync with APs 2nd timeout.
// //
for (Timer = StartSyncTimer (); for (Timer = StartSyncTimer ();
!IsSyncTimerTimeout (Timer) && !IsSyncTimerTimeout (Timer);
!AllCpusInSmmWithExceptions (ARRIVAL_EXCEPTION_BLOCKED | ARRIVAL_EXCEPTION_SMI_DISABLED);
) )
{ {
mSmmMpSyncData->AllApArrivedWithException = AllCpusInSmmWithExceptions (ARRIVAL_EXCEPTION_BLOCKED | ARRIVAL_EXCEPTION_SMI_DISABLED);
if (mSmmMpSyncData->AllApArrivedWithException) {
break;
}
CpuPause (); CpuPause ();
} }
} }
@ -1887,6 +1895,8 @@ InitializeMpSyncData (
*mSmmMpSyncData->InsideSmm = FALSE; *mSmmMpSyncData->InsideSmm = FALSE;
*mSmmMpSyncData->AllCpusInSync = FALSE; *mSmmMpSyncData->AllCpusInSync = FALSE;
mSmmMpSyncData->AllApArrivedWithException = FALSE;
for (CpuIndex = 0; CpuIndex < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; CpuIndex++) { for (CpuIndex = 0; CpuIndex < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; CpuIndex++) {
mSmmMpSyncData->CpuData[CpuIndex].Busy = mSmmMpSyncData->CpuData[CpuIndex].Busy =
(SPIN_LOCK *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Busy + mSemaphoreSize * CpuIndex); (SPIN_LOCK *)((UINTN)mSmmCpuSemaphores.SemaphoreCpu.Busy + mSemaphoreSize * CpuIndex);

View File

@ -1,7 +1,7 @@
/** @file /** @file
Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU. Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR> Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
@ -428,6 +428,7 @@ typedef struct {
volatile SMM_CPU_SYNC_MODE EffectiveSyncMode; volatile SMM_CPU_SYNC_MODE EffectiveSyncMode;
volatile BOOLEAN SwitchBsp; volatile BOOLEAN SwitchBsp;
volatile BOOLEAN *CandidateBsp; volatile BOOLEAN *CandidateBsp;
volatile BOOLEAN AllApArrivedWithException;
EFI_AP_PROCEDURE StartupProcedure; EFI_AP_PROCEDURE StartupProcedure;
VOID *StartupProcArgs; VOID *StartupProcArgs;
} SMM_DISPATCHER_MP_SYNC_DATA; } SMM_DISPATCHER_MP_SYNC_DATA;
@ -1488,4 +1489,30 @@ IsRestrictedMemoryAccess (
VOID VOID
); );
/**
Choose blocking or non-blocking mode to Wait for all APs.
@param[in] This A pointer to the EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL instance.
@param[in] BlockingMode Blocking or non-blocking mode.
@retval EFI_SUCCESS All APs have arrived SMM mode except SMI disabled APs.
@retval EFI_TIMEOUT There are APs not in SMM mode in given timeout constraint.
**/
EFI_STATUS
EFIAPI
SmmCpuRendezvous (
IN EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL *This,
IN BOOLEAN BlockingMode
);
/**
Insure when this function returns, no AP will execute normal mode code before entering SMM, except SMI disabled APs.
**/
VOID
SmmWaitForApArrival (
VOID
);
#endif #endif

View File

@ -4,7 +4,7 @@
# This SMM driver performs SMM initialization, deploy SMM Entry Vector, # This SMM driver performs SMM initialization, deploy SMM Entry Vector,
# provides CPU specific services in SMM. # provides CPU specific services in SMM.
# #
# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> # Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
# #
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
@ -108,6 +108,7 @@
gEfiSmmCpuServiceProtocolGuid ## PRODUCES gEfiSmmCpuServiceProtocolGuid ## PRODUCES
gEdkiiSmmMemoryAttributeProtocolGuid ## PRODUCES gEdkiiSmmMemoryAttributeProtocolGuid ## PRODUCES
gEfiMmMpProtocolGuid ## PRODUCES gEfiMmMpProtocolGuid ## PRODUCES
gEdkiiSmmCpuRendezvousProtocolGuid ## PRODUCES
[Guids] [Guids]
gEfiAcpiVariableGuid ## SOMETIMES_CONSUMES ## HOB # it is used for S3 boot. gEfiAcpiVariableGuid ## SOMETIMES_CONSUMES ## HOB # it is used for S3 boot.

View File

@ -1,7 +1,7 @@
## @file UefiCpuPkg.dec ## @file UefiCpuPkg.dec
# This Package provides UEFI compatible CPU modules and libraries. # This Package provides UEFI compatible CPU modules and libraries.
# #
# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2007 - 2022, Intel Corporation. All rights reserved.<BR>
# #
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
# #
@ -62,6 +62,9 @@
## @libraryclass Provides function for loading microcode. ## @libraryclass Provides function for loading microcode.
MicrocodeLib|Include/Library/MicrocodeLib.h MicrocodeLib|Include/Library/MicrocodeLib.h
## @libraryclass Provides function for SMM CPU Rendezvous Library.
SmmCpuRendezvousLib|Include/Library/SmmCpuRendezvousLib.h
[Guids] [Guids]
gUefiCpuPkgTokenSpaceGuid = { 0xac05bf33, 0x995a, 0x4ed4, { 0xaa, 0xb8, 0xef, 0x7a, 0xe8, 0xf, 0x5c, 0xb0 }} gUefiCpuPkgTokenSpaceGuid = { 0xac05bf33, 0x995a, 0x4ed4, { 0xaa, 0xb8, 0xef, 0x7a, 0xe8, 0xf, 0x5c, 0xb0 }}
gMsegSmramGuid = { 0x5802bce4, 0xeeee, 0x4e33, { 0xa1, 0x30, 0xeb, 0xad, 0x27, 0xf0, 0xe4, 0x39 }} gMsegSmramGuid = { 0x5802bce4, 0xeeee, 0x4e33, { 0xa1, 0x30, 0xeb, 0xad, 0x27, 0xf0, 0xe4, 0x39 }}
@ -78,6 +81,7 @@
[Protocols] [Protocols]
## Include/Protocol/SmmCpuService.h ## Include/Protocol/SmmCpuService.h
gEfiSmmCpuServiceProtocolGuid = { 0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 }} gEfiSmmCpuServiceProtocolGuid = { 0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 }}
gEdkiiSmmCpuRendezvousProtocolGuid = { 0xaa00d50b, 0x4911, 0x428f, { 0xb9, 0x1a, 0xa5, 0x9d, 0xdb, 0x13, 0xe2, 0x4c }}
## Include/Protocol/SmMonitorInit.h ## Include/Protocol/SmMonitorInit.h
gEfiSmMonitorInitProtocolGuid = { 0x228f344d, 0xb3de, 0x43bb, { 0xa4, 0xd7, 0xea, 0x20, 0xb, 0x1b, 0x14, 0x82 }} gEfiSmMonitorInitProtocolGuid = { 0x228f344d, 0xb3de, 0x43bb, { 0xa4, 0xd7, 0xea, 0x20, 0xb, 0x1b, 0x14, 0x82 }}

View File

@ -61,6 +61,7 @@
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
SmmCpuRendezvousLib|UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf
[LibraryClasses.common.SEC] [LibraryClasses.common.SEC]
PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@ -173,6 +174,7 @@
} }
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf
UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf
[BuildOptions] [BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES