2 * ACPI wakeup real mode startup stub
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>
15 /* This should match the structure in wakeup.h */
16 .section ".data", "aw"
20 video_mode: .short 0 /* Video mode number */
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 */
28 pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */
29 pmode_behavior: .long 0 /* Wakeup behavior flags */
30 realmode_flags: .long 0
32 signature: .long WAKEUP_HEADER_SIGNATURE
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... */
62 andb $~X86_CR0_PE, %al
69 movl $rm_stack_end, %esp
77 /* Clear the EFLAGS but remember if we have EFLAGS.ID */
78 movl $X86_EFLAGS_ID, %ecx
88 andl %ecx, %edi /* %edi is zero iff CPUID & %cr4 are missing */
90 /* Check header signature... */
92 cmpl $WAKEUP_HEADER_SIGNATURE, %eax
95 /* Check we really have everything... */
96 movl end_signature, %eax
97 cmpl $REALMODE_END_SIGNATURE, %eax
100 /* Call the C code */
103 /* Restore MISC_ENABLE before entering protected mode, in case
104 BIOS decided to clear XD_DISABLE during S3. */
105 movl pmode_behavior, %edi
106 btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %edi
109 movl pmode_misc_en, %eax
110 movl pmode_misc_en + 4, %edx
111 movl $MSR_IA32_MISC_ENABLE, %ecx
115 /* Do any other stuff... */
118 /* This could also be done in C code... */
122 btl $WAKEUP_BEHAVIOR_RESTORE_CR4, %edi
127 btl $WAKEUP_BEHAVIOR_RESTORE_EFER, %edi
129 movl pmode_efer, %eax
130 movl pmode_efer + 4, %edx
137 /* This really couldn't... */
138 movl pmode_entry, %eax
141 ljmpl $__KERNEL_CS, $pa_startup_32
142 /* -> jmp *%eax in trampoline_32.S */
152 .section ".rodata","a"
155 * Set up the wakeup GDT. We set these up as Big Real Mode,
156 * that is, with limits set to 4 GB. At least the Lenovo
157 * Thinkpad X61 is known to need this for the video BIOS
158 * initialization quirk to work; this is likely to also
159 * be the case for other laptops or integrated video devices.
164 .word 3*8-1 /* Self-descriptor */
168 .word 0xffff /* 16-bit code segment @ real_mode_base */
169 .long 0x9b000000 + pa_real_mode_base
170 .word 0x008f /* big real mode */
172 .word 0xffff /* 16-bit data segment @ real_mode_base */
173 .long 0x93000000 + pa_real_mode_base
174 .word 0x008f /* big real mode */
177 .section ".rodata","a"
180 /* This is the standard real-mode IDT */
183 .word 0xffff /* limit */
184 .long 0 /* address */