summaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/acpi/wakeup_32.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/acpi/wakeup_32.S')
-rw-r--r--arch/x86/kernel/acpi/wakeup_32.S101
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
+