Linux kernel interrupt subsystem (1) -- arm gic hardware, armgic
In a system, interruption is a very important component. With interruption, the system can improve system efficiency without having to keep polling (polling) for events, in addition, interrupt control is usually distributed in various places, and different parts are controlled by different functional programs, so that the system can work normally only by performing their respective duties and working properly together. In general, interrupt control is divided into three parts: module, interrupt controller, and processor. The module usually has registers to control whether the interrupt function can be enabled, and interrupt trigger conditions; the interrupt controller can manage the interrupt priority and so on, while the processor that handles all interruptions has a register to set whether to respond to the interrupt.
1. panoramic view
The general Interrupt Controller Used in the ARM system is GIC (Generic Interrupt Controller), which currently has four versions, V1 ~ V4 (V2 supports up to 8 ARM cores, V3/V4 supports more ARM cores, mainly used for ARM64 system structure ). Currently, you can only download the GIC architecture specification of Version 2 from the ARM website. The GIC-500 supports up to 128 cpu cores, which requires that the ARM core must be an ARMV8 Instruction Set (such as a Cortex-A57) that complies with the GIC architecture specification version 3. This article mainly describes GIC-400, which is more suitable for embedded systems and complies with version 2's GIC architecture specification. The GIC-400 is connected to one or more ARM processors through an on-chip Bus such as AMBA (Advanced Microcontroller Bus Architecture. First, let's look at a panoramic view of the role of GIC in the system ).
From this figure, it can be seen that GIC is a bridge between peripheral interrupt and CPU, and also a channel (with management functions) for inter-CPU interruption. It is responsible for detecting, managing, and distributing interrupt, you can:
Enable or disable interruption;
Group interruptions to group 0 or group 1 (use FIQ, Group0, and Group1 in the security system as non-security systems and connect to IRQ );
In a multi-core system, interruptions are allocated to different processors;
Set the level trigger or edge trigger mode (not equal to the peripheral trigger mode );
Virtualization extension;
The arm cpu has only two external connections, one is IRQ and the other is FIQ. The corresponding processing modes are generally IRQ and FIQ respectively) processing mode. Therefore, at last, the GIC needs to integrate the interrupted sink into two lines to connect to the CPU.
2. Detailed Design
After introducing the overall impression, we will introduce the details in the following sections. Before introduction, we will first understand several concepts involved in GIC. There are three types of interruption in GIC: SGI (Software-generated interrupt), PPI (Private peripheral interrupt), SPI (Shared peripheral interrupt ).
SGI: SGIs are generated by writing to the Software Generated Interrupt Register, GICD_SGIR. each CPU interface can generate a maximum of 16 SGIs, ID0-ID15, for each target processor. SGI is an interruption that can be triggered by software and is numbered 0 ~ 15, used for communication between each core.
PPI: a ppi is an interrupt that is specific to a single processor. all PPI signals are active-LOW level-sensitive. table 2-3shows the PPIs that are available for each processor. the PPI is the private peripheral interruption of each core, which is uniformly numbered 16-31. For example, the local timer of each CPU, that is, the interruption caused by the Arch Timer, is sent to the CPU through the PPI (the security is 29, non-security: 30 ).
SPI: SPIs are triggered by events generated on associated interrupt input lines. the GIC-400 can support up to 480 SPIs corresponding to the external IRQS [479: 0] signal. the number of SPIs available depends on the implemented configuration of the GIC-400. the permitted values are 0-480, in steps of 32. SPIs start at ID32.You can configure whether each SPI is edge-triggered on a rising edge or is act Ive-HIGH level-sensitive. SPI is the interruption generated by the system peripherals. It is a common interruption for each core and is numbered 32 ~ 1019, such as global timer, uart, gpio interrupt.
Let's look at the figure first:
It can be seen that the GIC can be clearly divided into two parts: the Distributor and the CPU Interface ). There are two types of CPU interfaces: one is the common processor interface and the other is the virtual machine interface. Virtual CPU interface is not described in detail in this article. The distributor should actually be called a aggregator. In the back-end design of the IC, layout will mix the middle disconnections (that is, the three interruptions mentioned above) introduced by each module to the GIC, then, the interruption of mixed aggregation is connected to the CPU's IRQ and FIQ online, so that the CPU has a sense of touch.
There is only one set of Distribute, so there is only one base address and multiple interfaces, because each CPU corresponds to one set of interfaces. Strictly speaking, the number of lines output by GIC should be the number of CPUs x 2. However, the base address of the interface seen by each CPU is also the same, the base address displayed in the program is the same.
The Distribute is responsible for sub-interrupt enabling, trigger mode setting, priority sorting, and CPU distribution. The overall interruption enabling and State maintenance are the responsibility of the Interface.
Overview of Distributor
Distributor is mainly used to detect the status of each interrupt source, control the behavior of each interrupt source, and distribute the interrupt events generated by each interrupt source to one or more specified CPU interfaces. Although Distributor can manage multiple interrupt sources, it always sends the highest-priority interrupt request to the CPU interface. Distributor's interrupt control includes:
(1) interrupt the enable or disable control. The Distributor has two levels of interrupt control. One is GIC_DIST_CTRL ). Once global disable occurs, any interrupt event generated by interrupt source will not be passed to the CPU interface. Another level is to control each interrupt source (GIC_DIST_ENABLE_CLEAR). disable an interrupt source will cause the interrupt event not to be distributed to the CPU interface, however, the distribution of interrupt events generated by other interrupt sources is not affected.
(2) control the distribution of Interrupt events with the highest priority to one or more CPU interfaces. When an interrupt event is distributed to multiple CPU interfaces, the internal logic of GIC should ensure that only one CPU is assert.
(3) priority control.
(4) set the interrupt attribute. For example, level-sensitive or edge-triggered.
(5) interrupt group settings
Distributor can manage several interrupt sources. These interrupt sources are identified by IDS, which we call interrupt IDs.
CPU interface
The CPU interface block is mainly used to interface with process. The main functions of this block include:
(A) enable or disable CPU interface interruption event to the connected CPU assert. For ARM, the interrupt signal line between the CPU interface block and the CPU is nIRQCPU and nFIQCPU. If disable is interrupted, even if the Distributor distributes an interruption event to the CPU interface, it does not notify processor of the nIRQ or nFIQ specified by assert.
(B) ackowledging interruption. Processor will respond to the CPU interface block for interruption. Once the interruption is answered, the Distributor will change the status of the interruption from pending to active. If no pending interruption occurs, the CPU interface will deassert nIRQCPU and nFIQCPU signal lines. If a new interrupt occurs in this process, the Distributor changes the state of the interrupt from pending to pending and active. At this time, the CPU interface will still maintain the asserted status of the nIRQ or nFIQ signal, that is, the next interruption to the processor signal.
(C) Notification of completion of interrupt handling. When the interrupt handler finishes an interrupt, it will write the CPU interface register to notify the gic cpu that the interrupt has been processed. This action notifies the Distributor to change the interrupt status to deactive, and allows other pending interrupt to submit to the CPU interface.
(D) Set priority mask. With priority mask, you can remove some low-priority interruptions from the mask, which will not be notified to the CPU.
(E) Set the preemption Policy
(F) When multiple interrupt events arrive at the same time, select a notification processor with the highest priority.
Different systems have different interruption affinity settings. For example, network servers always want to respond to network requests as soon as possible, and the power consumption is not very important. Therefore, different interruptions can be allocated to different CPUs, in order to respond to the interruption as soon as possible. In embedded systems, the power consumption is very important, and the interruption is usually bound to CPU0. In this way, when other CPUs are IDLE, they can enter the IDLE state to save power consumption, when the arm cpu runs normally, only Arch Timer is used, and Global Timer is not used, that is, the system Timer is not running. However, when the CPU power is disabled, the Arch Timer of the CPU will also be disabled. Therefore, when the CPU enters the IDLE state of power-off, you must switch its Timer to Global Timer first, in this way, when the next Timer arrives, if the CPU is not started, there will be an SGI interrupt sent by the CPU in the Global Timer. When there is an interruption, other modules will remove it from the power-off status, if it is CPU0, after the interruption is also received, other modules bring it out of the power-off status, but the interruption at this time is no longer SGI, but the interruption of Global Timer.
Generally, Distribute belongs to the system power field, and the interface belongs to the CPU power field. Therefore, the original value or weight of the Interface must be restored every time the CPU is powered off and powered on again (the system is powered continuously ).
New initialization. In addition, if you want to keep the CPU in the WFI state, you need to set the GICC_CTLR register of the Interface to 0. Otherwise, the CPU will exit from the WFI state.
The read value of the Register is different in safe and non-safe mode. This does not indicate that the register of the same address is backed up in safe and non-safe mode (like in IRQ and FIQ modes, some registers have backups), but because the properties of the bit in the register are different, some bit in the security register read 0 in the unsafe state, so after the CPU is reset, before switching to a non-security system, you must first set the GIC. Otherwise, the security system cannot respond to the interruption, that is, the security system cannot be used, and the CPU will stop and rest quietly. The phenomenon is as follows: the CPU is in the WFI status, and the system clock is stopped. Because the CPU's Arch-Timer does not respond, the tick count will not change.
3. interrupt handling process
The interrupt processing process is: the distributor caches the collected interruptions and sends the highest priority interrupt request to the CPU interface. The CPU reads an interrupt, in fact, it is to read a register of the interface, but this register stores the interrupt number. At this time, the interrupt status is changed from pending to active. After the cpu completes processing, the interrupt number is written to the interface of the GIC, tell GIC that the process is complete. You can clear the interrupt.
Command to view how interrupts are allocated to CPU usage and response times on the system:
# Cat/proc/interrupts
4. Registers
Refer:
Ddi0471b_gic400_r0p1_trm1 _
IHI 0048B, ARM Generic Interrupt Controller Architecture Specification, Ver 2.0.pdf
Http://www.wowotech.net/linux_kenrel/gic_driver.html
Http://blog.csdn.net/velanjun/article/details/8757862
Http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/index.html