Linux interrupt processing flow

  

First, the interrupt system hardware architecture:

arm cortex-A9, the interrupt controller on A15 is GIC400 (lower version has GIC390, PL190, etc.), the hardware logic diagram is < Br>

EXTINT0-EXTINT2: Set EINT0— EINT7, EINT8— EINT15, EINT16— EINT23 trigger mode (high level trigger, low level trigger, falling edge trigger, rising edge trigger).

EINTPEND: This is the interrupt pending register. Write 1 when clearing, and write 1 clear afterwards. When an external interrupt (EINT4-EINT23) occurs, the corresponding bit will be set. Why are there no EINT0-EINT3 because they are controlled by the last 4 bits of the SRCPND register.

EINTMASK: This is simple, it is used for masking interrupts. That is to say, when the bit is 1, the interrupt is invalid.

There are 8 registers for internal interrupts:

SUBSRCPND: When an interrupt occurs, the corresponding bit is set to 1, indicating that an interrupt has occurred.

INTSUBMSK: The previous one is a bunch of interrupt mask registers.

SRCPND: When an interrupt occurs, the corresponding bit is set to 1, indicating that one or a type of interrupt has occurred.

INTMSK: Used to mask the interrupt identified by the SRCPND register. However, only IRQ interrupts can be masked and FIQ interrupts cannot be masked.

INTMOD: When a bit in INTMOD is set to 1, its corresponding interrupt is set to FIQ and the CPU will enter the fast interrupt mode.

PRIORITY: Used to set the priority of IRQ interrupts.

INTPND: After the interrupt priority arbiter selects the highest priority interrupt, the corresponding bit in the INTPND register is set, and then the CPU enters interrupt mode to process it. Only one bit of this register is set at the same time.

INTOFFSET: Used to indicate which bit in the INTPND register is set, that is, the value of bit x in which the bit [x] of the INTPND is 1 is recorded. It is automatically cleared when INTPND and SRCPND are cleared.

The above register description is taken from the forum post, the source author is unknown.

Second, the interrupt system software abstract architecture

1) The following figure is the relationship diagram of the Linux kernel interrupt system related data structure, in the "deep linux kernel architecture", the interrupt system is divided into three Level:

High-level Interrupt Service routine: The device-driven interrupt handler, corresponding to the irqacton in the figure.

Interrupt Flow Handling: interrupt flow control (the original book translates to interrupt current control, I don't think it is possible, although this part is related to the state of the signal source, such as an edge-triggered interrupt or a level-triggered interrupt, but it The main responsibility is still: when to call the control of the hardware operation mask, ack, etc.).

Chip-Level hardware Encapsulation: The hardware device layer, mask, ack and other interrupt system hardware registers, corresponding to the irq_chip in the figure.

2) irq_desc: is a global array, each interrupt source corresponds to a descriptor.

3) handle_irq: It is the handler entry for each different type of interrupt source. The call path is: asm_do_IRQ->handle_irq->generic_handle_irq->generic_handle_irq_desc-> handle_irq. Different types of interrupt sources use different processing methods. When the interrupt subsystem is initialized, the function irq_set_handler is used to set or directly assign a value to the function pointer.

irq_chip: It replaces the old version of hw_interrupt_type. The function set in the structure is the mask, unmask, response ack, mask_ack, etc. corresponding to the hardware operation of the interrupt source. It is set by the function irq_set_chip when the interrupt subsystem is initialized. .

handle_level_irq handles the interrupt source type triggered by the level signal. This function will call the chip's irq_mask, irq_ack to mask and ack (tell the interrupt controller, someone has responded to the interrupt, and can continue to generate the next new interrupt. The interrupt signal source, otherwise the interrupt will be processed repeatedly;

handle_egde_irq handles the type of interrupt source triggered by the edge signal, only ack can, no mask is required, the next new type of interrupt can be pending SRCPEND register.

For multi-core CPUs, if the other core is processing the interrupt, it can be identified by the function irqd_irq_inprogress detecting whether the irq_desc -> irq_data->state_use_accessors state is IRQD_IRQ_INPROGRESS.

handle_irq(=handle_level_irq or handle_egde_irq or ...) will call the real device interrupt handler action-> handler via handle_irq_event->handle_irq_event_percpu (version 2.6 for handle_IRQ_event).

4) irqaction: It corresponds to the specific device interrupt description, the handler is the specific isr interrupt service function, dev_id is used to distinguish the different devices in the shared interrupt, the next pointer points to the same interrupt source (shared interrupt) next The device's irqaction, when the interrupt occurs, the shared interrupt device isr will be called, so each device's isr must have the ability to determine whether the interrupt is issued by the device. A paragraph about shared interrupts "Linux Device Drivers": "Whenever two or more drivers are sharing interrupt lines, and hardware interrupts interrupt the processor on this line, the kernel calls each registered for this interrupt. The handler, passing its dev_id to each. Therefore, a shared handler must be able to recognize its own interrupt and should exit quickly when its own device is not interrupted. & rdquo; I think this statement is wrong, first The interrupt signal is just an electrical signal on io. It is impossible to pass the dev_id information to the cpu. The kernel does not know which device is sending the interrupt signal. If there is a known dev_id, there is no need to call all the Sharing the interrupted isr.

Therefore, each device's isr is to determine whether the interrupt is issued by itself. Hardware support is required. For example, by simply checking the flag register of a device, it is not the device, and immediately exits the interrupt.

In addition, when dealing with shared interrupts, you cannot disable or enable irq in a device. This will affect other devices that share interrupts.

Third, interrupted software processing flow

Copyright © Windows knowledge All Rights Reserved