]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
UefiCpuPkg S3ResumePei: Signal S3SmmInitDone
[mirror_edk2.git] / UefiCpuPkg / Universal / Acpi / S3Resume2Pei / S3Resume.c
index 3afd0ff0e395859679c22afae22fc51bd9fa368a..4ae168a2c3ce4cad274a679019b29328fa4b88ca 100644 (file)
@@ -1,10 +1,11 @@
 /** @file\r
-  This module produces the EFI_PEI_S3_RESUME_PPI.\r
+  This module produces the EFI_PEI_S3_RESUME2_PPI.\r
   This module works with StandAloneBootScriptExecutor to S3 resume to OS.\r
-  This module will excute the boot script saved during last boot and after that,\r
+  This module will execute the boot script saved during last boot and after that,\r
   control is passed to OS waking up handler.\r
 \r
-  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions\r
 \r
 #include <Guid/AcpiS3Context.h>\r
 #include <Guid/BootScriptExecutorVariable.h>\r
-#include <Guid/Performance.h>\r
+#include <Guid/ExtendedFirmwarePerformance.h>\r
+#include <Guid/EndOfS3Resume.h>\r
+#include <Guid/S3SmmInitDone.h>\r
 #include <Ppi/ReadOnlyVariable2.h>\r
 #include <Ppi/S3Resume2.h>\r
 #include <Ppi/SmmAccess.h>\r
 #include <Ppi/PostBootScriptTable.h>\r
 #include <Ppi/EndOfPeiPhase.h>\r
+#include <Ppi/SmmCommunication.h>\r
 \r
 #include <Library/DebugLib.h>\r
 #include <Library/BaseLib.h>\r
 #include <Library/LockBoxLib.h>\r
 #include <IndustryStandard/Acpi.h>\r
 \r
+/**\r
+  This macro aligns the address of a variable with auto storage\r
+  duration down to CPU_STACK_ALIGNMENT.\r
+\r
+  Since the stack grows downward, the result preserves more of the\r
+  stack than the original address (or the same amount), not less.\r
+**/\r
+#define STACK_ALIGN_DOWN(Ptr) \\r
+          ((UINTN)(Ptr) & ~(UINTN)(CPU_STACK_ALIGNMENT - 1))\r
+\r
+#define PAGING_1G_ADDRESS_MASK_64  0x000FFFFFC0000000ull\r
+\r
 #pragma pack(1)\r
 typedef union {\r
   struct {\r
@@ -138,6 +154,22 @@ typedef union {
   UINT64    Uint64;\r
 } PAGE_TABLE_1G_ENTRY;\r
 \r
+//\r
+// Define two type of smm communicate headers.\r
+// One for 32 bits PEI + 64 bits DXE, the other for 32 bits PEI + 32 bits DXE case.\r
+//\r
+typedef struct {\r
+  EFI_GUID  HeaderGuid;\r
+  UINT32    MessageLength;\r
+  UINT8     Data[1];\r
+} SMM_COMMUNICATE_HEADER_32;\r
+\r
+typedef struct {\r
+  EFI_GUID  HeaderGuid;\r
+  UINT64    MessageLength;\r
+  UINT8     Data[1];\r
+} SMM_COMMUNICATE_HEADER_64;\r
+\r
 #pragma pack()\r
 \r
 //\r
@@ -193,6 +225,18 @@ S3RestoreConfig2 (
   IN EFI_PEI_S3_RESUME2_PPI  *This\r
   );\r
 \r
+/**\r
+  Set data segment selectors value including DS/ES/FS/GS/SS.\r
+\r
+  @param[in]  SelectorValue      Segment selector value to be set.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+AsmSetDataSelectors (\r
+  IN UINT16   SelectorValue\r
+  );\r
+\r
 //\r
 // Globals\r
 //\r
@@ -216,6 +260,12 @@ EFI_PEI_PPI_DESCRIPTOR mPpiListEndOfPeiTable = {
   0\r
 };\r
 \r
+EFI_PEI_PPI_DESCRIPTOR mPpiListS3SmmInitDoneTable = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gEdkiiS3SmmInitDoneGuid,\r
+  0\r
+};\r
+\r
 //\r
 // Global Descriptor Table (GDT)\r
 //\r
@@ -232,6 +282,8 @@ GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {
 /* 0x40 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},\r
 };\r
 \r
+#define DATA_SEGEMENT_SELECTOR        0x18\r
+\r
 //\r
 // IA32 Gdt register\r
 //\r
@@ -240,129 +292,101 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {
   (UINTN) mGdtEntries\r
   };\r
 \r
+\r
+/**\r
+  The function will check if current waking vector is long mode.\r
+\r
+  @param  AcpiS3Context                 a pointer to a structure of ACPI_S3_CONTEXT\r
+\r
+  @retval TRUE   Current context need long mode waking vector.\r
+  @retval FALSE  Current context need not long mode waking vector.\r
+**/\r
+BOOLEAN\r
+IsLongModeWakingVector (\r
+  IN ACPI_S3_CONTEXT                *AcpiS3Context\r
+  )\r
+{\r
+  EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs;\r
+\r
+  Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable));\r
+  if ((Facs == NULL) ||\r
+      (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||\r
+      ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)) ) {\r
+    // Something wrong with FACS\r
+    return FALSE;\r
+  }\r
+  if (Facs->XFirmwareWakingVector != 0) {\r
+    if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
+        ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&\r
+        ((Facs->Flags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0)) {\r
+      // Both BIOS and OS wants 64bit vector\r
+      if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+        return TRUE;\r
+      }\r
+    }\r
+  }\r
+  return FALSE;\r
+}\r
+\r
 /**\r
-  Performance measure function to get S3 detailed performance data.\r
+  Signal to SMM through communication buffer way.\r
+\r
+  @param[in]  HandlerType       SMI handler type to be signaled.\r
 \r
-  This function will getS3 detailed performance data and saved in pre-reserved ACPI memory.\r
 **/\r
 VOID\r
-WriteToOsS3PerformanceData (\r
-  VOID\r
+SignalToSmmByCommunication (\r
+  IN EFI_GUID   *HandlerType\r
   )\r
 {\r
-  EFI_STATUS                                    Status;\r
-  EFI_PHYSICAL_ADDRESS                          mAcpiLowMemoryBase;\r
-  PERF_HEADER                                   *PerfHeader;\r
-  PERF_DATA                                     *PerfData;\r
-  UINT64                                        Ticker;\r
-  UINTN                                         Index;\r
-  EFI_PEI_READ_ONLY_VARIABLE2_PPI               *VariableServices;\r
-  UINTN                                         VarSize;\r
-  UINTN                                         LogEntryKey;\r
-  CONST VOID                                    *Handle;\r
-  CONST CHAR8                                   *Token;\r
-  CONST CHAR8                                   *Module;\r
-  UINT64                                        StartTicker;\r
-  UINT64                                        EndTicker;\r
-  UINT64                                        StartValue;\r
-  UINT64                                        EndValue;\r
-  BOOLEAN                                       CountUp;\r
-  UINT64                                        Freq;\r
+  EFI_STATUS                         Status;\r
+  EFI_PEI_SMM_COMMUNICATION_PPI      *SmmCommunicationPpi;\r
+  UINTN                              CommSize;\r
+  SMM_COMMUNICATE_HEADER_32          Header32;\r
+  SMM_COMMUNICATE_HEADER_64          Header64;\r
+  VOID                               *CommBuffer;\r
+\r
+  DEBUG ((DEBUG_INFO, "Signal %g to SMM - Enter\n", HandlerType));\r
 \r
   //\r
-  // Retrive time stamp count as early as possilbe\r
+  // This buffer consumed in DXE phase, so base on DXE mode to prepare communicate buffer.\r
+  // Detect whether DXE is 64 bits mode.\r
+  // if (sizeof(UINTN) == sizeof(UINT64), PEI already 64 bits, assume DXE also 64 bits.\r
+  // or (FeaturePcdGet (PcdDxeIplSwitchToLongMode)), DXE will switch to 64 bits.\r
   //\r
-  Ticker = GetPerformanceCounter ();\r
-\r
-  Freq   = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
-\r
-  Freq   = DivU64x32 (Freq, 1000);\r
+  if ((sizeof(UINTN) == sizeof(UINT64)) || (FeaturePcdGet (PcdDxeIplSwitchToLongMode))) {\r
+    CommBuffer = &Header64;\r
+    Header64.MessageLength = 0;\r
+    CommSize = OFFSET_OF (SMM_COMMUNICATE_HEADER_64, Data);\r
+  } else {\r
+    CommBuffer = &Header32;\r
+    Header32.MessageLength = 0;\r
+    CommSize = OFFSET_OF (SMM_COMMUNICATE_HEADER_32, Data);\r
+  }\r
+  CopyGuid (CommBuffer, HandlerType);\r
 \r
   Status = PeiServicesLocatePpi (\r
-             &gEfiPeiReadOnlyVariable2PpiGuid,\r
+             &gEfiPeiSmmCommunicationPpiGuid,\r
              0,\r
              NULL,\r
-             (VOID **) &VariableServices\r
+             (VOID **)&SmmCommunicationPpi\r
              );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  VarSize   = sizeof (EFI_PHYSICAL_ADDRESS);\r
-  Status = VariableServices->GetVariable (\r
-                               VariableServices,\r
-                               L"PerfDataMemAddr",\r
-                               &gPerformanceProtocolGuid,\r
-                               NULL,\r
-                               &VarSize,\r
-                               &mAcpiLowMemoryBase\r
-                               );\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Fail to retrieve variable to log S3 performance data \n"));\r
-    return;\r
-  }\r
-\r
-  PerfHeader = (PERF_HEADER *) (UINTN) mAcpiLowMemoryBase;\r
-\r
-  if (PerfHeader->Signiture != PERFORMANCE_SIGNATURE) {\r
-    DEBUG ((EFI_D_ERROR, "Performance data in ACPI memory get corrupted! \n"));\r
+    DEBUG ((DEBUG_ERROR, "Locate Smm Communicate Ppi failed (%r)!\n", Status));\r
     return;\r
   }\r
 \r
-  //\r
-  // Record total S3 resume time.\r
-  //\r
-  if (EndValue >= StartValue) {\r
-    PerfHeader->S3Resume = Ticker - StartValue;\r
-    CountUp              = TRUE;\r
-  } else {\r
-    PerfHeader->S3Resume = StartValue - Ticker;\r
-    CountUp              = FALSE;\r
+  Status = SmmCommunicationPpi->Communicate (\r
+                                  SmmCommunicationPpi,\r
+                                  (VOID *)CommBuffer,\r
+                                  &CommSize\r
+                                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "SmmCommunicationPpi->Communicate return failure (%r)!\n", Status));\r
   }\r
 \r
-  //\r
-  // Get S3 detailed performance data\r
-  //\r
-  Index = 0;\r
-  LogEntryKey = 0;\r
-  while ((LogEntryKey = GetPerformanceMeasurement (\r
-                          LogEntryKey,\r
-                          &Handle,\r
-                          &Token,\r
-                          &Module,\r
-                          &StartTicker,\r
-                          &EndTicker)) != 0) {\r
-    if (EndTicker != 0) {\r
-      PerfData = &PerfHeader->S3Entry[Index];\r
-\r
-      //\r
-      // Use File Handle to specify the different performance log for PEIM.\r
-      // File Handle is the base address of PEIM FFS file.\r
-      //\r
-      if ((AsciiStrnCmp (Token, "PEIM", PEI_PERFORMANCE_STRING_SIZE) == 0) && (Handle != NULL)) {\r
-        AsciiSPrint (PerfData->Token, PERF_TOKEN_LENGTH, "0x%11p", Handle);\r
-      } else {\r
-        AsciiStrnCpy (PerfData->Token, Token, PERF_TOKEN_LENGTH);\r
-      }\r
-      if (StartTicker == 1) {\r
-        StartTicker = StartValue;\r
-      }\r
-      if (EndTicker == 1) {\r
-        EndTicker = StartValue;\r
-      }\r
-      Ticker = CountUp? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
-      PerfData->Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
-\r
-      //\r
-      // Only Record > 1ms performance data so that more big performance can be recorded.\r
-      //\r
-      if ((Ticker > Freq) && (++Index >= PERF_PEI_ENTRY_MAX_NUM)) {\r
-        //\r
-        // Reach the maximum number of PEI performance log entries.\r
-        //\r
-        break;\r
-      }\r
-    }\r
-  }\r
-  PerfHeader->S3EntryNum = (UINT32) Index;\r
+  DEBUG ((DEBUG_INFO, "Signal %g to SMM - Exit (%r)\n", HandlerType, Status));\r
+  return;\r
 }\r
 \r
 /**\r
@@ -390,12 +414,34 @@ S3ResumeBootOs (
   //\r
   AsmWriteIdtr (&PeiS3ResumeState->Idtr);\r
 \r
+  if (PeiS3ResumeState->ReturnStatus != EFI_SUCCESS) {\r
+    //\r
+    // Report Status code that boot script execution is failed\r
+    //\r
+    REPORT_STATUS_CODE (\r
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+      (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_BOOT_SCRIPT_ERROR)\r
+      );\r
+  }\r
+\r
+  //\r
+  // NOTE: Because Debug Timer interrupt and system interrupts will be disabled \r
+  // in BootScriptExecuteDxe, the rest code in S3ResumeBootOs() cannot be halted\r
+  // by soft debugger.\r
+  //\r
+\r
+  PERF_END (NULL, "ScriptExec", NULL, 0);\r
+\r
   //\r
   // Install BootScriptDonePpi\r
   //\r
+  PERF_START_EX (NULL, "BootScriptDonePpi", NULL, 0, PERF_INMODULE_START_ID);\r
+\r
   Status = PeiServicesInstallPpi (&mPpiListPostScriptTable);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  PERF_END_EX (NULL, "BootScriptDonePpi", NULL, 0, PERF_INMODULE_END_ID);\r
+\r
   //\r
   // Get ACPI Table Address\r
   //\r
@@ -404,24 +450,41 @@ S3ResumeBootOs (
   if ((Facs == NULL) ||\r
       (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||\r
       ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)) ) {\r
+    //\r
+    // Report Status code that no valid vector is found\r
+    //\r
+    REPORT_STATUS_CODE (\r
+      EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
+      (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_OS_WAKE_ERROR)\r
+      );\r
     CpuDeadLoop ();\r
     return ;\r
   }\r
 \r
-  //\r
-  // report status code on S3 resume\r
-  //\r
-  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE);\r
-\r
   //\r
   // Install EndOfPeiPpi\r
   //\r
+  PERF_START_EX (NULL, "EndOfPeiPpi", NULL, 0, PERF_INMODULE_START_ID);\r
+\r
   Status = PeiServicesInstallPpi (&mPpiListEndOfPeiTable);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  PERF_CODE (\r
-    WriteToOsS3PerformanceData ();\r
-    );\r
+  PERF_END_EX (NULL, "EndOfPeiPpi", NULL, 0, PERF_INMODULE_END_ID);\r
+\r
+  PERF_START_EX (NULL, "EndOfS3Resume", NULL, 0, PERF_INMODULE_START_ID);\r
+\r
+  DEBUG ((DEBUG_INFO, "Signal EndOfS3Resume\n"));\r
+  //\r
+  // Signal EndOfS3Resume to SMM.\r
+  //\r
+  SignalToSmmByCommunication (&gEdkiiEndOfS3ResumeGuid);\r
+\r
+  PERF_END_EX (NULL, "EndOfS3Resume", NULL, 0, PERF_INMODULE_END_ID);\r
+\r
+  //\r
+  // report status code on S3 resume\r
+  //\r
+  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE);\r
 \r
   AsmTransferControl = (ASM_TRANSFER_CONTROL)(UINTN)PeiS3ResumeState->AsmTransferControl;\r
   if (Facs->XFirmwareWakingVector != 0) {\r
@@ -429,13 +492,20 @@ S3ResumeBootOs (
     // Switch to native waking vector\r
     //\r
     TempStackTop = (UINTN)&TempStack + sizeof(TempStack);\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a() Stack Base: 0x%x, Stack Size: 0x%x\n",\r
+      __FUNCTION__,\r
+      TempStackTop,\r
+      sizeof (TempStack)\r
+      ));\r
     if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
         ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&\r
         ((Facs->Flags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0)) {\r
       //\r
       // X64 long mode waking vector\r
       //\r
-      DEBUG (( EFI_D_ERROR, "Transfer to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));\r
+      DEBUG ((DEBUG_INFO, "Transfer to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));\r
       if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
         AsmEnablePaging64 (\r
           0x38,\r
@@ -445,14 +515,23 @@ S3ResumeBootOs (
           (UINT64)(UINTN)TempStackTop\r
           );\r
       } else {\r
+        //\r
+        // Report Status code that no valid waking vector is found\r
+        //\r
+        REPORT_STATUS_CODE (\r
+          EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
+          (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_OS_WAKE_ERROR)\r
+          );\r
         DEBUG (( EFI_D_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n"));\r
         ASSERT (FALSE);\r
+        CpuDeadLoop ();\r
+        return ;\r
       }\r
     } else {\r
       //\r
       // IA32 protected mode waking vector (Page disabled)\r
       //\r
-      DEBUG (( EFI_D_ERROR, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));\r
+      DEBUG ((DEBUG_INFO, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));\r
       SwitchStack (\r
         (SWITCH_STACK_ENTRY_POINT) (UINTN) Facs->XFirmwareWakingVector,\r
         NULL,\r
@@ -464,10 +543,18 @@ S3ResumeBootOs (
     //\r
     // 16bit Realmode waking vector\r
     //\r
-    DEBUG (( EFI_D_ERROR, "Transfer to 16bit OS waking vector - %x\r\n", (UINTN)Facs->FirmwareWakingVector));\r
+    DEBUG ((DEBUG_INFO, "Transfer to 16bit OS waking vector - %x\r\n", (UINTN)Facs->FirmwareWakingVector));\r
     AsmTransferControl (Facs->FirmwareWakingVector, 0x0);\r
   }\r
 \r
+  //\r
+  // Report Status code the failure of S3Resume\r
+  //\r
+  REPORT_STATUS_CODE (\r
+    EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
+    (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_OS_WAKE_ERROR)\r
+    );\r
+\r
   //\r
   // Never run to here\r
   //\r
@@ -479,10 +566,12 @@ S3ResumeBootOs (
   If BootScriptExector driver will not run in 64-bit mode, this function will do nothing. \r
 \r
   @param S3NvsPageTableAddress   PageTableAddress in ACPINvs\r
+  @param Build4GPageTableOnly    If BIOS just build 4G page table only\r
 **/\r
 VOID\r
 RestoreS3PageTables (\r
-  IN UINTN                                         S3NvsPageTableAddress\r
+  IN UINTN                                         S3NvsPageTableAddress,\r
+  IN BOOLEAN                                       Build4GPageTableOnly\r
   )\r
 {\r
   if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
@@ -502,17 +591,23 @@ RestoreS3PageTables (
     VOID                                          *Hob;\r
     BOOLEAN                                       Page1GSupport;\r
     PAGE_TABLE_1G_ENTRY                           *PageDirectory1GEntry;\r
+    UINT64                                        AddressEncMask;\r
+\r
+    //\r
+    // Make sure AddressEncMask is contained to smallest supported address field\r
+    //\r
+    AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;\r
 \r
     //\r
     // NOTE: We have to ASSUME the page table generation format, because we do not know whole page table information.\r
     // The whole page table is too large to be saved in SMRAM.\r
     //\r
-    // The assumption is : whole page table is allocated in CONTINOUS memory and CR3 points to TOP page.\r
+    // The assumption is : whole page table is allocated in CONTINUOUS memory and CR3 points to TOP page.\r
     //\r
-    DEBUG ((EFI_D_ERROR, "S3NvsPageTableAddress - %x\n", S3NvsPageTableAddress));\r
+    DEBUG ((DEBUG_INFO, "S3NvsPageTableAddress - %x (%x)\n", (UINTN)S3NvsPageTableAddress, (UINTN)Build4GPageTableOnly));\r
 \r
     //\r
-    // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.\r
+    // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.\r
     //\r
     PageMap = (PAGE_MAP_AND_DIRECTORY_POINTER *)S3NvsPageTableAddress;\r
     S3NvsPageTableAddress += SIZE_4KB;\r
@@ -552,6 +647,14 @@ RestoreS3PageTables (
       PhysicalAddressBits = 48;\r
     }\r
 \r
+    //\r
+    // NOTE: In order to save time to create full page table, we just create 4G page table by default.\r
+    // And let PF handler in BootScript driver to create more on request.\r
+    //\r
+    if (Build4GPageTableOnly) {\r
+      PhysicalAddressBits = 32;\r
+      ZeroMem (PageMap, EFI_PAGES_TO_SIZE(2));\r
+    }\r
     //\r
     // Calculate the table entries needed.\r
     //\r
@@ -576,7 +679,7 @@ RestoreS3PageTables (
       //\r
       // Make a PML4 Entry\r
       //\r
-      PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;\r
+      PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry | AddressEncMask;\r
       PageMapLevel4Entry->Bits.ReadWrite = 1;\r
       PageMapLevel4Entry->Bits.Present = 1;\r
 \r
@@ -587,7 +690,7 @@ RestoreS3PageTables (
           //\r
           // Fill in the Page Directory entries\r
           //\r
-          PageDirectory1GEntry->Uint64 = (UINT64)PageAddress;\r
+          PageDirectory1GEntry->Uint64 = (UINT64)PageAddress | AddressEncMask;\r
           PageDirectory1GEntry->Bits.ReadWrite = 1;\r
           PageDirectory1GEntry->Bits.Present = 1;\r
           PageDirectory1GEntry->Bits.MustBe1 = 1;\r
@@ -604,7 +707,7 @@ RestoreS3PageTables (
           //\r
           // Fill in a Page Directory Pointer Entries\r
           //\r
-          PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;\r
+          PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry | AddressEncMask;\r
           PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
           PageDirectoryPointerEntry->Bits.Present = 1;\r
     \r
@@ -612,7 +715,7 @@ RestoreS3PageTables (
             //\r
             // Fill in the Page Directory entries\r
             //\r
-            PageDirectoryEntry->Uint64 = (UINT64)PageAddress;\r
+            PageDirectoryEntry->Uint64 = (UINT64)PageAddress | AddressEncMask;\r
             PageDirectoryEntry->Bits.ReadWrite = 1;\r
             PageDirectoryEntry->Bits.Present = 1;\r
             PageDirectoryEntry->Bits.MustBe1 = 1;\r
@@ -652,8 +755,9 @@ S3ResumeExecuteBootScript (
   IA32_DESCRIPTOR            *IdtDescriptor;\r
   VOID                       *IdtBuffer;\r
   PEI_S3_RESUME_STATE        *PeiS3ResumeState;\r
+  BOOLEAN                    InterruptStatus;\r
 \r
-  DEBUG ((EFI_D_ERROR, "S3ResumeExecuteBootScript()\n"));\r
+  DEBUG ((DEBUG_INFO, "S3ResumeExecuteBootScript()\n"));\r
 \r
   //\r
   // Attempt to use content from SMRAM first\r
@@ -679,25 +783,33 @@ S3ResumeExecuteBootScript (
                               NULL,\r
                               (VOID **) &SmmAccess\r
                               );\r
+    if (!EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_INFO, "Close all SMRAM regions before executing boot script\n"));\r
+  \r
+      for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
+        Status = SmmAccess->Close ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+      }\r
 \r
-    DEBUG ((EFI_D_ERROR, "Close all SMRAM regions before executing boot script\n"));\r
-\r
-    for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
-      Status = SmmAccess->Close ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+      DEBUG ((DEBUG_INFO, "Lock all SMRAM regions before executing boot script\n"));\r
+  \r
+      for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
+        Status = SmmAccess->Lock ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+      }\r
     }\r
 \r
-    DEBUG ((EFI_D_ERROR, "Lock all SMRAM regions before executing boot script\n"));\r
-\r
-    for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
-      Status = SmmAccess->Lock ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
-    }\r
+    DEBUG ((DEBUG_INFO, "Signal S3SmmInitDone\n"));\r
+    //\r
+    // Install S3SmmInitDone PPI.\r
+    //\r
+    Status = PeiServicesInstallPpi (&mPpiListS3SmmInitDoneTable);\r
+    ASSERT_EFI_ERROR (Status);\r
+    //\r
+    // Signal S3SmmInitDone to SMM.\r
+    //\r
+    SignalToSmmByCommunication (&gEdkiiS3SmmInitDoneGuid);\r
   }\r
 \r
   if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
-    //\r
-    // Need reconstruct page table here, since we do not trust ACPINvs.\r
-    //\r
-    RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress);\r
     AsmWriteCr3 ((UINTN)AcpiS3Context->S3NvsPageTableAddress);\r
   }\r
 \r
@@ -708,39 +820,73 @@ S3ResumeExecuteBootScript (
     //\r
     IdtDescriptor = (IA32_DESCRIPTOR *) (UINTN) (AcpiS3Context->IdtrProfile);\r
     //\r
-    // Make sure the newly allcated IDT align with 16-bytes\r
+    // Make sure the newly allocated IDT align with 16-bytes\r
     // \r
     IdtBuffer = AllocatePages (EFI_SIZE_TO_PAGES((IdtDescriptor->Limit + 1) + 16));\r
-    ASSERT (IdtBuffer != NULL);\r
+    if (IdtBuffer == NULL) {\r
+      REPORT_STATUS_CODE (\r
+        EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
+        (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_RESUME_FAILED)\r
+        );\r
+      ASSERT (FALSE);\r
+    }\r
+    //\r
+    // Additional 16 bytes allocated to save IA32 IDT descriptor and Pei Service Table Pointer\r
+    // IA32 IDT descriptor will be used to setup IA32 IDT table for 32-bit Framework Boot Script code\r
+    // \r
+    ZeroMem (IdtBuffer, 16);\r
+    AsmReadIdtr ((IA32_DESCRIPTOR *)IdtBuffer);\r
     CopyMem ((VOID*)((UINT8*)IdtBuffer + 16),(VOID*)(IdtDescriptor->Base), (IdtDescriptor->Limit + 1));\r
     IdtDescriptor->Base = (UINTN)((UINT8*)IdtBuffer + 16);\r
     *(UINTN*)(IdtDescriptor->Base - sizeof(UINTN)) = (UINTN)GetPeiServicesTablePointer ();\r
   }\r
 \r
+  InterruptStatus = SaveAndDisableInterrupts ();\r
   //\r
   // Need to make sure the GDT is loaded with values that support long mode and real mode.\r
   //\r
   AsmWriteGdtr (&mGdt);\r
+  //\r
+  // update segment selectors per the new GDT.\r
+  //\r
+  AsmSetDataSelectors (DATA_SEGEMENT_SELECTOR);\r
+  //\r
+  // Restore interrupt state.\r
+  //\r
+  SetInterruptState (InterruptStatus);\r
 \r
   //\r
   // Prepare data for return back\r
   //\r
   PeiS3ResumeState = AllocatePool (sizeof(*PeiS3ResumeState));\r
-  ASSERT (PeiS3ResumeState != NULL);\r
-  DEBUG (( EFI_D_ERROR, "PeiS3ResumeState - %x\r\n", PeiS3ResumeState));\r
+  if (PeiS3ResumeState == NULL) {\r
+    REPORT_STATUS_CODE (\r
+      EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
+      (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_RESUME_FAILED)\r
+      );\r
+    ASSERT (FALSE);\r
+  }\r
+  DEBUG ((DEBUG_INFO, "PeiS3ResumeState - %x\r\n", PeiS3ResumeState));\r
   PeiS3ResumeState->ReturnCs           = 0x10;\r
   PeiS3ResumeState->ReturnEntryPoint   = (EFI_PHYSICAL_ADDRESS)(UINTN)S3ResumeBootOs;\r
-  PeiS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)&Status;\r
+  PeiS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)STACK_ALIGN_DOWN (&Status);\r
   //\r
   // Save IDT\r
   //\r
   AsmReadIdtr (&PeiS3ResumeState->Idtr);\r
+  \r
+  //\r
+  // Report Status Code to indicate S3 boot script execution\r
+  //\r
+  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_S3_BOOT_SCRIPT);\r
+\r
+  PERF_START (NULL, "ScriptExec", NULL, 0);\r
 \r
   if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
     //\r
     // X64 S3 Resume\r
     //\r
-    DEBUG (( EFI_D_ERROR, "Enable X64 and transfer control to Standalone Boot Script Executor\r\n"));\r
+    DEBUG ((DEBUG_INFO, "Enable X64 and transfer control to Standalone Boot Script Executor\r\n"));\r
 \r
     //\r
     // Switch to long mode to complete resume.\r
@@ -756,7 +902,7 @@ S3ResumeExecuteBootScript (
     //\r
     // IA32 S3 Resume\r
     //\r
-    DEBUG (( EFI_D_ERROR, "transfer control to Standalone Boot Script Executor\r\n"));\r
+    DEBUG ((DEBUG_INFO, "transfer control to Standalone Boot Script Executor\r\n"));\r
     SwitchStack (\r
       (SWITCH_STACK_ENTRY_POINT) (UINTN) EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint,\r
       (VOID *)AcpiS3Context,\r
@@ -811,7 +957,6 @@ S3RestoreConfig2 (
   PEI_SMM_ACCESS_PPI                            *SmmAccess;\r
   UINTN                                         Index;\r
   ACPI_S3_CONTEXT                               *AcpiS3Context;\r
-  EFI_PEI_READ_ONLY_VARIABLE2_PPI               *VariableServices;\r
   EFI_PHYSICAL_ADDRESS                          TempEfiBootScriptExecutorVariable;\r
   EFI_PHYSICAL_ADDRESS                          TempAcpiS3Context;\r
   BOOT_SCRIPT_EXECUTOR_VARIABLE                 *EfiBootScriptExecutorVariable;\r
@@ -819,28 +964,13 @@ S3RestoreConfig2 (
   EFI_SMRAM_DESCRIPTOR                          *SmramDescriptor;\r
   SMM_S3_RESUME_STATE                           *SmmS3ResumeState;\r
   VOID                                          *GuidHob;\r
+  BOOLEAN                                       Build4GPageTableOnly;\r
+  BOOLEAN                                       InterruptStatus;\r
 \r
-  DEBUG ((EFI_D_ERROR, "Enter S3 PEIM\r\n"));\r
+  TempAcpiS3Context = 0;\r
+  TempEfiBootScriptExecutorVariable = 0;\r
 \r
-  Status = PeiServicesLocatePpi (\r
-                            &gPeiSmmAccessPpiGuid,\r
-                            0,\r
-                            NULL,\r
-                            (VOID **) &SmmAccess\r
-                            );\r
-  for (Index = 0; !EFI_ERROR (Status); Index++) {\r
-    Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
-  }\r
-\r
-  Status = PeiServicesLocatePpi (\r
-                            &gEfiPeiReadOnlyVariable2PpiGuid,\r
-                            0,\r
-                            NULL,\r
-                            (VOID **) &VariableServices\r
-                            );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+  DEBUG ((DEBUG_INFO, "Enter S3 PEIM\r\n"));\r
 \r
   VarSize = sizeof (EFI_PHYSICAL_ADDRESS);\r
   Status = RestoreLockBox (\r
@@ -850,9 +980,6 @@ S3RestoreConfig2 (
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  AcpiS3Context = (ACPI_S3_CONTEXT *)(UINTN)TempAcpiS3Context;\r
-  ASSERT (AcpiS3Context != NULL);\r
-\r
   Status = RestoreLockBox (\r
              &gEfiAcpiS3ContextGuid,\r
              NULL,\r
@@ -860,7 +987,10 @@ S3RestoreConfig2 (
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  VarSize   = sizeof (TempEfiBootScriptExecutorVariable);\r
+  AcpiS3Context = (ACPI_S3_CONTEXT *)(UINTN)TempAcpiS3Context;\r
+  ASSERT (AcpiS3Context != NULL);\r
+\r
+  VarSize   = sizeof (EFI_PHYSICAL_ADDRESS);\r
   Status = RestoreLockBox (\r
              &gEfiBootScriptExecutorVariableGuid,\r
              &TempEfiBootScriptExecutorVariable,\r
@@ -876,13 +1006,17 @@ S3RestoreConfig2 (
   ASSERT_EFI_ERROR (Status);\r
 \r
   EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *) (UINTN) TempEfiBootScriptExecutorVariable;\r
-\r
-  DEBUG (( EFI_D_ERROR, "AcpiS3Context = %x\n", AcpiS3Context));\r
-  DEBUG (( EFI_D_ERROR, "Waking Vector = %x\n", ((EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable)))->FirmwareWakingVector));\r
-  DEBUG (( EFI_D_ERROR, "AcpiS3Context->AcpiFacsTable = %x\n", AcpiS3Context->AcpiFacsTable));\r
-  DEBUG (( EFI_D_ERROR, "AcpiS3Context->S3NvsPageTableAddress = %x\n", AcpiS3Context->S3NvsPageTableAddress));\r
-  DEBUG (( EFI_D_ERROR, "AcpiS3Context->S3DebugBufferAddress = %x\n", AcpiS3Context->S3DebugBufferAddress));\r
-  DEBUG (( EFI_D_ERROR, "EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = %x\n", EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint));\r
+  ASSERT (EfiBootScriptExecutorVariable != NULL);\r
+\r
+  DEBUG (( DEBUG_INFO, "AcpiS3Context = %x\n", AcpiS3Context));\r
+  DEBUG (( DEBUG_INFO, "Waking Vector = %x\n", ((EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable)))->FirmwareWakingVector));\r
+  DEBUG (( DEBUG_INFO, "AcpiS3Context->AcpiFacsTable = %x\n", AcpiS3Context->AcpiFacsTable));\r
+  DEBUG (( DEBUG_INFO, "AcpiS3Context->IdtrProfile = %x\n", AcpiS3Context->IdtrProfile));  \r
+  DEBUG (( DEBUG_INFO, "AcpiS3Context->S3NvsPageTableAddress = %x\n", AcpiS3Context->S3NvsPageTableAddress));\r
+  DEBUG (( DEBUG_INFO, "AcpiS3Context->S3DebugBufferAddress = %x\n", AcpiS3Context->S3DebugBufferAddress));\r
+  DEBUG (( DEBUG_INFO, "AcpiS3Context->BootScriptStackBase = %x\n", AcpiS3Context->BootScriptStackBase));\r
+  DEBUG (( DEBUG_INFO, "AcpiS3Context->BootScriptStackSize = %x\n", AcpiS3Context->BootScriptStackSize));\r
+  DEBUG (( DEBUG_INFO, "EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = %x\n", EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint));\r
 \r
   //\r
   // Additional step for BootScript integrity - we only handle BootScript and BootScriptExecutor.\r
@@ -896,11 +1030,33 @@ S3RestoreConfig2 (
     CpuDeadLoop ();\r
   }\r
 \r
+  if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+    //\r
+    // Need reconstruct page table here, since we do not trust ACPINvs.\r
+    //\r
+    if (IsLongModeWakingVector (AcpiS3Context)) {\r
+      Build4GPageTableOnly = FALSE;\r
+    } else {\r
+      Build4GPageTableOnly = TRUE;\r
+    }\r
+    RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress, Build4GPageTableOnly);\r
+  }\r
+\r
   //\r
   // Attempt to use content from SMRAM first\r
   //\r
   GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);\r
   if (GuidHob != NULL) {\r
+    Status = PeiServicesLocatePpi (\r
+                              &gPeiSmmAccessPpiGuid,\r
+                              0,\r
+                              NULL,\r
+                              (VOID **) &SmmAccess\r
+                              );\r
+    for (Index = 0; !EFI_ERROR (Status); Index++) {\r
+      Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+    }\r
+\r
     SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);\r
     SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;\r
 \r
@@ -908,26 +1064,21 @@ S3RestoreConfig2 (
     SmmS3ResumeState->ReturnEntryPoint   = (EFI_PHYSICAL_ADDRESS)(UINTN)S3ResumeExecuteBootScript;\r
     SmmS3ResumeState->ReturnContext1     = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context;\r
     SmmS3ResumeState->ReturnContext2     = (EFI_PHYSICAL_ADDRESS)(UINTN)EfiBootScriptExecutorVariable;\r
-    SmmS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)&Status;\r
-\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 Signature                = %x\n", SmmS3ResumeState->Signature));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 Stack Base               = %x\n", SmmS3ResumeState->SmmS3StackBase));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 Stack Size               = %x\n", SmmS3ResumeState->SmmS3StackSize));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 Resume Entry Point       = %x\n", SmmS3ResumeState->SmmS3ResumeEntryPoint));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 CR0                      = %x\n", SmmS3ResumeState->SmmS3Cr0));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 CR3                      = %x\n", SmmS3ResumeState->SmmS3Cr3));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 CR4                      = %x\n", SmmS3ResumeState->SmmS3Cr4));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 Return CS                = %x\n", SmmS3ResumeState->ReturnCs));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 Return Entry Point       = %x\n", SmmS3ResumeState->ReturnEntryPoint));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 Return Context1          = %x\n", SmmS3ResumeState->ReturnContext1));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 Return Context2          = %x\n", SmmS3ResumeState->ReturnContext2));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 Return Stack Pointer     = %x\n", SmmS3ResumeState->ReturnStackPointer));\r
-    DEBUG (( EFI_D_ERROR, "SMM S3 Smst                     = %x\n", SmmS3ResumeState->Smst));\r
-\r
-    //\r
-    // Disable interrupt of Debug timer.\r
-    //\r
-    SaveAndSetDebugTimerInterrupt (FALSE);\r
+    SmmS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)STACK_ALIGN_DOWN (&Status);\r
+\r
+    DEBUG (( DEBUG_INFO, "SMM S3 Signature                = %x\n", SmmS3ResumeState->Signature));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 Stack Base               = %x\n", SmmS3ResumeState->SmmS3StackBase));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 Stack Size               = %x\n", SmmS3ResumeState->SmmS3StackSize));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 Resume Entry Point       = %x\n", SmmS3ResumeState->SmmS3ResumeEntryPoint));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 CR0                      = %x\n", SmmS3ResumeState->SmmS3Cr0));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 CR3                      = %x\n", SmmS3ResumeState->SmmS3Cr3));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 CR4                      = %x\n", SmmS3ResumeState->SmmS3Cr4));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 Return CS                = %x\n", SmmS3ResumeState->ReturnCs));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 Return Entry Point       = %x\n", SmmS3ResumeState->ReturnEntryPoint));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 Return Context1          = %x\n", SmmS3ResumeState->ReturnContext1));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 Return Context2          = %x\n", SmmS3ResumeState->ReturnContext2));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 Return Stack Pointer     = %x\n", SmmS3ResumeState->ReturnStackPointer));\r
+    DEBUG (( DEBUG_INFO, "SMM S3 Smst                     = %x\n", SmmS3ResumeState->Smst));\r
 \r
     if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) {\r
       SwitchStack (\r
@@ -942,11 +1093,29 @@ S3RestoreConfig2 (
       // Switch to long mode to complete resume.\r
       //\r
 \r
+      InterruptStatus = SaveAndDisableInterrupts ();\r
       //\r
       // Need to make sure the GDT is loaded with values that support long mode and real mode.\r
       //\r
       AsmWriteGdtr (&mGdt);\r
+      //\r
+      // update segment selectors per the new GDT.\r
+      //      \r
+      AsmSetDataSelectors (DATA_SEGEMENT_SELECTOR);\r
+      //\r
+      // Restore interrupt state.\r
+      //\r
+      SetInterruptState (InterruptStatus);\r
+\r
       AsmWriteCr3 ((UINTN)SmmS3ResumeState->SmmS3Cr3);\r
+\r
+      //\r
+      // Disable interrupt of Debug timer, since IDT table cannot work in long mode.\r
+      // NOTE: On x64 platforms, because DisablePaging64() will disable interrupts,\r
+      // the code in S3ResumeExecuteBootScript() cannot be halted by soft debugger.\r
+      //\r
+      SaveAndSetDebugTimerInterrupt (FALSE);\r
+\r
       AsmEnablePaging64 (\r
         0x38,\r
         SmmS3ResumeState->SmmS3ResumeEntryPoint,\r