IDT in C

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
PlayOS

IDT in C

Post by PlayOS »

Hi all,

I am having trouble getting my IDT to work using C Code. I have a fully working one that is done in ASM, however I want to initialize and manage it in C. Below is the details of my problem :-

I have these constants defined

#define MEMORY_KERNEL_DATA 0x400000
#define KERNEL_IDT_LOCATION 0x800

Before I jump to my kernel I load the IDTR with the appropriate stuff (ie: size and base address) and then the first thing my kernel does is setup the IDT. Below is what the kernel does :

This function installs interrupt gate handlers

Code: Select all

DWORD INSTALL_INTERRUPT_GATE( BYTE bIdx, WORD wDesc, DWORD dwAddr, WORD wAttrs )
{
   // Local data
   DWORD dwPrevAddr;

   // Get a ptr to the entry
   WORD* wIdt = (WORD*)(MEMORY_KERNEL_DATA + KERNEL_IDT_LOCATION + (bIdx * 8));

   // Save the return address
   dwPrevAddr = ((wIdt[3] << 16) | wIdt[0]);

   // Write the entry
   *wIdt = (WORD)(dwAddr);
   wIdt += 2;       // I have tried wIdt++ and it doesn't work either
   *wIdt = wDesc;
   wIdt += 2;
   *wIdt = wAttrs;
   wIdt += 2;
   *wIdt = (WORD)(dwAddr >> 16);

   // Return the previous handler address
   return dwPrevAddr;
}
I call this function for each of the exception handlers and each of the IRQ handlers and to install a default handler for all the other ints. Once I have done this I call this function :

Code: Select all

VOID PIC_REMAP()
{
   // ICW1
   OUTPORTB( 0X20, 0X11 );
   OUTPORTB( 0XA0, 0X11 );

   // ICW2
   OUTPORTB( 0X21, 0X20 );
   OUTPORTB( 0XA1, 0X28 );

   // ICW3
   OUTPORTB( 0X21, 0X04 );
   OUTPORTB( 0XA1, 0X02 );

   // ICW4
   OUTPORTB( 0X21, 0X01 );
   OUTPORTB( 0XA1, 0X01 );

   // OPEN IRQ'S
   OUTPORTB( 0X21, 0X00 );
   OUTPORTB( 0XA1, 0X00 );
}
The IRQs are installed at int 32-47.

Once this is all done I STI() and I get the 3rd exception error, can anyone see the problem in this code, I think that it is my INSTALL_INTERRUPT_GATE() function.

thanks.
PlayOS

Re:IDT in C

Post by PlayOS »

Hi,

If I have my ISRs in C, then do I need an ASM wrapper for each one?

If not then how do I do an IRET in C, is this possible?

Thanks.
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:IDT in C

Post by Pype.Clicker »

PlayOS wrote: Hi,

If I have my ISRs in C, then do I need an ASM wrapper for each one?
If not then how do I do an IRET in C, is this possible?
Thanks.
yes, you need an ASM wrapper for each C isr (except if you know how to tell the CPU not to garbage the registers, etc. but i still it is safer and more portable to call the C handler from a clean ASM stub.

now, this does not mean you can't have most of the job done by a common wrapper (the interrupt-specific wrapper could just push a value on the stack to inform the common wrapper part which C function is to be called ;) )
PlayOS

Re:IDT in C

Post by PlayOS »

I am actually having problems with my IDT, for some reason I am unable to get it working. Should I initialize my IDT in ASM or C?

In ASM I have a completely working IDT, however I am trying to implement it in C without any luck.

How is your IDT implemented?

thanks for your help.
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:IDT in C

Post by Pype.Clicker »

my own IDT is set up by a asm code that sets up every asm wrapper for exception & interrupts - they should not be modified once set up. on top of this, a C mechanism has a separated list of handlers for every interrupt & exception ... and *those* lists are programmable by the C code ...

i think this is the best way to handle the problem (and not forcing the module/whatever developers to worry about registers etc. while you already had to worry with them with timer, etc.)

the less ASM code you got, the better you'll feel when debugging ;)
PlayOS

Re:IDT in C

Post by PlayOS »

That is similar to what I am doing (without any success yet :() I have a list of handlers that are called by the wrappers which perform the IRET once the handler returns, however now that I have added this stuff I am getting the bochs error that is in that other thread of mine.

I'll keep at it, it will come in the end (I Hope)

thanks again.
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:IDT in C

Post by Pype.Clicker »

could i see your asm wrapper ? it is likely that you miss something in the push/pop pairs and that you IRET on something that is not the stack frame the CPU pushed on the stack ...
PlayOS

Re:IDT in C

Post by PlayOS »

OK, this is the wrapper for Int 56 :

_INT_056_WRAPPER:
   PUSH   EAX
   MOV      EAX, DWORD [KERNEL_IDT_HANDLER_TABLE + 0224]
   CALL   EAX
   POP      EAX
   IRET

The kernel IDT handler table is just a list of 4 byte ptrs to handler functions, each wrapper does the same thing, gets and calls the handler address then returns.

Is it possible to determine what interrupt number is being called, from within the handler itself?

I mean if I could determine what interrupt was being called then this wrapper could be generic for all interrupts, just multiplying the interrupt number by 4 would give me the correct handler address.

thanks.
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:IDT in C

Post by Pype.Clicker »

you should know that C will allow itself to change some registers without feeling the need to push/pop them on the stack (mainly eax, edx and edi, if i remember well) ... thus, imho, you should *really* add a pusha/popa pair in your handler ...

for the interrupt number from the handler, the response is unfortunately no: if you want to know what handler has been called, you need to keep track of it by yourself :(
Post Reply