首页 > 其他分享 >GIC V3中断

GIC V3中断

时间:2024-10-13 16:33:10浏览次数:1  
标签:GICD 中断 Register V3 GIC Interrupt CPU

GIC(Generic Interrupt Controller)是ARM公司提供的一个通用的中断控制器,其architecture specification目前有四个版本,V1~V4(V2最多支持8个ARM core,V3/V4支持更多的ARM core,主要用于ARM64服务器系统结构)。目前在ARM官方网站只能下载到Version 2的GIC architecture specification,因此,本文主要描述符合V2规范的GIC硬件及其驱动。

具体GIC硬件的实现形态有两种,一种是在ARM vensor研发自己的SOC的时候,会向ARM公司购买GIC的IP,这些IP包括的型号有:PL390,GIC-400,GIC-500。其中GIC-500最多支持128个 cpu core,它要求ARM core必须是ARMV8指令集的(例如Cortex-A57),符合GIC architecture specification version 3。另外一种形态是ARM vensor直接购买ARM公司的Cortex A9或者A15的IP,Cortex A9或者A15中会包括了GIC的实现,当然,这些实现也是符合GIC V2的规格。

1. ARM中断控制器

1.1 ARM支持中断类型ARM GIC-v2支持三种类型的中断:

SGI:软件触发中断(Software Generated Interrupt),通常用于多核间通讯,最多支持16个SGI中断,硬件中断号从ID0~ID15。SGI通常在Linux内核中被用作 IPI 中断(inter-processor interrupts),并会送达到系统指定的CPU上。

PPI:私有外设中断(Private Peripheral Interrupt),是每个CPU私有的中断。最多支持16个PPI中断,硬件中断号从ID16~ID31。PPI通常会送达到指定的CPU上,应用场景有CPU本地时钟。

SPI:公用外设中断(Shared Peripheral Interrupt),最多可以支持988个外设中断,硬件中断号从ID32~ID1019。

1.2 GIC检测中断流程

GIC主要由两部分组成,分别是仲裁单元(Distributor)和CPU接口(Interface)模块

从图中可以看出, GIC 可以清晰的划分成两个部分:仲裁( Distributor )和 CPU 接口(CPU Interface)。CPU interface有两种,一种就是和普通processor接口,另外一种是和虚拟机接口的。Virtual CPU interface在本文中不会详细描述。分发器其实应该叫汇聚器,在 IC 的后端设计中, layout 会把各个模块引过来的中断线(就是上面说的三种中断)混接到 GIC 上,然后把混聚合的中断接到 CPU 的 IRQ 和 FIQ 线上,这样 CPU 就有触觉了

其中 Distribute 只有一套,故基地址也只有一个,而 Interface 有多套,因为每个 CPU 都对应一套 interface 。

其中各个子中断使能,设置触发方式,优先级排序,分发到哪个 CPU 上这些功能由 Distribute 负责,总的中断的使能,状态的维护由 Interface 负责。

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。

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的中断,那么CPU interface就会deassert nIRQCPU和nFIQCPU信号线。如果在这个过程中又产生了新的中断,那么Distributor就会把该中断的状态从pending状态修改成pending and active。这时候,CPU interface仍然会保持nIRQ或者nFIQ信号的asserted状态,也就是向processor signal下一个中断。

(c)中断处理完毕的通知。当interrupt handler处理完了一个中断的时候,会向写CPU interface的寄存器从而通知GIC CPU已经处理完该中断。做这个动作一方面是通知Distributor将中断状态修改为deactive,另外一方面,可以允许其他的pending的interrupt向CPU interface提交。

(d)设定priority mask。通过priority mask,可以mask掉一些优先级比较低的中断,这些中断不会通知到CPU。

(e)设定preemption的策略

(f)在多个中断事件同时到来的时候,选择一个优先级最高的通知processor

GIC仲裁单元:为每一个中断维护一个状态机,分别是:inactive、pending、active and pending、active。

下面是来自IHI0048B GIC-V2规格书3.2.4 Interrupt handling state machine截图:

GIC检测中断流程如下:

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

(2) 对处于pending状态的中断,仲裁单元回确定目标CPU,将中断请求发送到这个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感知到软件读取了该寄存器后,又分为如下情况:

* 如果该中断源是pending状态,那么转改将变成active。(*C*)

* 如果该中断又重新产生,那么pending状态变成active and pending。(*D*)

* 如果该中断是active状态,现在变成active and pending。(*A2*)

(6) 当处理器完成中断服务,必须发送一个完成信号EOI(End Of Interrupt)给GIC控制器。软件写GICC_EOIR寄存器,状态变成inactive。(*E1*)

补充:

(7) 对于level triggered类型中断来说,当触发电平消失,状态从active and pending变成active。(*B2*)

常用路径是A1->D->B2->E1。

1.2.1 GIC中断抢占

GIC中断控制器支持中断优先级抢占,一个高优先级中断可以抢占一个低优先级且处于active状态的中断,即GIC仲裁单元会记录和比较当前优先级最高的pending状态,然后去抢占当前中断,并且发送这个最高优先级的中断请求给CPU,CPU应答了高优先级中断,暂停低优先级中断服务,进而去处理高优先级中断。

GIC会将pending状态优先级最高的中断请求发送给CPU。

1.2.2 Linux对中断抢占处理

从GIC角度看,GIC会发送高优先级中断请求给CPU。

但是目前CPU处于关中断状态,需要等低优先级中断处理完毕,直到发送EOI给GIC。

然后CPU才会响应pending状态中优先级最高的中断进行处理。

所以Linux下:

  1. 高优先级中断无法抢占正在执行的低优先级中断。

2.同处于pending状态的中断,优先响应高优先级中断进行处理。

1.3 GIC中断时序

img

首先给出前提条件:

  • N和M用来标识两个外设中断,N的优先级大于M
  • 两个中断都是SPI类型,level trigger,active-high
  • 两个中断被配置为去同一个CPU
  • 都被配置成 group 0,通过FIQ触发中断

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

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

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

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

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

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

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

  •   T61时刻:CPU(Linux中断服务例程)读取GICC_IAR寄存器,即软件响应了中断N。这时仲裁单元把中断N的状态从pending变成active and pending。
  •   T64时刻:在中断N被Linux相应3个时钟内,CPU Interface模块完成对nFIQCPU[n]信号的deasserts,即拉高nFIQCPU[n]信号。
  •   T126时刻:外设也deassert了该中断N。
  •   T128时刻:仲裁单元移出了中断N的pending状态。
  •   T131时刻:Linux服务程序把中断N的硬件ID号写入GICC_EOIR寄存器来完成中断N的全部处理过程。

(8) T146时刻:在向GICC_EOIR寄存器写入中断N中断号后的tph个时钟后,仲裁单元会选择下一个最高优先级中断,即中断M,发送中断请求给CPU Interface模块。CPU Interface会拉低nFIQCPU[n]信号来向CPU报告外设M的中断请求。

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

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

1.4 GIC中 寄存器描述

1.4.1 Distributor

img

一种实现是:

偏移 名称 可读写 复位后 作用
0x000 GICD_CTLR RW 0x00000000[c] Distributor Control Register写入1使能控制器,必备
0x004 GICD_TYPER RO Configuration-dependent[d] Interrupt Controller Type Register其中可以查看中断线的总数
0x008 GICD_IIDR RO 0x0200143B Distributor Implementer Identification Register, GICD_IIDR存了一些版本信息
0x080-0x0BC GICD_IGROUPRn RW 0x00000000 Interrupt Group Registers[e]一个位图,控制中断属于A组还是B组
0x100 GICD_ISENABLERn RW[f] SGIs and PPIs:0x0000FFFF Interrupt Set-Enable Registers一个位图,用于使能各个中断,写入1使能。有用
0x104-0x13C SPIs: 0x00000000
0x180 GICD_ICENABLERn RW[f] 0x0000FFFF Interrupt Clear-Enable Registers和上一个寄存器类似,作用相反,写入1禁止。
0x184-0x1BC 0x00000000
0x200-0x23C GICD_ISPENDRn RW 0x00000000 Interrupt Set-Pending Registerspend位图,写入1可以进入pend状态
0x280-0x2BC GICD_ICPENDRn RW 0x00000000 Interrupt Clear-Pending Registers同上,写入1效果相反,阻止pend状态
0x300-0x33C GICD_ISACTIVERn RW 0x00000000 Interrupt Set-Active Registers位图,写入1可以激活中断
0x380-0x3BC GICD_ICACTIVERn RW 0x00000000 Interrupt Clear-Active Registers写入1反激活中断
0x400-0x5FC GICD_IPRIORITYRn RW 0x00000000 Interrupt Priority Registers存着各个中断的优先级,每8位算一个
0x800-0x81C GICD_ITARGETSRn RO[h] - Interrupt Processor Targets Registers[i]某个中断应该发往哪个处理器进行处理
0x820-0x9FC RW 0x00000000
0xC00 GICD_ICFGRn RO SGIs: 0xAAAAAAAA Interrupt Configuration Registers, GICD_ICFGRn配置中断是低电平触发还是下降沿触发
0xC04 RO PPIs: 0x55540000
0xC08-0xC7C RW[j] SPIs: 0x55555555
0xD00 GICD_PPISR RO 0x00000000 Private Peripheral Interrupt Status Register, GICD_PPISR一般没用
0xD04-0xD3C GICD_SPISRn RO 0x00000000 Shared Peripheral Interrupt Status Registers, GICD_SPISRn没用
0xF00 GICD_SGIR WO - Software Generated Interrupt Register控制软中断
0xF10-0xF1C GICD_CPENDSGIRn RW 0x00000000 SGI Clear-Pending Registers软中断的pend位
0xF20-0xF2C GICD_SPENDSGIRn RW 0x00000000 SGI Set-Pending Registers同上,不过写入1时停止pend
0xFD0 GICD_PIDR4 RO 0x00000004 Peripheral ID 4 Register
0xFD4 GICD_PIDR5 RO 0x00000000 Peripheral ID 5 Register
0xFD8 GICD_PIDR6 RO 0x00000000 Peripheral ID 6 Register
0xFDC GICD_PIDR7 RO 0x00000000 Peripheral ID 7 Register
0xFE0 GICD_PIDR0 RO 0x00000090 Peripheral ID 0 Register
0xFE4 GICD_PIDR1 RO 0x000000B4 Peripheral ID 1 Register
0xFE8 GICD_PIDR2 RO 0x0000002B Peripheral ID 2 Register
0xFEC GICD_PIDR3 RO 0x00000000 Peripheral ID 3 Register
0xFF0 GICD_CIDR0 RO 0x0000000D Component ID 0 Register
0xFF4 GICD_CIDR1 RO 0x000000F0 Component ID 1 Register
0xFF8 GICD_CIDR2 RO 0x00000005 Component ID 2 Register
0xFFC GICD_CIDR3 RO 0x000000B1 Component ID 3 Register

1.4.2 CPU Interface

Offset Name Type Reset Description[a]
0x0000 GICC_CTLR RW 0x00000000 CPU Interface Control Register 使能位。写入1使能
0x0004 GICC_PMR RW 0x00000000 Interrupt Priority Mask Register限制中断最低优先级,高于此值无法中断,最好写大一点
0x0008 GICC_BPR RW 0x00000002 Binary Point RegisterThe minimum value of the Binary Point Register depends on which security-banked copy is considered:0x2Secure copy0x3Non-secure copy优先级分组
0x000C GICC_IAR RO 0x000003FF Interrupt Acknowledge Register只读,中断id
0x0010 GICC_EOIR WO - End of Interrupt Register写入以告知cpu已经处理完中断
0x0014 GICC_RPR RO 0x000000FF Running Priority Register当前中断优先级
0x0018 GICC_HPPIR RO 0x000003FF Highest Priority Pending Interrupt Register最高优先级中断号及其pend值
0x001C GICC_ABPR RW 0x00000003 Aliased Binary Point RegisterThe minimum value of the Aliased Binary Point Register is 0x3.别名寄存器
0x0020 GICC_AIAR RO 0x000003FF Aliased Interrupt Acknowledge Register别名寄存器
0x0024 GICC_AEOIR WO - Aliased End of Interrupt Register别名寄存器
0x0028 GICC_AHPPIR RO 0x000003FF Aliased Highest Priority Pending Interrupt Register别名寄存器
0x00D0 GICC_APR0 RW 0x00000000 Active Priority Register用于保存和恢复
0x00E0 GICC_NSAPR0 RW 0x00000000 Non-Secure Active Priority Register用于保存和恢复
0x00FC GICC_IIDR RO 0x0202143B CPU Interface Identification Register, GICC_IIDR存着版本信息
0x1000 GICC_DIR WO - Deactivate Interrupt Register

参考文档:

DDI0471B_gic400_r0p1_trm.pdf

IHI 0048B, ARM Generic Interrupt Controller Architecture Specification, Ver 2.0.pdf

标签:GICD,中断,Register,V3,GIC,Interrupt,CPU
From: https://www.cnblogs.com/linhaostudy/p/18462519

相关文章

  • ARM Cortex-M3/M4内核架构:中断处理过程
    目录一、概述1.保存现场?什么是现场?现场包括什么?2.怎么处理异常?我们先来简单介绍下。3.又怎么恢复现场?4.异常进入流程(核心流程)二、保存现场三、恢复现场1、EXC_RETURN2、恢复现场四、异常处理优化1、末尾连锁2、延时到达3、出栈抢占五、总结一、概述中断......
  • .Net微信服务商平台ApiV3接口
    转载:https://www.cnblogs.com/xilen/p/15380183.html开始在开始之前建议仔细读微信官方文档,接口规则及api文档https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay-1.shtmlhttps://pay.weixin.qq.com/wiki/doc/apiv3_partner/index.shtml目录整个流程开......
  • 002、v3admin学习,设置npm的端口和ip
    1、使用命令行npmrundev启动v3admin的时候,会有多个ip地址以及端口 2、在vite.config.ts中,修改host为false和port为1314 3、ctrl+c结束端口,并运行npmrundev来启动。可以看到只有一个http://localhost:1314/端口启动了。 4、浏览器打开,可以正常显示。5、效果如下:......
  • 51单片机中断与定时器
    一.中断源  INT0  外部中断0    P3^2引脚低电平或者下降沿信号  INT1  外部中断1    P3^3引脚低电平或者下降沿信号  T0    定时器0中断   定时器/计数器0计数回0溢出  T1    定时器1中断   定时器/计数器1计数......
  • Linux软中断ksoftirqd
    前言在上一篇 LINUX软中断-softirq的描述中,提到过ksoftirqd,这篇文章就介绍ksoftirqdksoftirqd是什么?ksoftirqd是个内核线程,在创建的时候是绑定cpu的,每一个core对应生成一个ksoftirqd线程比如当前系统有4个core~#psaux|grepksoftirqdroot30.00.00......
  • 【无标题】STM32 的中断系统
       中断概述 在主程序运行过程中, 出现了特定事件, 使得 CPU 暂停当前正在运行的程序, 转而去 处理这个事件, 等这个事件处理完成之后, CPU 再回到刚才被打断的位置继续处理, 这就 是中断。 那个打断 CPU 执行的特定事件, 我们一般称之为中断源。 被中断源打断......
  • 5、在设备树中指定中断——在代码中获取中断
    1设备树里中断节点的语法参考文档:内核Documentation\devicetree\bindings\interrupt-controller\interrupts.txt设备树里的中断控制器中断的硬件框图如下: 在硬件上,“中断控制器”只有GIC这一个,但是我们在软件上也可以把上图中的“GPIO”称为“中断控制器”。很多芯片有多......
  • 4、Linux中断系统中的重要数据结构
    本节内容,可以从request_irq(include/linux/interrupt.h)函数一路分析得到。能弄清楚下面这个图,对Linux中断系统的掌握也基本到位了 最核心的结构体是irq_desc,之前为了易于理解,我们说在Linux内核中有一个中断数组,对于每一个硬件中断,都有一个数组项,这个数组就是irq_desc......
  • 浏览器事件处理机制:从硬件中断到事件驱动
    关键词:硬件中断,事件驱动,浏览器事件监听,操作系统抽象层,跨平台兼容性,事件冒泡与捕获摘要:本文深入探讨浏览器事件处理机制,从硬件中断到事件驱动模型,揭示了用户输入如何转化为页面响应。我们将了解操作系统的抽象层如何巧妙地连接硬件和应用程序,以及浏览器如何实现......
  • 浏览器事件处理机制:从硬件中断到事件驱动
    关键词:硬件中断,事件驱动,浏览器事件监听,操作系统抽象层,跨平台兼容性,事件冒泡与捕获摘要:本文深入探讨浏览器事件处理机制,从硬件中断到事件驱动模型,揭示了用户输入如何转化为页面响应。我们将了解操作系统的抽象层如何巧妙地连接硬件和应用程序,以及浏览器如何实现......