Skip to content

Task 2: AI-Assisted Linux Interrupt Understanding

What is an interrupt?

An interrupt is an event that alters the normal execution flow of a program and can be generated by hardware devices or by the CPU itself. When an interrupt occurs, the current flow of execution is suspended and an interrupt handler runs. After the interrupt handler runs, the previous execution flow is resumed.

Interrupts can be grouped into categories based on source and maskability:

  • synchronous: generated by executing an instruction
  • asynchronous: generated by an external event
  • maskable
    • can be ignored/postponed
    • signaled via INT pin
  • non-maskable
    • cannot be ignored
    • signaled via NMI pin

Synchronous interrupts (usually called exceptions) handle conditions detected by the processor during instruction execution. Divide-by-zero and system call related events are examples.

Asynchronous interrupts are external events generated by I/O devices. For example, a network card can generate an interrupt to signal packet arrival.

Most interrupts are maskable, meaning handling can be postponed while interrupts are disabled and resumed later. However, some critical interrupts cannot be disabled/postponed.

Exceptions

There are two sources for exceptions:

  • processor-detected
    • faults
    • traps
    • aborts
  • programmed
    • int n

Processor-detected exceptions are raised when an abnormal condition is detected while executing an instruction.

A fault is reported before instruction completion and can usually be corrected. The saved EIP/RIP points to the faulting instruction, so execution may retry that instruction after correction (e.g., page fault).

A trap is reported after instruction completion. The saved EIP/RIP points to the next instruction after the one that caused the trap (e.g., debug trap).

Question

Quiz: For each item, think about which labels apply: Exception, Interrupt, Maskable, Nonmaskable, Trap, Fault.

  • Watchdog
  • Demand paging
  • Division by zero
  • Timer
  • System call
  • Breakpoint

Hardware Concepts

Programmable Interrupt Controller

A device that supports interrupts has an output pin for signaling an Interrupt Request (IRQ). IRQ pins connect to a Programmable Interrupt Controller (PIC), and PIC connects to the CPU INTR pin.

A PIC usually has ports used to exchange information with the CPU. When a device on an IRQ line needs CPU attention, a high-level flow is:

  1. Device raises interrupt on IRQn.
  2. PIC converts IRQ to a vector number.
  3. PIC raises interrupt on CPU INTR.
  4. PIC waits for CPU acknowledgment before raising the next interrupt.
  5. CPU acknowledges and starts handling the interrupt.

Once an interrupt is acknowledged, the controller can request another interrupt even if previous handling has not fully completed, so nested interrupts are possible depending on OS control.

The interrupt controller can disable each IRQ line individually, helping ensure serialized execution for selected handlers.

Interrupt controllers in SMP systems

In SMP systems, there can be multiple controllers. On x86, each core has a local APIC for local interrupts (e.g., timers, thermal sensors), while I/O APIC distributes external IRQs to CPU cores.

Interrupt Control

To synchronize shared data between interrupt handlers and concurrent code paths (driver init/processing), interrupts are enabled/disabled in a controlled way.

This can be done at multiple levels:

  • device level
    • program device control registers
  • PIC/controller level
    • disable a specific IRQ line
  • CPU level
    • on x86, classic instructions include:
      • cli (clear interrupt flag)
      • sti (set interrupt flag)

Interrupt priorities

Most architectures support interrupt priorities. When enabled, nested interrupts are typically allowed only for interrupts with higher priority than the current priority level.

Interrupt handling on x86 architecture

Interrupt Descriptor Table (IDT)

On x86, each interrupt/exception vector maps to an IDT entry (gate). The IDT is used by the CPU as a jump table to find the corresponding handler.

Key points:

  • vector space has 256 entries
  • low vectors are generally reserved for exceptions
  • a dedicated vector is used for the syscall interface
  • the CPU locates the IDT via IDTR

Gate types and handler address

Common x86 gate types:

  • interrupt gate: enters handler and clears IF (maskable interrupts disabled)
  • trap gate: enters handler without clearing IF
  • task gate: generally not used in Linux fast-path interrupt handling

Handler target is computed from segment selector + offset fields in the gate descriptor.

Interrupt stack frame and return

On entry, CPU saves execution state on stack (e.g., flags and return address fields). Some exceptions also push an error code.

On return, x86 uses iret/iretq to restore saved state and resume interrupted execution. If privilege level changed on entry, return also restores prior privilege/stack context.

High-level request handling sequence

When an interrupt/exception is taken, CPU performs a sequence that includes:

  1. checking privilege transition needs
  2. switching stack if required
  3. saving return state
  4. transferring control to the selected handler

Interrupt handling in Linux

Linux handling is often explained in phases:

  1. critical entry/dispatch phase
  2. immediate device-handler phase
  3. deferred phase for non-urgent work

In early phases, local interrupt state is tightly controlled to protect critical handling. Later, deferred execution improves latency and throughput.

Interrupt context

Code running between interrupt entry and return is in interrupt context. Important properties:

  • not associated with a normal user process context
  • should not sleep or perform operations that require scheduling
  • should keep work short and deterministic

Shared interrupts and generic dispatch

One IRQ line may be shared by multiple devices. Generic IRQ code dispatches the line to registered actions (irqaction) under descriptor control (irq_desc). This is where handler chains and per-line flow handlers are coordinated.

Deferrable work

Linux defers non-critical work out of hard IRQ handling. Common mechanisms include:

  • softirq/tasklet style bottom-half execution
  • threaded interrupt handlers
  • workqueues (process context)

Timers

Timer events are a canonical interrupt-driven workload. Architecture entry and generic IRQ dispatch eventually connect to timer framework callbacks, which then drive periodic time accounting and scheduled timer callbacks.

Question

Task: Use AI tools plus source reading to recover the complete interrupt-related function path for this scope:

  • Start function (init/main.c): trap_init()
  • Target vector: X86_TRAP_NMI

You must identify relevant functions on this path and explain each function's concrete role with source evidence.

Required output

Create task2/interrupt_flow.md with:

  1. Prompt Log At least 3 prompts used for AI-assisted code navigation.

  2. Verified Function Path A function chain from trap_init() to end (at least 8 steps)

  3. Function Notes For every function in your chain, write 1-3 sentences about what it does in this specific flow.

  4. Short Summary No more than 250 words summarizing the whole flow in your own words.

Rules

  1. AI may help search/summarize/propose candidate paths.
  2. You must verify all key claims from source code.
  3. Do not submit AI-generated code.