changelog:
2019年02月17日 初稿
2020年03月1日 fix typos以及增加中断路由

1. 前言

GIC,Generic Interrupt Controller。是ARM公司提供的一个通用的中断控制器。主要作用为:
接受硬件中断信号,并经过一定处理后,分发给对应的CPU进行处理。

当前GIC 有四个版本,GIC v1~v4, 主要区别如下表:

本文主要介绍GIC v3控制器, 基于linux kernel 4.19.0。

2. GIC v3中断类别

GICv3定义了以下中断类型:
SPI (Shared Peripheral Interrupt)
公用的外部设备中断,也定义为共享中断。可以多个Cpu或者说Core处理,不限定特定的Cpu。比如按键触发一个中断,手机触摸屏触发的中断。
PPI (Private Peripheral Interrupt)
私有外设中断。这是每个核心私有的中断。PPI会送达到指定的CPU上,应用场景有CPU本地时钟。
SGI (Software Generated Interrupt)
软件触发的中断。软件可以通过写GICD_SGIR寄存器来触发一个中断事件,一般用于核间通信。
LPI (Locality-specific Peripheral Interrupt)
LPI是GICv3中的新特性,它们在很多方面与其他类型的中断不同。LPI始终是基于消息的中断,它们的配置保存在表中而不是寄存器。比如PCIe的MSI/MSI-x中断。

硬件中断号 中断类型
0-15 SGI
16 - 31 PPI
32 - 1019 SPI
1020 - 1023 用于指示特殊情况的特殊中断
1024 - 8191 Reservd
8192 - MAX LPI

3. GIC v3组成


GICv3控制器由以下部分组成:
distributor: SPI中断的管理,将中断发送给redistributor
redistributor: PPI,SGI,LPI中断的管理,将中断发送给cpu interface
cpu interface: 传输中断给core
ITS: Interrupt Translation Service, 用来解析LPI中断
其中,cpu interface是实现在core内部的,distributor,redistributor,ITS是实现在gic内部的.

Distributor 详述
Distributor的主要的作用是检测各个interrupt source的状态,控制各个interrupt source的行为,分发各个interrupt source产生的中断事件分发到指定的一个或者多个CPU interface上。虽然Distributor可以管理多个interrupt source,但是它总是把优先级最高的那个interrupt请求送往CPU interface。
Distributor对中断的控制包括:
(1)中断enable或者disable的控制。Distributor对中断的控制分成两个级别。一个是全局中断的控制(GIC_DIST_CTRL)。一旦disable了全局的中断,那么任何的interrupt source产生的interrupt event都不会被传递到CPU interface。另外一个级别是对针对各个interrupt source进行控制(GIC_DIST_ENABLE_CLEAR),disable某一个interrupt source会导致该interrupt event不会分发到CPU interface,但不影响其他interrupt source产生interrupt event的分发。
(2)控制将当前优先级最高的中断事件分发到一个或者一组CPU interface。当一个中断事件分发到多个CPU interface的时候,GIC的内部逻辑应该保证只assert 一个CPU。
(3)优先级控制。
(4)interrupt属性设定。例如是level-sensitive还是edge-triggered
(5)interrupt group的设定
Distributor可以管理若干个interrupt source,这些interrupt source用ID来标识,我们称之interrupt ID。

Redistributor详述
对于每个连接的PE,都有一个Redistributor.
该block的主要功能包括:
(1)启用和禁用SGI和PPI。
(2)设置SGI和PPI的优先级。
(3)将每个PPI设置为电平触发或边缘触发。
(4)将每个SGI和PPI分配给中断组。
(5)控制SGI和PPI的状态。
(6)内存中数据结构的基址控制,支持LPI的相关中断属性和挂起状态。
(7)电源管理支持。

CPU interface详述
CPU interface这个block主要用于和process进行接口。
该block的主要功能包括:
(a)enable或者disable CPU interface向连接的CPU assert中断事件。对于ARM,CPU interface block和CPU之间的中断信号线是nIRQCPU和nFIQCPU。如果disable了中断,那么即便是Distributor分发了一个中断事件到CPU interface,但是也不会assert指定的nIRQ或者nFIQ通知processor。
(b)ackowledging中断。processor会向CPU interface block应答中断(应答当前优先级最高的那个中断),中断一旦被应答,Distributor就会把该中断的状态从pending状态修改成active或者pending and active(这是和该interrupt source的信号有关,例如如果是电平中断并且保持了该asserted电平,那么就是pending and active)。processor ack了中断之后,CPU interface就会deassert nIRQCPU和nFIQCPU信号线。
(c)中断处理完毕的通知。当interrupt handler处理完了一个中断的时候,会向写CPU interface的寄存器从而通知GIC CPU已经处理完该中断。做这个动作一方面是通知Distributor将中断状态修改为deactive,另外一方面,CPU interface会priority drop,从而允许其他的pending的interrupt向CPU提交。
(d)设定priority mask。通过priority mask,可以mask掉一些优先级比较低的中断,这些中断不会通知到CPU。
(e)设定preemption的策略
(f)在多个中断事件同时到来的时候,选择一个优先级最高的通知processor

3. 中断路由

gicv3使用hierarchy来标识一个具体的core, 如下图是一个4层的结构(aarch64)

<affinity level 3>.<affinity level 2>.<affinity level 1>.<affinity level 0> 组成一个PE的路由。
每一个core的affnity值可以通过MPDIR_EL1寄存器获取, 每一个affinity占用8bit.
配置对应core的MPIDR值,可以将中断路由到该core上。

各个affinity的定义是根据SOC自己的定义
比如可能affinity3代表socketid,affinity2 代表clusterid, affnity1代表coreid, affnity0代表thread id.

以gic 设置中断路由为例:
中断亲和性的设置的通用函数为irq_set_affinity, 具体调用如下:

+-> irq_set_affinity()...+-> irq_do_set_affinity()+-> chip->set_affnity()+->gic_set_affinity()
static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,bool force)
{/* If interrupt was enabled, disable it first */enabled = gic_peek_irq(d, GICD_ISENABLER);  -------- (1)if (enabled)gic_mask_irq(d);reg = gic_dist_base(d) + GICD_IROUTER + (gic_irq(d) * 8);val = gic_mpidr_to_affinity(cpu_logical_map(cpu));            --------- (2)gic_write_irouter(val, reg);                 ------ (3)irq_data_update_effective_affinity(d, cpumask_of(cpu));return IRQ_SET_MASK_OK_DONE;
}

gic_set_affinity先判断当前中断是否使能,如果使能则disable掉该中断;

然后根据gic_mpidr_to_affinity函数获取需要绑定中断到对应core的路由,

static u64 gic_mpidr_to_affinity(unsigned long mpidr)
{u64 aff;aff = ((u64)MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8  |MPIDR_AFFINITY_LEVEL(mpidr, 0));return aff;
}

aff 就是通过对应core的MPIDR_EL1寄存器获取affinity0~3的值,并组成一个新的32bit value;

最后将获取的value写进gic irouter寄存器并更新中断的亲和性配置。

4. 中断处理流程


从上图可以看出,中断处理可以分成两类:
(1)中断要通过distributor的中断流程
–>外设发起中断,发送给distributor
–>distributor将该中断,分发给合适的re-distributor
–>re-distributor将中断信息,发送给cpu interface。
–>cpu interface产生合适的中断异常给处理器
–>处理器接收该异常,并且软件处理该中断

它的中断状态机如下图所示

有四种中断状态:

中断状态 描述
Inactive 中断即没有Pending也没有Active
Pending 由于外设硬件产生了中断事件(或者软件触发)该中断事件已经通过硬件信号通知到GIC,等待GIC分配的那个CPU进行处理
Active CPU已经应答(acknowledge)了该interrupt请求,并且正在处理中
Active and Pending 当一个中断源处于Active状态的时候,同一中断源又触发了中断,进入pending状态

processor ack了一个中断后,该中断会被设定为active。当处理完成后,仍然要通知GIC,中断已经处理完毕了。这时候,如果没有pending的中断,GIC就会将该interrupt设定为inactive状态。操作GIC中的End of Interrupt Register可以完成end of interrupt事件通知。

(2)中断不通过distributor,比如LPI中断
外设发起中断,发送给ITS
–>ITS分析中断,决定将来发送的re-distributor
–>ITS将中断发送给合适的re-distributor

4. LPI

LPI是基于消息的中断。中断信息不在通过中断线进行传递,而是通过memory。
gic内部提供一个寄存器,当外设往这个地址写入数据时,就往gic发送了一个中断。
在soc系统中,外设想要发送中断给gic,是需要一根中断线的。如果现在一个外设,需要增加一个中断,那么就要增加一根中断线,然后连接到gic。这样就需要修改设计。而引入了LPI之后,当外设需要增加中断,只需要使用LPI方式,传输中断即可,不需要修改soc设计。

传统的GIC流程:

在传统的GIC流程中如上图,外围设备的中断触发线是引出到GIC上的,这样可以理解为一个物理的SIGNAL,比如一个高电平信号,边沿触发信号。

消息中断流程:

使用消息将中断从外设转发到中断控制器,无需每个中断源提供专用信号。 这样的一个好处是,可以减少中断线的个数。

在GICv3中,SPI可以是基于消息的中断,但LPI始终是基于消息的中断。

5.ITS

引入了LPI之后,gicv3中,还加入了ITS组件,interrupt translation service。ITS将接收到的LPI中断,进行解析,然后发送到对应的redistributor,再由redistributor将中断信息,发送给cpu interface。

外设,通过写GITS_TRANSLATER寄存器,发起LPI中断。写操作,给ITS提供2个信息:
EventID: 值保存在GITS_TRANSLATER寄存器中,表示外设发送中断的事件类型
DeviceID: 表示哪一个外设发起LPI中断。该值的传递,是实现自定义,例如,可以使用AXI的user信号来传递。
ITS将DeviceID和eventID,通过一系列查表,得到LPI中断号,再使用LPI中断号查表,得到该中断的目标cpu。

ITS将LPI中断号,LPI中断对应的目标cpu,发送给对应的redistributor。redistributor再将该中断信息,发送给CPU。

6.参考资料

GICv3_Software_Overview_Official_Release_B

ARM GICv3中断控制器相关推荐

  1. ARM通用中断控制器GIC之中断控制

    在阅读本章之前,可以参考笔者之前关于GIC的一些描述: ARM通用中断控制器GIC(generic Interrupt Controller)简介 ARM架构Generic Interrupt Con ...

  2. ARM通用中断控制器GIC之中断处理简介

    在阅读本章之前,可以参考笔者之前关于GIC的一些描述: ARM通用中断控制器GIC(generic Interrupt Controller)简介 ARM架构Generic Interrupt Con ...

  3. ARM GIC中断控制器介绍

    1 GIC : Generic Interrupt Controller Distributor–detecting, disabling, prioritizing, directing inter ...

  4. ARM通用中断控制器GIC(generic Interrupt Controller)简介

    参考文档: Documentation – Arm Developer  ARM Generic Interrupt Controller Architecture Specification 目录 ...

  5. Linux 中断 —— ARM GIC 中断控制器

    GIC(Generic Interrupt Controller)是ARM公司提供的一个通用的中断控制器,其architecture specification目前有四个版本,V1-V4(V2最多支持 ...

  6. ARM通用中断控制器GIC之中断处理状态机 Interrupt handling state machine

    中断有四种状态:inactive,pending,active 和active and pending.而产生中断的方式有两种,一种是通过写pending寄存器,让中断进入pending状态,可以忽略 ...

  7. ARM GICv3 ITS介绍及代码分析

    前言: 在ARM gicv3中断控制器,有提到过ITS的作用,本篇就ITS进行更详细的介绍以及分析linux 内核中ITS代码的实现. 本文基于linux 4.19,介绍DT方式初始化的ITS代码. ...

  8. ARM GICv3 GIC代码分析

    前言 在前一篇博文(ARM GICv3中断控制器)中, 介绍了GIC的一些基本概念,本文主要分析了linux kernel中GIC v3中断控制器的代码(drivers/irqchip/irq-gic ...

  9. linux中断子系统 - 中断控制器的注册

    文章系列 linux中断子系统 - 中断及执行流程 linux中断子系统 - 申请中断 linux中断子系统 - irq_desc的创建 linux中断子系统 - 中断控制器的注册 1. 前言 中断控 ...

最新文章

  1. 昵称到拼音php,php 汉字转换拼音程序_PHP教程
  2. 什么是PRD、MRD与BRD?
  3. 服务发现系统之consul入门
  4. 房价越高的地方资产越高?北京户均资产890万?
  5. TOP命令及参数解析
  6. Zabbix监控nginx status
  7. keras笔记-模型保存以及tensorboard的使用
  8. 中国联通5G-NR 900MHz基站设备技术白皮书(2022)
  9. 一周新闻纵览:谷歌浏览器信息泄露,出卖个人信息获利终落网,严查App偷窥乱象
  10. vue 下载文件的两种方法
  11. 一些嵌入式开发有用的github上的开源代码库
  12. 怎么恢复电脑的无线网服务器,电脑搜不到无线网络怎么恢复|电脑搜不到无线网络的恢复方法...
  13. 苹果开发者账号续费相关问题
  14. 声反馈系统:陷波型啸叫抑制器的啸叫检测方法大总结
  15. php导出word 模板,Laravel+phpword导出word
  16. 【Hadoop的初级理解】
  17. 【Photoshop CS5永久序列号】一次输入永久使用
  18. 税务会计实务【13】
  19. 黑名单电话自动拦截【Android】
  20. MySQL 无密码登录

热门文章

  1. 双向可控硅漏电流 ?- 解决方法
  2. 求根计算机在线,在线一元方程求解计算工具-一元函数自动求解在线计算器
  3. leaflet基本使用
  4. 菜鸟笔记-DuReader阅读理解基线模型代码阅读笔记(八)—— 模型训练-训练
  5. PE系统是什么?怎么进入PE重装电脑系统
  6. 一图了解群、交换群、环、交换环、整环、域的区别与联系
  7. 性能测试结果分析结果
  8. 加班的程序员:996 没有未来
  9. 【Matlab】MATLAB矩阵处理
  10. 微信小程序学习(实战)