From 68f06742379437e412f9699cc3c82421f4684b67 Mon Sep 17 00:00:00 2001 From: Chen Fan Date: Mon, 9 Mar 2015 06:43:11 +0000 Subject: [PATCH] UefiCpuPkg/MpService: Put APs to sleep when not busy. Add a new sleeping state for APs, when no procedure execution, put AP to sleep. when need to execute procedure, only need to wake up this AP by sent SIPI. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Chen Fan Reviewed-by: Jeff Fan Reviewed-by: Jordan Justen git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17023 6f19259b-4bc3-4df7-8a09-765794883524 --- UefiCpuPkg/CpuDxe/CpuMp.c | 62 +++++++++++++++++++++++++++++++++++---- UefiCpuPkg/CpuDxe/CpuMp.h | 3 +- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c index 25c909193e..e5d2f5f7e2 100644 --- a/UefiCpuPkg/CpuDxe/CpuMp.c +++ b/UefiCpuPkg/CpuDxe/CpuMp.c @@ -298,9 +298,15 @@ CheckAndUpdateAllAPsToIdleState ( SetApProcedure (&mMpSystemData.CpuDatas[NextNumber], mMpSystemData.Procedure, mMpSystemData.ProcedureArgument); + // + // If this AP previous state is blocked, we should + // wake up this AP by sent a SIPI. and avoid + // re-involve the sleeping state. we must call + // SetApProcedure() first. + // + ResetProcessorToIdleState (&mMpSystemData.CpuDatas[NextNumber]); } } - SetApState (CpuData, CpuStateIdle); } } @@ -343,7 +349,8 @@ ResetAllFailedAPs ( } CpuState = GetApState (CpuData); - if (CpuState != CpuStateIdle) { + if (CpuState != CpuStateIdle && + CpuState != CpuStateSleeping) { if (mMpSystemData.FailedList != NULL) { (*mMpSystemData.FailedList)[mMpSystemData.FailedListIndex++] = Number; } @@ -615,6 +622,7 @@ StartupAllAPs ( CPU_DATA_BLOCK *CpuData; UINTN Number; CPU_STATE APInitialState; + CPU_STATE CpuState; CpuData = NULL; @@ -655,7 +663,9 @@ StartupAllAPs ( continue; } - if (GetApState (CpuData) != CpuStateIdle) { + CpuState = GetApState (CpuData); + if (CpuState != CpuStateIdle && + CpuState != CpuStateSleeping) { return EFI_NOT_READY; } } @@ -694,13 +704,24 @@ StartupAllAPs ( // state 1 by 1, until the previous 1 finished its task // if not "SingleThread", all APs are put to ready state from the beginning // - if (GetApState (CpuData) == CpuStateIdle) { + 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) { @@ -847,6 +868,7 @@ StartupThisAP ( ) { CPU_DATA_BLOCK *CpuData; + CPU_STATE CpuState; CpuData = NULL; @@ -877,13 +899,24 @@ StartupThisAP ( return EFI_INVALID_PARAMETER; } - if (GetApState (CpuData) != CpuStateIdle) { + 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; @@ -1021,6 +1054,7 @@ EnableDisableAP ( { CPU_DATA_BLOCK *CpuData; BOOLEAN TempStopCheckState; + CPU_STATE CpuState; CpuData = NULL; TempStopCheckState = FALSE; @@ -1046,7 +1080,9 @@ EnableDisableAP ( return EFI_INVALID_PARAMETER; } - if (GetApState (CpuData) != CpuStateIdle) { + CpuState = GetApState (CpuData); + if (CpuState != CpuStateIdle && + CpuState != CpuStateSleeping) { return EFI_UNSUPPORTED; } @@ -1201,6 +1237,20 @@ ProcessorToIdleState ( 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 (); diff --git a/UefiCpuPkg/CpuDxe/CpuMp.h b/UefiCpuPkg/CpuDxe/CpuMp.h index a6478c087c..cb3460f355 100644 --- a/UefiCpuPkg/CpuDxe/CpuMp.h +++ b/UefiCpuPkg/CpuDxe/CpuMp.h @@ -80,7 +80,8 @@ typedef enum { CpuStateBlocked, CpuStateReady, CpuStateBusy, - CpuStateFinished + CpuStateFinished, + CpuStateSleeping } CPU_STATE; /** -- 2.39.2