aboutsummaryrefslogtreecommitdiff
path: root/arch/x86/kernel/acpi/realmode/wakeup.S
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-04-18 08:25:51 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-18 08:25:51 -0700
commit9e9abecfc0ff3a9ad2ead954b37bbfcb863c775e (patch)
tree0c3ffda953b82750638a06507591ad587b565ff2 /arch/x86/kernel/acpi/realmode/wakeup.S
parentd7bb545d86825e635cab33a1dd81ca0ad7b92887 (diff)
parent77ad386e596c6b0930cc2e09e3cce485e3ee7f72 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86: (613 commits) x86: standalone trampoline code x86: move suspend wakeup code to C x86: coding style fixes to arch/x86/kernel/acpi/sleep.c x86: setup_trampoline() - fix section mismatch warning x86: section mismatch fixes, #1 x86: fix paranoia about using BIOS quickboot mechanism. x86: print out buggy mptable x86: use cpu_online() x86: use cpumask_of_cpu() x86: remove unnecessary tmp local variable x86: remove unnecessary memset() x86: use ioapic_read_entry() and ioapic_write_entry() x86: avoid redundant loop in io_apic_level_ack_pending() x86: remove superfluous initialisation in boot code. x86: merge mpparse_{32,64}.c x86: unify mp_register_gsi x86: unify mp_config_acpi_legacy_irqs x86: unify mp_register_ioapic x86: unify uniq_io_apic_id x86: unify smp_scan_config ...
Diffstat (limited to 'arch/x86/kernel/acpi/realmode/wakeup.S')
-rw-r--r--arch/x86/kernel/acpi/realmode/wakeup.S113
1 files changed, 113 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..f9b77fb37e5
--- /dev/null
+++ b/arch/x86/kernel/acpi/realmode/wakeup.S
@@ -0,0 +1,113 @@
+/*
+ * ACPI wakeup real mode startup stub
+ */
+#include <asm/segment.h>
+#include <asm/msr-index.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+ .code16
+ .section ".header", "a"
+
+/* This should match the structure in wakeup.h */
+ .globl wakeup_header
+wakeup_header:
+video_mode: .short 0 /* Video mode number */
+pmode_return: .byte 0x66, 0xea /* ljmpl */
+ .long 0 /* offset goes here */
+ .short __KERNEL_CS
+pmode_cr0: .long 0 /* Saved %cr0 */
+pmode_cr3: .long 0 /* Saved %cr3 */
+pmode_cr4: .long 0 /* Saved %cr4 */
+pmode_efer: .quad 0 /* Saved EFER */
+pmode_gdt: .quad 0
+realmode_flags: .long 0
+real_magic: .long 0
+trampoline_segment: .word 0
+signature: .long 0x51ee1111
+
+ .text
+ .globl _start
+ .code16
+wakeup_code:
+_start:
+ cli
+ cld
+
+ /* Set up segments */
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+
+ movl $wakeup_stack_end, %esp
+
+ /* Clear the EFLAGS */
+ pushl $0
+ popfl
+
+ /* Check header signature... */
+ movl signature, %eax
+ cmpl $0x51ee1111, %eax
+ jne bogus_real_magic
+
+ /* Check we really have everything... */
+ movl end_signature, %eax
+ cmpl $0x65a22c82, %eax
+ jne bogus_real_magic
+
+ /* Call the C code */
+ calll main
+
+ /* Do any other stuff... */
+
+#ifndef CONFIG_64BIT
+ /* This could also be done in C code... */
+ movl pmode_cr3, %eax
+ movl %eax, %cr3
+
+ movl pmode_cr4, %ecx
+ jecxz 1f
+ movl %ecx, %cr4
+1:
+ movl pmode_efer, %eax
+ movl pmode_efer + 4, %edx
+ movl %eax, %ecx
+ orl %edx, %ecx
+ jz 1f
+ movl $0xc0000080, %ecx
+ wrmsr
+1:
+
+ lgdtl pmode_gdt
+
+ /* This really couldn't... */
+ movl pmode_cr0, %eax
+ movl %eax, %cr0
+ jmp pmode_return
+#else
+ pushw $0
+ pushw trampoline_segment
+ pushw $0
+ lret
+#endif
+
+bogus_real_magic:
+1:
+ hlt
+ jmp 1b
+
+ .data
+ .balign 4
+ .globl HEAP, heap_end
+HEAP:
+ .long wakeup_heap
+heap_end:
+ .long wakeup_stack
+
+ .bss
+wakeup_heap:
+ .space 2048
+wakeup_stack:
+ .space 2048
+wakeup_stack_end: