[X64] Support S3 resume on 64-bit build (#698)

This will support S3 resume path on X64 thru 16-bit waking vector.
- Port WakeUp code from EDKII
- Remove duplicated calls of FindS3Info from CpuInit
- Verified with Yocto on a WHL board
- TBD: 64-bit waking vector with supported OS

Signed-off-by: Aiden Park <aiden.park@intel.com>
This commit is contained in:
Aiden Park 2020-04-29 21:23:56 -07:00 committed by GitHub
parent 17828b4e1d
commit eae81b7bc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 35 deletions

View File

@ -727,7 +727,11 @@ FindAcpiWakeVectorAndJump (
Hdr = (EFI_ACPI_COMMON_HEADER *) (UINTN)XsdtEntry[Index]; Hdr = (EFI_ACPI_COMMON_HEADER *) (UINTN)XsdtEntry[Index];
if (Hdr->Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { if (Hdr->Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
Facp = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *) Hdr; Facp = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *) Hdr;
Facs = (EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Facp->FirmwareCtrl; if (Facp->XFirmwareCtrl != 0) {
Facs = (EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Facp->XFirmwareCtrl;
} else {
Facs = (EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)Facp->FirmwareCtrl;
}
if (Facs->Signature == EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) { if (Facs->Signature == EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
WakeVector = Facs->FirmwareWakingVector; WakeVector = Facs->FirmwareWakingVector;
// Calculate CRC32 for 0x00000000 ---> BootLoaderRsvdMemBase and // Calculate CRC32 for 0x00000000 ---> BootLoaderRsvdMemBase and
@ -737,7 +741,7 @@ FindAcpiWakeVectorAndJump (
return; return;
} }
} }
CopyMem ((VOID *)(UINTN)WakeUpBuffer, &WakeUp, WakeUpSize); CopyMem ((VOID *)(UINTN)WakeUpBuffer, (VOID *)(UINTN)&WakeUp, WakeUpSize);
DoWake = (DOWAKEUP)(UINTN)WakeUpBuffer; DoWake = (DOWAKEUP)(UINTN)WakeUpBuffer;
DEBUG ((DEBUG_INIT, "Jump to Wake vector = 0x%x\n", WakeVector)); DEBUG ((DEBUG_INIT, "Jump to Wake vector = 0x%x\n", WakeVector));
DoWake (WakeVector); DoWake (WakeVector);

View File

@ -17,32 +17,36 @@ ASM_PFX(WakeUpBuffer):
global ASM_PFX(WakeUp) global ASM_PFX(WakeUp)
ASM_PFX(WakeUp): ASM_PFX(WakeUp):
push rbp ; rcx S3WakingVector :DWORD
mov ebp, esp lea eax, [.0]
mov edx, dword [ASM_PFX(WakeUpBuffer)] mov r8, 0x2800000000
lea eax, [jmp_retf - ASM_PFX(WakeUp) + edx ] or rax, r8
push 28h ; CS
push rax push rax
mov ecx, [ebp + 8]
shrd ebx, ecx, 20 shrd ebx, ecx, 20
and ecx, 0fh and ecx, 0xf
mov bx, cx mov bx, cx
lea eax, [os_jmp_addr - ASM_PFX(WakeUp) + edx ] mov [@jmp_addr + 1], ebx
mov [eax], ebx
retf retf
jmp_retf: BITS 16
db 0b8h, 30h, 0 ; mov ax, 30h as selector .0:
mov ax, 0x30
mov ds, ax mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
mov ss, ax mov ss, ax
mov rax, cr0 ; Get control register 0 mov eax, cr0
db 66h mov ebx, cr4
db 83h, 0e0h, 0feh ; and eax, 0fffffffeh ; Clear PE bit (bit #0) and eax, ((~ 0x80000001) & 0xffffffff)
db 0fh, 22h, 0c0h ; mov cr0, eax ; Activate real mode and bl, ~ (1 << 5)
db 0eah ; jmp far @jmp_addr mov cr0, eax
os_jmp_addr dd 0 mov ecx, 0xc0000080
rdmsr
and ah, ~ 1
wrmsr
mov cr4, ebx
@jmp_addr:
jmp 0x0:0x0
global ASM_PFX(WakeUpSize) global ASM_PFX(WakeUpSize)
ASM_PFX(WakeUpSize): ASM_PFX(WakeUpSize):

View File

@ -7,13 +7,13 @@
**/ **/
#include <MpInitLibInternal.h> #include <MpInitLibInternal.h>
MP_ASSEMBLY_ADDRESS_MAP mAddressMap; STATIC MP_ASSEMBLY_ADDRESS_MAP mAddressMap;
ALL_CPU_INFO mSysCpuInfo; STATIC ALL_CPU_INFO mSysCpuInfo;
volatile ALL_CPU_TASK mSysCpuTask; STATIC volatile ALL_CPU_TASK mSysCpuTask;
volatile MP_DATA_EXCHANGE_STRUCT mMpDataStruct; STATIC volatile MP_DATA_EXCHANGE_STRUCT mMpDataStruct;
UINT8 *mBackupBuffer; STATIC UINT8 *mBackupBuffer;
UINT32 mMpInitPhase = EnumMpInitNull; STATIC UINT32 mMpInitPhase = EnumMpInitNull;
STATIC SMMBASE_INFO *mSmmBaseInfo = NULL;
/** /**
The function is called by PerformQuickSort to sort CPU_INFO by ApicId. The function is called by PerformQuickSort to sort CPU_INFO by ApicId.
@ -143,17 +143,15 @@ CpuInit (
} }
if (PcdGet8 (PcdSmmRebaseMode) == SMM_REBASE_ENABLE_ON_S3_RESUME_ONLY) { if (PcdGet8 (PcdSmmRebaseMode) == SMM_REBASE_ENABLE_ON_S3_RESUME_ONLY) {
if (GetBootMode() == BOOT_ON_S3_RESUME) { if ((GetBootMode() == BOOT_ON_S3_RESUME) && (mSmmBaseInfo != NULL)) {
SmmBaseInfo = (SMMBASE_INFO *) FindS3Info (SMMBASE_INFO_COMM_ID); SmmBaseInfo = mSmmBaseInfo;
if (SmmBaseInfo != NULL) { for (CpuIdx = 0; CpuIdx < SmmBaseInfo->SmmBaseHdr.Count; CpuIdx++) {
for (CpuIdx = 0; CpuIdx < SmmBaseInfo->SmmBaseHdr.Count; CpuIdx++) { if (ApicId == SmmBaseInfo->SmmBase[CpuIdx].ApicId) {
if (ApicId == SmmBaseInfo->SmmBase[CpuIdx].ApicId) { SmmRebase (Index, ApicId, SmmBaseInfo->SmmBase[CpuIdx].SmmBase);
SmmRebase (Index, ApicId, SmmBaseInfo->SmmBase[CpuIdx].SmmBase); break;
break;
}
} }
ASSERT (CpuIdx < SmmBaseInfo->SmmBaseHdr.Count);
} }
ASSERT (CpuIdx < SmmBaseInfo->SmmBaseHdr.Count);
} }
} else if (PcdGet8 (PcdSmmRebaseMode) == SMM_REBASE_ENABLE) { } else if (PcdGet8 (PcdSmmRebaseMode) == SMM_REBASE_ENABLE) {
SmmRebase (Index, ApicId, 0); SmmRebase (Index, ApicId, 0);
@ -369,6 +367,15 @@ MpInit (
// //
mMpDataStruct.ApDoneCounter = 0; mMpDataStruct.ApDoneCounter = 0;
//
// Get SMM Base Info for S3 resume
//
if (GetBootMode() == BOOT_ON_S3_RESUME) {
mSmmBaseInfo = (SMMBASE_INFO *) FindS3Info (SMMBASE_INFO_COMM_ID);
} else {
mSmmBaseInfo = NULL;
}
// //
// Send Init-SIPI-SIPI to all APs and wait for completion // Send Init-SIPI-SIPI to all APs and wait for completion
// It includes a 200us delay for AP's check-in // It includes a 200us delay for AP's check-in