1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
| .text
| #include <linux/linkage.h>
| #include <asm/segment.h>
| #include <asm/page_types.h>
|
| # Copyright 2003, 2008 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
|
| .code32
| ALIGN
|
| ENTRY(wakeup_pmode_return)
| 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
|
| 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
|
| ENTRY(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
|
| .data
| ALIGN
| ENTRY(saved_magic) .long 0
| ENTRY(saved_eip) .long 0
|
| # saved registers
| saved_idt: .long 0,0
| saved_ldt: .long 0
| saved_tss: .long 0
|
|