diff options
Diffstat (limited to 'arch/x86/kernel/acpi/realmode/wakeup.S')
| -rw-r--r-- | arch/x86/kernel/acpi/realmode/wakeup.S | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S index f9b77fb37e5b..3355973b12ac 100644 --- a/arch/x86/kernel/acpi/realmode/wakeup.S +++ b/arch/x86/kernel/acpi/realmode/wakeup.S | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <asm/msr-index.h> | 5 | #include <asm/msr-index.h> |
| 6 | #include <asm/page.h> | 6 | #include <asm/page.h> |
| 7 | #include <asm/pgtable.h> | 7 | #include <asm/pgtable.h> |
| 8 | #include <asm/processor-flags.h> | ||
| 8 | 9 | ||
| 9 | .code16 | 10 | .code16 |
| 10 | .section ".header", "a" | 11 | .section ".header", "a" |
| @@ -24,6 +25,11 @@ pmode_gdt: .quad 0 | |||
| 24 | realmode_flags: .long 0 | 25 | realmode_flags: .long 0 |
| 25 | real_magic: .long 0 | 26 | real_magic: .long 0 |
| 26 | trampoline_segment: .word 0 | 27 | trampoline_segment: .word 0 |
| 28 | _pad1: .byte 0 | ||
| 29 | wakeup_jmp: .byte 0xea /* ljmpw */ | ||
| 30 | wakeup_jmp_off: .word 3f | ||
| 31 | wakeup_jmp_seg: .word 0 | ||
| 32 | wakeup_gdt: .quad 0, 0, 0 | ||
| 27 | signature: .long 0x51ee1111 | 33 | signature: .long 0x51ee1111 |
| 28 | 34 | ||
| 29 | .text | 35 | .text |
| @@ -34,11 +40,34 @@ _start: | |||
| 34 | cli | 40 | cli |
| 35 | cld | 41 | cld |
| 36 | 42 | ||
| 43 | /* Apparently some dimwit BIOS programmers don't know how to | ||
| 44 | program a PM to RM transition, and we might end up here with | ||
| 45 | junk in the data segment descriptor registers. The only way | ||
| 46 | to repair that is to go into PM and fix it ourselves... */ | ||
| 47 | movw $16, %cx | ||
| 48 | lgdtl %cs:wakeup_gdt | ||
| 49 | movl %cr0, %eax | ||
| 50 | orb $X86_CR0_PE, %al | ||
| 51 | movl %eax, %cr0 | ||
| 52 | jmp 1f | ||
| 53 | 1: ljmpw $8, $2f | ||
| 54 | 2: | ||
| 55 | movw %cx, %ds | ||
| 56 | movw %cx, %es | ||
| 57 | movw %cx, %ss | ||
| 58 | movw %cx, %fs | ||
| 59 | movw %cx, %gs | ||
| 60 | |||
| 61 | andb $~X86_CR0_PE, %al | ||
| 62 | movl %eax, %cr0 | ||
| 63 | jmp wakeup_jmp | ||
| 64 | 3: | ||
| 37 | /* Set up segments */ | 65 | /* Set up segments */ |
| 38 | movw %cs, %ax | 66 | movw %cs, %ax |
| 39 | movw %ax, %ds | 67 | movw %ax, %ds |
| 40 | movw %ax, %es | 68 | movw %ax, %es |
| 41 | movw %ax, %ss | 69 | movw %ax, %ss |
| 70 | lidtl wakeup_idt | ||
| 42 | 71 | ||
| 43 | movl $wakeup_stack_end, %esp | 72 | movl $wakeup_stack_end, %esp |
| 44 | 73 | ||
| @@ -98,7 +127,14 @@ bogus_real_magic: | |||
| 98 | jmp 1b | 127 | jmp 1b |
| 99 | 128 | ||
| 100 | .data | 129 | .data |
| 101 | .balign 4 | 130 | .balign 8 |
| 131 | |||
| 132 | /* This is the standard real-mode IDT */ | ||
| 133 | wakeup_idt: | ||
| 134 | .word 0xffff /* limit */ | ||
| 135 | .long 0 /* address */ | ||
| 136 | .word 0 | ||
| 137 | |||
| 102 | .globl HEAP, heap_end | 138 | .globl HEAP, heap_end |
| 103 | HEAP: | 139 | HEAP: |
| 104 | .long wakeup_heap | 140 | .long wakeup_heap |
