文章目录
- 1. 缩略语
- 2. 简介
- 2.1. 中断类型
- 2.1.1 SGI软件中断
- 2.1.2 PPI私有外设中断
- 2.1.3 SPI 共享外设中断
- 2.1.4 LPI(locality-specific peripheral interrupts)
- 2.2. GIC 架构
- 2.2.1 Distributor
- 2.2.2 Redistributor
- 2.2.3 CPU Interfaces
- 2.3. 属性层次(affinity,亲和度相关)(待补充)
- 2.4. 中断状态
- 2.5. 中断分组
- 2.6. 中断生命周期
- 2.7. 中断流程
- 3. 寄存器
- 4. 参考资料
- 5. 问题记录
- 5.1.什么是屏蔽优先级?
- 5.2. 亲和度如何理解?如何应用
- 5.3. 哪个模块负责仲裁优先级?
- 5.5. 为什么GIC V3会把Interface放到Core中
- 5.6. Group与安全等级如何理解,在R52中如何理解
1. 缩略语
2. 简介
以下介绍均以ARM R52内核(GIC v3)介绍。
2.1. 中断类型
2.1.1 SGI软件中断
16个,中断号:0~15。通过向ICDSGIR寄存器写入SGI中断号、CPU ID,来产生一个软件中断;通过读ICCIAR寄存器或者向ICDICPR寄存器相应的比特位写1,可以清除中断。所有的SGI为边沿触发。通常用于处理器之间的通信,如linux内核电源管理模块中调用的ipi中断就是通过SGI实现的。
由软件触发,多用于核间通信。
2.1.2 PPI私有外设中断
16个,中断号:16~31,该类型中断是每个处理器私有的,即一个特定的中断只会被路由到特定的处理器上。且其同一个中断号在每个处理器上都可以有不同的中断,如对于一个拥有两个PE的smp系统,中断号16的PPI中断可以分别被注册为PE0和PE1的私有中断,它们可以被独立触发并被特定的PE独立处理SPI共享外设中断。
2.1.3 SPI 共享外设中断
中断号:32~1019,该类型中断不与特定的cpu绑定,可以根据affinity配置被路由到任意cpu或一组特定的cpu上。如一般的外设中断都是通过SPI方式连接的。
2.1.4 LPI(locality-specific peripheral interrupts)
LPI是一种基于消息的边沿中断。也就是,中断信息,不在通过中断线,进行传递,而是通过memory。gic内部,提供一个寄存器,当外设往这个地址,写入数据时,就往gic发送了一个中断。
在soc系统中,外设想要发送中断给gic,是需要一根中断线的。如果现在一个外设,需要增加一个中断,那么就要增加一根中断线,然后连接到gic。这样,就需要修改设计。而引入了LPI之后,当外设需要增加中断,只需要使用LPI方式,传输中断即可,不需要修改soc设计。
引入了LPI之后,GICv3中,还加入了ITS组件,interrupt translation service。ITS将接收到的LPI中断,进行解析,然后发送到对应的redistributor,再由redistributor将中断信息,发送给cpu interface。
外设通过写 GITS_TRANSLATER 寄存器,来传递消息中断。具体可见GIC架构图中Message based interrupts。
PS:GICv3支持,但是在Armv8-R未实现,即R52中未实现
2.2. GIC 架构
主要分为以下几部分,Distributor、Redistributor、CPU Interfaces三部分。
2.2.1 Distributor
- Group的使能;
- SPI的Group的配置,中断在软件层面分为FIQ和IRQ,在硬件上对应分为Group 0和Group 1,具体可以设置xxx寄存器,设置为0,选择Group0(FIQ),设置为1,选择Group 1(IRQ);
- SPI的使能、优先级、触发方式(电平还是边沿)、目标核,R52优先级支持5bit,最高32级优先级,值越小,优先级越高;优先级相同时,按自然优先级排序,ID越小优先级越高
- SPI的Pending、Active状态设置和清除。
2.2.2 Redistributor
- 电源管理,负责更新GIC模块的上下电状态,下电时,软件写ProcessorSleep=1,同时软件一直读取ChildrenAsleep,知道读到1为止。上电时,软件写ProcessorSleep=0,同时软件一直读取ChildrenAsleep,知道读到0为止。
- 配置PPI
- 配置SGI
PS:MCU进入睡眠模式后,Distributor是还在工作的,因为要依赖外部中断去唤醒CPU,而外部中断是要经过Distributor的,所以Distributor还在工作。
2.2.3 CPU Interfaces
- 提供当前Group0/1响应的中断ID(ICC_RPR 反应当前正在处理的中断优先级)
- 设置当前核的屏蔽优先级(ICC_PMR)
- 中断确认,中断执行完毕后,软件去设置标志位(ICC_IARn),告诉硬件中断执行完毕,优先级降低(不合理)
- 当前核的Group的使能
- 软中断触发(ICC_SGInR)
PS:
interfaces与Distributor的使能范围应该是不一样的,interfaces里面应该是分开关,Distributor里面应该是总开关。
针对同一个Core同时来了两个中断请求,具体的仲裁是在CPU Interfaces进行的。
2.3. 属性层次(affinity,亲和度相关)(待补充)
GICv3的一大变化,是对core的标识。对core不在使用单一数字来表示,而是使用属性层次来标识,和arm core使用MPIDR_EL1系统寄存器来标识core一致。
每个core,根据属性层次的不同,使用不同的标号来识别。如下图所示,是一个4层结构,那么对于一个core来说,就可以用xxx.xxx.xxx.xxx 来识别
但是R52只有三级,不支持Level3
2.4. 中断状态
Inactive:中断没激活也没挂起
Pending:中断产生,但是没有响应服务
Active:中断正在响应服务,但还没服务完
Active & Pending:中断在响应服务的过程中,又产生了中断请求
2.5. 中断分组
gicv3,将中断分成了2个大组,group0和group1。
group0:提供给EL3使用
group1:又分为2组,分别给安全中断和非安全中断使用
如下图所示:
以下是IRQ,FIQ与组的对应关系:
R52没有EL3
Armv8(R52)只支持安全状态,即CPU只有Secure EL0,EL1这种情况。
2.6. 中断生命周期
中断生命周期,如下图所示:
- generate:外设发起一个中断
- distribute:distributor对收到的中断源进行仲裁,然后发送给对应的cpu interface
- deliver:cpu interface将中断发送给core
- activate:core通过读取 GICC_IAR 寄存器,来对中断进行认可
- priority drop: core通过写 GICC_EOIR 寄存器,来实现优先级重置
- deactivation:core通过写 GICC_DIR 寄存器,来无效该中断
- 这个中断生命周期,和gicv2的中断生命周期是一样的。
2.7. 中断流程
下图是gic的中断流程,中断分成2类:
- 一类是中断要通过distributor,比如SPI中断
- 一类是中断不通过distributor,比如LPI中断
中断要通过distributor的中断流程
- 外设发起中断,发送给distributor
- distributor将该中断,分发给合适的re-distributor
- re-distributor将中断信息,发送给cpu interface。
- cpu interface产生合适的中断异常给处理器
- 处理器接收该异常,并且软件处理该中断
LPI中断的中断流程
- 外设发起中断,发送给ITS
- ITS分析中断,决定将来发送的re-distributor
- ITS将中断发送给合适的re-distributor
- re-distributor将中断信息,发送给cpu interface。
- cpu interface产生合适的中断异常给处理器
- 处理器接收该异常,并且软件处理该中断
3. 寄存器
分为两类,一类是放在GIC里面的外设寄存器,通过memory-mapped访问,一类是放在CPU里面的寄存器,内核直接通过汇编命令访问。
memory-mapped访问的寄存器:
- GICC: cpu interface寄存器
- GICD: distributor寄存器
- GICH: virtual interface控制寄存器,在hypervisor模式访问
- GICR: redistributor寄存器
- GICV: virtual cpu interface寄存器
- GITS: ITS寄存器
系统寄存器访问的寄存器:
- ICC: 物理 cpu interface 系统寄存器
- ICV: 虚拟 cpu interface 系统寄存器
- ICH: 虚拟 cpu interface 控制系统寄存器
4. 参考资料
GICv3:https://zhuanlan.zhihu.com/p/520133301
https://zhuanlan.zhihu.com/p/261379308
架构基础:https://zhuanlan.zhihu.com/p/261379308
GICv2:内部包含Distributor和Redistributor、Interface模块的功能,目前不确定完全与GICv3完全一样
https://zhuanlan.zhihu.com/p/527107797
5. 问题记录
5.1.什么是屏蔽优先级?
过滤优先级较小的中断,小于MASK优先级的中断不会通知到CPU。
PS:上电后,MASK为0,即屏蔽所有中断,想要响应中断,一定要初始化该参数。
5.2. 亲和度如何理解?如何应用
在R52里面全是0,目前是理解将亲和度相同的核聚集为一类。
5.3. 哪个模块负责仲裁优先级?
参考资料1:https://zhuanlan.zhihu.com/p/527107797
5.5. 为什么GIC V3会把Interface放到Core中
寄存器分为系统寄存器和外设寄存器两种,与内核相关的寄存器称为系统寄存器,Core可以直接通过汇编命令去访问,而外设寄存器是通过memory-mapped方式(一般会使用AXI总线)访问。
GICV2中,cpu interface的寄存器,是实现在GIC内部的,因此当core收到一个中断时,会通过axi总线(假设memory总线是axi总线),去访问cpu interface的寄存器。而中断在一个SOC系统中,是会频繁的产生的,这就意味着,core会频繁的去访问GIC的寄存器,这样会占用AXI总线的带宽,总而会影响中断的实时响应。而且core通过AXI总线去访问cpu interface寄存器,延迟,也比较大。
在gicv3中,将cpu interface从GIC中抽离出来,实现在core内部,而不实现在GIC中。core对cpu interface的访问,通过系统寄存器方式访问,也就是使用msr,mrs访问,那么core对cpu interface的寄存器访问,就加速了,而且还不占用AXI总线带宽。这样core对中断的处理,就加速了。
5.6. Group与安全等级如何理解,在R52中如何理解
配置为Group0后,无论当前Core的安全等级是什么,最后都是发起FIQ中断,如果配置Group1,则根据下表去对应。
①R52没有EL3(具体参考‘3.2.5.中断分组’)
②R52 Core状态只有SecureEL0,EL1