Kernel Interrupt Overview


What is an interrupt?

An interrupt is an event external to the currently executing program on the CPU e.g. a keyboard input or arrival of a network packet. When these events happen CPU is executing some random program which may be completely unrelated to the event. The hardware device associated with the event like keyboard or network device informs the processor so that it can be processed. This mechanism of informing processor about an event is called interrupt. As the name suggests it interrupts the processor from its current execution to inform the processor about pending event.

How does a device interrupt a processor?

In legacy systems like 8259 there are some fixed lines a device could assert that would let the processor know that an event has taken place. There are 8 supported interrupt lines on 8259. The interrupt line asserted would let the processor know what kind of interrupt is being asserted. A good source of more information about 8259 controller is PIC 8259 Wiki.

What is sharing of interrupts?

As there are only fixed number of interrupt lines what happens if there are more devices that need to be supported? One possible solution is that some interrupt line has to be shared by more than one device. When interrupt line is shared then different devices that are sharing the interrupt line has to provide some unique information to the processor to enable processor to determine which device has asserted the interrupt line. It is unnecessary to provide this information if interrupt line is not shared. 

What the processor does?

When a processor gets interrupted it is executing some program. The processor needs to save the context of the currently executing program before it can respond to the event that generated the interrupt. After saving the program context it calls the interrupt handler for the event that generated the interrupt.

How does the processor know which interrupt handler to run?

When the system is booting up the interrupts are disabled. There are interrupt gates that are set up at boot up time by the kernel. This point to the interrupt handler that needs to be called. The exact process is processor specific. When an interrupt happens, the processor disables the interrupts and depending upon the Interrupt Descriptor Table executes the corresponding interrupt handler for the interrupt. 

What does an interrupt handler do?

When an interrupt occurs, a common interrupt handler code is executed. The common interrupt handler first saves the context of the running process. This includes instruction pointer (IP), stack pointer and other registers needed to resume the process again. This context is usually saved on the stack. Then the context is changed to interrupt stack. The common interrupt handler uses this interrupt stack for its processing and parameter passing. For information about the kernel stack Please see Kernel stack for x86.

 The common interrupt handler code changes the interrupt level to disable all low priority interrupts than the interrupt currently being handled. Only a high priority interrupt could interrupt the interrupt handler. This could result in nested interrupts. The common interrupt handler then calls the specific interrupt handler specific to the current interrupt like keyboard interrupt or network interrupt. So for example e1000_intr is called for e1000e device. The tasks performed by this handler is device specific but there are few generic tasks that are performed like determining the cause of interrupt. The one important task for an interrupt handler is to re-enable the interrupts as soon as possible. The interrupt handler generally defers as much as functionality as possible to be handled later by bottom half. The bottom halves are executed with interrupt enabled. This allows better system response and less latency. In order to inform the bottom halves about the pending interrupts, the interrupt handler raises softirq. This basically adds a poll to a queue and the polling method is called from bottom half. Softirqs are disabled during the execution of bottom half unless nesting is allowed. Some interrupts may be shared. Under certain situations a special kernel thread is invoked to handle the softirqs.