中断管理基础学习笔记 - 1.概述

1. 前言

本专题我们开始学习进程管理部分。本文主要参考了《奔跑吧, Linux内核》、ULA、ULK的相关内容。
本节记录ARM架构下中断是如何管理的,Linux内核中的中断管理机制是如何设计与实现的,以及常用的下半部机制,如软中断、tasklet、workqueue等。本文及后续中断相关笔记均以qemu 5.0.0内嵌平台为例,中断控制器采用GIC-400控制器,支持GIC version2技术规范。

kernel版本:5.10
平台:arm64

注:
为方便阅读,正文标题采用分级结构标识,每一级用一个"-“表示,如:两级为”|- -", 三级为”|- - -“

2. 中断控制器

2.1 Linux内核中断管理分层架构

硬件层:CPU和中断控制器的连接;
处理器架构管理层:如CPU中断异常处理;
中断控制器管理层:如IRQ号的映射;
Linux内核通用中断处理层:如中断注册与中断处理

2.2 GIC中断控制器

在这里插入图片描述

  • GIC中断控制器构成
    1.distributor
    集中管理所有中断源
    (1)配置中断的优先级
    (2)设置每个中断可路由的CPU列表
    (3)向各个CPU interface配送最高优先级的中断
    (4)中断屏蔽、中断抢占
    (5)配置中断是边缘触发还是水平触发。
    2.cpu interface
    cpu interface是GIC连接到CPU的接口,每个cpu intterface提供了一个编程接口,主要功能包括:
    (0) 使能中断请求信号到CPU;
    (1) acknowledging中断,表示CPU接受到中断请求;
    (2)指示中断的处理完成;
    (3)设置处理器中断优先级,高于此优先级方可发送给处理器;
    (4)设置处理器的抢占策略;
    (5)确定处理器的最高优先级待处理中断?
  • 支持的中断类型
中断类型硬件中断号范围含义应用场景
SGI私有软件触发中断0~15用于多核之间的通信通常用于多核通信,linux通常用作IPI中断,传达到系统指定的CPU上
PPI私有外设中断16~31每个处理器核心私有的中断如CPU本地时钟local timer
SPI公用外设中断32~1019公用的外设中断用于公用外设的中断,如按键、SPI、TP等
  • 中断状态
    在这里插入图片描述
    inactive(不活跃)状态:中断处于无效状态;
    pending(等待)状态:中断处于有效状态,但是等待CPU响应该中断;
    active(活跃)状态:CPU已经响应中断;
    active and pending(活跃并等待)状态:CPU正在响应中断,但是该中断源又发送中断过来

参考: 《ARM® Generic Interrupt Controller Architecture version 2.0 》3.2.4 Interrupt handling state machine
Transition A1 or A2, add pending state
(1) For an SGI, occurs if either:
• Software writes to a GICD_SGIR that specifies the processor as a target.
• Software on the target processor writes to the GICD_SPENDSGIRn bit that corresponds to the required source processor and interrupt ID
(2) For an SPI or PPI, occurs if either:
• a peripheral asserts an interrupt request signal
• software writes to an GICD_ISPENDRn.
Transition B1 or B2, remove pending state
(1) For an SGI, occurs if software on the target processor writes to the relevant bit of the GICD_CPENDSGIRn.
(2) For an SPI or PPI, occurs if either:
• the level-sensitive interrupt is pending only because of the assertion of an input signal, and that signal is deasserted
• the interrupt is pending only because of the assertion of an edge-triggered interrupt signal, or a write to an GICD_ISPENDRn, and software writes to the corresponding GICD_ICPENDRn.
Transition C, pending to active
If the interrupt is enabled and of Sufficient priority to be signaled to the processor, occurs when software reads from the GICC_IAR
Transition D, pending to active and pending
(1) For an SGI, this transition occurs in either of the following circumstances:
•If a write to set the SGI state to pending occurs at approximately the same time as a read of GICC_IAR.
• When two or more pending SGIs with the same interrupt ID originate from the same source processor and target the same processor. If one of the SGIs follows transition C, the other SGIs follow transition D
(2) For an SPI or PPI this transition occurs if all the following apply:
• The interrupt is enabled.
• Software reads from the GICC_IAR. This read adds the active state to the interrupt.
• In addition, one of the following conditions applies:
— For a level-sensitive interrupt, the interrupt signal remains asserted. This is usually the case, because the peripheral does not deassert the interrupt until the processor has serviced the interrupt.
— For an edge-triggered interrupt, whether this transition occurs depends on the timing of the read of the GICC_IAR relative to the detection of the reassertion of the interrupt.Otherwise the read of the GICC_IAR causes transition C, possibly followed by transition A2.
Transition E1 or E2, remove active state
Occurs when software deactivates an interrupt by writing to either GICC_EOIR or GICC_DIR. For more information see Priority drop and interrupt deactivation on page 3-38. In a GIC implementation the includes the Virtualization Extensions, also occurs if the virtual CPU interface signals that the corresponding physical interrupt has been deactivated.

注:assert的意思就是把信号变为active(可以理解为有效),根据系统有求不同,该有效电平可以是高电平(即高有效)也可以是低电平(即低有效)。deassert的意思就是解除active状态,就是信号变为非active状态,可以是高也可以是低。
从如上可以看出,对于SPI:
! pending -> pending的条件是中断信号assert;
pending -> ! pending的条件是中断信号deassert;
pending -> active的条件是中断信号发送给cpu
active pending -> active or active -> inactive的条件是中断信号被deactive

参考:https://www.cnblogs.com/LoyenWang/p/12996812.html
在这里插入图片描述

  • GIC检测中断的流程
    1.当GIC检测到一个中断发生,会将中断标记为pending状态;
    2.distributor会从众多pending状态的中断中选择一个优先级最高的中断,发送到目标CPU的CPU interface;
    3.CPU interface决定这个中断是否可以发送给CPU,如果该中断的优先级满足要求,GIC会发生一个中断请求信号给该CPU;
    4.当一个CPU进入中断异常后,会去读取GICC_IAR寄存器来响应该中断。寄存器会返回硬件中断号,当GIC感知到软件读取了该寄存器:
    (1)如果中断源是pending状态,那么状态变为active;
    (2)如果该中断又重新产生,那么pending状态变为active and pending;
    (3)如果该中断是active状态,现在变为 active and pending;
    5.当处理器完成中断服务,必须发送一个完成信号EOI给GIC控制器(通过软件写EOIR),表示结束此中断的处理过程。

注:GIC总是会选择优先级最高的pending的中断发送给CPU
通过cat /proc/interrupts可以查看到当前平台的中断源,及对应的GIC硬件中断号和LINUX分配的软中断号(虚拟中断号)

3. 虚拟中断号和硬中断号

  • 虚拟中断号
<include/asm-generic/irq.h>
/*
* NR_IRQS is the upper bound of how many interrupts can be handled
* in the platform. It is used to size the static irq_map array,
* so don't make it too big.
*/
#ifndef NR_IRQS
#define NR_IRQS 64
#endif

NR_IRQS:表示系统支持的最大的虚拟中断号数量,它与平台相关

<kernel/irq/internals.h>
#ifdef CONFIG_SPARSE_IRQ
# define IRQ_BITMAP_BITS        (NR_IRQS + 8196)
#else
# define IRQ_BITMAP_BITS        NR_IRQS
#endif
<kernel/irq/irqdesc.c>
static DECLARE_BITMAP(allocated_irqs, IRQ_BITMAP_BITS);

Linux定义了位图来管理这些虚拟中断号,allocated_irqs变量分配IRQ_BITMAP_BITS个bit位,每个bit位代表一个中断

  • 硬中断号
    1.0~31中断号给了SGI和PPI
    2.其它外设中断号从32开始
    3.dts中会用interrupts = <硬中断号n>来指定硬件中断号,其中硬中断号n为板子上的硬件中断号,真正的硬件中断号32+n
    如下以qemu 5.0.0自带的DTS为例说明:
    在这里插入图片描述
    如上从dts中可看出串口的interrupts值为1,代表它在板级的硬件中断号为1,但是要对应到GIC的硬件中断号需要转换(因为外设硬中断号从32开始)
    在这里插入图片描述
    经转换后的硬件中断后为33,它对应GIC的硬件中断号
    4.每一款ARM SOC芯片设计阶段,各种中断和外设的分配情况要固定下来,通过查询芯片手册来确定外设的硬件中断号。

注:
dts中的interrupts域主要包含三个属性:
1.中断类型:GIC_SPI(共享外设重案,用0表示);GIC_PPI(私有外设中断,用1表示);
2.中断ID;
3.触发类型:IRQ_TYPE_EDGE_RISING:1,IRQ_TYPE_EDGE_FALLING:2,IRQ_TYPE_EDGE_BOTH:3,IRQ_TYPE_LEVEL_HIGH:4,IRQ_TYPE_LEVEL_LOW:8

4. 中断管理主要数据结构

在这里插入图片描述

  • struct irq_domain
    Linux 3.1引入,用来描述一个中断控制器, 对于GIC是在gic初始化时会注册irq_domain
  • struct irq_chip
    用于描述中断控制器底层操作相关的函数操作集合
  • struct irq_desc
    中断描述符,每个中断都有一个中断描述符
  • struct irqaction
    用于描述某个中断的处理函数

参考文档

  1. 奔跑吧,Linux内核
  2. ARM® Generic Interrupt Controller Architecture version 2.0
  3. 【原创】Linux中断子系统(一)-中断控制器及驱动分析
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值