aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/acpi/realmode/wakeup.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/acpi/realmode/wakeup.S')
-rw-r--r--arch/x86/kernel/acpi/realmode/wakeup.S170
1 files changed, 170 insertions, 0 deletions
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S
new file mode 100644
index 00000000000..b4fd836e405
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/wakeup.S
@@ -0,0 +1,170 @@
1/*
2 * ACPI wakeup real mode startup stub
3 */
4#include <asm/segment.h>
5#include <asm/msr-index.h>
6#include <asm/page_types.h>
7#include <asm/pgtable_types.h>
8#include <asm/processor-flags.h>
9#include "wakeup.h"
10
11 .code16
12 .section ".jump", "ax"
13 .globl _start
14_start:
15 cli
16 jmp wakeup_code
17
18/* This should match the structure in wakeup.h */
19 .section ".header", "a"
20 .globl wakeup_header
21wakeup_header:
22video_mode: .short 0 /* Video mode number */
23pmode_return: .byte 0x66, 0xea /* ljmpl */
24 .long 0 /* offset goes here */
25 .short __KERNEL_CS
26pmode_cr0: .long 0 /* Saved %cr0 */
27pmode_cr3: .long 0 /* Saved %cr3 */
28pmode_cr4: .long 0 /* Saved %cr4 */
29pmode_efer: .quad 0 /* Saved EFER */
30pmode_gdt: .quad 0
31pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */
32pmode_behavior: .long 0 /* Wakeup behavior flags */
33realmode_flags: .long 0
34real_magic: .long 0
35trampoline_segment: .word 0
36_pad1: .byte 0
37wakeup_jmp: .byte 0xea /* ljmpw */
38wakeup_jmp_off: .word 3f
39wakeup_jmp_seg: .word 0
40wakeup_gdt: .quad 0, 0, 0
41signature: .long WAKEUP_HEADER_SIGNATURE
42
43 .text
44 .code16
45wakeup_code:
46 cld
47
48 /* Apparently some dimwit BIOS programmers don't know how to
49 program a PM to RM transition, and we might end up here with
50 junk in the data segment descriptor registers. The only way
51 to repair that is to go into PM and fix it ourselves... */
52 movw $16, %cx
53 lgdtl %cs:wakeup_gdt
54 movl %cr0, %eax
55 orb $X86_CR0_PE, %al
56 movl %eax, %cr0
57 jmp 1f
581: ljmpw $8, $2f
592:
60 movw %cx, %ds
61 movw %cx, %es
62 movw %cx, %ss
63 movw %cx, %fs
64 movw %cx, %gs
65
66 andb $~X86_CR0_PE, %al
67 movl %eax, %cr0
68 jmp wakeup_jmp
693:
70 /* Set up segments */
71 movw %cs, %ax
72 movw %ax, %ds
73 movw %ax, %es
74 movw %ax, %ss
75 lidtl wakeup_idt
76
77 movl $wakeup_stack_end, %esp
78
79 /* Clear the EFLAGS */
80 pushl $0
81 popfl
82
83 /* Check header signature... */
84 movl signature, %eax
85 cmpl $WAKEUP_HEADER_SIGNATURE, %eax
86 jne bogus_real_magic
87
88 /* Check we really have everything... */
89 movl end_signature, %eax
90 cmpl $WAKEUP_END_SIGNATURE, %eax
91 jne bogus_real_magic
92
93 /* Call the C code */
94 calll main
95
96 /* Restore MISC_ENABLE before entering protected mode, in case
97 BIOS decided to clear XD_DISABLE during S3. */
98 movl pmode_behavior, %eax
99 btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax
100 jnc 1f
101
102 movl pmode_misc_en, %eax
103 movl pmode_misc_en + 4, %edx
104 movl $MSR_IA32_MISC_ENABLE, %ecx
105 wrmsr
1061:
107
108 /* Do any other stuff... */
109
110#ifndef CONFIG_64BIT
111 /* This could also be done in C code... */
112 movl pmode_cr3, %eax
113 movl %eax, %cr3
114
115 movl pmode_cr4, %ecx
116 jecxz 1f
117 movl %ecx, %cr4
1181:
119 movl pmode_efer, %eax
120 movl pmode_efer + 4, %edx
121 movl %eax, %ecx
122 orl %edx, %ecx
123 jz 1f
124 movl $MSR_EFER, %ecx
125 wrmsr
1261:
127
128 lgdtl pmode_gdt
129
130 /* This really couldn't... */
131 movl pmode_cr0, %eax
132 movl %eax, %cr0
133 jmp pmode_return
134#else
135 pushw $0
136 pushw trampoline_segment
137 pushw $0
138 lret
139#endif
140
141bogus_real_magic:
1421:
143 hlt
144 jmp 1b
145
146 .data
147 .balign 8
148
149 /* This is the standard real-mode IDT */
150wakeup_idt:
151 .word 0xffff /* limit */
152 .long 0 /* address */
153 .word 0
154
155 .globl HEAP, heap_end
156HEAP:
157 .long wakeup_heap
158heap_end:
159 .long wakeup_stack
160
161 .bss
162wakeup_heap:
163 .space 2048
164wakeup_stack:
165 .space 2048
166wakeup_stack_end:
167
168 .section ".signature","a"
169end_signature:
170 .long WAKEUP_END_SIGNATURE