GIC入门(二):寄存器组成,配置和中断处理
1.寄存器组成
GIC寄存器分为以下三组:
GIC_Distributor
GIC_Redistributor
CPU Interface
GIC_D & GIC_R两组寄存器用于配置中断,CPU Interface用于处理中断。
GICD_*:
distributor寄存器是memory-mapped,即占用地址空间,寄存器功能主要有:
为SPI中断设置优先级级别,路由SPI将其分配至不同的distributor,使能/关闭SPI,设置电平触发或沿触发,生成消息信号,控制SPI信号的active和pending状态,配置安全模型
GICR_*:
每个Core有一组对应的redistributor寄存器,也是memory-mapped,占有地址空间,这组寄存器的主要功能有:
使能/关闭PPI和SGI中断,设置SGI,PPI中断优先级,设置PPI的触发方式,给SGI,PPI分组,控制SGI,PPI的中断状态,控制内存中支持相关中断属性和LPI的挂起状态的数据结构的基本地址,为所连接的PE提供电源管理支持
CPU Interface(ICC_*_ELn):
每个core都有一组对应的CPU interface寄存器,这组寄存器是系统寄存器,主要功能有:
提供启动中断处理的通用配置,确认中断,执行优先级下降和中断终止,设置当前core的中断优先级mask,定义当前core的抢占策略,确定当前core的pending中断中的最高优先级
注:使用CPU Interface组寄存器之前需要写ICC_SRE_ELn.SRE使能。
2.配置GIC
本节内容介绍运行在多core的bare-metal环境下如何配置SPI,PPI和SGI,不涉及LPI的配置
配置GICD_CTRL.ARE = 1,设置GIC版本为V3
配置GICD_CTRL.EnableGrp1S = 1,使能Secure group1的中断分发,GICD_CTRL.EnableGrp1NS = 1,使能Non-Secure group1的中断分发,GICD_CTRL.EnableGrp0 = 1,使能group0的中断分发
以下配置需对每一组GICR操作:
配置GICR_WAKER.ProcessorSleep = 0,清除PE的offline状态。轮询GICR_WAKER.ChildrenAsleep直至值为0
如果PE offline状态下有需要其处理的中断,此中断会引起一个对PE的唤醒请求,之后电源管理系统会响应请求打开PE。
以下配置需对每一组ICC_*_ELn操作:
配置ICC_SRE_ELn.SRE = 1使能对应的ICC组寄存器
配置ICC_PMR_EL1设置被当前PE处理所需要的最小优先级
配置ICC_BPRn_EL1设置优先级分组和抢占
配置ICC_CTRL_EL1, ICC_CTRL_EL3设置如何处理中断
配置ICC_IGRPEN1_EL1,ICC_IGRPEN0_EL1,ICC_IGRPEN1_EL3使能中断组的信号
以下配置需对每个PE操作:
配置SCR_EL3和HCR_EL2,设置中断路由到哪个异常等级
配置PSTATE设置中断mask
配置VBAR_ELn指向内存中的中断向量表
如上文所说,SPI配置寄存器在GICD_*,PPI和SGI配置寄存器在GICR_*,如下图所示:
对每个单独的中断源,需要配置以下:
GICD_IPRIORITYn, GICR_IPRIORITYn配置中断优先级,优先级为8-bit值,0x0优先级最高,0xFF优先级最低;
GICD_IGROUPn, GICD_IGRPMODn, GICR_IGROUPn, GICR_IGRPMODn配置中断由哪个组接收处理,S-G0,S-G1,NS-G1
GICD_ICFGRn, GICR_ICFGRn配置中断触发方式:电平触发或沿触发
GICD_ISENABLERn, GICD_ICENABLER, GICR_ISENABLERn, GICR_ICENABLERn使能/关闭中断
Non-maskable配置中断为不可屏蔽中断,GIC V3.3之后支持此feature
GICD_IROUTERn.Interrupt_Routing_Mode配置SPI中断被传给特定PE还是所有PE
3.中断处理
3.1路由一个pending的中断到PE
PE接收中断之前需要依次检测以下内容:
检查与中断相关联的组是否启用
检查中断是否被使能
检查路由控制找到需要接收这个中断的PE
检查中断优先级,并与PE所设置的最低优先级比较,需要高于PE接收的最低优先级
检查正在运行的中断优先级,决定PE能否处理当前中断
3.2中断到达PE后的路由
当中断到达PE后,PE需要通过查看IAR寄存器得知中断来源,IAR寄存器有两种:
读取IAR寄存器获取INTID。当当前的安全状态和中断的安全状态不同时,不能在当前IAR读取到有效的INTID,此时会根据下表返回以下值:
下图示例当运行在S-EL1时触发NS-EL1中断时的调度流程:
更多时候,S-EL1不会立即调度进EL3,而是会完成当前任务后通过SMC陷入EL3再进行中断处理,如下图所示:
3.3处理不同优先级
当PE不处理中断时,中断优先级记录为最低0xFF,处理中断时,中断优先级记录为当前正在处理的中断的优先级。高优先级的中断可以打断低优先级中断的处理并抢占CPU。
3.4关闭中断
PE处理中断关闭有两个步骤:当前PE中断优先级回落,设置当前中断状态为inactive
4 SGI中断
通过写入GIC中的以下寄存器可以触发SGI中断:
寄存器位域定义如下:
其中SGI ID设置INTID,INTID0-15是预留给SGI的中断号
IRM控制路由方式,IRM=0时中断被发送到PE ...,IRM=1时中断被发送到除当前PE外所有PE
需要注意的是,三个寄存器分别生成不同安全类型的中断,但是处于S状态的PE可以发送任何状态中断,处于NS的PE能否发送SG0的中断取决于寄存器GICR_NSACR的配置。