Triple fault on "unreal" mode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
RuneOfFire

Triple fault on "unreal" mode

Post 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:
Ozguxxx

Re:Triple fault on "unreal" mode

Post 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.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Triple fault on "unreal" mode

Post 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 ...
RuneOfFire

Re:Triple fault on "unreal" mode

Post 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. ;)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Triple fault on "unreal" mode

Post by Pype.Clicker »

kinda strange ...
Karig

Re:Triple fault on "unreal" mode

Post 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.)
Ozguxxx

Re:Triple fault on "unreal" mode

Post by Ozguxxx »

cool tutorial...
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Triple fault on "unreal" mode

Post 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 ...
RuneOfFire

Re:Triple fault on "unreal" mode

Post 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.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Triple fault on "unreal" mode

Post 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".
Karig

Re:Triple fault on "unreal" mode

Post 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 ;) )
Post Reply