diff options
author | Jeff Fan <jeff.fan@intel.com> | 2016-03-31 19:15:05 +0800 |
---|---|---|
committer | Hao Wu <hao.a.wu@intel.com> | 2016-07-06 11:11:31 +0800 |
commit | 5a005913347249598e61fc479bfbe5178d32de2e (patch) | |
tree | f5e25ee562365a6f55890addff642c6580af6434 /UefiCpuPkg | |
parent | bee07bd99a733442444f19faaff684dd8d759e23 (diff) | |
download | edk2-platforms-5a005913347249598e61fc479bfbe5178d32de2e.tar.xz |
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>
(cherry picked from commit 4da1ebf3b3c22ec3e09cef3fe5d1da6f40895e6d)
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r-- | UefiCpuPkg/CpuMpPei/CpuMpPei.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.c b/UefiCpuPkg/CpuMpPei/CpuMpPei.c index 950d61cc48..21c30bff5f 100644 --- a/UefiCpuPkg/CpuMpPei/CpuMpPei.c +++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.c @@ -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,6 +383,14 @@ 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;
}
}
@@ -394,6 +398,30 @@ ApCFunction ( }
/**
+ 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.
@param PeiCpuMpData Pointer to PEI CPU MP Data
@@ -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);
|