diff options
Diffstat (limited to 'arch/x86/kernel/acpi/wakeup_32.S')
-rw-r--r-- | arch/x86/kernel/acpi/wakeup_32.S | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S new file mode 100644 index 000000000..cf6908107 --- /dev/null +++ b/arch/x86/kernel/acpi/wakeup_32.S @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + .text +#include <linux/linkage.h> +#include <asm/segment.h> +#include <asm/page_types.h> + +# Copyright 2003, 2008 Pavel Machek <pavel@suse.cz + + .code32 + ALIGN + +SYM_CODE_START(wakeup_pmode_return) + movw $__KERNEL_DS, %ax + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + + movw $__USER_DS, %ax + movw %ax, %ds + movw %ax, %es + + # reload the gdt, as we need the full 32 bit address + lidt saved_idt + lldt saved_ldt + ljmp $(__KERNEL_CS), $1f +1: + movl %cr3, %eax + movl %eax, %cr3 + wbinvd + + # and restore the stack ... but you need gdt for this to work + movl saved_context_esp, %esp + + movl %cs:saved_magic, %eax + cmpl $0x12345678, %eax + jne bogus_magic + + # jump to place where we left off + movl saved_eip, %eax + jmp *%eax +SYM_CODE_END(wakeup_pmode_return) + +bogus_magic: + jmp bogus_magic + + + +save_registers: + sidt saved_idt + sldt saved_ldt + str saved_tss + + leal 4(%esp), %eax + movl %eax, saved_context_esp + movl %ebx, saved_context_ebx + movl %ebp, saved_context_ebp + movl %esi, saved_context_esi + movl %edi, saved_context_edi + pushfl + popl saved_context_eflags + + movl $ret_point, saved_eip + RET + + +restore_registers: + movl saved_context_ebp, %ebp + movl saved_context_ebx, %ebx + movl saved_context_esi, %esi + movl saved_context_edi, %edi + pushl saved_context_eflags + popfl + RET + +SYM_CODE_START(do_suspend_lowlevel) + call save_processor_state + call save_registers + pushl $3 + call x86_acpi_enter_sleep_state + addl $4, %esp + +# In case of S3 failure, we'll emerge here. Jump +# to ret_point to recover + jmp ret_point + .p2align 4,,7 +ret_point: + call restore_registers + call restore_processor_state + RET +SYM_CODE_END(do_suspend_lowlevel) + +.data +ALIGN +SYM_DATA(saved_magic, .long 0) +saved_eip: .long 0 + +# saved registers +saved_idt: .long 0,0 +saved_ldt: .long 0 +saved_tss: .long 0 + |