Won't execute default interrupt handler..

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
Benjamin1996
Member
Member
Posts: 78
Joined: Sat Apr 10, 2010 7:00 am
Location: Denmark

Won't execute default interrupt handler..

Post 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 :(.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Won't execute default interrupt handler..

Post 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
If a trainstation is where trains stop, what is a workstation ?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Won't execute default interrupt handler..

Post by gerryg400 »

Oh and be careful with packing of the following structure.

Code: Select all

    struct{
        size16 limit;
   size32 base;
    }entry;
- gerryg400
If a trainstation is where trains stop, what is a workstation ?
Benjamin1996
Member
Member
Posts: 78
Joined: Sat Apr 10, 2010 7:00 am
Location: Denmark

Re: Won't execute default interrupt handler..

Post 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" :).
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Won't execute default interrupt handler..

Post 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?
Benjamin1996
Member
Member
Posts: 78
Joined: Sat Apr 10, 2010 7:00 am
Location: Denmark

Re: Won't execute default interrupt handler..

Post 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 :(.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Won't execute default interrupt handler..

Post by neon »

Hello,

Are your structures packed? How are you installing your default Interrupt Routine (IR)?
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Benjamin1996
Member
Member
Posts: 78
Joined: Sat Apr 10, 2010 7:00 am
Location: Denmark

Re: Won't execute default interrupt handler..

Post 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
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Won't execute default interrupt handler..

Post 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));
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Benjamin1996
Member
Member
Posts: 78
Joined: Sat Apr 10, 2010 7:00 am
Location: Denmark

Re: Won't execute default interrupt handler..

Post by Benjamin1996 »

Thanks a lot, Neon. It works now :).
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Won't execute default interrupt handler..

Post 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 :)
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Won't execute default interrupt handler..

Post 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.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Won't execute default interrupt handler..

Post 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 ;)
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Won't execute default interrupt handler..

Post by neon »

Ah, good point.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Post Reply