Page 1 of 1

[Solved]My IDT appears to get broken when I call 'sti'!

Posted: Wed Aug 20, 2014 6:51 am
by codeforger
Hello,

I am having a probem with getting interruts working that I just cant figure.

My kernel sets up the GDT and IDT correctly: If I run the code below with line 27 and 29 of kernel.c commented out, the kernel works fine with no tripple faut, then using 'info gdt' and 'info idt' in bochs I can see that the GDT and IDT are well formed and contain the exact data I expect.

However, if I uncomment either line 27(kernel.c) or line 29 (kernel.c). Which are 'asm("sti");' and test1()(a function call that calls into kernel.asm with the two lines 'int 1' and 'ret').
I immediately get a tripple fault.

the tripple fault goes like so:
(excerpt from bochs.log)

Code: Select all

00084585552e[CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x06)
00084585552e[CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00084585552e[CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
As far as I can read this error, this means:
1) I get a 'opcode invalid exception' (the 0x06 vector)
2) That vector fails meaning;
3) I get a 'general protection fault exception' (the 0x0d vector)
4) That vector fails meaning;
5) I get a 'double fault exception' (the 0x08 vector)

Now usually I would except that getting any form of 'gate descriptor is not valid sys seg' error simply means my IDT is broken, however as above, I have proved the IDT is 'fine'.

So after the tripple fault I use bochs to once again 'info gdt' and 'info idt' and both are complete garbage.

I have no idea how calling either of these two small segments of code can result in both my GDT and IDT getting stomped on.

The log of the crash can be found at 'moss/bochs.log'

Thanks in advanced for everyones time.

Re: My IDT appears to get broken when I call 'sti' or 'int 1

Posted: Wed Aug 20, 2014 7:10 am
by mallard
Looking at the code, this doesn't seem quite right (in idt.c):

Code: Select all

extern isr_wrapper;
extern int_general_protection;
with this appering later:

Code: Select all

    for(int i = 0; i < IDT_SIZE; i++)
        encode_idt_entry(i, (unsigned)isr_wrapper, 0x08, 0x8E);
        encode_idt_entry(13, (unsigned)int_general_protection, 0x08, 0x8E);
Since there is no type specified in the "extern" lines, those "isr_wrapper" and "int_general_protection" will be assumed to be integers. Thus, it looks like you're using the integer value of the first few instructions of the handlers as the address, which obviously isn't going to work.

Try changing the "extern" lines to:

Code: Select all

 extern void isr_wrapper();
extern void int_general_protection();
and/or the "encode_idt_entry" lines to:

Code: Select all

    for(int i = 0; i < IDT_SIZE; i++)
        encode_idt_entry(i, (unsigned)&isr_wrapper, 0x08, 0x8E);
        encode_idt_entry(13, (unsigned)&int_general_protection, 0x08, 0x8E);
It's probably a good idea to pay attention to warnings in your build (you have "-Wall -Wextra" in the makefile, so something should come up, I get "warning: type defaults to ‘int’ in declaration of ‘test’ [-Wimplicit-int]" when I leave the type off an "extern"). Personally, I build with "-Werror" as well, as warnings are generally a sign of bad code.

Re: My IDT appears to get broken when I call 'sti' or 'int 1

Posted: Wed Aug 20, 2014 7:29 am
by codeforger
Hello,

IT WORKS! :D

So from how I see that, I wasnt passing the address of my simple isr, meaning that when the interupt happend and the processor attempted to jump to the isr, it jumped into garbage memory and caused the 'opcode invalid' interupt.

Thankyou very much.

I will clear out the rest of my warnings to make sure I have no more mistakes that can be caught by the compiler.