Merge tag 'mac80211-for-davem-2016-07-06' of git://git.kernel.org/pub/scm/linux/kerne...
[deliverable/linux.git] / arch / x86 / realmode / rm / wakeup_asm.S
CommitLineData
e44b7b75
PM
1/*
2 * ACPI wakeup real mode startup stub
3 */
8e029fcd 4#include <linux/linkage.h>
e44b7b75
PM
5#include <asm/segment.h>
6#include <asm/msr-index.h>
0341c14d
JF
7#include <asm/page_types.h>
8#include <asm/pgtable_types.h>
4b4f7280 9#include <asm/processor-flags.h>
c4845474 10#include "realmode.h"
d1ee4335 11#include "wakeup.h"
e44b7b75 12
8e029fcd 13 .code16
e44b7b75
PM
14
15/* This should match the structure in wakeup.h */
8e029fcd
JS
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)
e44b7b75
PM
34
35 .text
e44b7b75 36 .code16
8e029fcd
JS
37
38 .balign 16
39ENTRY(wakeup_start)
c9b77ccb 40 cli
e44b7b75
PM
41 cld
42
e5684ec4 43 LJMPW_RM(3f)
c9b77ccb 443:
4b4f7280
PA
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
c9b77ccb 54 ljmpw $8, $2f
4b4f7280
PA
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
e5684ec4 64 LJMPW_RM(3f)
4b4f7280 653:
e44b7b75
PM
66 /* Set up segments */
67 movw %cs, %ax
8e029fcd
JS
68 movw %ax, %ss
69 movl $rm_stack_end, %esp
e44b7b75
PM
70 movw %ax, %ds
71 movw %ax, %es
8e029fcd
JS
72 movw %ax, %fs
73 movw %ax, %gs
e44b7b75 74
8e029fcd 75 lidtl wakeup_idt
e44b7b75 76
1396adc3 77 /* Clear the EFLAGS */
73201dbe
PA
78 pushl $0
79 popfl
e44b7b75
PM
80
81 /* Check header signature... */
82 movl signature, %eax
d1ee4335 83 cmpl $WAKEUP_HEADER_SIGNATURE, %eax
e44b7b75
PM
84 jne bogus_real_magic
85
86 /* Check we really have everything... */
87 movl end_signature, %eax
61f54461 88 cmpl $REALMODE_END_SIGNATURE, %eax
e44b7b75
PM
89 jne bogus_real_magic
90
91 /* Call the C code */
92 calll main
93
7a313666
KC
94 /* Restore MISC_ENABLE before entering protected mode, in case
95 BIOS decided to clear XD_DISABLE during S3. */
73201dbe
PA
96 movl pmode_behavior, %edi
97 btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %edi
7a313666
KC
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
e44b7b75
PM
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
73201dbe 113 btl $WAKEUP_BEHAVIOR_RESTORE_CR4, %edi
1396adc3 114 jnc 1f
73201dbe
PA
115 movl pmode_cr4, %eax
116 movl %eax, %cr4
e44b7b75 1171:
73201dbe 118 btl $WAKEUP_BEHAVIOR_RESTORE_EFER, %edi
1396adc3 119 jnc 1f
e44b7b75
PM
120 movl pmode_efer, %eax
121 movl pmode_efer + 4, %edx
cfaa71ee 122 movl $MSR_EFER, %ecx
e44b7b75
PM
123 wrmsr
1241:
125
126 lgdtl pmode_gdt
127
128 /* This really couldn't... */
968ff9ee
PA
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 */
e44b7b75 134#else
f37240f1 135 jmp trampoline_start
e44b7b75
PM
136#endif
137
138bogus_real_magic:
1391:
140 hlt
141 jmp 1b
142
c9b77ccb
JS
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
c9b77ccb 153 .balign 16
8e029fcd 154GLOBAL(wakeup_gdt)
c9b77ccb
JS
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 */
8e029fcd 166END(wakeup_gdt)
c9b77ccb 167
8e029fcd 168 .section ".rodata","a"
4b4f7280
PA
169 .balign 8
170
171 /* This is the standard real-mode IDT */
8e029fcd
JS
172 .balign 16
173GLOBAL(wakeup_idt)
4b4f7280
PA
174 .word 0xffff /* limit */
175 .long 0 /* address */
176 .word 0
8e029fcd 177END(wakeup_idt)
This page took 0.611417 seconds and 5 git commands to generate.