Merge branches 'core-urgent-for-linus', 'perf-urgent-for-linus' and 'sched-urgent...
[pandora-kernel.git] / arch / x86 / kernel / acpi / realmode / wakeup.S
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
21 wakeup_header:
22 video_mode:     .short  0       /* Video mode number */
23 pmode_return:   .byte   0x66, 0xea      /* ljmpl */
24                 .long   0       /* offset goes here */
25                 .short  __KERNEL_CS
26 pmode_cr0:      .long   0       /* Saved %cr0 */
27 pmode_cr3:      .long   0       /* Saved %cr3 */
28 pmode_cr4:      .long   0       /* Saved %cr4 */
29 pmode_efer:     .quad   0       /* Saved EFER */
30 pmode_gdt:      .quad   0
31 realmode_flags: .long   0
32 real_magic:     .long   0
33 trampoline_segment:     .word 0
34 _pad1:          .byte   0
35 wakeup_jmp:     .byte   0xea    /* ljmpw */
36 wakeup_jmp_off: .word   3f
37 wakeup_jmp_seg: .word   0
38 wakeup_gdt:     .quad   0, 0, 0
39 signature:      .long   WAKEUP_HEADER_SIGNATURE
40
41         .text
42         .code16
43 wakeup_code:
44         cld
45
46         /* Apparently some dimwit BIOS programmers don't know how to
47            program a PM to RM transition, and we might end up here with
48            junk in the data segment descriptor registers.  The only way
49            to repair that is to go into PM and fix it ourselves... */
50         movw    $16, %cx
51         lgdtl   %cs:wakeup_gdt
52         movl    %cr0, %eax
53         orb     $X86_CR0_PE, %al
54         movl    %eax, %cr0
55         jmp     1f
56 1:      ljmpw   $8, $2f
57 2:
58         movw    %cx, %ds
59         movw    %cx, %es
60         movw    %cx, %ss
61         movw    %cx, %fs
62         movw    %cx, %gs
63
64         andb    $~X86_CR0_PE, %al
65         movl    %eax, %cr0
66         jmp     wakeup_jmp
67 3:
68         /* Set up segments */
69         movw    %cs, %ax
70         movw    %ax, %ds
71         movw    %ax, %es
72         movw    %ax, %ss
73         lidtl   wakeup_idt
74
75         movl    $wakeup_stack_end, %esp
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         /* Do any other stuff... */
95
96 #ifndef CONFIG_64BIT
97         /* This could also be done in C code... */
98         movl    pmode_cr3, %eax
99         movl    %eax, %cr3
100
101         movl    pmode_cr4, %ecx
102         jecxz   1f
103         movl    %ecx, %cr4
104 1:
105         movl    pmode_efer, %eax
106         movl    pmode_efer + 4, %edx
107         movl    %eax, %ecx
108         orl     %edx, %ecx
109         jz      1f
110         movl    $MSR_EFER, %ecx
111         wrmsr
112 1:
113
114         lgdtl   pmode_gdt
115
116         /* This really couldn't... */
117         movl    pmode_cr0, %eax
118         movl    %eax, %cr0
119         jmp     pmode_return
120 #else
121         pushw   $0
122         pushw   trampoline_segment
123         pushw   $0
124         lret
125 #endif
126
127 bogus_real_magic:
128 1:
129         hlt
130         jmp     1b
131
132         .data
133         .balign 8
134
135         /* This is the standard real-mode IDT */
136 wakeup_idt:
137         .word   0xffff          /* limit */
138         .long   0               /* address */
139         .word   0
140
141         .globl  HEAP, heap_end
142 HEAP:
143         .long   wakeup_heap
144 heap_end:
145         .long   wakeup_stack
146
147         .bss
148 wakeup_heap:
149         .space  2048
150 wakeup_stack:
151         .space  2048
152 wakeup_stack_end:
153
154         .section ".signature","a"
155 end_signature:
156         .long   WAKEUP_END_SIGNATURE