Remember that before the kernel enables the interrupts, it must load
the initial address of the IDT table into the
register and initialize all the entries of that table. This activity
is done while initializing the system (see Appendix A).
instruction allows a User Mode
process to issue an interrupt signal that has an arbitrary vector
ranging from 0 to 255. Therefore, initialization of the IDT must be
done carefully, to block illegal interrupts and exceptions simulated
by User Mode processes via
int instructions. This
can be achieved by setting the DPL field of the Interrupt or Trap
Gate Descriptor to 0. If the process attempts to issue one of these
interrupt signals, the control unit checks the CPL value against the
DPL field and issues a “General
In a few cases, however, a User Mode process must be able to issue a programmed exception. To allow this, it is sufficient to set the DPL field of the corresponding Interrupt or Trap Gate Descriptors to 3 — that is, as high as possible.
Let’s now see how Linux implements this strategy.
As mentioned in the earlier section Section 4.2.3, Intel provides three types of interrupt descriptors: Task, Interrupt, and Trap Gate Descriptors. Task Gate Descriptors are irrelevant to Linux, but its Interrupt Descriptor Table contains several Interrupt and Trap Gate Descriptors. Linux classifies them as follows, using a slightly different breakdown and terminology from Intel:
- Interrupt gate
An Intel interrupt gate that cannot be accessed by a User Mode process (the gate’s DPL field is equal to 0). All Linux interrupt handlers are activated by means of interrupt gates, and all are restricted to Kernel Mode.
- System gate
An Intel trap gate that can be accessed by a User Mode process (the gate’s DPL field is equal to 3). The four Linux exception handlers associated with the vectors 3, 4, 5, and 128 are activated by means of system gates, so the four assembly language instructions
int $0x80can be issued in User Mode.
- Trap gate
An Intel trap gate that cannot be accessed by a User Mode process (the gate’s DPL field is equal to 0). Most Linux exception handlers are activated by means of trap gates.
The following architecture-dependent functions are used to insert gates in the IDT:
Inserts an interrupt gate in the n th IDT entry. The Segment Selector inside the gate is set to the kernel code’s Segment Selector. The Offset field is set to
addr, which is the address of the interrupt handler. The DPL field is set to 0.
Inserts a trap gate in the n th IDT entry. The Segment Selector inside the gate is set to the kernel code’s Segment Selector. The Offset field is set to
addr, which is the address of the exception handler. The DPL field is set to 3.
Similar to the previous function, except the DPL field is set to 0.
The IDT is initialized and used by the BIOS routines when the computer still operates in Real Mode. Once Linux takes over, however, the IDT is moved to another area of RAM and initialized a second time, since Linux does not use any BIOS routines (see Appendix A).
idt variable points to the IDT, while the IDT
itself is stored in the
idt_table table, which
includes 256 entries. The 6-byte
idt_descr variable stores both the size of the IDT
and its address and is used only when the kernel initializes the
idtr register with the
assembly language instruction.
During kernel initialization, the
assembly language function starts by filling all 256 entries of
idt_table with the same interrupt gate, which
refers to the
ignore_int( ) interrupt handler:
setup_idt: lea ignore_int, %edx movl $(_ _KERNEL_CS << 16), %eax movw %dx, %ax /* selector = 0x0010 = cs */ movw $0x8e00, %dx /* interrupt gate, dpl=0, present */ lea idt_table, %edi mov $256, %ecx rp_sidt: movl %eax, (%edi) movl %edx, 4(%edi) addl $8, %edi dec %ecx jne rp_sidt ret
ignore_int( ) interrupt handler, which is in
assembly language, may be viewed as a null handler that executes the
Saves the content of some registers in the stack
printk( )function to print an “Unknown interrupt” system message
Restores the register contents from the stack
iretinstruction to restart the interrupted program
ignore_int( ) handler should never be
executed. The occurrence of “Unknown
interrupt” messages on the console or in the log
files denotes either a hardware problem (an I/O device is issuing
unforeseen interrupts) or a kernel problem (an interrupt or exception
is not being handled properly).
Following this preliminary initialization, the kernel makes a second pass in the IDT to replace some of the null handlers with meaningful trap and interrupt handlers. Once this is done, the IDT includes a specialized interrupt, trap, or system gate for each different exception issued by the control unit and for each IRQ recognized by the interrupt controller.
 Some Pentium models have the notorious " f00f” bug, which allows a User Mode program to freeze the system. When executing on such CPUs, Linux uses a workaround based on storing the IDT in a write-protected page frame. The workaround for the bug is offered as an option when the user compiles the kernel.