|
@@ -5,6 +5,7 @@
|
|
|
#include <asm/msr-index.h>
|
|
|
#include <asm/page.h>
|
|
|
#include <asm/pgtable.h>
|
|
|
+#include <asm/processor-flags.h>
|
|
|
|
|
|
.code16
|
|
|
.section ".header", "a"
|
|
@@ -24,6 +25,11 @@ pmode_gdt: .quad 0
|
|
|
realmode_flags: .long 0
|
|
|
real_magic: .long 0
|
|
|
trampoline_segment: .word 0
|
|
|
+_pad1: .byte 0
|
|
|
+wakeup_jmp: .byte 0xea /* ljmpw */
|
|
|
+wakeup_jmp_off: .word 3f
|
|
|
+wakeup_jmp_seg: .word 0
|
|
|
+wakeup_gdt: .quad 0, 0, 0
|
|
|
signature: .long 0x51ee1111
|
|
|
|
|
|
.text
|
|
@@ -34,11 +40,34 @@ _start:
|
|
|
cli
|
|
|
cld
|
|
|
|
|
|
+ /* Apparently some dimwit BIOS programmers don't know how to
|
|
|
+ program a PM to RM transition, and we might end up here with
|
|
|
+ junk in the data segment descriptor registers. The only way
|
|
|
+ to repair that is to go into PM and fix it ourselves... */
|
|
|
+ movw $16, %cx
|
|
|
+ lgdtl %cs:wakeup_gdt
|
|
|
+ movl %cr0, %eax
|
|
|
+ orb $X86_CR0_PE, %al
|
|
|
+ movl %eax, %cr0
|
|
|
+ jmp 1f
|
|
|
+1: ljmpw $8, $2f
|
|
|
+2:
|
|
|
+ movw %cx, %ds
|
|
|
+ movw %cx, %es
|
|
|
+ movw %cx, %ss
|
|
|
+ movw %cx, %fs
|
|
|
+ movw %cx, %gs
|
|
|
+
|
|
|
+ andb $~X86_CR0_PE, %al
|
|
|
+ movl %eax, %cr0
|
|
|
+ jmp wakeup_jmp
|
|
|
+3:
|
|
|
/* Set up segments */
|
|
|
movw %cs, %ax
|
|
|
movw %ax, %ds
|
|
|
movw %ax, %es
|
|
|
movw %ax, %ss
|
|
|
+ lidtl wakeup_idt
|
|
|
|
|
|
movl $wakeup_stack_end, %esp
|
|
|
|
|
@@ -98,7 +127,14 @@ bogus_real_magic:
|
|
|
jmp 1b
|
|
|
|
|
|
.data
|
|
|
- .balign 4
|
|
|
+ .balign 8
|
|
|
+
|
|
|
+ /* This is the standard real-mode IDT */
|
|
|
+wakeup_idt:
|
|
|
+ .word 0xffff /* limit */
|
|
|
+ .long 0 /* address */
|
|
|
+ .word 0
|
|
|
+
|
|
|
.globl HEAP, heap_end
|
|
|
HEAP:
|
|
|
.long wakeup_heap
|