aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/realmode/rm/wakeup_asm.S
diff options
context:
space:
mode:
authorJarkko Sakkinen <jarkko.sakkinen@intel.com>2012-05-08 14:22:42 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2012-05-08 14:48:45 -0400
commitc4845474a01f699966272536e8416222e3f2d2cb (patch)
tree8d590924f5ab164981368822f7534f42eaabae30 /arch/x86/realmode/rm/wakeup_asm.S
parentb429dbf6e866bd6dadb56fae66f61f611cde57ff (diff)
x86, realmode: flattened rm hierachy
Simplified hierarchy under rm directory to a flat directory because it is not anymore really justified to have own directory for wakeup code. It only adds more complexity. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com> Link: http://lkml.kernel.org/r/1336501366-28617-20-git-send-email-jarkko.sakkinen@intel.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/realmode/rm/wakeup_asm.S')
-rw-r--r--arch/x86/realmode/rm/wakeup_asm.S181
1 files changed, 181 insertions, 0 deletions
diff --git a/arch/x86/realmode/rm/wakeup_asm.S b/arch/x86/realmode/rm/wakeup_asm.S
new file mode 100644
index 000000000000..8a57c5a05fbc
--- /dev/null
+++ b/arch/x86/realmode/rm/wakeup_asm.S
@@ -0,0 +1,181 @@
1/*
2 * ACPI wakeup real mode startup stub
3 */
4#include <linux/linkage.h>
5#include <asm/segment.h>
6#include <asm/msr-index.h>
7#include <asm/page_types.h>
8#include <asm/pgtable_types.h>
9#include <asm/processor-flags.h>
10#include "realmode.h"
11#include "wakeup.h"
12
13 .code16
14
15/* This should match the structure in wakeup.h */
16 .section ".data", "aw"
17
18 .balign 16
19GLOBAL(wakeup_header)
20 video_mode: .short 0 /* Video mode number */
21 pmode_entry: .long 0
22 pmode_cs: .short __KERNEL_CS
23 pmode_cr0: .long 0 /* Saved %cr0 */
24 pmode_cr3: .long 0 /* Saved %cr3 */
25 pmode_cr4: .long 0 /* Saved %cr4 */
26 pmode_efer: .quad 0 /* Saved EFER */
27 pmode_gdt: .quad 0
28 pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */
29 pmode_behavior: .long 0 /* Wakeup behavior flags */
30 realmode_flags: .long 0
31 real_magic: .long 0
32 signature: .long WAKEUP_HEADER_SIGNATURE
33END(wakeup_header)
34
35 .text
36 .code16
37
38 .balign 16
39ENTRY(wakeup_start)
40 cli
41 cld
42
43 LJMPW_RM(3f)
443:
45 /* Apparently some dimwit BIOS programmers don't know how to
46 program a PM to RM transition, and we might end up here with
47 junk in the data segment descriptor registers. The only way
48 to repair that is to go into PM and fix it ourselves... */
49 movw $16, %cx
50 lgdtl %cs:wakeup_gdt
51 movl %cr0, %eax
52 orb $X86_CR0_PE, %al
53 movl %eax, %cr0
54 ljmpw $8, $2f
552:
56 movw %cx, %ds
57 movw %cx, %es
58 movw %cx, %ss
59 movw %cx, %fs
60 movw %cx, %gs
61
62 andb $~X86_CR0_PE, %al
63 movl %eax, %cr0
64 LJMPW_RM(3f)
653:
66 /* Set up segments */
67 movw %cs, %ax
68 movw %ax, %ss
69 movl $rm_stack_end, %esp
70 movw %ax, %ds
71 movw %ax, %es
72 movw %ax, %fs
73 movw %ax, %gs
74
75 lidtl wakeup_idt
76
77 /* Clear the EFLAGS */
78 pushl $0
79 popfl
80
81 /* Check header signature... */
82 movl signature, %eax
83 cmpl $WAKEUP_HEADER_SIGNATURE, %eax
84 jne bogus_real_magic
85
86 /* Check we really have everything... */
87 movl end_signature, %eax
88 cmpl $WAKEUP_END_SIGNATURE, %eax
89 jne bogus_real_magic
90
91 /* Call the C code */
92 calll main
93
94 /* Restore MISC_ENABLE before entering protected mode, in case
95 BIOS decided to clear XD_DISABLE during S3. */
96 movl pmode_behavior, %eax
97 btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax
98 jnc 1f
99
100 movl pmode_misc_en, %eax
101 movl pmode_misc_en + 4, %edx
102 movl $MSR_IA32_MISC_ENABLE, %ecx
103 wrmsr
1041:
105
106 /* Do any other stuff... */
107
108#ifndef CONFIG_64BIT
109 /* This could also be done in C code... */
110 movl pmode_cr3, %eax
111 movl %eax, %cr3
112
113 movl pmode_cr4, %ecx
114 jecxz 1f
115 movl %ecx, %cr4
1161:
117 movl pmode_efer, %eax
118 movl pmode_efer + 4, %edx
119 movl %eax, %ecx
120 orl %edx, %ecx
121 jz 1f
122 movl $MSR_EFER, %ecx
123 wrmsr
1241:
125
126 lgdtl pmode_gdt
127
128 /* This really couldn't... */
129 movl pmode_entry, %eax
130 movl pmode_cr0, %ecx
131 movl %ecx, %cr0
132 ljmpl $__KERNEL_CS, $pa_startup_32
133 /* -> jmp *%eax in trampoline_32.S */
134#else
135 jmp trampoline_data
136#endif
137
138bogus_real_magic:
1391:
140 hlt
141 jmp 1b
142
143 .section ".rodata","a"
144
145 /*
146 * Set up the wakeup GDT. We set these up as Big Real Mode,
147 * that is, with limits set to 4 GB. At least the Lenovo
148 * Thinkpad X61 is known to need this for the video BIOS
149 * initialization quirk to work; this is likely to also
150 * be the case for other laptops or integrated video devices.
151 */
152
153 .balign 16
154GLOBAL(wakeup_gdt)
155 .word 3*8-1 /* Self-descriptor */
156 .long pa_wakeup_gdt
157 .word 0
158
159 .word 0xffff /* 16-bit code segment @ real_mode_base */
160 .long 0x9b000000 + pa_real_mode_base
161 .word 0x008f /* big real mode */
162
163 .word 0xffff /* 16-bit data segment @ real_mode_base */
164 .long 0x93000000 + pa_real_mode_base
165 .word 0x008f /* big real mode */
166END(wakeup_gdt)
167
168 .section ".rodata","a"
169 .balign 8
170
171 /* This is the standard real-mode IDT */
172 .balign 16
173GLOBAL(wakeup_idt)
174 .word 0xffff /* limit */
175 .long 0 /* address */
176 .word 0
177END(wakeup_idt)
178
179 .section ".signature","a"
180end_signature:
181 .long WAKEUP_END_SIGNATURE