]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
UefiCpuPkg: INF/DEC file updates to EDK II packages
[mirror_edk2.git] / UefiCpuPkg / Universal / Acpi / S3Resume2Pei / S3Resume.c
index 4ff4c45ede3008a5ed206eefe3eb785635a9030c..aa1c8032915879eae905b4bfc0dbecb1b938f6d8 100644 (file)
@@ -1,10 +1,10 @@
 /** @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
   control is passed to OS waking up handler.\r
 \r
-  Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions\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
 #pragma pack(1)\r
 typedef union {\r
   struct {\r
@@ -193,6 +203,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
@@ -232,6 +254,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
@@ -284,7 +308,9 @@ WriteToOsS3PerformanceData (
              NULL,\r
              (VOID **) &VariableServices\r
              );\r
-  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
 \r
   VarSize   = sizeof (EFI_PHYSICAL_ADDRESS);\r
   Status = VariableServices->GetVariable (\r
@@ -341,6 +367,7 @@ WriteToOsS3PerformanceData (
         AsciiSPrint (PerfData->Token, PERF_TOKEN_LENGTH, "0x%11p", Handle);\r
       } else {\r
         AsciiStrnCpy (PerfData->Token, Token, PERF_TOKEN_LENGTH);\r
+        PerfData->Token[PERF_TOKEN_LENGTH] = '\0';\r
       }\r
       if (StartTicker == 1) {\r
         StartTicker = StartValue;\r
@@ -365,6 +392,41 @@ WriteToOsS3PerformanceData (
   PerfHeader->S3EntryNum = (UINT32) Index;\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
   Jump to OS waking vector.\r
   The function will install boot script done PPI, report S3 resume status code, and then jump to OS waking vector.\r
@@ -390,6 +452,22 @@ 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
@@ -406,6 +484,13 @@ 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
@@ -447,8 +532,17 @@ 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
@@ -470,6 +564,14 @@ S3ResumeBootOs (
     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
@@ -481,10 +583,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
@@ -511,7 +615,7 @@ RestoreS3PageTables (
     //\r
     // The assumption is : whole page table is allocated in CONTINOUS memory and CR3 points to TOP page.\r
     //\r
-    DEBUG ((EFI_D_ERROR, "S3NvsPageTableAddress - %x\n", S3NvsPageTableAddress));\r
+    DEBUG ((EFI_D_ERROR, "S3NvsPageTableAddress - %x (%x)\n", (UINTN)S3NvsPageTableAddress, (UINTN)Build4GPageTableOnly));\r
 \r
     //\r
     // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.\r
@@ -554,6 +658,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
@@ -654,6 +766,7 @@ 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
 \r
@@ -681,17 +794,18 @@ S3ResumeExecuteBootScript (
                               NULL,\r
                               (VOID **) &SmmAccess\r
                               );\r
+    if (!EFI_ERROR (Status)) {\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
+      }\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
-    }\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
+      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
     }\r
   }\r
 \r
@@ -721,10 +835,19 @@ S3ResumeExecuteBootScript (
     *(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
@@ -734,11 +857,16 @@ S3ResumeExecuteBootScript (
   DEBUG (( EFI_D_ERROR, "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
@@ -817,7 +945,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
@@ -825,28 +952,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
-\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
+  TempAcpiS3Context = 0;\r
+  TempEfiBootScriptExecutorVariable = 0;\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 ((EFI_D_ERROR, "Enter S3 PEIM\r\n"));\r
 \r
   VarSize = sizeof (EFI_PHYSICAL_ADDRESS);\r
   Status = RestoreLockBox (\r
@@ -856,9 +968,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
@@ -866,7 +975,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
@@ -882,12 +994,16 @@ S3RestoreConfig2 (
   ASSERT_EFI_ERROR (Status);\r
 \r
   EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *) (UINTN) TempEfiBootScriptExecutorVariable;\r
+  ASSERT (EfiBootScriptExecutorVariable != NULL);\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->IdtrProfile = %x\n", AcpiS3Context->IdtrProfile));  \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, "AcpiS3Context->BootScriptStackBase = %x\n", AcpiS3Context->BootScriptStackBase));\r
+  DEBUG (( EFI_D_ERROR, "AcpiS3Context->BootScriptStackSize = %x\n", AcpiS3Context->BootScriptStackSize));\r
   DEBUG (( EFI_D_ERROR, "EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = %x\n", EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint));\r
 \r
   //\r
@@ -906,7 +1022,12 @@ S3RestoreConfig2 (
     //\r
     // Need reconstruct page table here, since we do not trust ACPINvs.\r
     //\r
-    RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress);\r
+    if (IsLongModeWakingVector (AcpiS3Context)) {\r
+      Build4GPageTableOnly = FALSE;\r
+    } else {\r
+      Build4GPageTableOnly = TRUE;\r
+    }\r
+    RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress, Build4GPageTableOnly);\r
   }\r
 \r
   //\r
@@ -914,6 +1035,16 @@ S3RestoreConfig2 (
   //\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
@@ -921,7 +1052,7 @@ 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
+    SmmS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)STACK_ALIGN_DOWN (&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
@@ -937,11 +1068,6 @@ S3RestoreConfig2 (
     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
-\r
     if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) {\r
       SwitchStack (\r
         (SWITCH_STACK_ENTRY_POINT)(UINTN)SmmS3ResumeState->SmmS3ResumeEntryPoint,\r
@@ -955,11 +1081,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