Add DisableAp/EnableAp.

to notify CPU driver on convert MONITOR wakeup to HLT wakeup.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
This commit is contained in:
Jiewen Yao 2016-10-28 21:42:02 +08:00
parent acbdef4d55
commit 25c4e6b9a5
2 changed files with 171 additions and 17 deletions

View File

@ -52,6 +52,8 @@ FRM_COMMUNICATION_DATA mCommunicationData = {
EFI_GUID gFrmFileName = FRM_FILE_GUID_NAME;
EFI_GUID gStmServiceFileName = STM_SERVICE_FILE_GUID_NAME;
EFI_MP_SERVICES_PROTOCOL *mMpService;
UINTN Argc = 0;
CHAR16 *Argv[10];
CHAR16 *ArgBuffer;
@ -676,6 +678,93 @@ LoadImageFromFile (
return Status;
}
/**
This service lets the caller enable or disable all APs from this point onward.
This service may only be called from the BSP.
@param[in] EnableAP Specifies the new state for the processor for
enabled, FALSE for disabled.
**/
VOID
EnableDisableAllAps(
IN BOOLEAN EnableAP
)
{
EFI_STATUS Status;
UINTN Index;
UINTN BspIndex;
UINTN NumberOfCPUs;
UINTN NumberOfEnabledCPUs;
Status = mMpService->GetNumberOfProcessors(
mMpService,
&NumberOfCPUs,
&NumberOfEnabledCPUs
);
ASSERT_EFI_ERROR(Status);
Status = mMpService->WhoAmI(
mMpService,
&BspIndex
);
ASSERT_EFI_ERROR(Status);
for (Index = 0; Index < NumberOfCPUs; Index++) {
if (Index == BspIndex) {
continue;
}
Status = mMpService->EnableDisableAP(
mMpService,
Index,
EnableAP,
NULL
);
ASSERT_EFI_ERROR(Status);
}
}
/**
This function launch FRM.
**/
VOID
LaunchFrm (
VOID
)
{
FRM_ENTRYPOINT FrmEntryPoint;
EFI_TPL OldTpl;
//
// Because FRM will wake up AP, we need notify MP_CPU driver.
// E.g. if MP_CPU driver puts APs to MONITOR state (not of HLT),
// the MONITOR_WAKE does not work after FRM returns.
//
// So we disable all APs here, then enable all APs after FRM return.
//
EnableDisableAllAps(FALSE);
//
// RaiseTPL to disable interrupt
//
OldTpl = gBS->RaiseTPL(TPL_HIGH_LEVEL);
//
// Run FRM entrypoint
//
FrmEntryPoint = (FRM_ENTRYPOINT)(UINTN)mCommunicationData.ImageEntrypoint;
FrmEntryPoint (&mCommunicationData);
gBS->RestoreTPL(OldTpl);
//
// Re-enable all APs to notify MP_CPU that AP's state is changed.
//
EnableDisableAllAps(TRUE);
return;
}
/**
Get RSDP ACPI table by Guid.
@ -776,7 +865,6 @@ LoaderEntrypoint (
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS Address;
EFI_MP_SERVICES_PROTOCOL *MpService;
EFI_CPU_ARCH_PROTOCOL *CpuArch;
UINTN NumberOfCPUs;
UINTN NumberOfEnabledCPUs;
@ -784,7 +872,6 @@ LoaderEntrypoint (
UINT64 TimerPeriod;
VOID *SmMonitorServiceProtocol;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
FRM_ENTRYPOINT Entry;
EFI_TCG2_PROTOCOL *Tcg2;
EFI_TCG_PROTOCOL *Tcg;
EFI_TCG2_BOOT_SERVICE_CAPABILITY Tcg2ProtocolCapability;
@ -853,13 +940,13 @@ LoaderEntrypoint (
//
// Get CPU Number
//
Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpService);
Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&mMpService);
ASSERT_EFI_ERROR (Status);
Status = MpService->GetNumberOfProcessors (
MpService,
&NumberOfCPUs,
&NumberOfEnabledCPUs
);
Status = mMpService->GetNumberOfProcessors (
mMpService,
&NumberOfCPUs,
&NumberOfEnabledCPUs
);
ASSERT_EFI_ERROR (Status);
//
@ -964,7 +1051,6 @@ LoaderEntrypoint (
);
ASSERT_EFI_ERROR (Status);
Entry = (FRM_ENTRYPOINT)(UINTN)mCommunicationData.ImageEntrypoint;
Entry(&mCommunicationData);
LaunchFrm ();
return Status;
}

View File

@ -59,6 +59,8 @@ BOOLEAN gEntered = FALSE;
EFI_EVENT mFrmLaunchEvent;
EFI_MP_SERVICES_PROTOCOL *mMpService;
/**
This function returns measured image size.
@ -584,6 +586,51 @@ LoadImageFromFv (
return Status;
}
/**
This service lets the caller enable or disable all APs from this point onward.
This service may only be called from the BSP.
@param[in] EnableAP Specifies the new state for the processor for
enabled, FALSE for disabled.
**/
VOID
EnableDisableAllAps(
IN BOOLEAN EnableAP
)
{
EFI_STATUS Status;
UINTN Index;
UINTN BspIndex;
UINTN NumberOfCPUs;
UINTN NumberOfEnabledCPUs;
Status = mMpService->GetNumberOfProcessors(
mMpService,
&NumberOfCPUs,
&NumberOfEnabledCPUs
);
ASSERT_EFI_ERROR(Status);
Status = mMpService->WhoAmI(
mMpService,
&BspIndex
);
ASSERT_EFI_ERROR(Status);
for (Index = 0; Index < NumberOfCPUs; Index++) {
if (Index == BspIndex) {
continue;
}
Status = mMpService->EnableDisableAP(
mMpService,
Index,
EnableAP,
NULL
);
ASSERT_EFI_ERROR(Status);
}
}
/**
This function launch FRM.
@ -595,12 +642,34 @@ LaunchFrm (
)
{
FRM_ENTRYPOINT FrmEntryPoint;
EFI_TPL OldTpl;
//
// Because FRM will wake up AP, we need notify MP_CPU driver.
// E.g. if MP_CPU driver puts APs to MONITOR state (not of HLT),
// the MONITOR_WAKE does not work after FRM returns.
//
// So we disable all APs here, then enable all APs after FRM return.
//
EnableDisableAllAps(FALSE);
//
// RaiseTPL to disable interrupt
//
OldTpl = gBS->RaiseTPL(TPL_HIGH_LEVEL);
//
// Run FRM entrypoint
//
FrmEntryPoint = (FRM_ENTRYPOINT)(UINTN)mCommunicationData.ImageEntrypoint;
FrmEntryPoint (&mCommunicationData);
gBS->RestoreTPL(OldTpl);
//
// Re-enable all APs to notify MP_CPU that AP's state is changed.
//
EnableDisableAllAps(TRUE);
return;
}
@ -753,7 +822,6 @@ LoaderEntrypoint (
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS Address;
EFI_MP_SERVICES_PROTOCOL *MpService;
EFI_CPU_ARCH_PROTOCOL *CpuArch;
UINTN NumberOfCPUs;
UINTN NumberOfEnabledCPUs;
@ -837,13 +905,13 @@ LoaderEntrypoint (
//
// Get CPU Number
//
Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpService);
Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&mMpService);
ASSERT_EFI_ERROR (Status);
Status = MpService->GetNumberOfProcessors (
MpService,
&NumberOfCPUs,
&NumberOfEnabledCPUs
);
Status = mMpService->GetNumberOfProcessors (
mMpService,
&NumberOfCPUs,
&NumberOfEnabledCPUs
);
ASSERT_EFI_ERROR (Status);
//