Each hardware device controller capable of issuing interrupt requests usually has a single
output line designed as the Interrupt ReQuest (IRQ) line. All existing IRQ lines are connected
to the input line of a hardware circuit called the Programmable Interrupt Controller, which
performs the following actions.
1. Monitors the IRQ lines, checking for raised signals. If two or more IRQ lines are raised, selects
the one having the lower pin number.
2. If a raised signal occurs on an IRQ line:
a. Converts the raised signal received into a corresponding vector.
b. Stores the vector in an Interrupt Controller I/O port, thus allowing the CPU to read it via the
data bus.
c. Sends a raised signal to the processor INTR pin --- that is, issues an interrupt.
d. Waits until the CPU acknowledges the interrupt signal by writing into one of the Programmable
Interrupt Controller (PIC) I/O ports; when this occurs, clears the INTR line.
3. Go back to step 1.
The IRQ lines are sequentially numbered starting from 0; therefore, the first IRQ line is usually denoted
as IRQ0. Intel's default vector associated with IRQn is n + 32. As mentioned before, the mapping function
between IRQs and vectors can be modified by issuing suitable I/O instructions to the Interrupt Controller
ports.
Each IRQ line can be selectively disabled. Thus, the PIC can be programmed to disable IRQs. That is, the
PIC can be told to stop issuing interrupts that refer to a given IRQ line, or to resume issuing them. Disabled
interrupts are not lost; the PIC sends them to the CPU as soon as they are enabled again. This feature is used
by most interrupt handlers, because it allows them to process IRQs of the same type serially.
Selective enabling/disabling of IRQs is not the same as global masking/unmasking of maskable interrupts.
When the IF flag of the eflags register is clear, each maskable interrupt issued by the PIC is temporarily
ignored by the CPU. The cli and sti assembly language instructions, respectively, clear and set that flag.
Taaditional PICs are implemented by connecting "in cascade" two 8259A-style external chips. Each chip can
handle up to eight different IRQ input lines. Because the INT output line of the slave PIC is connected to the
IRQ2 pin of the master PIC, the number of available IRQ lines is limited to 15.
The Advanced Programmable Interrupt Controller (APIC)
The previous description refers to PICs designed for uniprocessor systems. If the system includes a single CPU,
the output line of the master PIC can be connected in a straightforward way to the INTR pin the CPU. However,
if the system includes two or more CPUs, this approach is no longer valid and more sophisticated PICs are needed.
Being able to deliver interrupts to each CPU in the system is crucial for fully exploiting the parallelism of the SMP
architecture. For that reason, Intel introduced starting with Pentium III a new component designated as the I/O
Advanced Programmable Interrupt Controller (I/O APIC). This chip is the advanced version of the old 8259A
Programmable Interrupt Controller; to support old operating systems, recent motherboards include two types of
chip. Moreover, all current 80x86 microprocessors incldude a local APIC. Each local APIC has 32-bit registers, an
internal clock; a local timer device; and two additional IRQ lines, LINT0 and LINT1, reserved for local APIC interrupt.
All local APICs are connected to an external I/O APIC, giving rise to a multi-APIC system.
The figure 4-1 illustrates in a schematic way the structure of a multi-APIC system. An APIC bus connects the frontend
I/O APIC to the local APICs. The IRQ lines coming from the devices are connected to the I/O APIC, which therefore acts
as a router with respect to a local APICs. In the motherboards of the Pentium III and earlier processors, the APIC bus
was a serial three-line bus; starting with the Pentium 4, the APIC bus is implemented by means of the system bus.
However, because the APIC bus and its message are invisiable to software, we won't give further details.
The I/O APIC consists of a set of 24 IRQ lines, a 24-entry Interrupt Redirection Table, programmable registers, and
a message unit for sending and receiving APIC message over the APIC bus. Unlike IRQ pins of the 8259A, interrupt
priority is not related to pin number: each entry in the Redirection Table can be individually programmed to indicate
the interrupt vector and priority, the destination processor, and how the processor is selected. The information in the
Redirection Table is ued to translate each external IRQ signal into a message to one or more local APIC units via the
APIC bus.
Interrupt requests coming from external hardware devices can be distributed among the available CPUs in two ways:
Static distribution: The IRQ signal is delivered to the local APICs listed in the corresponding Redirection Table entry.
The interrupt is delivered to one specific CPU, to a subset of CPUs, or to all CPUs at once (broadcast mode).
Dynamic distribution: The IRQ signal is delivered to the local APIC of the processor that is executing the process with
the lowest priority. Every local APIC has a programmable task priority register (TPR), which is ued to compute the
priority of the currently running process. Intel expects this register to be modified in an operating system kernel by
each process switch. If two or more CPUs share the lowest priority, the load is distributed between them using a
technique called arbitration. Each CPU is assigned a different arbitration priority ranging from 0 (lowest) to 15 (highest)
in the arbitration priority register of the local APIC.
Every time an interrupt is delivered to a CPU, its corresponding arbitration priority is automatically set to 0, while
the arbitration priority of any other CPU is increased. When the arbitration priority register becomes greater than 15, it is
set to the previous priority of the winning CPU increased by 1. Therefore, interrupts are distributed in a round-robin fashion
among CPUs with the same task priority. (Aside: The Pentium 4 local APIC doesn't have an arbitration priority register;
the arbitration mechanism is hidden in the bus arbitration circuitry. The Intel manuals state that if the operating system
kernel does not regularly update the task priority registers, performance may be suboptimal because interrupts might
always be serviced by the same CPU.)
Besides distributing interrupts among processors, the multi-APIC system allows CPUs to generate interprocessor interrupts.
When a CPU wishes to send an interrupt to another CPU, it stores the interrupt vector and the identifier of the target's local
APIC in the Interrupt Command Register (ICR) of its own local APIC. A message is then sent via the APIC bus to the target's
local APIC, which therefore issues a corresponding interrupt to its own CPU.
Interprocessor interrupts (in short, IPIs) are a crucial component of the SMP architecture. They are actively used by
Linux to exchange messages among CPUs.
Many of the current uniprocessor systems include an I/O APIC chip, which may be configured in two distinct ways:
1. As a standard 8259A-style external PIC connected to the CPU. The local APIC is disabled and the two LINT0 and
LINT1 local IRQ lines are configured, respectively, as the INTR and NMI pins.
2. As a standard external I/O APIC. The local APIC is enabled, and all external interrupts are received through the
I/O APIC.