[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];
if (Hdr->Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
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) {
WakeVector = Facs->FirmwareWakingVector;
// Calculate CRC32 for 0x00000000 ---> BootLoaderRsvdMemBase and
@ -737,7 +741,7 @@ FindAcpiWakeVectorAndJump (
return;
}
}
CopyMem ((VOID *)(UINTN)WakeUpBuffer, &WakeUp, WakeUpSize);
CopyMem ((VOID *)(UINTN)WakeUpBuffer, (VOID *)(UINTN)&WakeUp, WakeUpSize);
DoWake = (DOWAKEUP)(UINTN)WakeUpBuffer;
DEBUG ((DEBUG_INIT, "Jump to Wake vector = 0x%x\n", WakeVector));
DoWake (WakeVector);

View File

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

View File

@ -7,13 +7,13 @@
**/
#include <MpInitLibInternal.h>
MP_ASSEMBLY_ADDRESS_MAP mAddressMap;
ALL_CPU_INFO mSysCpuInfo;
volatile ALL_CPU_TASK mSysCpuTask;
volatile MP_DATA_EXCHANGE_STRUCT mMpDataStruct;
UINT8 *mBackupBuffer;
UINT32 mMpInitPhase = EnumMpInitNull;
STATIC MP_ASSEMBLY_ADDRESS_MAP mAddressMap;
STATIC ALL_CPU_INFO mSysCpuInfo;
STATIC volatile ALL_CPU_TASK mSysCpuTask;
STATIC volatile MP_DATA_EXCHANGE_STRUCT mMpDataStruct;
STATIC UINT8 *mBackupBuffer;
STATIC UINT32 mMpInitPhase = EnumMpInitNull;
STATIC SMMBASE_INFO *mSmmBaseInfo = NULL;
/**
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 (GetBootMode() == BOOT_ON_S3_RESUME) {
SmmBaseInfo = (SMMBASE_INFO *) FindS3Info (SMMBASE_INFO_COMM_ID);
if (SmmBaseInfo != NULL) {
for (CpuIdx = 0; CpuIdx < SmmBaseInfo->SmmBaseHdr.Count; CpuIdx++) {
if (ApicId == SmmBaseInfo->SmmBase[CpuIdx].ApicId) {
SmmRebase (Index, ApicId, SmmBaseInfo->SmmBase[CpuIdx].SmmBase);
break;
}
if ((GetBootMode() == BOOT_ON_S3_RESUME) && (mSmmBaseInfo != NULL)) {
SmmBaseInfo = mSmmBaseInfo;
for (CpuIdx = 0; CpuIdx < SmmBaseInfo->SmmBaseHdr.Count; CpuIdx++) {
if (ApicId == SmmBaseInfo->SmmBase[CpuIdx].ApicId) {
SmmRebase (Index, ApicId, SmmBaseInfo->SmmBase[CpuIdx].SmmBase);
break;
}
ASSERT (CpuIdx < SmmBaseInfo->SmmBaseHdr.Count);
}
ASSERT (CpuIdx < SmmBaseInfo->SmmBaseHdr.Count);
}
} else if (PcdGet8 (PcdSmmRebaseMode) == SMM_REBASE_ENABLE) {
SmmRebase (Index, ApicId, 0);
@ -369,6 +367,15 @@ MpInit (
//
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
// It includes a 200us delay for AP's check-in