[FREELDR] Fix an inconsistency bug when switching the CPU state back to 16-bit real...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 2 Oct 2019 01:20:10 +0000 (03:20 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 7 Oct 2019 23:30:15 +0000 (01:30 +0200)
commit0d6631c2da3eb593623af9cff8fef86530aecd55
treee299df96d42653fa656d7dca4e65ed86b3d64891
parent25badcfbbdc4f6f58546ff3b1920bbe6d9d3498e
[FREELDR] Fix an inconsistency bug when switching the CPU state back to 16-bit real mode.

Basically it appeared that without this fix, the CPU was somehow residing
in an inconsistent state, that made it crash when a full 16-bit real-mode
to 32-bit protected mode transition occurred. (Encountered when trying
to load Linux, see problem description below.)
In that situation, Bochs reports that the CPU is in "compatibility mode".

The fix is based from information from Fig.1-6 "Operating Modes of the
AMD64 Architecture" (page 12) and Chapter 14 (pages 429-446) of the
"AMD64 Architecture Programmer’s Manual Volume 2: System Programming"
https://www.amd.com/system/files/TechDocs/24593.pdf

*** THE PROBLEM ***

When booting Linux using x86 FreeLdr everything goes well.

When trying to do the same using x64 FreeLdr, the Linux code (both the
boot sector, the setup sector and the main kernel contents) is all
correctly loaded and relocated in memory as in the x86 case. We then pass
control to the decompressing code that appears to succeed. However, once
it has finished and "Parsing ELF file..." step has been run, the next
step "Booting the kernel..." crashes with a CPU Triple-Fault.

This problem **DOES NOT HAPPEN** when booting from GRUB.

Log excerpt from Bochs:

<snip>

00089459736i[BIOS  ] Booting from 07c0:0000
00089782775i[SER   ] com1: FIFO enabled
00095994535i[BIOS  ] int13_harddisk: function 41, unmapped device for ELDL=81
00095998517i[BIOS  ] int13_harddisk: function 08, unmapped device for ELDL=81
00397139785i[BIOS  ] KBD: unsupported int 16h function 03
00397143625i[BIOS  ] *** int 15h function AX=e980, BX=0000 not yet supported!
00523008104e[CPU0  ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
00523008104e[CPU0  ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
00523008104i[CPU0  ] CPU is in compatibility mode (active)
00523008104i[CPU0  ] CS.mode = 32 bit
00523008104i[CPU0  ] SS.mode = 32 bit
00523008104i[CPU0  ] EFER   = 0x00000500
00523008104i[CPU0  ] | RAX=00000000e0000011  RBX=0000000000000000
00523008104i[CPU0  ] | RCX=0000000000000000  RDX=0000000000000000
00523008104i[CPU0  ] | RSP=00000000004f8000  RBP=000000000082e003
00523008104i[CPU0  ] | RSI=0000000000099800  RDI=00000000c0611000
00523008104i[CPU0  ] |  R8=0000000000109000   R9=0000000000009020
00523008104i[CPU0  ] | R10=00000000000007e3  R11=000000000000e958
00523008104i[CPU0  ] | R12=0000000000000000  R13=0000000000000000
00523008104i[CPU0  ] | R14=0000000000000000  R15=0000000000000000
00523008104i[CPU0  ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
00523008104i[CPU0  ] | SEG sltr(index|ti|rpl)     base    limit G D
00523008104i[CPU0  ] |  CS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00523008104i[CPU0  ] |  DS:0018( 0003| 0|  0) 00000000 ffffffff 1 1
00523008104i[CPU0  ] |  SS:0018( 0003| 0|  0) 00000000 ffffffff 1 1
00523008104i[CPU0  ] |  ES:0018( 0003| 0|  0) 00000000 ffffffff 1 1
00523008104i[CPU0  ] |  FS:0018( 0003| 0|  0) 00000000 ffffffff 1 1
00523008104i[CPU0  ] |  GS:0018( 0003| 0|  0) 00000000 ffffffff 1 1
00523008104i[CPU0  ] |  MSR_FS_BASE:0000000000000000
00523008104i[CPU0  ] |  MSR_GS_BASE:0000000000000000
00523008104i[CPU0  ] | RIP=0000000000409327 (0000000000409327)
00523008104i[CPU0  ] | CR0=0xe0000011 CR2=0x0000000000409327
00523008104i[CPU0  ] | CR3=0x005b5000 CR4=0x000000a0
00523008104i[CPU0  ] 0x0000000000409327: (instruction unavailable) page not present
00523008104p[CPU0  ] >>PANIC<< exception(): 3rd (13) exception with no resolution

<snip>
boot/freeldr/freeldr/arch/realmode/amd64.S