]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuMpPei/CpuMpPei.c
UefiCpuPkg/CpuMpPei: Fix potential AP mwait wakeup issue
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / CpuMpPei.c
index 950d61cc4853797dd3b6f67879481d9114d5a351..ef1c2812e2bf7f0ca620ecde61102bdd0e9592ad 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   CPU PEI Module installs CPU Multiple Processor PPI.\r
 \r
-  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -355,10 +355,6 @@ ApCFunction (
       }\r
     }\r
     ApStartupSignalBuffer = PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal;\r
-    //\r
-    // Clear AP start-up signal\r
-    //\r
-    *ApStartupSignalBuffer = 0;\r
     while (TRUE) {\r
       DisableInterrupts ();\r
       if (PeiCpuMpData->ApLoopMode == ApInMwaitLoop) {\r
@@ -387,12 +383,44 @@ ApCFunction (
       // otherwise place AP in loop again\r
       //\r
       if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {\r
+        //\r
+        // Clear AP start-up signal when AP waken up\r
+        //\r
+        InterlockedCompareExchange32 (\r
+          (UINT32 *)ApStartupSignalBuffer,\r
+          WAKEUP_AP_SIGNAL,\r
+          0\r
+        );\r
         break;\r
       }\r
     }\r
   }\r
 }\r
 \r
+/**\r
+  Write AP start-up signal to wakeup AP.\r
+\r
+  @param ApStartupSignalBuffer  Pointer to AP wakeup signal\r
+**/\r
+VOID\r
+WriteStartupSignal (\r
+  IN volatile UINT32        *ApStartupSignalBuffer\r
+  )\r
+{\r
+  *ApStartupSignalBuffer = WAKEUP_AP_SIGNAL;\r
+  //\r
+  // If AP is waken up, StartupApSignal should be cleared.\r
+  // Otherwise, write StartupApSignal again till AP waken up.\r
+  //\r
+  while (InterlockedCompareExchange32 (\r
+          (UINT32 *)ApStartupSignalBuffer,\r
+          WAKEUP_AP_SIGNAL,\r
+          WAKEUP_AP_SIGNAL\r
+          ) != 0) {\r
+    CpuPause ();\r
+  }\r
+}\r
+\r
 /**\r
   This function will be called by BSP to wakeup AP.\r
 \r
@@ -462,11 +490,11 @@ WakeUpAP (
     if (Broadcast) {\r
       for (Index = 0; Index < PeiCpuMpData->CpuCount; Index++) {\r
         if (Index != PeiCpuMpData->BspNumber) {\r
-          *(PeiCpuMpData->CpuData[Index].StartupApSignal) = WAKEUP_AP_SIGNAL;\r
+          WriteStartupSignal (PeiCpuMpData->CpuData[Index].StartupApSignal);\r
         }\r
       }\r
     } else {\r
-      *(PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal) = WAKEUP_AP_SIGNAL;\r
+      WriteStartupSignal (PeiCpuMpData->CpuData[ProcessorNumber].StartupApSignal);\r
     }\r
   } else {\r
     ASSERT (FALSE);\r
@@ -826,7 +854,6 @@ CpuMpPeimInit (
 {\r
   EFI_STATUS           Status;\r
   PEI_CPU_MP_DATA      *PeiCpuMpData;\r
-  UINT32               ProcessorCount;\r
 \r
   //\r
   // Load new GDT table on BSP\r
@@ -839,7 +866,7 @@ CpuMpPeimInit (
   //\r
   // Count processor number and collect processor information\r
   //\r
-  ProcessorCount = CountProcessorNumber (PeiCpuMpData);\r
+  CountProcessorNumber (PeiCpuMpData);\r
   //\r
   // Build location of PEI CPU MP DATA buffer in HOB\r
   //\r