gic_architecture_specification解读一

1 中断类型

GIC 中断类型有3种:SGI(Software-generated interrupt)、PPI(Private peripheral interrupt )、SPI(Shared peripheral interrupt)。

SGI: SGI为软件可以触发的中断,统一编号为0~15,用于各个core之间的通信。

PPI: PPI为每个 core 的私有外设中断,统一编号为 16-31 。例如每个 CPU 的 local timer 即 Arch Timer 产生的中断就是通过 PPI 发送给 CPU 的(安全为29,非安全为30)。

SPI: SPI 是系统的外设产生的中断,为各个 core 公用的中断,统一编号为 32~1019 ,如 global timer 、uart 、gpio 产生的中断。

2 中断状态

在这里插入图片描述

下这些状态是用于GIC的distrabutour和cpu interface以及连接的processor之间。
Inactive : 一个中断不是active或者pending状态。
Pending: 硬件出发一个到GIC的中断或者由software产生的一个中断,并且等待目标processor服务。
Active: 发给GIC的中断已经被processor ack,并且正在被服务并且还没结束。
Active and pending : processor正在服务一个中断,并且GIC正在pending同样中断源的中断。

3 状态转换

图1

3.1 Transition A1 or A2, add pending state

增加pending状态,A1: Inactive----->Pending A2: Active----->Active and pending
2
对于SGI,发生下面条件之一:

  1. 软件写 GICD_SGIR寄存器: 指定processor作为目的。
  2. 在processor侧的软件写 GICD_SPENDSGIRn位,这个位对应着需要的源processor和interrupt ID。

3
对于SPI,发生下面条件之一:
3. 外围设备产生一个中断请求信号
4. 软件写一个 GICD_ISPENDRn

3.2 Transition B1 or B2, remove pending state

删除pending状态,B1: Pending----->Inactive B2: Active and pending------->Active

在这里插入图片描述
看的不是很明白:
对于SPI或者PPI:

  1. 电平中断只有在触发了一个中断,并且电平信号已经消失才处于pending状态
  2. 只有当边沿中断触发了或者写个值到 GICD_ISPENDRn 或者软件写进GIC_ICPENDRn才处于pending状态。

3.3 Transition C,pending to active

1

中断使能了,并且有足够的优先级发送给processor,只有当软件读取 GICC_IAR寄存器时候,发生这样的状态转换

3.4 Transition D,pending to active and pending

在这里插入图片描述
对于SPI或者PPI

  1. 这个中断使能
  2. 软件读取 GICC_IAR。读取操作会添加active状态。
  3. 有下面连个操作之一
    3.1 对于电平中断,中断信号保持触发。通常就是一种情况,就是外围设备保持有效电平只到这个这个processor处理完这个中断。 (也就是在这个中断被active,中断有效电平还保持,且中断没处理完的期间就是ative and pending状态)。
    3.2 对于边沿触发,是否发生pending->pending and active转换,取决于读取 GICC_IAR和检测到这个中断重新触发的相对时序。
    如果边沿触发,这这个中断处于pending,然后读取GICC_IAR,会导致C(pending->active),然后再次检测到这个中断,会导致A2(Active–> active and pending)。
    如果边沿触发,这个中断处于pending,然后再触发同一中断,然后再读取GICC_IAR,这个导致pending->active to pending。(这个是自己理解,后续有错误在纠正)。
    这边的时序要后续,根据实际的例子再纠正。

5

4 GIC检测流程

流程:
(1) 当GIC检测到一个中断发生时,会将该中断标记为pending状态(A1)。

(2) 对处于pending状态的中断,仲裁单元回确定目标CPU。

(3) 对于每个CPU,仲裁单元会从众多pending状态的中断中选择一个优先级最高的中断,发送到目标CPU的CPU Interface模块上。

(4) CPU Interface会决定这个中断是否可以发送给CPU。如果该终端优先级满足要求,GIC会发生一个中断信号给该CPU。

(5) 当一个CPU进入中断异常后,会去读取GICC_IAR寄存器来响应该中断(一般是Linux内核的中断处理程序来读寄存器)。寄存器会返回硬件中断号(hardware interrupt ID),对于SGI中断来说是返回源CPU的ID。
当GIC感知到软件读取了该寄存器后,根据触发方式,走同流程:

电平触发方式:
1)如果该中断源是pending状态,会变成activing and pending ( D2: pending----->activing and pending)。
2)  在processor已经ack了中断,GIC中的CPU interface模块 deassert nFIQCPU信号线,解除发向该CPU的中断请求。
3)  中断服务程序操作了N外设的控制寄存器(ack外设的中断),也就是外设deassert了其interrupt request signal。
4)  Distributor解除这个中断的pending状态,因此这个interrupt source的状态设定为active  (B2 : Active and pending---->active)
5)  软件操作End of Interrupt寄存器,标识中断完成。  (E1:  ACtive-->Inactive)
边沿触发方式:
1)一个中断处于pending(GIC感知寄存器后),然后变成了Active (C : Pending-->Active)
2) 如果这个中断处于pending,然后再触发这个中断(GIC感知寄存器后),然后变成了Active and pending ( D : Pending --> Active and Pending)
3) 这这个中断处于pending,然后读取GICC_IAR,会导致C(pending->active),然后再次检测到这个中断,会导致A2(Active--> active and pending)。

电平触发的常用路径: A1->B->D2->E1
边沿触发的常用路径: A1->C->E1

5. 解析实例

8
首先给出前提条件:

(a)N和M用来标识两个外设中断,N的优先级大于M

(b)两个中断都是SPI类型,level trigger,active-high

(c)两个中断被配置为去同一个CPU

(d)都被配置成group 0,通过FIQ触发中断

处理流程:
(1) T1时刻:GIC的Distributor(总裁单元)检测到中断M的电平变化。

(2) T2时刻:Distributor(仲裁单元)设置中断M的状态为pending。

(3) T17时刻:CPU Interface模块会拉低nFIQCPU[n]信号。在中断M的状态变成pending后,大概需要15个时钟周期后会拉低nFIQCPU[n]信号来向CPU报告中断请求(assertion)。仲裁单元需要这些时间来计算哪个是pending状态下优先级最高的中断。CPU interface的ack寄存器(GICC_IAR)的内容会修改成M interrupt source对应的ID

(4) T42时刻:仲裁单元检测到另外一个优先级更高的中断N。

(5) T43时刻:仲裁单元用中断N替换中断M为当前pending状态下优先级最高的中断,并设置中断N为pending状态。

(6) T58时刻:经过tph个时钟后,CPU Interface拉低你FIOCPU[n]信号来通知CPU。因为此信号在T17时刻已经assert CPU了,因此实际的电平信号仍然保持assertede,CPU Interface模块会更新GICC_IAR寄存器的Interrupt ID域,该域的值变成中断N的硬件中断号。

(7) T61~T131时刻:Linux对中断N的服务程序--------------------------------------------------------------中断服务程序处理段,从GICC_IAR开始到GICC_EOIR结束。

T61时刻:CPU(Linux中断服务例程)读取GICC_IAR寄存器,获取了当前优先级最高的,并且状态是pending的interrupt ID(也就是N interrupt source对应的ID)。通过读该寄存器,CPU也就ack了该interrupt source N。这时候,Distributor将N这个interrupt source的状态设定为pending and active(因为是电平触发,只要外部仍然有asserted的电平信号,那么一定就是pending的,而该中断是正在被CPU处理的中断,因此状态是pending and active)
注意:T61标识CPU开始服务该中断

T64时刻:3个clock之后,由于CPU已经ack了中断,因此GIC中CPU interface模块 deassert nFIQCPU信号线,解除发向该CPU的中断请求
  
  T126时刻:由于中断服务程序操作了N外设的控制寄存器(ack外设的中断),因此N外设deassert了其interrupt request signal。
  
  T128时刻:Distributor解除N外设的pending状态,因此N这个interrupt source的状态设定为active 。

T131时刻: 软件操作End of Interrupt寄存器(向GICC_EOIR寄存器写入N对应的interrupt ID),标识中断处理结束。Distributor将N这个interrupt source的状态修改为idle
注意:T61~T131是CPU服务N外设中断的的时间区域,这个期间,如果有高优先级的中断pending,会发生中断的抢占(硬件意义的),这时候CPU interface会向CPU assert 新的中断

(8) T146时刻:大约15个clock之后,Distributor向CPU interface报告当前pending且优先级最高的interrupt source,也就是M了。漫长的pending之后,M终于迎来了春天。CPU interface拉低nFIQCPU信号线,向CPU报告M外设的中断请求。这时候,CPU interface的ack寄存器(GICC_IAR)的内容会修改成M interrupt source对应的ID

(9) T211时刻:Linux中断服务程序读取GICC_IAR寄存器来响应中断,仲裁单元设置中断M的状态为active and pending。

(10) T214时刻:在CPU响应中断后的3个时钟内,CPU Interface模块拉高nFIOCPU[n]信号来完成deassert动作。

参考

Linux中断管理1

linux kernel的中断子系统之(七):GIC代码分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值