Page 1 of 1

Triple fault on "unreal" mode

Posted: Mon Feb 09, 2004 7:05 pm
by RuneOfFire
Could someone look over this code and tell me why I get a triple fault on the return to real mode?

It works fine if "jmp $" before going back to real mode, but for some reason it doesn't like it. I feel like I'm missing some stupid mistake, maybe someone else will see what I overlooked.

(This code is basically the same code used in John Fine's BOOTF)

Code: Select all

[BITS 16], [ORG 0], STAGE1_ADDRESS is correct, interrupts off
...

   lgdt      [STAGE1_ADDRESS+gdtr]
   mov      ebx, cr0
   or      bl, 1
   mov      cr0, ebx

.0:   in      al, 0x64                        ; enable A20
   test      al, 2
   jnz      .0
   mov      al, 0xD1
   out      0x64, al
.1:   in      al, 0x64
   and      al, 2
   jnz      .1
   mov      al, 0xDF
   out      0x60, al

   mov      ax, LINEAR_DATA_SEL
   mov      ds, ax
   mov      es, ax

   and      bl, 11111110b
   mov      cr0, ebx

   jmp      short $

...

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   16-bit limit/32-bit linear base address of GDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdtr:
   dw      gdt_end-gdt-1                     ; GDT limit
   dd      STAGE1_ADDRESS+gdt               ; linear, physical address of GDT

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Global Descriptor Table (GDT)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdt:
; null descriptor
   dw      0                           ; limit 15:0
   dw      0                           ; base 15:0
   db      0                           ; base 23:16
   db      0                           ; type
   db      0                           ; limit 19:16, flags
   db      0                           ; base 31:24
; linear code segment descriptor
LINEAR_CODE_SEL equ $-gdt
   dw      0xFFFF
   dw      0
   db      0
   db      0x9A                        ; present, ring 0, code, non-conforming, readable
   db      0xCF
   db      0
; linear data segment descriptor
LINEAR_DATA_SEL equ $-gdt
   dw      0xFFFF
   dw      0
   db      0
   db      0x92                        ; present, ring 0, data, expand-up, writbale
   db      0xCF
   db      0

gdt_end:

Re:Triple fault on "unreal" mode

Posted: Tue Feb 10, 2004 1:38 am
by Ozguxxx
Well, I guess you are not loading cs with a valid real mode segment so this might cause a problem you must do a far jump to next instruction after going into rmode to load cs with a real mode value, of course in far jump you must obey real mode realm rules not virtual realm rules... :) I mean you must not use selectors, you must use segment register value that you calculate. I hope I could help, good luck.

Re:Triple fault on "unreal" mode

Posted: Tue Feb 10, 2004 3:50 am
by Pype.Clicker
your '[ORG 0]' is a blinking-red warning sign to my senses ... i fear you're in a CS = 0x7C0, IP= 0000 boot approach, which means GDT pointers have to be adjusted (but you seem to have done this)...

i would rather initialize A20 gate either before or after the switch to unreal mode is completed, but putting it inline between the two cr0 modification is error-prone imho ...

i guess all this stuff is protected against interruptions by cli/sti that we do not see here ... if an interrupt occurs while you're in pmode, you'll be doomed.

i also assume you know unreal mode is for *data* only and that you're not trying to jump further than 0xFFFF within your code segment.

having bochs's register dump and seeing the faulty instruction would definitely help ...

Re:Triple fault on "unreal" mode

Posted: Tue Feb 10, 2004 2:02 pm
by RuneOfFire
Nah, CS was actually 0, but anyway.. I solved the problem.
Someone on IRC suggested that CS was being mangled because I was doing a 16-bit jump, so I changed

Code: Select all

jmp short $
to

Code: Select all

o32 jmp short $
...and it worked fine. ;)

Re:Triple fault on "unreal" mode

Posted: Tue Feb 10, 2004 5:33 pm
by Pype.Clicker
kinda strange ...

Re:Triple fault on "unreal" mode

Posted: Tue Feb 10, 2004 5:38 pm
by Karig
If you have any other problems, may I humbly offer you my own code for entering unreal mode (http://www.karig.net/0004.html)? (The page has a pretty complete explanation of the code I wrote.)

Re:Triple fault on "unreal" mode

Posted: Thu Feb 12, 2004 11:20 am
by Ozguxxx
cool tutorial...

Re:Triple fault on "unreal" mode

Posted: Thu Feb 12, 2004 1:41 pm
by Pype.Clicker
it think

Code: Select all

  lgdt      [STAGE1_ADDRESS+gdtr]
should rather have no 'STAGE1_ADDRESS' ...

note that GPF may occur in unreal mode, especially if the selector was not valid when loaded or if the segment's limit wasn't 4GB ...

Re:Triple fault on "unreal" mode

Posted: Thu Feb 12, 2004 3:27 pm
by RuneOfFire
The code I was using seemed unstable, and changing code that was unrelated would randomly mess up the segment registers...

Karig's code worked great. I'm using that now, but for some reason I can't use interrupts... int 0x13 gives me a nice "RIP > CS.limit" in bochs.

Re:Triple fault on "unreal" mode

Posted: Fri Feb 13, 2004 3:33 am
by Pype.Clicker
do you have the IP value at that point ? i'm also wondering why karig's GDT has code segments with the type "98" while i'm used to "9A". If only i had my HollyManuals nearby, i could lookup what was that 2nd bit, but i guess it's "non-conforming" or "readable".

Re:Triple fault on "unreal" mode

Posted: Sat Feb 14, 2004 7:41 am
by Karig
Type "98" is an execute-only code segment (no reads allowed); "9A" permits reading the code. In this context you could go with either one, because of course unreal mode doesn't use memory protection; it's just a variation on real mode.

I was actually using "9A" in my GDT because I am specifically working on an OS without memory protection (I'm nostalgic for my old Commodore 64 ;) )