summaryrefslogtreecommitdiff
path: root/sys/arch/i386/boot/asm.S
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/i386/boot/asm.S')
-rw-r--r--sys/arch/i386/boot/asm.S16
1 files changed, 11 insertions, 5 deletions
diff --git a/sys/arch/i386/boot/asm.S b/sys/arch/i386/boot/asm.S
index 18261ffad28..5d9f708eef5 100644
--- a/sys/arch/i386/boot/asm.S
+++ b/sys/arch/i386/boot/asm.S
@@ -103,10 +103,13 @@ xprot:
*/
ENTRY(prot_to_real)
# set up a dummy stack frame for the second seg change.
- movl _ourseg, %eax
- pushw %ax
- movl $xreal, %eax # gas botches pushw $xreal - extra bytes 0, 0
- pushw %ax # decode to add %al, (%eax) (%al usually 0)
+ # Adjust the intersegment jump instruction following
+ # the clearing of protected mode bit.
+ # This is self-modifying code, but we need a writable
+ # code segment, and an intersegment return does not give us that.
+ movl _ourseg, %eax
+ movw %ax, xreal-2
+
# Change to use16 mode.
ljmp $0x28, $x16
@@ -121,7 +124,10 @@ x16:
# make intersegment jmp to flush the processor pipeline
# using the fake stack frame set up earlier
# and reload CS register
- lret
+ # Here we have an 16 bits intersegment jump.
+ .byte 0xea
+ .word xreal
+ .word 0
xreal:
# we are in real mode now