Revision: 19362
http://sourceforge.net/p/edk2/code/19362
Author: vanjeff
Date: 2015-12-18 05:50:19 +0000 (Fri, 18 Dec 2015)
Log Message:
-----------
UefiCpuPkg/CpuMpPei: Place APs in proper loop mode after AP execution
After AP function is executed, we will place AP in proper loop mode. Because AP
maybe waken up by SMI or other reasons. We need to read signature in monitor
buffer to check if APs is waken up by BSP. If it is not waken up by BSP, we will
continue to place them into proper loop mode.
(Sync patch r19345 from main trunk.)
Contributed-under: TianoCore Contribution Agreement 1.0
Cc: Feng Tian <[email protected]>
Cc: Michael Kinney <[email protected]>
Cc: Jordan Justen <[email protected]>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <[email protected]>
Tested-by: Michael Kinney <[email protected]>
Reviewed-by: Michael Kinney <[email protected]>
Revision Links:
--------------
http://sourceforge.net/p/edk2/code/19345
Modified Paths:
--------------
branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.c
branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.h
branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
Modified: branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.c
===================================================================
--- branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.c 2015-12-18 05:49:28 UTC
(rev 19361)
+++ branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.c 2015-12-18 05:50:19 UTC
(rev 19362)
@@ -273,68 +273,124 @@
UINTN ProcessorNumber;
EFI_AP_PROCEDURE Procedure;
UINTN BistData;
+ volatile UINT32 *ApStartupSignalBuffer;
PeiCpuMpData = ExchangeInfo->PeiCpuMpData;
- if (PeiCpuMpData->InitFlag) {
- ProcessorNumber = NumApsExecuting;
+ while (TRUE) {
+ if (PeiCpuMpData->InitFlag) {
+ ProcessorNumber = NumApsExecuting;
+ //
+ // Sync BSP's Control registers to APs
+ //
+ RestoreVolatileRegisters (&PeiCpuMpData->CpuData[0].VolatileRegisters,
FALSE);
+ //
+ // This is first time AP wakeup, get BIST information from AP stack
+ //
+ BistData = *(UINTN *) (PeiCpuMpData->Buffer + ProcessorNumber *
PeiCpuMpData->CpuApStackSize - sizeof (UINTN));
+ PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 = (UINT32) BistData;
+ PeiCpuMpData->CpuData[ProcessorNumber].ApicId = GetInitialApicId ();
+ if (PeiCpuMpData->CpuData[ProcessorNumber].ApicId >= 0xFF) {
+ //
+ // Set x2APIC mode if there are any logical processor reporting
+ // an APIC ID of 255 or greater.
+ //
+ AcquireSpinLock(&PeiCpuMpData->MpLock);
+ PeiCpuMpData->X2ApicEnable = TRUE;
+ ReleaseSpinLock(&PeiCpuMpData->MpLock);
+ }
+ //
+ // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.
+ //
+ MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);
+ MicrocodeDetect ();
+ PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
+ } else {
+ //
+ // Execute AP function if AP is not disabled
+ //
+ GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
+ if (PeiCpuMpData->ApLoopMode == ApInHltLoop) {
+ //
+ // Restore AP's volatile registers saved
+ //
+ RestoreVolatileRegisters
(&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);
+ }
+
+ if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&
+ (PeiCpuMpData->ApFunction != 0)) {
+ PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;
+ Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;
+ //
+ // Invoke AP function here
+ //
+ Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);
+ //
+ // Re-get the processor number due to BSP/AP maybe exchange in AP
function
+ //
+ GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
+ PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
+ }
+ }
+
//
- // Sync BSP's Control registers to APs
+ // AP finished executing C code
//
- RestoreVolatileRegisters (&PeiCpuMpData->CpuData[0].VolatileRegisters,
FALSE);
+ InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);
+
//
- // This is first time AP wakeup, get BIST information from AP stack
+ // Place AP is specified loop mode
//
- BistData = *(UINTN *) (PeiCpuMpData->Buffer + ProcessorNumber *
PeiCpuMpData->CpuApStackSize - sizeof (UINTN));
- PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 = (UINT32) BistData;
- PeiCpuMpData->CpuData[ProcessorNumber].ApicId = GetInitialApicId ();
- if (PeiCpuMpData->CpuData[ProcessorNumber].ApicId >= 0xFF) {
+ if (PeiCpuMpData->ApLoopMode == ApInHltLoop) {
//
- // Set x2APIC mode if there are any logical processor reporting
- // an APIC ID of 255 or greater.
+ // Save AP volatile registers
//
- AcquireSpinLock(&PeiCpuMpData->MpLock);
- PeiCpuMpData->X2ApicEnable = TRUE;
- ReleaseSpinLock(&PeiCpuMpData->MpLock);
+ SaveVolatileRegisters
(&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
+ //
+ // Place AP in Hlt-loop
+ //
+ while (TRUE) {
+ DisableInterrupts ();
+ CpuSleep ();
+ CpuPause ();
+ }
}
+ ApStartupSignalBuffer =
PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal;
//
- // Sync BSP's Mtrr table to all wakeup APs and load microcode on APs.
+ // Clear AP start-up signal
//
- MtrrSetAllMtrrs (&PeiCpuMpData->MtrrTable);
- MicrocodeDetect ();
- PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
- } else {
- //
- // Execute AP function if AP is not disabled
- //
- GetProcessorNumber (PeiCpuMpData, &ProcessorNumber);
- //
- // Restore AP's volatile registers saved
- //
- RestoreVolatileRegisters
(&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);
+ *ApStartupSignalBuffer = 0;
+ while (TRUE) {
+ DisableInterrupts ();
+ if (PeiCpuMpData->ApLoopMode == ApInMwaitLoop) {
+ //
+ // Place AP in Mwait-loop
+ //
+ AsmMonitor ((UINTN)ApStartupSignalBuffer, 0, 0);
+ if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) {
+ //
+ // If AP start-up signal is not set, place AP into
+ // the maximum C-state
+ //
+ AsmMwait (PeiCpuMpData->ApTargetCState << 4, 0);
+ }
+ } else if (PeiCpuMpData->ApLoopMode == ApInRunLoop) {
+ //
+ // Place AP in Run-loop
+ //
+ CpuPause ();
+ } else {
+ ASSERT (FALSE);
+ }
- if ((PeiCpuMpData->CpuData[ProcessorNumber].State != CpuStateDisabled) &&
- (PeiCpuMpData->ApFunction != 0)) {
- PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateBusy;
- Procedure = (EFI_AP_PROCEDURE)(UINTN)PeiCpuMpData->ApFunction;
//
- // Invoke AP function here
+ // If AP start-up signal is written, AP is waken up
+ // otherwise place AP in loop again
//
- Procedure ((VOID *)(UINTN)PeiCpuMpData->ApFunctionArgument);
- PeiCpuMpData->CpuData[ProcessorNumber].State = CpuStateIdle;
+ if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {
+ break;
+ }
}
}
-
- //
- // AP finished executing C code
- //
- InterlockedIncrement ((UINT32 *)&PeiCpuMpData->FinishedCount);
-
- //
- // Save AP volatile registers
- //
- SaveVolatileRegisters
(&PeiCpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
-
- AsmCliHltLoop ();
}
/**
Modified: branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.h
===================================================================
--- branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.h 2015-12-18 05:49:28 UTC
(rev 19361)
+++ branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.h 2015-12-18 05:50:19 UTC
(rev 19362)
@@ -38,6 +38,7 @@
#include <Library/SynchronizationLib.h>
#include <Library/TimerLib.h>
#include <Library/UefiCpuLib.h>
+#include <Library/CpuLib.h>
#include "Microcode.h"
@@ -50,6 +51,8 @@
CpuStateDisabled
} CPU_STATE;
+#define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')
+
typedef enum {
ApInHltLoop = 1,
ApInMwaitLoop = 2,
Modified: branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
===================================================================
--- branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.inf 2015-12-18 05:49:28 UTC
(rev 19361)
+++ branches/UDK2015/UefiCpuPkg/CpuMpPei/CpuMpPei.inf 2015-12-18 05:50:19 UTC
(rev 19362)
@@ -66,6 +66,7 @@
SynchronizationLib
TimerLib
UefiCpuLib
+ CpuLib
[Ppis]
gEfiPeiMpServicesPpiGuid ## PRODUCES
------------------------------------------------------------------------------
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits