mirror of https://github.com/acidanthera/audk.git
UefiCpuPkg/CpuDxe: Consume MpInitLib to produce CPU MP Protocol services
Consume MP Initialize library to produce CPU MP Protocol services to simply the code. v4: 1. Update CpuDxe.c file header to mention it produces CPU Arch protocol. 2. Update BistData type from UINT32 to EFI_HEALTH_FLAG. 3. Move some header location from CpuMp.h to CpuDxe.h. v3: 1. Move the code Consume MpInitLib APIs to produce CPU MP Protocol from patch #40 to this patch. 2. Add DxeMpInitLib.inf in DSC file Cc: Michael Kinney <michael.d.kinney@intel.com> Cc: Feng Tian <feng.tian@intel.com> Cc: Giri P Mudusuru <giri.p.mudusuru@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Michael Kinney <michael.d.kinney@intel.com> Tested-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Michael Kinney <michael.d.kinney@intel.com>
This commit is contained in:
parent
89fa1bf218
commit
7fadaacd50
|
@ -1,5 +1,5 @@
|
|||
/** @file
|
||||
CPU DXE Module.
|
||||
CPU DXE Module to produce CPU ARCH Protocol.
|
||||
|
||||
Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
CPU DXE Module.
|
||||
CPU DXE Module to produce CPU ARCH Protocol and CPU MP Protocol.
|
||||
|
||||
Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -18,6 +18,10 @@
|
|||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/Cpu.h>
|
||||
#include <Protocol/MpService.h>
|
||||
|
||||
#include <Ppi/SecPlatformInformation.h>
|
||||
#include <Ppi/SecPlatformInformation2.h>
|
||||
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
|
@ -33,6 +37,10 @@
|
|||
#include <Library/UefiLib.h>
|
||||
#include <Library/CpuExceptionHandlerLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/ReportStatusCodeLib.h>
|
||||
#include <Library/MpInitLib.h>
|
||||
|
||||
#include <Guid/IdleLoopEvent.h>
|
||||
#include <Guid/VectorHandoffTable.h>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
## @file
|
||||
# Simple CPU driver installs CPU Architecture Protocol.
|
||||
# CPU driver installs CPU Architecture Protocol and CPU MP protocol.
|
||||
#
|
||||
# Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
|
@ -41,10 +41,9 @@
|
|||
UefiCpuLib
|
||||
UefiLib
|
||||
CpuExceptionHandlerLib
|
||||
TimerLib
|
||||
SynchronizationLib
|
||||
HobLib
|
||||
ReportStatusCodeLib
|
||||
MpInitLib
|
||||
|
||||
[Sources]
|
||||
ApStartup.c
|
||||
|
@ -71,7 +70,7 @@
|
|||
|
||||
[Protocols]
|
||||
gEfiCpuArchProtocolGuid ## PRODUCES
|
||||
gEfiMpServiceProtocolGuid ## SOMETIMES_PRODUCES
|
||||
gEfiMpServiceProtocolGuid ## PRODUCES
|
||||
|
||||
[Guids]
|
||||
gIdleLoopEventGuid ## CONSUMES ## Event
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// /** @file
|
||||
// Simple CPU driver installs CPU Architecture Protocol.
|
||||
// CPU driver installs CPU Architecture Protocol and CPU MP Protocol.
|
||||
//
|
||||
// Simple CPU driver installs CPU Architecture Protocol.
|
||||
// CPU driver installs CPU Architecture Protocol and CPU MP Protocol.
|
||||
//
|
||||
// Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
// Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// This program and the accompanying materials
|
||||
// are licensed and made available under the terms and conditions of the BSD License
|
||||
|
@ -16,7 +16,7 @@
|
|||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "Installs CPU Architecture Protocol"
|
||||
#string STR_MODULE_ABSTRACT #language en-US "CPU driver installs CPU Architecture Protocol and CPU MP Protocol."
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "Simple CPU driver installs CPU Architecture Protocol."
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "CPU driver installs CPU Architecture Protocol and CPU MP Protocol."
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// /** @file
|
||||
// CpuDxe Localized Strings and Content
|
||||
//
|
||||
// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
// Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// This program and the accompanying materials
|
||||
// are licensed and made available under the terms and conditions of the BSD License
|
||||
|
@ -15,6 +15,6 @@
|
|||
|
||||
#string STR_PROPERTIES_MODULE_NAME
|
||||
#language en-US
|
||||
"CPU Architectural DXE Driver"
|
||||
"CPU Architectural and CPU Multi-processor DXE Driver"
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
CPU DXE Module.
|
||||
CPU DXE Module to produce CPU MP Protocol.
|
||||
|
||||
Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
|
@ -21,6 +21,7 @@ UINTN gPollInterval = 100; // 100 microseconds
|
|||
|
||||
MP_SYSTEM_DATA mMpSystemData;
|
||||
EFI_HANDLE mMpServiceHandle = NULL;
|
||||
UINTN mNumberOfProcessors = 1;
|
||||
EFI_EVENT mExitBootServicesEvent = (EFI_EVENT)NULL;
|
||||
|
||||
VOID *mCommonStack = 0;
|
||||
|
@ -28,7 +29,6 @@ VOID *mTopOfApCommonStack = 0;
|
|||
VOID *mApStackStart = 0;
|
||||
|
||||
volatile BOOLEAN mAPsAlreadyInitFinished = FALSE;
|
||||
volatile BOOLEAN mStopCheckAllAPsStatus = TRUE;
|
||||
|
||||
EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = {
|
||||
GetNumberOfProcessors,
|
||||
|
@ -102,6 +102,7 @@ IsBSP (
|
|||
@retval CPU_STATE the AP status
|
||||
|
||||
**/
|
||||
STATIC
|
||||
CPU_STATE
|
||||
GetApState (
|
||||
IN CPU_DATA_BLOCK *CpuData
|
||||
|
@ -123,6 +124,7 @@ GetApState (
|
|||
@param State The AP status
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
SetApState (
|
||||
IN CPU_DATA_BLOCK *CpuData,
|
||||
|
@ -452,13 +454,10 @@ GetNumberOfProcessors (
|
|||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!IsBSP ()) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
*NumberOfProcessors = mMpSystemData.NumberOfProcessors;
|
||||
*NumberOfEnabledProcessors = mMpSystemData.NumberOfEnabledProcessors;
|
||||
return EFI_SUCCESS;
|
||||
return MpInitLibGetNumberOfProcessors (
|
||||
NumberOfProcessors,
|
||||
NumberOfEnabledProcessors
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -495,20 +494,7 @@ GetProcessorInfo (
|
|||
OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
|
||||
)
|
||||
{
|
||||
if (ProcessorInfoBuffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!IsBSP ()) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
CopyMem (ProcessorInfoBuffer, &mMpSystemData.CpuDatas[ProcessorNumber], sizeof (EFI_PROCESSOR_INFORMATION));
|
||||
return EFI_SUCCESS;
|
||||
return MpInitLibGetProcessorInfo (ProcessorNumber, ProcessorInfoBuffer, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -659,155 +645,14 @@ StartupAllAPs (
|
|||
OUT UINTN **FailedCpuList OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CPU_DATA_BLOCK *CpuData;
|
||||
UINTN Number;
|
||||
CPU_STATE APInitialState;
|
||||
CPU_STATE CpuState;
|
||||
|
||||
CpuData = NULL;
|
||||
|
||||
if (FailedCpuList != NULL) {
|
||||
*FailedCpuList = NULL;
|
||||
}
|
||||
|
||||
if (!IsBSP ()) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (mMpSystemData.NumberOfProcessors == 1) {
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
if (Procedure == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// temporarily stop checkAllAPsStatus for avoid resource dead-lock.
|
||||
//
|
||||
mStopCheckAllAPsStatus = TRUE;
|
||||
|
||||
for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
|
||||
CpuData = &mMpSystemData.CpuDatas[Number];
|
||||
if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
|
||||
//
|
||||
// Skip BSP
|
||||
//
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
|
||||
//
|
||||
// Skip Disabled processors
|
||||
//
|
||||
continue;
|
||||
}
|
||||
|
||||
CpuState = GetApState (CpuData);
|
||||
if (CpuState != CpuStateIdle &&
|
||||
CpuState != CpuStateSleeping) {
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
}
|
||||
|
||||
mMpSystemData.Procedure = Procedure;
|
||||
mMpSystemData.ProcedureArgument = ProcedureArgument;
|
||||
mMpSystemData.WaitEvent = WaitEvent;
|
||||
mMpSystemData.Timeout = TimeoutInMicroseconds;
|
||||
mMpSystemData.TimeoutActive = (BOOLEAN) (TimeoutInMicroseconds != 0);
|
||||
mMpSystemData.FinishCount = 0;
|
||||
mMpSystemData.StartCount = 0;
|
||||
mMpSystemData.SingleThread = SingleThread;
|
||||
mMpSystemData.FailedList = FailedCpuList;
|
||||
mMpSystemData.FailedListIndex = 0;
|
||||
APInitialState = CpuStateReady;
|
||||
|
||||
for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
|
||||
CpuData = &mMpSystemData.CpuDatas[Number];
|
||||
if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
|
||||
//
|
||||
// Skip BSP
|
||||
//
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
|
||||
//
|
||||
// Skip Disabled processors
|
||||
//
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Get APs prepared, and put failing APs into FailedCpuList
|
||||
// if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready
|
||||
// state 1 by 1, until the previous 1 finished its task
|
||||
// if not "SingleThread", all APs are put to ready state from the beginning
|
||||
//
|
||||
CpuState = GetApState (CpuData);
|
||||
if (CpuState == CpuStateIdle ||
|
||||
CpuState == CpuStateSleeping) {
|
||||
mMpSystemData.StartCount++;
|
||||
|
||||
SetApState (CpuData, APInitialState);
|
||||
|
||||
if (APInitialState == CpuStateReady) {
|
||||
SetApProcedure (CpuData, Procedure, ProcedureArgument);
|
||||
//
|
||||
// If this AP previous state is Sleeping, we should
|
||||
// wake up this AP by sent a SIPI. and avoid
|
||||
// re-involve the sleeping state. we must call
|
||||
// SetApProcedure() first.
|
||||
//
|
||||
if (CpuState == CpuStateSleeping) {
|
||||
ResetProcessorToIdleState (CpuData);
|
||||
}
|
||||
}
|
||||
|
||||
if (SingleThread) {
|
||||
APInitialState = CpuStateBlocked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mStopCheckAllAPsStatus = FALSE;
|
||||
|
||||
if (WaitEvent != NULL) {
|
||||
//
|
||||
// non blocking
|
||||
//
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Blocking temporarily stop CheckAllAPsStatus()
|
||||
//
|
||||
mStopCheckAllAPsStatus = TRUE;
|
||||
|
||||
while (TRUE) {
|
||||
CheckAndUpdateAllAPsToIdleState ();
|
||||
if (mMpSystemData.FinishCount == mMpSystemData.StartCount) {
|
||||
Status = EFI_SUCCESS;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// task timeout
|
||||
//
|
||||
if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) {
|
||||
ResetAllFailedAPs();
|
||||
Status = EFI_TIMEOUT;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
MicroSecondDelay (gPollInterval);
|
||||
mMpSystemData.Timeout -= gPollInterval;
|
||||
}
|
||||
|
||||
Done:
|
||||
|
||||
return Status;
|
||||
return MpInitLibStartupAllAPs (
|
||||
Procedure,
|
||||
SingleThread,
|
||||
WaitEvent,
|
||||
TimeoutInMicroseconds,
|
||||
ProcedureArgument,
|
||||
FailedCpuList
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -908,90 +753,14 @@ StartupThisAP (
|
|||
OUT BOOLEAN *Finished OPTIONAL
|
||||
)
|
||||
{
|
||||
CPU_DATA_BLOCK *CpuData;
|
||||
CPU_STATE CpuState;
|
||||
|
||||
CpuData = NULL;
|
||||
|
||||
if (Finished != NULL) {
|
||||
*Finished = FALSE;
|
||||
}
|
||||
|
||||
if (!IsBSP ()) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (Procedure == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// temporarily stop checkAllAPsStatus for avoid resource dead-lock.
|
||||
//
|
||||
mStopCheckAllAPsStatus = TRUE;
|
||||
|
||||
CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
|
||||
if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT) ||
|
||||
!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CpuState = GetApState (CpuData);
|
||||
if (CpuState != CpuStateIdle &&
|
||||
CpuState != CpuStateSleeping) {
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
|
||||
SetApState (CpuData, CpuStateReady);
|
||||
|
||||
SetApProcedure (CpuData, Procedure, ProcedureArgument);
|
||||
//
|
||||
// If this AP previous state is Sleeping, we should
|
||||
// wake up this AP by sent a SIPI. and avoid
|
||||
// re-involve the sleeping state. we must call
|
||||
// SetApProcedure() first.
|
||||
//
|
||||
if (CpuState == CpuStateSleeping) {
|
||||
ResetProcessorToIdleState (CpuData);
|
||||
}
|
||||
|
||||
CpuData->Timeout = TimeoutInMicroseconds;
|
||||
CpuData->WaitEvent = WaitEvent;
|
||||
CpuData->TimeoutActive = (BOOLEAN) (TimeoutInMicroseconds != 0);
|
||||
CpuData->Finished = Finished;
|
||||
|
||||
mStopCheckAllAPsStatus = FALSE;
|
||||
|
||||
if (WaitEvent != NULL) {
|
||||
//
|
||||
// Non Blocking
|
||||
//
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Blocking
|
||||
//
|
||||
while (TRUE) {
|
||||
if (GetApState (CpuData) == CpuStateFinished) {
|
||||
SetApState (CpuData, CpuStateIdle);
|
||||
break;
|
||||
}
|
||||
|
||||
if (CpuData->TimeoutActive && CpuData->Timeout < 0) {
|
||||
ResetProcessorToIdleState (CpuData);
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
MicroSecondDelay (gPollInterval);
|
||||
CpuData->Timeout -= gPollInterval;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
return MpInitLibStartupThisAP (
|
||||
Procedure,
|
||||
ProcessorNumber,
|
||||
WaitEvent,
|
||||
TimeoutInMicroseconds,
|
||||
ProcedureArgument,
|
||||
Finished
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1037,10 +806,7 @@ SwitchBSP (
|
|||
IN BOOLEAN EnableOldBSP
|
||||
)
|
||||
{
|
||||
//
|
||||
// Current always return unsupported.
|
||||
//
|
||||
return EFI_UNSUPPORTED;
|
||||
return MpInitLibSwitchBSP (ProcessorNumber, EnableOldBSP);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1093,62 +859,7 @@ EnableDisableAP (
|
|||
IN UINT32 *HealthFlag OPTIONAL
|
||||
)
|
||||
{
|
||||
CPU_DATA_BLOCK *CpuData;
|
||||
BOOLEAN TempStopCheckState;
|
||||
CPU_STATE CpuState;
|
||||
|
||||
CpuData = NULL;
|
||||
TempStopCheckState = FALSE;
|
||||
|
||||
if (!IsBSP ()) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// temporarily stop checkAllAPsStatus for initialize parameters.
|
||||
//
|
||||
if (!mStopCheckAllAPsStatus) {
|
||||
mStopCheckAllAPsStatus = TRUE;
|
||||
TempStopCheckState = TRUE;
|
||||
}
|
||||
|
||||
CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
|
||||
if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CpuState = GetApState (CpuData);
|
||||
if (CpuState != CpuStateIdle &&
|
||||
CpuState != CpuStateSleeping) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (EnableAP) {
|
||||
if (!(TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT))) {
|
||||
mMpSystemData.NumberOfEnabledProcessors++;
|
||||
}
|
||||
CpuStatusFlagOr (CpuData, PROCESSOR_ENABLED_BIT);
|
||||
} else {
|
||||
if (TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
|
||||
mMpSystemData.NumberOfEnabledProcessors--;
|
||||
}
|
||||
CpuStatusFlagAndNot (CpuData, PROCESSOR_ENABLED_BIT);
|
||||
}
|
||||
|
||||
if (HealthFlag != NULL) {
|
||||
CpuStatusFlagAndNot (CpuData, (UINT32)~PROCESSOR_HEALTH_STATUS_BIT);
|
||||
CpuStatusFlagOr (CpuData, (*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT));
|
||||
}
|
||||
|
||||
if (TempStopCheckState) {
|
||||
mStopCheckAllAPsStatus = FALSE;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
return MpInitLibEnableDisableAP (ProcessorNumber, EnableAP, HealthFlag);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1182,383 +893,7 @@ WhoAmI (
|
|||
OUT UINTN *ProcessorNumber
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINT32 ProcessorId;
|
||||
|
||||
if (ProcessorNumber == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ProcessorId = GetApicId ();
|
||||
for (Index = 0; Index < mMpSystemData.NumberOfProcessors; Index++) {
|
||||
if (mMpSystemData.CpuDatas[Index].Info.ProcessorId == ProcessorId) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*ProcessorNumber = Index;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Terminate AP's task and set it to idle state.
|
||||
|
||||
This function terminates AP's task due to timeout by sending INIT-SIPI,
|
||||
and sends it to idle state.
|
||||
|
||||
@param CpuData the pointer to CPU_DATA_BLOCK of specified AP
|
||||
|
||||
**/
|
||||
VOID
|
||||
ResetProcessorToIdleState (
|
||||
IN CPU_DATA_BLOCK *CpuData
|
||||
)
|
||||
{
|
||||
ResetApStackless ((UINT32)CpuData->Info.ProcessorId);
|
||||
}
|
||||
|
||||
/**
|
||||
Application Processors do loop routine
|
||||
after switch to its own stack.
|
||||
|
||||
@param Context1 A pointer to the context to pass into the function.
|
||||
@param Context2 A pointer to the context to pass into the function.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ProcessorToIdleState (
|
||||
IN VOID *Context1, OPTIONAL
|
||||
IN VOID *Context2 OPTIONAL
|
||||
)
|
||||
{
|
||||
UINTN ProcessorNumber;
|
||||
CPU_DATA_BLOCK *CpuData;
|
||||
EFI_AP_PROCEDURE Procedure;
|
||||
volatile VOID *ProcedureArgument;
|
||||
|
||||
AsmApDoneWithCommonStack ();
|
||||
|
||||
while (!mAPsAlreadyInitFinished) {
|
||||
CpuPause ();
|
||||
}
|
||||
|
||||
WhoAmI (&mMpServicesTemplate, &ProcessorNumber);
|
||||
CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
|
||||
|
||||
//
|
||||
// Avoid forcibly reset AP caused the AP got lock not release.
|
||||
//
|
||||
if (CpuData->LockSelf == (INTN) GetApicId ()) {
|
||||
ReleaseSpinLock (&CpuData->CpuDataLock);
|
||||
}
|
||||
|
||||
//
|
||||
// Avoid forcibly reset AP caused the timeout AP State is not
|
||||
// updated.
|
||||
//
|
||||
GetMpSpinLock (CpuData);
|
||||
if (CpuData->State == CpuStateBusy) {
|
||||
CpuData->Procedure = NULL;
|
||||
}
|
||||
CpuData->State = CpuStateIdle;
|
||||
ReleaseMpSpinLock (CpuData);
|
||||
|
||||
while (TRUE) {
|
||||
GetMpSpinLock (CpuData);
|
||||
ProcedureArgument = CpuData->Parameter;
|
||||
Procedure = CpuData->Procedure;
|
||||
ReleaseMpSpinLock (CpuData);
|
||||
|
||||
if (Procedure != NULL) {
|
||||
SetApState (CpuData, CpuStateBusy);
|
||||
|
||||
Procedure ((VOID*) ProcedureArgument);
|
||||
|
||||
GetMpSpinLock (CpuData);
|
||||
CpuData->Procedure = NULL;
|
||||
CpuData->State = CpuStateFinished;
|
||||
ReleaseMpSpinLock (CpuData);
|
||||
} else {
|
||||
//
|
||||
// if no procedure to execution, we simply put AP
|
||||
// into sleeping state, and waiting BSP sent SIPI.
|
||||
//
|
||||
GetMpSpinLock (CpuData);
|
||||
if (CpuData->State == CpuStateIdle) {
|
||||
CpuData->State = CpuStateSleeping;
|
||||
}
|
||||
ReleaseMpSpinLock (CpuData);
|
||||
}
|
||||
|
||||
if (GetApState (CpuData) == CpuStateSleeping) {
|
||||
CpuSleep ();
|
||||
}
|
||||
|
||||
CpuPause ();
|
||||
}
|
||||
|
||||
CpuSleep ();
|
||||
CpuDeadLoop ();
|
||||
}
|
||||
|
||||
/**
|
||||
Checks AP' status periodically.
|
||||
|
||||
This function is triggerred by timer perodically to check the
|
||||
state of AP forStartupThisAP() executed in non-blocking mode.
|
||||
|
||||
@param Event Event triggered.
|
||||
@param Context Parameter passed with the event.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
CheckThisAPStatus (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
CPU_DATA_BLOCK *CpuData;
|
||||
CPU_STATE CpuState;
|
||||
|
||||
CpuData = (CPU_DATA_BLOCK *) Context;
|
||||
if (CpuData->TimeoutActive) {
|
||||
CpuData->Timeout -= gPollInterval;
|
||||
}
|
||||
|
||||
CpuState = GetApState (CpuData);
|
||||
|
||||
if (CpuState == CpuStateFinished) {
|
||||
if (CpuData->Finished) {
|
||||
*CpuData->Finished = TRUE;
|
||||
}
|
||||
SetApState (CpuData, CpuStateIdle);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (CpuData->TimeoutActive && CpuData->Timeout < 0) {
|
||||
if (CpuState != CpuStateIdle &&
|
||||
CpuData->Finished) {
|
||||
*CpuData->Finished = FALSE;
|
||||
}
|
||||
ResetProcessorToIdleState (CpuData);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
CpuData->TimeoutActive = FALSE;
|
||||
gBS->SignalEvent (CpuData->WaitEvent);
|
||||
CpuData->WaitEvent = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks APs' status periodically.
|
||||
|
||||
This function is triggerred by timer perodically to check the
|
||||
state of APs for StartupAllAPs() executed in non-blocking mode.
|
||||
|
||||
@param Event Event triggered.
|
||||
@param Context Parameter passed with the event.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
CheckAllAPsStatus (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
CPU_DATA_BLOCK *CpuData;
|
||||
UINTN Number;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (mMpSystemData.TimeoutActive) {
|
||||
mMpSystemData.Timeout -= gPollInterval;
|
||||
}
|
||||
|
||||
if (mStopCheckAllAPsStatus) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// avoid next timer enter.
|
||||
//
|
||||
Status = gBS->SetTimer (
|
||||
mMpSystemData.CheckAllAPsEvent,
|
||||
TimerCancel,
|
||||
0
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
if (mMpSystemData.WaitEvent != NULL) {
|
||||
CheckAndUpdateAllAPsToIdleState ();
|
||||
//
|
||||
// task timeout
|
||||
//
|
||||
if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) {
|
||||
ResetAllFailedAPs();
|
||||
//
|
||||
// force exit
|
||||
//
|
||||
mMpSystemData.FinishCount = mMpSystemData.StartCount;
|
||||
}
|
||||
|
||||
if (mMpSystemData.FinishCount != mMpSystemData.StartCount) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
mMpSystemData.TimeoutActive = FALSE;
|
||||
gBS->SignalEvent (mMpSystemData.WaitEvent);
|
||||
mMpSystemData.WaitEvent = NULL;
|
||||
mStopCheckAllAPsStatus = TRUE;
|
||||
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// check each AP status for StartupThisAP
|
||||
//
|
||||
for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
|
||||
CpuData = &mMpSystemData.CpuDatas[Number];
|
||||
if (CpuData->WaitEvent) {
|
||||
CheckThisAPStatus (NULL, (VOID *)CpuData);
|
||||
}
|
||||
}
|
||||
|
||||
EXIT:
|
||||
Status = gBS->SetTimer (
|
||||
mMpSystemData.CheckAllAPsEvent,
|
||||
TimerPeriodic,
|
||||
EFI_TIMER_PERIOD_MICROSECONDS (100)
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
/**
|
||||
Application Processor C code entry point.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ApEntryPointInC (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
VOID* TopOfApStack;
|
||||
UINTN ProcessorNumber;
|
||||
|
||||
if (!mAPsAlreadyInitFinished) {
|
||||
FillInProcessorInformation (FALSE, mMpSystemData.NumberOfProcessors);
|
||||
TopOfApStack = (UINT8*)mApStackStart + gApStackSize;
|
||||
mApStackStart = TopOfApStack;
|
||||
|
||||
//
|
||||
// Store the Stack address, when reset the AP, We can found the original address.
|
||||
//
|
||||
mMpSystemData.CpuDatas[mMpSystemData.NumberOfProcessors].TopOfStack = TopOfApStack;
|
||||
mMpSystemData.NumberOfProcessors++;
|
||||
mMpSystemData.NumberOfEnabledProcessors++;
|
||||
} else {
|
||||
WhoAmI (&mMpServicesTemplate, &ProcessorNumber);
|
||||
//
|
||||
// Get the original stack address.
|
||||
//
|
||||
TopOfApStack = mMpSystemData.CpuDatas[ProcessorNumber].TopOfStack;
|
||||
}
|
||||
|
||||
SwitchStack (
|
||||
(SWITCH_STACK_ENTRY_POINT)(UINTN)ProcessorToIdleState,
|
||||
NULL,
|
||||
NULL,
|
||||
TopOfApStack);
|
||||
}
|
||||
|
||||
/**
|
||||
This function is called by all processors (both BSP and AP) once and collects MP related data.
|
||||
|
||||
@param Bsp TRUE if the CPU is BSP
|
||||
@param ProcessorNumber The specific processor number
|
||||
|
||||
@retval EFI_SUCCESS Data for the processor collected and filled in
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FillInProcessorInformation (
|
||||
IN BOOLEAN Bsp,
|
||||
IN UINTN ProcessorNumber
|
||||
)
|
||||
{
|
||||
CPU_DATA_BLOCK *CpuData;
|
||||
UINT32 ProcessorId;
|
||||
|
||||
CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
|
||||
ProcessorId = GetApicId ();
|
||||
CpuData->Info.ProcessorId = ProcessorId;
|
||||
CpuData->Info.StatusFlag = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;
|
||||
if (Bsp) {
|
||||
CpuData->Info.StatusFlag |= PROCESSOR_AS_BSP_BIT;
|
||||
}
|
||||
CpuData->Info.Location.Package = ProcessorId;
|
||||
CpuData->Info.Location.Core = 0;
|
||||
CpuData->Info.Location.Thread = 0;
|
||||
CpuData->State = Bsp ? CpuStateBusy : CpuStateIdle;
|
||||
|
||||
CpuData->Procedure = NULL;
|
||||
CpuData->Parameter = NULL;
|
||||
InitializeSpinLock (&CpuData->CpuDataLock);
|
||||
CpuData->LockSelf = -1;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Prepare the System Data.
|
||||
|
||||
@retval EFI_SUCCESS the System Data finished initilization.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
InitMpSystemData (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
ZeroMem (&mMpSystemData, sizeof (MP_SYSTEM_DATA));
|
||||
|
||||
mMpSystemData.NumberOfProcessors = 1;
|
||||
mMpSystemData.NumberOfEnabledProcessors = 1;
|
||||
|
||||
mMpSystemData.CpuDatas = AllocateZeroPool (sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber);
|
||||
ASSERT(mMpSystemData.CpuDatas != NULL);
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_TIMER | EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
CheckAllAPsStatus,
|
||||
NULL,
|
||||
&mMpSystemData.CheckAllAPsEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Set timer to check all APs status.
|
||||
//
|
||||
Status = gBS->SetTimer (
|
||||
mMpSystemData.CheckAllAPsEvent,
|
||||
TimerPeriodic,
|
||||
EFI_TIMER_PERIOD_MICROSECONDS (100)
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// BSP
|
||||
//
|
||||
FillInProcessorInformation (TRUE, 0);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
return MpInitLibWhoAmI (ProcessorNumber);;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1580,8 +915,8 @@ CollectBistDataFromHob (
|
|||
EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance;
|
||||
EFI_SEC_PLATFORM_INFORMATION_CPU BspCpuInstance;
|
||||
UINTN ProcessorNumber;
|
||||
UINT32 InitialLocalApicId;
|
||||
CPU_DATA_BLOCK *CpuData;
|
||||
EFI_PROCESSOR_INFORMATION ProcessorInfo;
|
||||
EFI_HEALTH_FLAGS BistData;
|
||||
|
||||
SecPlatformInformation2 = NULL;
|
||||
SecPlatformInformation = NULL;
|
||||
|
@ -1622,23 +957,22 @@ CollectBistDataFromHob (
|
|||
}
|
||||
|
||||
while ((NumberOfData--) > 0) {
|
||||
for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {
|
||||
CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
|
||||
InitialLocalApicId = (UINT32) CpuData->Info.ProcessorId;
|
||||
if (InitialLocalApicId == CpuInstance[NumberOfData].CpuLocation) {
|
||||
for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {
|
||||
MpInitLibGetProcessorInfo (ProcessorNumber, &ProcessorInfo, &BistData);
|
||||
if (ProcessorInfo.ProcessorId == CpuInstance[NumberOfData].CpuLocation) {
|
||||
//
|
||||
// Update CPU health status for MP Services Protocol according to BIST data.
|
||||
//
|
||||
if (CpuInstance[NumberOfData].InfoRecord.IA32HealthFlags.Uint32 != 0) {
|
||||
CpuData->Info.StatusFlag &= ~PROCESSOR_HEALTH_STATUS_BIT;
|
||||
//
|
||||
// Report Status Code that self test is failed
|
||||
//
|
||||
REPORT_STATUS_CODE (
|
||||
EFI_ERROR_CODE | EFI_ERROR_MAJOR,
|
||||
(EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)
|
||||
);
|
||||
}
|
||||
BistData = CpuInstance[NumberOfData].InfoRecord.IA32HealthFlags;
|
||||
}
|
||||
if (BistData.Uint32 != 0) {
|
||||
//
|
||||
// Report Status Code that self test is failed
|
||||
//
|
||||
REPORT_STATUS_CODE (
|
||||
EFI_ERROR_CODE | EFI_ERROR_MAJOR,
|
||||
(EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1692,115 +1026,37 @@ InitializeMpSupport (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
MTRR_SETTINGS MtrrSettings;
|
||||
UINTN Timeout;
|
||||
UINTN NumberOfProcessors;
|
||||
UINTN NumberOfEnabledProcessors;
|
||||
|
||||
gMaxLogicalProcessorNumber = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
|
||||
if (gMaxLogicalProcessorNumber < 1) {
|
||||
NumberOfProcessors = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
|
||||
if (NumberOfProcessors < 1) {
|
||||
DEBUG ((DEBUG_ERROR, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
InitMpSystemData ();
|
||||
|
||||
//
|
||||
// Only perform AP detection if PcdCpuMaxLogicalProcessorNumber is greater than 1
|
||||
//
|
||||
if (gMaxLogicalProcessorNumber > 1) {
|
||||
if (NumberOfProcessors > 1) {
|
||||
Status = MpInitLibInitialize ();
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
gApStackSize = (UINTN) PcdGet32 (PcdCpuApStackSize);
|
||||
ASSERT ((gApStackSize & (SIZE_4KB - 1)) == 0);
|
||||
|
||||
mApStackStart = AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));
|
||||
ASSERT (mApStackStart != NULL);
|
||||
|
||||
//
|
||||
// the first buffer of stack size used for common stack, when the amount of AP
|
||||
// more than 1, we should never free the common stack which maybe used for AP reset.
|
||||
//
|
||||
mCommonStack = mApStackStart;
|
||||
mTopOfApCommonStack = (UINT8*) mApStackStart + gApStackSize;
|
||||
mApStackStart = mTopOfApCommonStack;
|
||||
|
||||
PrepareAPStartupCode ();
|
||||
|
||||
StartApsStackless ();
|
||||
MpInitLibGetNumberOfProcessors (&NumberOfProcessors, &NumberOfEnabledProcessors);
|
||||
mNumberOfProcessors = NumberOfProcessors;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "Detect CPU count: %d\n", mMpSystemData.NumberOfProcessors));
|
||||
if (mMpSystemData.NumberOfProcessors == 1) {
|
||||
FreeApStartupCode ();
|
||||
if (mCommonStack != NULL) {
|
||||
FreePages (mCommonStack, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));
|
||||
}
|
||||
}
|
||||
|
||||
mMpSystemData.CpuDatas = ReallocatePool (
|
||||
sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber,
|
||||
sizeof (CPU_DATA_BLOCK) * mMpSystemData.NumberOfProcessors,
|
||||
mMpSystemData.CpuDatas);
|
||||
|
||||
//
|
||||
// Release all APs to complete initialization and enter idle loop
|
||||
//
|
||||
mAPsAlreadyInitFinished = TRUE;
|
||||
|
||||
//
|
||||
// Wait for all APs to enter idle loop.
|
||||
//
|
||||
Timeout = 0;
|
||||
do {
|
||||
if (CheckAllAPsSleeping ()) {
|
||||
break;
|
||||
}
|
||||
MicroSecondDelay (gPollInterval);
|
||||
Timeout += gPollInterval;
|
||||
} while (Timeout <= PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));
|
||||
ASSERT (Timeout <= PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));
|
||||
DEBUG ((EFI_D_ERROR, "Detect CPU count: %d\n", mNumberOfProcessors));
|
||||
|
||||
//
|
||||
// Update CPU healthy information from Guided HOB
|
||||
//
|
||||
CollectBistDataFromHob ();
|
||||
|
||||
//
|
||||
// Synchronize MTRR settings to APs.
|
||||
//
|
||||
MtrrGetAllMtrrs (&MtrrSettings);
|
||||
Status = mMpServicesTemplate.StartupAllAPs (
|
||||
&mMpServicesTemplate, // This
|
||||
SetMtrrsFromBuffer, // Procedure
|
||||
TRUE, // SingleThread
|
||||
NULL, // WaitEvent
|
||||
0, // TimeoutInMicrosecsond
|
||||
&MtrrSettings, // ProcedureArgument
|
||||
NULL // FailedCpuList
|
||||
);
|
||||
ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_STARTED);
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&mMpServiceHandle,
|
||||
&gEfiMpServiceProtocolGuid, &mMpServicesTemplate,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
if (mMpSystemData.NumberOfProcessors > 1 && mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) {
|
||||
if (mApStackStart != NULL) {
|
||||
FreePages (mApStackStart, EFI_SIZE_TO_PAGES (
|
||||
(gMaxLogicalProcessorNumber - mMpSystemData.NumberOfProcessors) *
|
||||
gApStackSize));
|
||||
}
|
||||
}
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_SIGNAL_EXIT_BOOT_SERVICES,
|
||||
TPL_CALLBACK,
|
||||
ExitBootServicesCallback,
|
||||
NULL,
|
||||
&mExitBootServicesEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
#include <Ppi/SecPlatformInformation2.h>
|
||||
#include <Protocol/MpService.h>
|
||||
#include <Library/SynchronizationLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/ReportStatusCodeLib.h>
|
||||
|
||||
/**
|
||||
Initialize Multi-processor support.
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
|
||||
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
|
||||
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
|
||||
MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
|
||||
|
||||
[LibraryClasses.common.DXE_SMM_DRIVER]
|
||||
SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
|
||||
|
|
Loading…
Reference in New Issue