Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(Writing kernel) How do I modify the interrupt descriptor table?

I am writing a small kernel just to poke around the low level stuff a bit. Right now, it boots in Virtual Box and I can display text to the screen, allocate some memory, and other really basic things. It's written in C++ and a little asm.

One of the things I wanted to explore was the mechanism behind multi-tasking. As I understand it, it goes something like this:

  1. The kernel initializes the Interrupt Descriptor Table so that an interrupt is issued periodically (e.g. a millisecond) and calls a routine defined in the kernel.
  2. When the routine is called, it can decide to set the code/data segments and stack pointer to those of another program's context, a "context-switch."

So, it seemed simple in concept, but I knew the details were going to be a lot hairier. I've found a few things on line, but the terminology varies a lot, and the examples seem to be from contexts I don't have (like from within the Linux kernel).

However, the way to set the descriptor tables seems to be like this:

  1. Send some data to the PIC (outb and what-not) to initialize it.
  2. Prepare an interrupt table in memory, with function pointers to the routines you want, being careful that the functions are capable of being signal handlers.
  3. Load the table with lidt.

However, I can't find much on specifically doing these things, or whether this is even correct. Does anyone have resources for a bewildered kernel writer?

like image 720
rovaughn Avatar asked Apr 29 '12 03:04

rovaughn


People also ask

How does an interrupt descriptor table work?

The IDTR register is used to store both the linear base address and the limit (length in bytes minus 1) of the IDT. When an interrupt occurs, the processor multiplies the interrupt vector by the entry size (8 for protected mode, 16 for long mode) and adds the result to the IDT base address.

What is the size of an interrupt gate descriptor located in IDT?

6 bytes are required to store the interrupt gate descriptor, each descriptor comprises of 32 bits of segment selector and 16 bits of offset.


1 Answers

When your PC boots, the BIOS programs the PIC in such a way that IRQ0 through IRQ15 are bound to int 8 through int 0Fh and int 70h through int 77h. This is OK for the real address mode, in which the BIOS operates and MSDOS works.

But you need to change this mapping when switching to the protected mode because some important exceptions are on int 8 through int 0Fh (most notably, #GP, #SS, #PF). You want that because you want to be able to easily distinguish between these exceptions and hardware interrupts coming from the timer and the real-time clock, the keyboard and the mouse, the disks and I/O ports (serial and parallel).

This is probably the first step you've outlined. So, look up online "PIC interrupt remapping" or something of that sort. Also, download some specs for the 8259 chip (the PIC) to have a better idea of what you're doing and how it actually works. "HelpPC" is a good old reference that contains some of the information on the various PC hardware.

There are also "PCGPE" (PC Game Programming Encyclopedia) and "RBIL" (Ralf Brown's Interrupt List) that may help a lot.

IVT/IDT setup is described in the Intel and AMD CPU documentation. It's all there. Not the most pleasant read, but the most detailed and authoritative.

There are many websites of home-brew OS hobbyists and the like, where you can find more details and snippets of code.

like image 51
Alexey Frunze Avatar answered Oct 02 '22 12:10

Alexey Frunze