2 #include <linux/linkage.h>
3 #include <asm/segment.h>
7 # wakeup_code runs in real mode, and at unknown address (determined at run-time).
8 # Therefore it must only use relative jumps/calls.
10 # Do we need to deal with A20? It is okay: ACPI specs says A20 must be enabled
12 # If physical address of wakeup_code is 0x12345, BIOS should call us with
13 # cs = 0x1234, eip = 0x05
40 movw $0x0e00 + 'L', %fs:(0x10)
47 movw %ax, %ds # Make ds:0 point to wakeup_start
50 testl $4, realmode_flags - wakeup_code
54 mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board
56 pushl $0 # Kill any dangerous flags
59 movl real_magic - wakeup_code, %eax
60 cmpl $0x12345678, %eax
63 testl $1, realmode_flags - wakeup_code
67 movw %ax, %ds # Bios might have played with that
71 testl $2, realmode_flags - wakeup_code
73 mov video_mode - wakeup_code, %ax
78 movl $swsusp_pg_dir-__PAGE_OFFSET, %eax
81 testl $1, real_efer_save_restore - wakeup_code
83 # restore efer setting
84 movl real_save_efer_edx - wakeup_code, %edx
85 movl real_save_efer_eax - wakeup_code, %eax
89 # make sure %cr4 is set correctly (features, etc)
90 movl real_save_cr4 - wakeup_code, %eax
93 # need a gdt -- use lgdtl to force 32-bit operands, in case
94 # the GDT is located past 16 megabytes.
95 lgdtl real_save_gdt - wakeup_code
97 movl real_save_cr0 - wakeup_code, %eax
101 movl real_magic - wakeup_code, %eax
102 cmpl $0x12345678, %eax
105 testl $8, realmode_flags - wakeup_code
109 ljmpl $__KERNEL_CS, $wakeup_pmode_return
111 real_save_gdt: .word 0
113 real_save_cr0: .long 0
114 real_save_cr3: .long 0
115 real_save_cr4: .long 0
118 realmode_flags: .long 0
119 real_efer_save_restore: .long 0
120 real_save_efer_edx: .long 0
121 real_save_efer_eax: .long 0
126 /* This code uses an extended set of video mode numbers. These include:
127 * Aliases for standard modes
131 * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
132 * of compatibility when extending the table. These are between 0x00 and 0xff.
134 #define VIDEO_FIRST_MENU 0x0000
136 /* Standard BIOS video modes (BIOS number + 0x0100) */
137 #define VIDEO_FIRST_BIOS 0x0100
139 /* VESA BIOS video modes (VESA number + 0x0200) */
140 #define VIDEO_FIRST_VESA 0x0200
142 /* Video7 special modes (BIOS number + 0x0900) */
143 #define VIDEO_FIRST_V7 0x0900
145 # Setting of user mode (AX=mode ID) => CF=success
147 # For now, we only handle VESA modes (0x0200..0x03ff). To handle other
148 # modes, we should probably compile in the video code from the boot
152 subb $VIDEO_FIRST_VESA>>8, %bh
161 orw $0x4000, %bx # Use linear frame buffer
162 movw $0x4f02, %ax # VESA BIOS mode set call
164 cmpw $0x004f, %ax # AL=4f if implemented
165 jnz setbad # AH=0 if OK
174 wakeup_stack_begin: # Stack grows down
176 .org 0xff0 # Just below end of page
183 movw $__KERNEL_DS, %ax
190 # reload the gdt, as we need the full 32 bit address
194 ljmp $(__KERNEL_CS),$1f
200 # and restore the stack ... but you need gdt for this to work
201 movl saved_context_esp, %esp
203 movl %cs:saved_magic, %eax
204 cmpl $0x12345678, %eax
207 # jump to place where we left off
216 # acpi_copy_wakeup_routine
218 # Copy the above routine to low memory.
221 # %eax: place to copy wakeup routine to
223 # Returned address is location of code in low memory (past data and stack)
225 ENTRY(acpi_copy_wakeup_routine)
233 movl nx_enabled, %edx
234 movl %edx, real_efer_save_restore - wakeup_start (%eax)
235 testl $1, real_efer_save_restore - wakeup_start (%eax)
240 mov $0xc0000080, %ecx
242 movl %edx, real_save_efer_edx - wakeup_start (%ebx)
243 movl %eax, real_save_efer_eax - wakeup_start (%ebx)
248 movl %edx, real_save_cr3 - wakeup_start (%eax)
250 movl %edx, real_save_cr4 - wakeup_start (%eax)
252 movl %edx, real_save_cr0 - wakeup_start (%eax)
253 sgdt real_save_gdt - wakeup_start (%eax)
255 movl saved_videomode, %edx
256 movl %edx, video_mode - wakeup_start (%eax)
257 movl acpi_realmode_flags, %edx
258 movl %edx, realmode_flags - wakeup_start (%eax)
259 movl $0x12345678, real_magic - wakeup_start (%eax)
260 movl $0x12345678, saved_magic
266 movl %eax, saved_context_esp
267 movl %ebx, saved_context_ebx
268 movl %ebp, saved_context_ebp
269 movl %esi, saved_context_esi
270 movl %edi, saved_context_edi
271 pushfl ; popl saved_context_eflags
273 movl $ret_point, saved_eip
278 movl saved_context_ebp, %ebp
279 movl saved_context_ebx, %ebx
280 movl saved_context_esi, %esi
281 movl saved_context_edi, %edi
282 pushl saved_context_eflags ; popfl
285 ENTRY(do_suspend_lowlevel)
286 call save_processor_state
289 call acpi_enter_sleep_state
292 # In case of S3 failure, we'll emerge here. Jump
293 # to ret_point to recover
297 call restore_registers
298 call restore_processor_state
303 ENTRY(saved_magic) .long 0
304 ENTRY(saved_eip) .long 0