]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg: Supporting S3 in 64bit PEI
authorKuo, Ted <ted.kuo@intel.com>
Fri, 16 Dec 2022 12:46:26 +0000 (20:46 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 19 Dec 2022 06:12:56 +0000 (06:12 +0000)
https://bugzilla.tianocore.org/show_bug.cgi?id=4195
1.Updated the GDT table in VTF0 to align with the one in S3Resume2Pei.
  By doing so can simplify the changes to enable S3 in 64bit PEI.
2.Use SwitchStack() between PEI and SMM in S3 resume path when both
  are in the same execution mode.
3.Transfer from PEI to OS waking vector by calling SwitchStack() when
  both are in the same execution mode.
4.Removed the debug assertion in S3Resume.c to support 64bit PEI.

Reviewed-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Ashraf Ali S <ashraf.ali.s@intel.com>
Cc: Chinni B Duggapu <chinni.b.duggapu@intel.com>
Signed-off-by: Ted Kuo <ted.kuo@intel.com>
UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c

index 9b45c442c98ed90540eb0f13913562650ccf0316..fb4a44eab69b585de666252573b34863e40325e8 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Code for Processor S3 restoration\r
 \r
-Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>\r
 SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
@@ -783,7 +783,11 @@ SmmRestoreCpu (
   SmmS3ResumeState = mSmmS3ResumeState;\r
   ASSERT (SmmS3ResumeState != NULL);\r
 \r
-  if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {\r
+  //\r
+  // Setup 64bit IDT in 64bit SMM env when called from 32bit PEI.\r
+  // Note: 64bit PEI and 32bit DXE is not a supported combination.\r
+  //\r
+  if ((SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode) == TRUE)) {\r
     //\r
     // Save the IA32 IDT Descriptor\r
     //\r
@@ -846,9 +850,10 @@ SmmRestoreCpu (
   DEBUG ((DEBUG_INFO, "SMM S3 Return Stack Pointer     = %x\n", SmmS3ResumeState->ReturnStackPointer));\r
 \r
   //\r
-  // If SMM is in 32-bit mode, then use SwitchStack() to resume PEI Phase\r
+  // If SMM is in 32-bit mode or PcdDxeIplSwitchToLongMode is FALSE, then use SwitchStack() to resume PEI Phase.\r
+  // Note: 64bit PEI and 32bit DXE is not a supported combination.\r
   //\r
-  if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) {\r
+  if ((SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) || (FeaturePcdGet (PcdDxeIplSwitchToLongMode) == FALSE)) {\r
     DEBUG ((DEBUG_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));\r
 \r
     SwitchStack (\r
index deef00f9c6e9899bca24a36d7c061c604f673e76..b4b327f60c817d1dcf48ac5185652272fa331832 100644 (file)
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable                 ## CONSUMES\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer             ## CONSUMES\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock         ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode         ## CONSUMES\r
 \r
 [Pcd]\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## SOMETIMES_CONSUMES\r
index 0e79a3984b168fa435e4186e046eb5451a58dac2..f59fc6ead4ba2751011acd063c09065c40794860 100644 (file)
@@ -2,7 +2,7 @@
 ; @file\r
 ; Transition from 16 bit real mode into 32 bit flat protected mode\r
 ;\r
-; Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>\r
+; Copyright (c) 2008 - 2022, Intel Corporation. All rights reserved.<BR>\r
 ; SPDX-License-Identifier: BSD-2-Clause-Patent\r
 ;\r
 ;------------------------------------------------------------------------------\r
@@ -92,7 +92,7 @@ ALIGN   16
 \r
 GDT_BASE:\r
 ; null descriptor\r
-NULL_SEL            equ $-GDT_BASE\r
+NULL_SEL            equ $-GDT_BASE    ; Selector [0x0]\r
     DW      0            ; limit 15:0\r
     DW      0            ; base 15:0\r
     DB      0            ; base 23:16\r
@@ -100,42 +100,67 @@ NULL_SEL            equ $-GDT_BASE
     DB      0            ; limit 19:16, flags\r
     DB      0            ; base 31:24\r
 \r
+; Spare segment descriptor\r
+SPARE1_SEL          equ $-GDT_BASE    ; Selector [0x8]\r
+    DW      0            ; limit 15:0\r
+    DW      0            ; base 15:0\r
+    DB      0            ; base 23:16\r
+    DB      0            ; sys flag, dpl, type\r
+    DB      0            ; limit 19:16, flags\r
+    DB      0            ; base 31:24\r
+\r
+; linear code segment descriptor\r
+LINEAR_CODE_SEL     equ $-GDT_BASE    ; Selector [0x10]\r
+    DW      0xffff       ; limit 15:0\r
+    DW      0            ; base 15:0\r
+    DB      0            ; base 23:16\r
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE)           ; 09Bh\r
+    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)  ; 0CFh\r
+    DB      0            ; base 31:24\r
+\r
 ; linear data segment descriptor\r
-LINEAR_SEL          equ $-GDT_BASE\r
+LINEAR_SEL          equ $-GDT_BASE    ; Selector [0x18]\r
     DW      0xffff       ; limit 15:0\r
     DW      0            ; base 15:0\r
     DB      0            ; base 23:16\r
-    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(DATA32_TYPE)\r
-    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)\r
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(DATA32_TYPE)           ; 093h\r
+    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)  ; 0CFh\r
     DB      0            ; base 31:24\r
 \r
-; linear code segment descriptor\r
-LINEAR_CODE_SEL     equ $-GDT_BASE\r
+; Spare segment descriptor\r
+SPARE2_SEL          equ $-GDT_BASE    ; Selector [0x20]\r
+    DW      0            ; limit 15:0\r
+    DW      0            ; base 15:0\r
+    DB      0            ; base 23:16\r
+    DB      0            ; sys flag, dpl, type\r
+    DB      0            ; limit 19:16, flags\r
+    DB      0            ; base 31:24\r
+\r
+; linear code (16-bit) segment descriptor\r
+LINEAR_CODE16_SEL   equ $-GDT_BASE    ; Selector [0x28]\r
     DW      0xffff       ; limit 15:0\r
     DW      0            ; base 15:0\r
     DB      0            ; base 23:16\r
-    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE)\r
-    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)\r
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE)           ; 09Bh\r
+    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)  ; 08Fh\r
     DB      0            ; base 31:24\r
 \r
-%ifdef ARCH_X64\r
-; linear code (64-bit) segment descriptor\r
-LINEAR_CODE64_SEL   equ $-GDT_BASE\r
+; linear data (16-bit) segment descriptor\r
+LINEAR_DATA16_SEL   equ $-GDT_BASE    ; Selector [0x30]\r
     DW      0xffff       ; limit 15:0\r
     DW      0            ; base 15:0\r
     DB      0            ; base 23:16\r
-    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE64_TYPE)\r
-    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(1)|UPPER_LIMIT(0xf)\r
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(DATA32_TYPE)           ; 093h\r
+    DB      0\r
     DB      0            ; base 31:24\r
-%endif\r
 \r
-; linear code segment descriptor\r
-LINEAR_CODE16_SEL     equ $-GDT_BASE\r
+; linear code (64-bit) segment descriptor\r
+LINEAR_CODE64_SEL   equ $-GDT_BASE    ; Selector [0x38]\r
     DW      0xffff       ; limit 15:0\r
     DW      0            ; base 15:0\r
     DB      0            ; base 23:16\r
-    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE)\r
-    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)\r
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE64_TYPE)           ; 09Bh\r
+    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(1)|UPPER_LIMIT(0xf)  ; 0AFh\r
     DB      0            ; base 31:24\r
 \r
 GDT_END:\r
index 8419a4e32acbde9fc3ece2f33a08f5a6901f4830..e82f179569e9a0ef285cf2d2330bd6715de14f11 100644 (file)
@@ -4,7 +4,7 @@
   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 - 2019, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>\r
   Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
 \r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
@@ -332,9 +332,8 @@ IsLongModeWakingVector (
         ((Facs->OspmFlags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0))\r
     {\r
       // Both BIOS and OS wants 64bit vector\r
-      if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
-        return TRUE;\r
-      }\r
+      ASSERT ((FeaturePcdGet (PcdDxeIplSwitchToLongMode)) || (sizeof (UINTN) == sizeof (UINT64)));\r
+      return TRUE;\r
     }\r
   }\r
 \r
@@ -521,8 +520,11 @@ S3ResumeBootOs (
       //\r
       // X64 long mode waking vector\r
       //\r
-      DEBUG ((DEBUG_INFO, "Transfer to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));\r
+      DEBUG ((DEBUG_INFO, "Transfer from PEI to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));\r
       if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+        //\r
+        // 32bit PEI calls to 64bit OS S3 waking vector\r
+        //\r
         AsmEnablePaging64 (\r
           0x38,\r
           Facs->XFirmwareWakingVector,\r
@@ -531,29 +533,58 @@ 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 ((DEBUG_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n"));\r
-        ASSERT (FALSE);\r
-        CpuDeadLoop ();\r
-        return;\r
+        if (sizeof (UINTN) == sizeof (UINT64)) {\r
+          //\r
+          // 64bit PEI calls to 64bit OS S3 waking vector\r
+          //\r
+          SwitchStack (\r
+            (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,\r
+            NULL,\r
+            NULL,\r
+            (VOID *)(UINTN)TempStackTop\r
+            );\r
+        } else {\r
+          //\r
+          // Report Status code that no valid waking vector is found.\r
+          // Note: 32bit PEI + 32bit DXE firmware calling to 64bit OS S3 waking vector is an invalid configuration.\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 ((DEBUG_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n"));\r
+          ASSERT (FALSE);\r
+          CpuDeadLoop ();\r
+          return;\r
+        }\r
       }\r
     } else {\r
       //\r
       // IA32 protected mode waking vector (Page disabled)\r
       //\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
-        NULL,\r
-        (VOID *)(UINTN)TempStackTop\r
-        );\r
+      if (sizeof (UINTN) == sizeof (UINT64)) {\r
+        //\r
+        // 64bit PEI calls to 32bit OS S3 waking vector\r
+        //\r
+        AsmDisablePaging64 (\r
+          0x10,\r
+          (UINT32)Facs->XFirmwareWakingVector,\r
+          0,\r
+          0,\r
+          (UINT32)TempStackTop\r
+          );\r
+      } else {\r
+        //\r
+        // 32bit PEI calls to 32bit OS S3 waking vector\r
+        //\r
+        SwitchStack (\r
+          (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,\r
+          NULL,\r
+          NULL,\r
+          (VOID *)(UINTN)TempStackTop\r
+          );\r
+      }\r
     }\r
   } else {\r
     //\r
@@ -579,7 +610,7 @@ S3ResumeBootOs (
 \r
 /**\r
   Restore S3 page table because we do not trust ACPINvs content.\r
-  If BootScriptExector driver will not run in 64-bit mode, this function will do nothing.\r
+  If BootScriptExecutor 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
@@ -590,7 +621,7 @@ RestoreS3PageTables (
   IN BOOLEAN  Build4GPageTableOnly\r
   )\r
 {\r
-  if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+  if ((FeaturePcdGet (PcdDxeIplSwitchToLongMode)) || (sizeof (UINTN) == sizeof (UINT64))) {\r
     UINT32                          RegEax;\r
     UINT32                          RegEdx;\r
     UINT8                           PhysicalAddressBits;\r
@@ -825,7 +856,7 @@ S3ResumeExecuteBootScript (
     SignalToSmmByCommunication (&gEdkiiS3SmmInitDoneGuid);\r
   }\r
 \r
-  if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+  if ((FeaturePcdGet (PcdDxeIplSwitchToLongMode)) || (sizeof (UINTN) == sizeof (UINT64))) {\r
     AsmWriteCr3 ((UINTN)AcpiS3Context->S3NvsPageTableAddress);\r
   }\r
 \r
@@ -1021,7 +1052,7 @@ S3RestoreConfig2 (
     CpuDeadLoop ();\r
   }\r
 \r
-  if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+  if ((FeaturePcdGet (PcdDxeIplSwitchToLongMode)) || (sizeof (UINTN) == sizeof (UINT64))) {\r
     //\r
     // Need reconstruct page table here, since we do not trust ACPINvs.\r
     //\r
@@ -1039,13 +1070,6 @@ S3RestoreConfig2 (
   //\r
   GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);\r
   if (GuidHob != NULL) {\r
-    //\r
-    // Below SwitchStack/AsmEnablePaging64 function has\r
-    // assumption that it's in 32 bits mode now.\r
-    // Add ASSERT code to indicate this assumption.\r
-    //\r
-    ASSERT (sizeof (UINTN) == sizeof (UINT32));\r
-\r
     Status = PeiServicesLocatePpi (\r
                &gPeiSmmAccessPpiGuid,\r
                0,\r
@@ -1079,7 +1103,12 @@ S3RestoreConfig2 (
     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
+    //\r
+    // Directly do the switch stack when PEI and SMM env run in the same execution mode.\r
+    //\r
+    if (((SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) && (sizeof (UINTN) == sizeof (UINT32))) ||\r
+        ((SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) && (sizeof (UINTN) == sizeof (UINT64))))\r
+    {\r
       SwitchStack (\r
         (SWITCH_STACK_ENTRY_POINT)(UINTN)SmmS3ResumeState->SmmS3ResumeEntryPoint,\r
         (VOID *)AcpiS3Context,\r