| /* 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 |
| ENTRY(saved_magic) .long 0 |
| saved_eip: .long 0 |
| |
| # saved registers |
| saved_idt: .long 0,0 |
| saved_ldt: .long 0 |
| saved_tss: .long 0 |
| |