mirror of https://github.com/acidanthera/audk.git
UefiCpuPkg/CpuMpPei: Fix potential AP mwait wakeup issue
If ApLoopMode is set to ApInMwaitLoop, AP will be placed into C-State by mwait instruction. BSP will wakeup AP by write start-up signal in monitor address. However, AP maybe waken by SMI/NMI/MCE and other condition. On this case, AP will check if BSP wants to wakeup itself really. If not, AP will continue to execute mwait to C-State. One potential issue: BSP may not recognize AP was wakeup from C-State by other event and BSP still writes start-up signal to wakeup AP. But AP does not aware it and still execute mwait instruction to C-State. So, AP cannot be wakeup on this case. This fix is let AP to clear start-up signal when it really is wakeup to execute AP function. And BSP will write start-up signal till AP clears it. Cc: Michael Kinney <michael.d.kinney@intel.com> Cc: Feng Tian <feng.tian@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com>
This commit is contained in:
parent
587d204ccd
commit
4da1ebf3b3
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
CPU PEI Module installs CPU Multiple Processor PPI.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2015 - 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
|
||||
|
@ -355,10 +355,6 @@ ApCFunction (
|
|||
}
|
||||
}
|
||||
ApStartupSignalBuffer = PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal;
|
||||
//
|
||||
// Clear AP start-up signal
|
||||
//
|
||||
*ApStartupSignalBuffer = 0;
|
||||
while (TRUE) {
|
||||
DisableInterrupts ();
|
||||
if (PeiCpuMpData->ApLoopMode == ApInMwaitLoop) {
|
||||
|
@ -387,12 +383,44 @@ ApCFunction (
|
|||
// otherwise place AP in loop again
|
||||
//
|
||||
if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {
|
||||
//
|
||||
// Clear AP start-up signal when AP waken up
|
||||
//
|
||||
InterlockedCompareExchange32 (
|
||||
(UINT32 *)ApStartupSignalBuffer,
|
||||
WAKEUP_AP_SIGNAL,
|
||||
0
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Write AP start-up signal to wakeup AP.
|
||||
|
||||
@param ApStartupSignalBuffer Pointer to AP wakeup signal
|
||||
**/
|
||||
VOID
|
||||
WriteStartupSignal (
|
||||
IN volatile UINT32 *ApStartupSignalBuffer
|
||||
)
|
||||
{
|
||||
*ApStartupSignalBuffer = WAKEUP_AP_SIGNAL;
|
||||
//
|
||||
// If AP is waken up, StartupApSignal should be cleared.
|
||||
// Otherwise, write StartupApSignal again till AP waken up.
|
||||
//
|
||||
while (InterlockedCompareExchange32 (
|
||||
(UINT32 *)ApStartupSignalBuffer,
|
||||
WAKEUP_AP_SIGNAL,
|
||||
WAKEUP_AP_SIGNAL
|
||||
) != 0) {
|
||||
CpuPause ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This function will be called by BSP to wakeup AP.
|
||||
|
||||
|
@ -462,11 +490,11 @@ WakeUpAP (
|
|||
if (Broadcast) {
|
||||
for (Index = 0; Index < PeiCpuMpData->CpuCount; Index++) {
|
||||
if (Index != PeiCpuMpData->BspNumber) {
|
||||
*(PeiCpuMpData->CpuData[Index].StartupApSignal) = WAKEUP_AP_SIGNAL;
|
||||
WriteStartupSignal (PeiCpuMpData->CpuData[Index].StartupApSignal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*(PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal) = WAKEUP_AP_SIGNAL;
|
||||
WriteStartupSignal (PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal);
|
||||
}
|
||||
} else {
|
||||
ASSERT (FALSE);
|
||||
|
|
Loading…
Reference in New Issue