]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/MpInitLib: Fix S3 resume hang issue.
authorEric Dong <eric.dong@intel.com>
Wed, 27 Jun 2018 08:42:51 +0000 (16:42 +0800)
committerEric Dong <eric.dong@intel.com>
Thu, 19 Jul 2018 05:06:49 +0000 (13:06 +0800)
When resume from S3 and CPU loop mode is MWait mode,
if driver calls APs to do task at EndOfPei point, the
APs can't been wake up and bios hang at that point.

The root cause is PiSmmCpuDxeSmm driver wakes up APs
with HLT mode during S3 resume phase to do SMM relocation.
After this task, PiSmmCpuDxeSmm driver not restore APs
context which make CpuMpPei driver saved wake up buffer
not works.

The solution for this issue is let CpuMpPei driver hook
S3SmmInitDone ppi notification. In this notify function,
it check whether Cpu Loop mode is not HLT mode. If yes,
CpuMpPei driver will set a flag to force BSP use INIT-SIPI
-SIPI command to wake up the APs.

Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/Library/MpInitLib/MpLib.h
UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
UefiCpuPkg/Library/MpInitLib/PeiMpLib.c

index 722db2a01ffe913cdf0c9809516c311e10559d1e..e5c701ddeb464d36a66321343f07931dd93e93bb 100644 (file)
@@ -985,13 +985,15 @@ WakeUpAP (
   CpuMpData->FinishedCount = 0;\r
   ResetVectorRequired = FALSE;\r
 \r
-  if (CpuMpData->ApLoopMode == ApInHltLoop ||\r
+  if (CpuMpData->WakeUpByInitSipiSipi ||\r
       CpuMpData->InitFlag   != ApInitDone) {\r
     ResetVectorRequired = TRUE;\r
     AllocateResetVector (CpuMpData);\r
     FillExchangeInfoData (CpuMpData);\r
     SaveLocalApicTimerSetting (CpuMpData);\r
-  } else if (CpuMpData->ApLoopMode == ApInMwaitLoop) {\r
+  }\r
+\r
+  if (CpuMpData->ApLoopMode == ApInMwaitLoop) {\r
     //\r
     // Get AP target C-state each time when waking up AP,\r
     // for it maybe updated by platform again\r
@@ -1076,6 +1078,13 @@ WakeUpAP (
   if (ResetVectorRequired) {\r
     FreeResetVector (CpuMpData);\r
   }\r
+\r
+  //\r
+  // After one round of Wakeup Ap actions, need to re-sync ApLoopMode with\r
+  // WakeUpByInitSipiSipi flag. WakeUpByInitSipiSipi flag maybe changed by\r
+  // S3SmmInitDone Ppi.\r
+  //\r
+  CpuMpData->WakeUpByInitSipiSipi = (CpuMpData->ApLoopMode == ApInHltLoop);\r
 }\r
 \r
 /**\r
@@ -1648,6 +1657,9 @@ MpInitLibInitialize (
   //\r
   CpuMpData->ApLoopMode = ApLoopMode;\r
   DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode));\r
+\r
+  CpuMpData->WakeUpByInitSipiSipi = (CpuMpData->ApLoopMode == ApInHltLoop);\r
+\r
   //\r
   // Set up APs wakeup signal buffer\r
   //\r
index 6958080ac192c3146d59ad97144e7e8bf59edd6b..9d0b866d097962208437352f208eb1f80ff4d9b7 100644 (file)
@@ -250,6 +250,15 @@ struct _CPU_MP_DATA {
   UINT32                         ProcessorFlags;\r
   UINT64                         MicrocodeDataAddress;\r
   UINT32                         MicrocodeRevision;\r
+\r
+  //\r
+  // Whether need to use Init-Sipi-Sipi to wake up the APs.\r
+  // Two cases need to set this value to TRUE. One is in HLT\r
+  // loop mode, the other is resume from S3 which loop mode\r
+  // will be hardcode change to HLT mode by PiSmmCpuDxeSmm \r
+  // driver.\r
+  //\r
+  BOOLEAN                        WakeUpByInitSipiSipi;\r
 };\r
 \r
 extern EFI_GUID mCpuInitMpLibHobGuid;\r
index fa84e392af1d72d3fbfdd8c01519c73c2ac0fb89..43a3b3b036f03585aef5df258440e5b3645ab198 100644 (file)
@@ -44,6 +44,7 @@
 [Packages]\r
   MdePkg/MdePkg.dec\r
   UefiCpuPkg/UefiCpuPkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
 \r
 [LibraryClasses]\r
   BaseLib\r
@@ -54,6 +55,7 @@
   CpuLib\r
   UefiCpuLib\r
   SynchronizationLib\r
+  PeiServicesLib\r
 \r
 [Pcd]\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## CONSUMES\r
@@ -64,3 +66,5 @@
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode                       ## CONSUMES\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate                   ## SOMETIMES_CONSUMES\r
 \r
+[Guids]\r
+  gEdkiiS3SmmInitDoneGuid
\ No newline at end of file
index 92f28681e45a72a254a52e25dda0c86d225de22a..06d966b22719d5f95e3071b0dd2943fd4f817f95 100644 (file)
 **/\r
 \r
 #include "MpLib.h"\r
+#include <Library/PeiServicesLib.h>\r
+#include <Guid/S3SmmInitDone.h>\r
+\r
+/**\r
+  S3 SMM Init Done notification function.\r
+\r
+  @param  PeiServices      Indirect reference to the PEI Services Table.\r
+  @param  NotifyDesc       Address of the notification descriptor data structure.\r
+  @param  InvokePpi        Address of the PPI that was invoked.\r
+\r
+  @retval EFI_SUCCESS      The function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NotifyOnS3SmmInitDonePpi (\r
+  IN  EFI_PEI_SERVICES                              **PeiServices,\r
+  IN  EFI_PEI_NOTIFY_DESCRIPTOR                     *NotifyDesc,\r
+  IN  VOID                                          *InvokePpi\r
+  );\r
+\r
+\r
+//\r
+// Global function\r
+//\r
+EFI_PEI_NOTIFY_DESCRIPTOR        mS3SmmInitDoneNotifyDesc = {\r
+  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
+  &gEdkiiS3SmmInitDoneGuid,\r
+  NotifyOnS3SmmInitDonePpi\r
+};\r
+\r
+/**\r
+  The function prototype for invoking a function on an Application Processor.\r
+\r
+  This definition is used by the UEFI MP Serices Protocol, and the\r
+  PI SMM System Table.\r
+\r
+  @param[in,out] Buffer  The pointer to private data buffer.\r
+**/\r
+VOID\r
+EmptyApProcedure (\r
+  IN OUT VOID * Buffer\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  S3 SMM Init Done notification function.\r
+\r
+  @param  PeiServices      Indirect reference to the PEI Services Table.\r
+  @param  NotifyDesc       Address of the notification descriptor data structure.\r
+  @param  InvokePpi        Address of the PPI that was invoked.\r
+\r
+  @retval EFI_SUCCESS      The function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NotifyOnS3SmmInitDonePpi (\r
+  IN  EFI_PEI_SERVICES                              **PeiServices,\r
+  IN  EFI_PEI_NOTIFY_DESCRIPTOR                     *NotifyDesc,\r
+  IN  VOID                                          *InvokePpi\r
+  )\r
+{\r
+  CPU_MP_DATA     *CpuMpData;\r
+\r
+  CpuMpData = GetCpuMpData ();\r
+\r
+  //\r
+  // PiSmmCpuDxeSmm driver hardcode change the loop mode to HLT mode.\r
+  // So in this notify function, code need to check the current loop\r
+  // mode, if it is not HLT mode, code need to change loop mode back\r
+  // to the original mode.\r
+  //\r
+  if (CpuMpData->ApLoopMode != ApInHltLoop) {\r
+    CpuMpData->WakeUpByInitSipiSipi = TRUE;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 \r
 /**\r
   Enable Debug Agent to support source debugging on AP function.\r
@@ -240,7 +321,15 @@ InitMpGlobalData (
   IN CPU_MP_DATA               *CpuMpData\r
   )\r
 {\r
+  EFI_STATUS  Status;\r
+\r
   SaveCpuMpData (CpuMpData);\r
+\r
+  ///\r
+  /// Install Notify\r
+  ///\r
+  Status = PeiServicesNotifyPpi (&mS3SmmInitDoneNotifyDesc);\r
+  ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
 /**\r