GIC由Distributor和CPU interface两部分组成,如果支持虚拟化扩展,还有virtual CPU interface。本文主要介绍Distributor和CPU interface的基本功能。
文章目录
- 一,中断分发器Distributor
- 二,处理器接口 CPU interface
- 三,中断ID
一,中断分发器Distributor
Distributor模块负责将中断进行优先级划分(prioritization),并且转发(distribution)到指定的CPU interface中,与Distributor相关的寄存器均以GICD_作为前缀。Distributor集中控制所有的中断源,决定每个中断的优先级,并将对于每个CPU interface,将优先级最高的中断转发到指定CPU interface。Distributor提供了编程接口用于:
- 全局性地转发中断到CPU interface
- 可以使能或禁止(Enabling or disabling)每个中断
- 为每个中断设置优先级(priority level )
- 为每个中断设置目标处理器列表(target processor list)
- 为每个外设中断(PPI和SPI)设置为电平敏感还是边缘触发
- 将中断设置为Group0还是Group1(即Secure还是Non-Secure)
- 转发SGI中断到一个或者多个目标处理器
此外,Distributor还提供: - 每个中断状态的可见性
- 在软件层面设置或清除一个外设中断的pending状态
二,处理器接口 CPU interface
每个CPU interface都为处理器提供一个与GIC相连的可编程接口:
- 可以将中断请求发送给处理器
- 确认一个中断
- 指示中断处理的完成
- 为处理器设置中断优先级掩码(中断优先级阈值,超过该阈值才会被传送给处理器)
- 为处理器定义中断抢占策略
- 为处理器决定正在pending状态的最高优先级中断。
当把CPU interface使能后,CPU interface能够把当前处于pending状态中优先级最高的中断发送给处理器,CPU interface需要考虑中断优先级掩码以及中断抢占策略,来判断中断是否有足够的优先级转发到处理器。在任何时候,与CPU interface相连的处理器能够从 GICC_HPPIR寄存器中读取到当前处于active状态的最高优先级中断。
在ARM处理器实现中,传统的中断请求会被断言为IRQ或者FIQ。
处理器通过读取GICC_IAR(Interrupt Acknowledge Register)可以获知中断请求,该寄存器将返回: - 处于pending状态的最高优先级中断ID
- 或者非正常情况下,该中断ID为虚假ID
当处理器在CPU interface中确认了中断,Distributor将会把该中断的状态由pending改为active或者active and pending。此时,CPU interface可以向处理器发送另一个中断信号,以抢占处理器上active的中断。
当 处理器中的中断处理器(interrupt handler)完成了中断的处理,它会往CPU interface相关寄存器中写入数据,提示中断处理完成,中断处理完成的过程分为两步: - 优先级下降(priority drop),这意味着被处理的中断的优先级不能再阻止向处理器发送另一个中断的信号。
- 中断失活(interrupt deactivation),意味着Distributor将会把该中断的active状态清除掉。
在GIC v1版本中,这两个过程是在处理器写入EOI(End of Interrupt)处理器的时,一起发生的。
在GIC v2版本中,GICC_CTLR寄存器中的 EOImode位定义了: - 当写入EOI寄存器时,两个阶段一起发生
- 两个阶段分开发生:
- priority drop发生在写入EOI寄存器时
- interrupt deactivation在之后发生,当处理器向CPU interface的Deactive Interrupt 寄存器写入时。
三,中断ID
中断以中断ID作为中断源的身份标识,每个CPU interface最多可见1020个中断。加上SPI和PPI的复用(banking),Distributor支持的中断将会更多。
GIC将1020个中断(ID0~ID1019)进行如下分配:
- 中断号为32至1019被SPI使用
- 中断号为0至31的中断,对CPU interface来说是私有的(private),并且这些中断在Distributor中被复用(banking)。一个复用的中断(banked interrupt)是指Distributor可以有多个相同中断ID的中断,虽然它们的中断ID相同 ,但是它们要被转发到的CPU interface却不同,即通过将中断ID和该中断要被转发到的CPU interface Number组成新的标识号码,实现Distributor中每个中断具有唯一标识码。这些被banked的中断可以被分为:
- 中断号0至15为SGI中断
- 中断号为16至31的为PPI中断
在多处理器系统中:
- 中断号为16至31的为PPI中断
- PPI中断将会被转发到一个特定的CPU interface中,并且对该CPU interface来说是私有的,在对该CPU interface中的中断进行优先级排序时,Distributor不会考虑与其他CPU interface相关的PPI
- 每个连接的处理器通过对Distributor中的GICD_SGIR寄存器进行写入指定的目标处理器列表和中断ID来产生SGI中断。在Distributor中,SGI可以通过:ID0至ID15的中断ID,目标处理器ID(0~7)以及源处理器ID(0 ~7)三者进行组合,以生成独一无二的识别号。当CPU interface使用中断ID与目标处理器进行通信时,它还会带上源处理器ID,这样目标处理器就能辨识出每个独一无二的SGI中断。SGI的复用(banking)意味着GIC可以同时处理多个SGI中断,且不会产生资源冲突。如果一个处理器没有连接上CPU interface,那么这个处理器写GICD_SGIR寄存器的操作将会被Distributor忽略。
在单处理器中,私有中断和共享中断没有区别,因为所有的中断都对该处理器可见,这种情况下,源处理器ID为0。 - 中断ID1020至1023为特殊目的而保留,比如1020为虚假中断ID。
软件可以为每个中断设置优先级,并且优先级和中断ID是相互独立的。
在任何实现了ARM安全扩展的系统中,为了支持处理器之间消息传递的一致模型,ARM强烈建议所有处理器保留: - ID0-ID7 for Non-secure interrupts
- ID8-ID15 for Secure interrupts.