aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/acpi/wakeup_32.S
diff options
context:
space:
mode:
authorPavel Machek <pavel@suse.cz>2008-04-10 17:28:10 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-17 11:41:37 -0400
commite44b7b7525ad9d43163ab5e60c784325419e0ea6 (patch)
treee2918917a97b4c9de4367e8778ed78afc762b9f8 /arch/x86/kernel/acpi/wakeup_32.S
parentf49688d459c5eaa62db3597cbfd3cb13e361d415 (diff)
x86: move suspend wakeup code to C
Move wakeup code to .c, so that video mode setting code can be shared between boot and wakeup. Remove nasty assembly code in 64-bit case by re-using trampoline code. Stack setup was fixed to clear high 16bits of %esp, maybe that fixes some machines. .c code sharing and morse code was done H. Peter Anvin, Sam Ravnborg reviewed kbuild related stuff, and it seems okay to him. Rafael did some cleanups. [rjw: * Made the patch stop breaking compilation on x86-32 * Added arch/x86/kernel/acpi/sleep.h * Got rid of compiler warnings in arch/x86/kernel/acpi/sleep.c * Fixed 32-bit compilation on x86-64 systems * Added include/asm-x86/trampoline.h and fixed the non-SMP compilation on 64-bit x86 * Removed arch/x86/kernel/acpi/sleep_32.c which was not used * Fixed some breakage caused by the integration of smpboot.c done under us in the meantime] Signed-off-by: Pavel Machek <pavel@suse.cz> Signed-off-by: H. Peter Anvin <hpa@zytor.com> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/acpi/wakeup_32.S')
-rw-r--r--arch/x86/kernel/acpi/wakeup_32.S247
1 files changed, 20 insertions, 227 deletions
diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S
index f53e3277f8e5..a12e6a9fb659 100644
--- a/arch/x86/kernel/acpi/wakeup_32.S
+++ b/arch/x86/kernel/acpi/wakeup_32.S
@@ -3,178 +3,12 @@
3#include <asm/segment.h> 3#include <asm/segment.h>
4#include <asm/page.h> 4#include <asm/page.h>
5 5
6# 6# Copyright 2003, 2008 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
7# wakeup_code runs in real mode, and at unknown address (determined at run-time).
8# Therefore it must only use relative jumps/calls.
9#
10# Do we need to deal with A20? It is okay: ACPI specs says A20 must be enabled
11#
12# If physical address of wakeup_code is 0x12345, BIOS should call us with
13# cs = 0x1234, eip = 0x05
14#
15
16#define BEEP \
17 inb $97, %al; \
18 outb %al, $0x80; \
19 movb $3, %al; \
20 outb %al, $97; \
21 outb %al, $0x80; \
22 movb $-74, %al; \
23 outb %al, $67; \
24 outb %al, $0x80; \
25 movb $-119, %al; \
26 outb %al, $66; \
27 outb %al, $0x80; \
28 movb $15, %al; \
29 outb %al, $66;
30
31ALIGN
32 .align 4096
33ENTRY(wakeup_start)
34wakeup_code:
35 wakeup_code_start = .
36 .code16
37
38 cli
39 cld
40
41 # setup data segment
42 movw %cs, %ax
43 movw %ax, %ds # Make ds:0 point to wakeup_start
44 movw %ax, %ss
45
46 testl $4, realmode_flags - wakeup_code
47 jz 1f
48 BEEP
491:
50 mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board
51
52 pushl $0 # Kill any dangerous flags
53 popfl
54
55 movl real_magic - wakeup_code, %eax
56 cmpl $0x12345678, %eax
57 jne bogus_real_magic
58
59 testl $1, realmode_flags - wakeup_code
60 jz 1f
61 lcall $0xc000,$3
62 movw %cs, %ax
63 movw %ax, %ds # Bios might have played with that
64 movw %ax, %ss
651:
66
67 testl $2, realmode_flags - wakeup_code
68 jz 1f
69 mov video_mode - wakeup_code, %ax
70 call mode_set
711:
72
73 # set up page table
74 movl $swsusp_pg_dir-__PAGE_OFFSET, %eax
75 movl %eax, %cr3
76
77 testl $1, real_efer_save_restore - wakeup_code
78 jz 4f
79 # restore efer setting
80 movl real_save_efer_edx - wakeup_code, %edx
81 movl real_save_efer_eax - wakeup_code, %eax
82 mov $0xc0000080, %ecx
83 wrmsr
844:
85 # make sure %cr4 is set correctly (features, etc)
86 movl real_save_cr4 - wakeup_code, %eax
87 movl %eax, %cr4
88
89 # need a gdt -- use lgdtl to force 32-bit operands, in case
90 # the GDT is located past 16 megabytes.
91 lgdtl real_save_gdt - wakeup_code
92
93 movl real_save_cr0 - wakeup_code, %eax
94 movl %eax, %cr0
95 jmp 1f
961:
97 movl real_magic - wakeup_code, %eax
98 cmpl $0x12345678, %eax
99 jne bogus_real_magic
100
101 testl $8, realmode_flags - wakeup_code
102 jz 1f
103 BEEP
1041:
105 ljmpl $__KERNEL_CS, $wakeup_pmode_return
106
107real_save_gdt: .word 0
108 .long 0
109real_save_cr0: .long 0
110real_save_cr3: .long 0
111real_save_cr4: .long 0
112real_magic: .long 0
113video_mode: .long 0
114realmode_flags: .long 0
115real_efer_save_restore: .long 0
116real_save_efer_edx: .long 0
117real_save_efer_eax: .long 0
118
119bogus_real_magic:
120 jmp bogus_real_magic
121
122/* This code uses an extended set of video mode numbers. These include:
123 * Aliases for standard modes
124 * NORMAL_VGA (-1)
125 * EXTENDED_VGA (-2)
126 * ASK_VGA (-3)
127 * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
128 * of compatibility when extending the table. These are between 0x00 and 0xff.
129 */
130#define VIDEO_FIRST_MENU 0x0000
131
132/* Standard BIOS video modes (BIOS number + 0x0100) */
133#define VIDEO_FIRST_BIOS 0x0100
134
135/* VESA BIOS video modes (VESA number + 0x0200) */
136#define VIDEO_FIRST_VESA 0x0200
137
138/* Video7 special modes (BIOS number + 0x0900) */
139#define VIDEO_FIRST_V7 0x0900
140
141# Setting of user mode (AX=mode ID) => CF=success
142
143# For now, we only handle VESA modes (0x0200..0x03ff). To handle other
144# modes, we should probably compile in the video code from the boot
145# directory.
146mode_set:
147 movw %ax, %bx
148 subb $VIDEO_FIRST_VESA>>8, %bh
149 cmpb $2, %bh
150 jb check_vesa
151
152setbad:
153 clc
154 ret
155
156check_vesa:
157 orw $0x4000, %bx # Use linear frame buffer
158 movw $0x4f02, %ax # VESA BIOS mode set call
159 int $0x10
160 cmpw $0x004f, %ax # AL=4f if implemented
161 jnz setbad # AH=0 if OK
162
163 stc
164 ret
165 7
166 .code32 8 .code32
167 ALIGN 9 ALIGN
168 10
169.org 0x800 11ENTRY(wakeup_pmode_return)
170wakeup_stack_begin: # Stack grows down
171
172.org 0xff0 # Just below end of page
173wakeup_stack:
174ENTRY(wakeup_end)
175
176.org 0x1000
177
178wakeup_pmode_return: 12wakeup_pmode_return:
179 movw $__KERNEL_DS, %ax 13 movw $__KERNEL_DS, %ax
180 movw %ax, %ss 14 movw %ax, %ss
@@ -187,7 +21,7 @@ wakeup_pmode_return:
187 lgdt saved_gdt 21 lgdt saved_gdt
188 lidt saved_idt 22 lidt saved_idt
189 lldt saved_ldt 23 lldt saved_ldt
190 ljmp $(__KERNEL_CS),$1f 24 ljmp $(__KERNEL_CS), $1f
1911: 251:
192 movl %cr3, %eax 26 movl %cr3, %eax
193 movl %eax, %cr3 27 movl %eax, %cr3
@@ -201,82 +35,41 @@ wakeup_pmode_return:
201 jne bogus_magic 35 jne bogus_magic
202 36
203 # jump to place where we left off 37 # jump to place where we left off
204 movl saved_eip,%eax 38 movl saved_eip, %eax
205 jmp *%eax 39 jmp *%eax
206 40
207bogus_magic: 41bogus_magic:
208 jmp bogus_magic 42 jmp bogus_magic
209 43
210 44
211##
212# acpi_copy_wakeup_routine
213#
214# Copy the above routine to low memory.
215#
216# Parameters:
217# %eax: place to copy wakeup routine to
218#
219# Returned address is location of code in low memory (past data and stack)
220#
221ENTRY(acpi_copy_wakeup_routine)
222 45
223 pushl %ebx 46save_registers:
224 sgdt saved_gdt 47 sgdt saved_gdt
225 sidt saved_idt 48 sidt saved_idt
226 sldt saved_ldt 49 sldt saved_ldt
227 str saved_tss 50 str saved_tss
228 51
229 movl nx_enabled, %edx
230 movl %edx, real_efer_save_restore - wakeup_start (%eax)
231 testl $1, real_efer_save_restore - wakeup_start (%eax)
232 jz 2f
233 # save efer setting
234 pushl %eax
235 movl %eax, %ebx
236 mov $0xc0000080, %ecx
237 rdmsr
238 movl %edx, real_save_efer_edx - wakeup_start (%ebx)
239 movl %eax, real_save_efer_eax - wakeup_start (%ebx)
240 popl %eax
2412:
242
243 movl %cr3, %edx
244 movl %edx, real_save_cr3 - wakeup_start (%eax)
245 movl %cr4, %edx
246 movl %edx, real_save_cr4 - wakeup_start (%eax)
247 movl %cr0, %edx
248 movl %edx, real_save_cr0 - wakeup_start (%eax)
249 sgdt real_save_gdt - wakeup_start (%eax)
250
251 movl saved_videomode, %edx
252 movl %edx, video_mode - wakeup_start (%eax)
253 movl acpi_realmode_flags, %edx
254 movl %edx, realmode_flags - wakeup_start (%eax)
255 movl $0x12345678, real_magic - wakeup_start (%eax)
256 movl $0x12345678, saved_magic
257 popl %ebx
258 ret
259
260save_registers:
261 leal 4(%esp), %eax 52 leal 4(%esp), %eax
262 movl %eax, saved_context_esp 53 movl %eax, saved_context_esp
263 movl %ebx, saved_context_ebx 54 movl %ebx, saved_context_ebx
264 movl %ebp, saved_context_ebp 55 movl %ebp, saved_context_ebp
265 movl %esi, saved_context_esi 56 movl %esi, saved_context_esi
266 movl %edi, saved_context_edi 57 movl %edi, saved_context_edi
267 pushfl ; popl saved_context_eflags 58 pushfl
268 59 popl saved_context_eflags
269 movl $ret_point, saved_eip 60
61 movl $ret_point, saved_eip
270 ret 62 ret
271 63
272 64
273restore_registers: 65restore_registers:
274 movl saved_context_ebp, %ebp 66 movl saved_context_ebp, %ebp
275 movl saved_context_ebx, %ebx 67 movl saved_context_ebx, %ebx
276 movl saved_context_esi, %esi 68 movl saved_context_esi, %esi
277 movl saved_context_edi, %edi 69 movl saved_context_edi, %edi
278 pushl saved_context_eflags ; popfl 70 pushl saved_context_eflags
279 ret 71 popfl
72 ret
280 73
281ENTRY(do_suspend_lowlevel) 74ENTRY(do_suspend_lowlevel)
282 call save_processor_state 75 call save_processor_state