[SOLVED] STI == Fatal Error

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
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

[SOLVED] STI == Fatal Error

Post by 01000101 »

Hey, recently I've been working on an experimental kernel written in Intel Assembly. What is happening is that when I enable interrupts, I get a triple fault from BOCHs saying that my CS selector is null. I'm pretty sure I set both the GDT and IDT entries properly, but then again, I'm getting an error so I'm not tooooo confident in that.

here's the bochs output.

Code: Select all

00001796618i[BIOS ] Booting from 0000:7c00
00005623545e[CPU0 ] return_protected: CS selector null
00005623545i[CPU0 ] CPU is in protected mode (active)
00005623545i[CPU0 ] CS.d_b = 32 bit
00005623545i[CPU0 ] SS.d_b = 32 bit
00005623545i[CPU0 ] EFER   = 0x00000000
00005623545i[CPU0 ] | RAX=000000000010ff11  RBX=0000000000000000
00005623545i[CPU0 ] | RCX=0000000000100000  RDX=0000000000000100
00005623545i[CPU0 ] | RSP=00000000000823bf  RBP=000000000008ffc0
00005623545i[CPU0 ] | RSI=00000000ffff88cb  RDI=0000000000080001
00005623545i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00005623545i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00005623545i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00005623545i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00005623545i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of DF if tf sf zf af PF cf
00005623545i[CPU0 ] | SEG selector     base    limit G D
00005623545i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00005623545i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00005623545i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005623545i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005623545i[CPU0 ] |  ES:0008( 0001| 0|  0) 00000000 000fffff 1 1
00005623545i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005623545i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00005623545i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00005623545i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00005623545i[CPU0 ] | RIP=000000000000fdac (000000000000fdac)
00005623545i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
00005623545i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00005623545i[CPU0 ] >> retf 0xc888 : CA88C8
I'll provide the IDT and GDT setup routines as well.

IDT setup:

Code: Select all

setup_real_idt:
        pusha
        call remap_irqs
        mov word  [0x00501000 + 00], word  0x07FF     ; Limit
        mov dword [0x00501000 + 02], dword 0x00501010 ; Base
        lidt [0x00501000]
        popa
        ret

;-------------------------------------------------------------;
;                    SETUP IDT ENTRY                          ;
; Registers Used:                                             ;
;   EAX = IRQ Entry Offset                                    ; 
;   EBX = IDT Base Address                                    ; 
;   EDX = IRQ Handler Base                                    ; 
;-------------------------------------------------------------;

setup_idt_entry:
        pusha
        add eax, 32
        imul eax, eax, 8
        mov ebx, 0x00501010
        
        mov word  [ebx + eax + 00], dx
        mov word  [ebx + eax + 02], word 0x0008
        mov byte  [ebx + eax + 04], byte 0x00
        mov byte  [ebx + eax + 05], byte 0x8E
        shr edx, 16
        mov word  [ebx + eax + 06], dx
        popa
        ret
GDT setup:

Code: Select all

call setup_real_gdt
        lgdt [0x00500000]
        
        jmp 08h:10200h 

setup_real_gdt:
        pusha
        mov word  [0x00500000 + 00], word  0x0017     ; Limit
        mov dword [0x00500000 + 02], dword 0x00500010 ; Base
        mov dword [0x00500010 + 00], dword 0x00000000 ; Null desc
        mov dword [0x00500010 + 04], dword 0x00000000 
        mov dword [0x00500010 + 08], dword 0x0000FFFF ; Code desc 
        mov dword [0x00500010 + 12], dword 0x00CF9A00
        mov dword [0x00500010 + 16], dword 0x0000FFFF ; Data desc
        mov dword [0x00500010 + 20], dword 0x00CF9200
        popa
        ret
before all of this, I set an entire meg of memory to 0 @ 0x00500000 just to make sure there is no garbage still there to mess things up.

[edit] BTW, this is also my first kernel attempt in assembly as I am usually a C programmer so any pointers / general tips would be appreciated [/edit]
Last edited by 01000101 on Tue Mar 11, 2008 2:02 pm, edited 1 time in total.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

You should probably investigate as to why ES == CS. If they're both non-conforming code segments, then why does ES == CS? And if they're both data segments, then why does ES == CS?!
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

I'm wondering for starters, why there's a far return, and WHY IT POPS 0xc888 ITEMS from the stack in the process.

To me, it looks like you're running something you didn't write in the first place
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Post by 01000101 »

To me, it looks like you're running something you didn't write in the first place
I assure you that this is all my code. There is deffinately not enough code here to produce a pop with so many values getting popped. The code I posted is probably 70% of the entire thing.

Also, I have no idea why the ES == CS, I've scanned the code and the only time ES is ever written to .. or even read from, is when I set it to the Data descriptor 0x10. It seems to change on its own.

The only far return I can think of is from STI? because that is the only place it crashes at. The next instruction after STI is a hlt, so it's not getting that far.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

HLT only halts the processor until the next interrupt fires, so putting it after STI isn't a great idea. Try a "jmp $" (or "jmp ." in AT&T syntax) instead.
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Post by 01000101 »

wait? hlt allows interrupts, but jmp $ doesnt?

I thought jmp just jumps to the same location over and over again, kind of like a for(;;);.... and that deffinately allows interrupts to.. interrupt.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

I said that HLT halts the processor UNTIL the next interrupt fires, and then it will continue to the next opcode.

If the opcode after that isn't specified and interrupts are enabled, you'll get stuck running unknown code.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Post by jal »

pcmattman wrote:If the opcode after that isn't specified and interrupts are enabled, you'll get stuck running unknown code.
Which is no doubt exactly what happens, given that Bochs dump.


JAL
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Post by 01000101 »

indeed it was.
Thanks for the help.
Post Reply