The IDT. Part 3 of boot loader

Standard

Ok!! My bad!! I got busy with some stuff so this post is a bit too late. To make it up, I’ll add two new posts, this one and the second is on UNIX ELF parasites. This one is the continuation to my post on GDT and it covers the Interrupts Descriptor Table or the IDT. Here it goes… enjoy the ride ;).

One last note: The rest of the internals of my NyxOS will be posted time to time, the next one is a deviation because I really want to share my “research” on the ELF parasites.`

There are several methods to communicate with foreign devices such as keyboard. The two most useful methods are Polling and Interrupts. Polling means spinning around in a tight loop, checking if the device is ready. Interrupts are generated dynamically and are usually more efficient because the CPU does not have to wait for the device to be ready. The device can “grab” the attention of the CPU when its ready.

Interrupts can be thought of as POSIX signals. The processor can register “signal handlers” that deal with the interrupt and return the processor back to its previous state after it is done dealing with them. Interrupts can be fired externally via IRQs or internally via the “int n” instructions.

Just like the GDT we have an IDT that tells the processor where the interrupt handlers for each handler reside. It is an array of 256 entries each corresponding to an interrupt. If an interrupt occurs that has no handler for it (not even NULL) the processor shall panic and reset.

Sometimes, a major interrupts such as page fault or divide-by-zero may occur. For such cases, processor defines 32 interrupt handlers that have to be non-null and well defined. They are as follows:

  • 0 – Division by zero exception
  • 1 – Debug exception
  • 2 – Non maskable interrupt
  • 3 – Breakpoint exception
  • 4 – ‘Into detected overflow’
  • 5 – Out of bounds exception
  • 6 – Invalid opcode exception
  • 7 – No coprocessor exception
  • 8 – Double fault (pushes an error code)
  • 9 – Coprocessor segment overrun
  • 10 – Bad TSS (pushes an error code)
  • 11 – Segment not present (pushes an error code)
  • 12 – Stack fault (pushes an error code)
  • 13 – General protection fault (pushes an error code)
  • 14 – Page fault (pushes an error code)
  • 15 – Unknown interrupt exception
  • 16 – Coprocessor fault
  • 17 – Alignment check exception
  • 18 – Machine check exception
  • 19-31 – Reserved

Ok fine, enough of theory, lets take a head first plunge into dark corners of my beloved NyxOS.

First we’ll see the format of the IDT, it looks like this:

  1. struct idt{
  2. unsigned short base_lower;
  3. unsigned short kseg; //kernel segment
  4. unsigned char zero; //always zero
  5. unsigned char flags;
  6. unsigned short base_upper;
  7. }__attribute__((packed));

Similar to the GDT ain’t it?! The flags feild is a bit different though, it looks like this…

the lower 5 bits are always 0b00110 or 14 in decimal. Bits 5-6 define the descriptor privilege level and last bit signifies if the entry is present.

  1. struct idt_ptr{
  2. unsigned short lim;
  3. unsigned int *base;
  4. }__attribute__((packed));

the structure above is the pointer to the IDT just like we had in GDT. We now have to define a function that sets each IDT entry and another function to load the IDT. NyxOS define the prior as idt_set_entry() and this is called, later, by IRQ code to designate each IRQ an entry in the IDT. idt_set_entry() is again similar to its GDT counterpart and it looks like this:

  1. void idt_set_entry(num, base, kseg, flags)
  2. unsigned char num;
  3. unsigned long base;
  4. unsigned short kseg;
  5. unsigned char flags;
  6. {
  7. idt_entry[num].base_lower = (base & 0xFFFF);
  8. idt_entry[num].base_upper = (base >> 16) & 0xFFFF;
  9. idt_entry[num].kseg = kseg;
  10. idt_entry[num].flags = flags;
  11. }

  1. num: interrupt number
  2. base: the base address of the handler
  3. kseg: code segment or data segment?
  4. flags: well you know… associated flags.

As mentioned above, idt_set_entry() is called whenever we need to add an interrupt handler in the IDT. A later post that will cover IRQ in detail will show the use of idt_set_entry().

After setting up the IDT we need to load it so that the processor knows it has an IDT ready to be used. Nyx defines  install_idt() function to do so:

  1. extern void idt_load();
  2. void install_idt()
  3. {
  4. iptr.lim = (sizeof(struct idt) * 256) – 1;
  5. iptr.base = (unsigned int *)&idt_entry;
  6.  
  7. //clear the entire IDT and set it with 0s
  8.  
  9. memset((unsigned char *) &idt_entry, 0, sizeof(struct idt) * 256);
  10.  
  11. idt_load();
  12. }

 Line number 9 sets up memory space required for 256 entries and fills it with 0s. Finally, the IDT is loaded with the idt_load() function that is actually an assembly language instruction defined in boot-header of Nyx. Basically, idt_load() looks like this:

  1. global idt_load
  2. extern iptr
  3. idt_load:
  4.  
  5. lidt [iptr] ; load the IDT with the pointer
  6. ret ; return to C code

Anyone familiar with even a little bit of NASM will notice that idt_load() is defined as global so that it can be called from elsewhere. The `lidt’ instruction takes the IDT pointer as the argument and loads the IDT as pointed to by the pointer. Lucid enough, eh? If not, mail me… I’ll try to make it clear :).

Well, thats that. Since I started working on that ELF parasite thing, I haven’t touched my Nyx and the project is in a segue from active to stagnant. Now since my ELF parasite stuff is nearing its end, I’ll have to rev up the development of Nyx. Anyways, I hope you enjoyed reading this one… any lauds/qualms/censuring etc can be commented or mailed to me directly at drona89@live.com.

Have a great day and happy hacking!

May the force be with you

Code_ninja

 

Advertisements

2 thoughts on “The IDT. Part 3 of boot loader

  1. My brother recommended I might like this blog. He was totally right. This post actually made my day. You cann’t imagine simply how much time I had spent for this information! Thanks!

    • hey 🙂 thanks a ton!! 🙂
      its been a while since I blogged about anything, busy with my college stuff (duh!!) anyways, I’m gonna blog more technical stuff soon… when I reach home for my winter break. 🙂
      May the force be with you

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s