Page 1 of 1

Won't execute default interrupt handler..

Posted: Sat May 01, 2010 9:49 am
by Benjamin1996
Hello everyone!
My problem is that my OS triple faults when I use my "generateInterrupt(int interrupt)" function, instead of executing my default interrupt handler (the function that's going to get executed if an "unmapped" interrupt occurs) which I installed in every of the 256 descriptors of the IDT, to test it :).
This is my "installIDT(short selector)" function:

Code: Select all

void installIDT(size16 selector){
    size16 nullIndex = 0;
    size16 handlerIndex = 0;
	
    for(nullIndex = 0; nullIndex < sizeof(IDT) * 256 - 1; nullIndex++){
        memorySet(&IDT[nullIndex], 0);
    }
	
    for(handlerIndex = 0; handlerIndex < 256; handlerIndex++){
	installIR(handlerIndex, 0x0080 | 0x000e, selector, (IRQHandler)defaultHandler);
    }
	
    loadIDT(sizeof(struct descriptor) * 256 - 1, (size32)&IDT[0]);
}
My "installIR(size32 index, size16 flags, size16 selector, IRQHandler IRQ)" function:

Code: Select all

void installIR(size32 index, size16 flags, size16 selector, IRQHandler IRQ){
    if(index > 256){
        return;
    }

    if(!IRQ){
	return;
    }

    size64 base = (size64)&(*IRQ);
    IDT[index].baseLow = base & 0xffff;
    IDT[index].baseHigh	= (base >> 16) & 0xffff;
    IDT[index].reserved	= 0;
    IDT[index].flags = flags;
    IDT[index].selector	= selector;
}
And these are my "loadIDT(short limit, int base)" & "generateInterrupt(int interrupt)" functions:

Code: Select all

void generateInterrupt(size32 interrupt){
    size32 number = interrupt;

    asm(
        "movb (%0), %%al\n\t"
	"mov %%al, (execute + 1)\n\t"
	"jmp execute\n\t"
	"execute: int $0"
	:
	: "a" (number));
}

void loadIDT(size16 limit, size32 base){
    struct{
        size16 limit;
	size32 base;
    }entry;
	
    entry.limit = limit;
    entry.base = base;

    asm("lidt (%0)" : : "p" (&entry));
}
And this is how I call the functions:

Code: Select all

installIDT(0x0008);
generateInterrupt(0x0015);
If I comment out the "generateInterrupt(0x0015)" function call, it works fine so it's probably the inline assembly in my "generateInterrupt(0x0015)" function, that causes the trouble.
(I suck at inline assembly (too complicated in my opinion :)))

Best regards,
Benjamin.

EDIT:
I'm sorry about the formatting of the code, but the forums always screws some parts of the code :(.

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 10:26 am
by gerryg400
That's some nasty inline assembler. I'm sure the processor would fault 4 times if it could.

Code: Select all

        "movb (%0), %%al\n\t"
I think if you remove this line it may work. Why do you have () around the %0 anyway? Have you disassembled your code and looked at it? You must do that. There may be others.

- gerryg400

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 10:29 am
by gerryg400
Oh and be careful with packing of the following structure.

Code: Select all

    struct{
        size16 limit;
   size32 base;
    }entry;
- gerryg400

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 10:42 am
by Benjamin1996
Well if I remove the line you suggested I'm quite sure it wouldn't work.
Maybe if I tell you what the function is supposed to do, you could write the code? :P
The function is supposed to move the value of "interrupt" into "al", and then move "al" (the value of "interrupt") into the parameter of the "int" instruction and then jump to the execute function, which will now execute int number "interrupt" :).

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 12:07 pm
by Owen
Lets rewrite the following inline assembly in pseudocode:

Code: Select all

    asm(
        "movb (%0), %%al\n\t"
	"mov %%al, (execute + 1)\n\t"
	"jmp execute\n\t"
	"execute: int $0"
	:
	: "a" (number));

al = *eax;
*(execute+1) = al
goto execute
execute: int $0
OK, so lets see...
First line should be "movb %0, %%al"... except that assembles to "movb %al, %al"...
Second line is almost right assuming that int is a two byte instruction where the second byte is the vector to jump to. I say almost because its not going to work on a multiprocessor machine...
The jump is superflous
The interrupt does what you want (or would if correctly modified)

Now, I have to ask: What is the purpose in creating a generalized int function? Would it not be better to, if really needed, make it a macro which always goes to a constant interrupt?

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 1:09 pm
by Benjamin1996
Owen wrote:Lets rewrite the following inline assembly in pseudocode:

Code: Select all

    asm(
        "movb (%0), %%al\n\t"
	"mov %%al, (execute + 1)\n\t"
	"jmp execute\n\t"
	"execute: int $0"
	:
	: "a" (number));

al = *eax;
*(execute+1) = al
goto execute
execute: int $0
OK, so lets see...
First line should be "movb %0, %%al"... except that assembles to "movb %al, %al"...
Second line is almost right assuming that int is a two byte instruction where the second byte is the vector to jump to. I say almost because its not going to work on a multiprocessor machine...
The jump is superflous
The interrupt does what you want (or would if correctly modified)

Now, I have to ask: What is the purpose in creating a generalized int function? Would it not be better to, if really needed, make it a macro which always goes to a constant interrupt?
Alright then, so I followed your advice and (again, for testing purposes) defined an "interrupt0()" function, like this:

Code: Select all

#define interrupt0() asm("int $0");
Yet, it still triple faults when I call "interrupt0()" in my kernels "kernel()" function :(.

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 1:22 pm
by neon
Hello,

Are your structures packed? How are you installing your default Interrupt Routine (IR)?

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 1:34 pm
by Benjamin1996
neon wrote:Hello,

Are your structures packed? How are you installing your default Interrupt Routine (IR)?
Look in the provided code, and you should find what you're looking for..
This is my "descriptor" structure:

Code: Select all

struct descriptor{
    size16 baseLow;
    size16 selector;
    size8 reserved;
    size8 flags;
    size16 baseHigh;
};
:D

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 1:39 pm
by neon
Oh, woops, messed that.

Both descriptor and your entry structure might not be packed right. If you are using GCC (or a GCC-like compiler), add __attribute__((packed)) after both structures. For example:

Code: Select all

struct s {

  ; members here

}__attribute__((packed));

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 2:48 pm
by Benjamin1996
Thanks a lot, Neon. It works now :).

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 5:21 pm
by Owen
Benjamin1996 wrote: Alright then, so I followed your advice and (again, for testing purposes) defined an "interrupt0()" function, like this:

Code: Select all

#define interrupt0() asm("int $0");
Yet, it still triple faults when I call "interrupt0()" in my kernels "kernel()" function :(.
My suggestion was more like

Code: Select all

#define INT(_n) asm volatile("int $" #_n)
though I must say I think you'll find such functions quickly become useless :)

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 5:49 pm
by neon
Hello,
Owen wrote:though I must say I think you'll find such functions quickly become useless :)
I personally dont think so. Abstracting common ASM instructions behind a common interface helps improve compiler compatibility in the same way inportb() and outportb() routines do when it comes to inline assembly language code.

I would agree with you if they do not ever switch compilers in the future (or switch to a compiler with same assembly syntax) though.

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 6:01 pm
by Owen
neon wrote:Hello,
Owen wrote:though I must say I think you'll find such functions quickly become useless :)
I personally dont think so. Abstracting common ASM instructions behind a common interface helps improve compiler compatibility in the same way inportb() and outportb() routines do when it comes to inline assembly language code.

I would agree with you if they do not ever switch compilers in the future (or switch to a compiler with same assembly syntax) though.
I'm referring to the fact that "int $x" is not something a kernel does often ;)

Re: Won't execute default interrupt handler..

Posted: Sat May 01, 2010 6:40 pm
by neon
Ah, good point.