- locality- specific peripheral interrupt(LPI):LPI是一个有针对性的外设中断,通过affinity路由到特定的PE。
- 为非安全group1中断
- 边沿触发
- 可以通过its进行路由
- 没有active状态,所以不需要明确的停用操作
- LPI总是message-based interrupt
- private peripheral interrupt(PPI):PPI是针对单个特定PE的外设中断,不同的PE可以使用同一个中断号来表示不同的事件
- 可以是任意group中断
- 支持电平触发或边沿触发
- 不使用ITS进行路由
- 有active状态,所以需要明确的停用操作
- 通常情况下,PPI被每个PE上的同一个中断源的不同实例所使用,从而允许一个共同的中断号被用于特定的事件,例如来自私有定时器的中断。
- shared peripheral interrupt(SPI):SPI时一种物理中断,它可以通过distributor路由到特定的PE进行除了,或路由到PE集群中某一个配置为可以接收这种中断类型的PE上。
- 可以是任意group中断
- 支持电平触发或边沿触发
- 从不使用ITS进行路由
- 有active状态,所以需要明确的停用操作
- 可以是message- based的中断
- software generated interrupt(SGI):SGI通常用于处理器间通信。通过向gic中的一个寄存器写入产生
- 可以是任意group中断
- 边沿触发
- 从不使用ITS进行路由
- 有active状态,所以需要明确的停用操作
边沿触发:在检测到一个中断信号的上升沿时被断言,然后无论该信号的状态如何都会保持断言,直到该中断被软件确认。
电平触发:只要中断信号的电平处于活动状态,它就会被断言。只要电平不活动,就会解除断言。
中断的路由与分发
INTIDs
中断会通过中断ID进行区分,中断ID需要遵循以下规则:
- 对于gicd与gicr中支持的中断ID位数有着如下限制:
- 如果不支持LPI,gicd中的INTID位数被限制在10位(2^10=1024),与早期的gic版本相同
- 如果支持LPI,INTID位数范围为14-24(8192~),具体在GICD_TYPER寄存器中定义
- 对于ITS中支持的INTID位数:
- 如果支持LPI,INTID位数范围为14-24,具体在GICS_TYPER寄存器中定义。
- ITS必须设置INTID位数,以便被转发到gicr中的中断是在它所支持的中断范围内,否则该行为是不可预测的。
- 对于CPU interface中支持的INTID位数:
- 在GIC V3中CPU interface支持16bits和24bits两种INTID字段。支持的中断ID位数由ICC_CTLR_EL1的ID位以及ICC_CTLR_EL3的ID位表示
有效的INTID位数由gicd和CPU interface中定义的大小来共同决定。将大于支持的位数大小的INTID转发给CPU interface是一个编程错误。未使用的INTID位数是RAZ(read as zero)。
Affinity Routing
亲和路由是一种基于分层地址的方式,用于识别特定的PE节点进行中断路由。
对于一个PE,亲和路由在aarch64状态下由MPIDR_EL1寄存器中定义,在aarch32状态下由MPIDR寄存器定义。亲和路由是一个32位的值,是由4个8位的亲和路由字段组成。
- 亲和路由级数:gic v3在aarch64状态下,支持4级或3级亲和路由。而在aarch32下只支持3级亲和路由。ICC_CTLR_EL3.A3V,ICC_CTLR_EL1.A3V,和GICD_TYPER.AV3表示是实现4级还是3级亲和路由。
- 亲和路由的使能:安全状态的亲和路由是在gicd中通过配置affinity routing enable位(ARE)来启用的。对于安全中断,GICD_CTLR.ARE_S 位被设置为1。对于非安全中断GICD_CTLR.ARE_NS位被设置为1。
中断处理与优先级
中断生命周期
GIC中断处理需要基于GIC中断的生命周期。这是一系列适用于任何GIC框架的高级过程。它为描述中断处理过程的详细步骤提供了基础。GIC还维护了一个状态机,在生命周期内控制中断状态的转换。
- generate interrupt:中断是由外设或者软件产生的。
- distribute:IRI执行中断分组、中断优先级并且控制终端向CPU interface的转发。
- deliver:CPU接口将中断传送到相应的PE。
- activate:当PE中的软件确认了一个信号,gic将最高的活动优先级设置给被激活的中断。对于SPI、SGI和PPI中断状态变为activate。
- priority drop:软件向gic发出信号,表示最高优先级的中断已经被处理到了可以放弃运行优先级的程度。然后运行优先级的值恢复到中断被确认前的值。这就是中断处理程序所指示的中断结束点。中断结束点也可以被配置成为中断的deactivation。
- deactivation:清除中断的活动状态,从而允许中断在pending状态下可以再次被使用。deactivation对于LPI来说是不需要的。deactivation可以被配置为在priority drop时同时发生,也可以在它之后发生。
CPU interface
CPU接口接收由gic IRI确认优先级的待处理中断,并且确认该中断是否为CPU接口中启用的中断分组,并且有足够的优先级向PE发出信号。接口连接的PE可以在任何时刻通过读取ICC_HPPIR0_EL1 or ICC_HPPIR1_EL1寄存器的值来确定pending状态下优先级最高的中断的INTID,以及通过读取ICC_RPR_EL1寄存器的值来确定CPU接口的运行优先级(running priority:对于没有发生过优先级下降的active中断的优先级称为运行优先级)。
当LPI被确认时,在gicr中,中断的pending状态变为not pending。gicr不会为LPI维持active
中断处理状态机
- A1、A2 : add pending state。这可能是外设产生中断的结果,也可能是软件产生中断的结果
- B1、B2 : remove pending state。如果中断是一个电平触发的中断,那么当中断被外设转置时或软件改变了等待状态时,就会发生这种转换。对于LPI,这种转换发生在对中断的确认时
- C :pending to active。如果中断是边沿触发的SPI、SGI和PPI,当PE确认了这个中断时,会发生这种转换。
- D:pending to active and pending。如果中断是电平触发的SPI、SGI和PPI,当PE确认了这个中断时,会发生这种转换。
- E1、E2:remove active state。当软件deactivate一个SPI、SGI或PPI中断时发生。
中断分组
ARM架构提供了两种安全状态(安全、非安全),每一个状态都关联独立的物理地址空间。GIC V3架构支持路由和处理两种安全状态相关的中断。GIC V3使用中断分组作为一种机制,使中断处理与ARM V8的异常模型和安全模型相匹配。
- group 0 的中断:ARM会在EL3处理这个中断
- 安全group 1的中断:ARM会在安全状态EL1处理这个中断
- 非安全的group 1的中断:在使用虚拟化的系统中,ARM会在非安全的EL2处理这个中断;在不使用虚拟化的系统中,ARM会在非安全的EL1处理这个中断。
在多处理器系统中,某个PE可能只支持安全状态下可用资源的访问或非安全状态下访问资源。如果:
- group 0 或者安全的group 1中断被转发到只支持非安全的PE上
- 非安全的group 1中断被转发到只支持安全的PE上
会被视为一个编程错误。
当一个group 0 的物理中断在所有的pending中断中有着最高的优先级,并且自身优先级足够时,通常被表示为FIQ。
当一个group 1 的物理中断在所有的pending中断中有着最高的优先级、自身优先级足够且满足以下条件中的某一个时,表示为FIQ,否则为IRQ
- 这个中断时其他安全状态的中断,即与当前PE执行的安全状态不同
- 该PE在EL3执行
中断优先级
中断优先级描述了:
- 中断优先权的配置和控制
- 待定中断的执行顺序
- 确定中断对目标PE的可见时间,包括中断优先级屏蔽、优先级分组、活动中断抢占。
在GIC优先级方案中,优先级数值越小,优先级越高。
GIC对中断优先级进行了分组。讲优先级值分成两个字段,即group priority组优先级 和 subpriority子优先级。抢占时,具有相同组优先级的中断被认为具有相同的优先级,不关注子优先级值为多少。当多个待处理中断具有相同的组优先级时,GIC会使用子优先级来决定优先处理哪一个pending状态的中断。当子优先级也相同时,GIC对于pending中断的选择是由具体实现来决定的。
GIC使用组优先级来决定一个pending状态的中断是否拥有足够的优先级(sufficient priority)来抢占正在PE执行的中断。
- pending中断的组优先级数值必须低于PE的运行优先级
- 中断的优先级值必须低于其优先级掩码的值
ICC_BPR0_EL1:表明了group 0中断组优先级和子优先级的位数
ICC_BPR1_EL1:表明了group 1中断组优先级和子优先级的位数
中断的抢占
定义:CPU interface支持在active中断完成前向目标PE发出优先级更高的待处理中断信号。
一个待处理中断只有在以下两种情况都满足时才会被CPU interface发给PE:
- 其优先级高于该CPU interface的屏蔽优先级(由ICC_PMR_EL1寄存器定义。该寄存器的复位值为0,会屏蔽所有的中断,GIC不向相关的PE发出信号。GIC在比较pending中断的优先级和优先级阈值时不使用组优先级)
- 它的组优先级高于该CPU interface上的运行优先级
抢占发生在PE接收新的中断时,并开始处理新的中断,而不是处理先前的active中断或者当前运行的程序。当这种情况发生时,最初的active中断被称为已经被抢占了。进程状态PSTATE中的DAIF位决定了PE是否通过采取中断来响应中断信号。
GIC多芯片操作
在多芯片系统中,主要影响的是SPI的行为。在多芯片系统中,每个chip上都要集成一个GIC。GIC对于多芯片系统最多支持16个chip。对于多芯片系统,PPI不需要任何特定的考虑。因为它们是被限制在单个chip上,并且通过对应chip上的相关GICR寄存器进行编程的。SGI在多芯片和单芯片配置中的表现也是一样的,它的路由寻址都是通过MPIDR进行的。
为了控制所有芯片配置的一致性,GIC使用了一组寄存器,它们定义了chip之间的连接。这些寄存器被称为路由表,由三种类型的寄存器组成:
- 芯片寄存器GICD_CHIPR
- 默认芯片寄存器GICD_DCHIPR
- 芯片状态寄存器GICD_CHIPSR
GICD_CHIPR定义了路由表。它规定了芯片所拥有的spi,以及芯片的访问方式。这个寄存器存在于多芯片配置中的每一个芯片上,因此每个芯片都有一个路由表的副本。
GICD_DCHIPR定义了当前负责路由表一致性的芯片。并且表明在什么时候进行路由表的更新。在多芯片配置中的每个芯片上都有该寄存器的一个副本
GICD_CHIPSR定义了当前芯片的状态细节。在多芯片配置中的每个芯片上都有该寄存器的一个副本。
复位时,在多芯片配置中的每个芯片实际上是一个独立的全功能GIC。为了使多芯片配置连贯,所有配置中的芯片都必须互相连接。并且一个芯片必须得拥有路由表。当配置中的多芯片连接起来之后,每32个spi被分为一个集合,每个芯片可以拥有若干个spi的集合,也就是芯片之间的SPI空间是分段的。按照路由表,不属于任何芯片的spi不能被使用。芯片上的SPI线只能用于属于自己的SPI。但是message-base SPI支持对任何芯片拥有的spi的访问。