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