【GIC】GICv3 基本规则
本章介绍了符合GICv3架构的中断控制器的基本操作。它还描述了不同的编程接口。
一.中断类型
- SPI(Shared Peripheral Interrupt)--共享外设中断
这是一个全局外设中断,可以路由到指定的PE,或路由到一组PE中的一个。
- PPI (Private Peripheral Interrupt)--私有外设中断
这是针对单个,特定的PE的外围中断。PPI的一个例子是来自PE的通用定时器的中断。
- SGI(Software Generated Interrupt)--软件生成的中断
SGI通常用于处理器间的通信,并通过向GIC中的SGI寄存器进行写入而生成。
- LPI(Locality-specific Peripheral Interrupt)--基于特定消息的中断
LPI是GICv3中新增的,它在很多方面都不同于其他类型的中断。特别是,LPI总是基于消息的中断,它的配置保存在内存中的表中,而不是寄存器中。
注:仅当GICD_CTLR.ARE_NS==1时,才支持LPIs
1.1中断标识符
每个中断源都由一个ID号标识,称为INTID。可用的INTID被分组为一个范围,每个范围都被分配给一个特定类型的中断。
1.2 中断如何发送给中断控制器
传统上,中断是使用专用的硬件信号从外围设备到中断控制器发出信号的。
GICv3支持这种模型,另外还支持基于消息的中断。基于消息的中断是通过对中断控制器中的寄存器的写入来设置和清除的中断。
使用消息将中断从外设转发到中断控制器,消除了对每个中断源的专用信号的要求。这对于大型系统的硬件设计者来说可能是一个优势,其中数百甚至数千个信号可以通过SoC路由,并汇聚到中断控制器上。也就是说,基于消息的中断解决了硬件连线的要求。
在GICv3中,SPI可以是基于消息的中断,但LPI始终是基于消息的中断。不同的寄存器用于不同的中断类型,如表4所示。
基于消息的中断对软件的影响
无论中断是作为消息发送还是使用专用信号,对中断处理器内部处理中断的方式影响不大。可能需要一些外设的配置。例如,可能需要指定中断控制器的地址。
二、中断状态机
中断控制器为每个SPI、PPI和SGI中断源维护一个状态机。此状态机包括以下四种状态:
注意:LPI没有Active或Active and pending状态
2.1 电平触发
- Inactive to Pending
当断言 (assert)中断源时,中断将从Inactive状态转换为Pending状态。此时,GIC向PE断言中断信号(如果中断被启用且具有足够的优先级)。
- Pending to Active & Pending
当PE通过读取CPU接口中的一个IARs(Interrupt Acknowledge Registers)来响应中断时,中断从pending转换到Active & Pending状态。此读取通常是在发生中断异常后执行的中断处理例程的一部分。然而,软件也可以轮询IAR。此时,GIC取消断言中断信号。
- Active & Pending to Active
当外围设备取消中断信号断言时,中断从Active & Pending转为Active。这通常发生在PE上执行的中断处理软件写入外围设备的状态寄存器。
- Active to Inactive
当PE写入CPU接口中的一个EOIR(End of Interrupt Registers)时,中断从Active转到Inactive。这表明PE已经完成了对中断的处理。
2.2 边沿触发
- Inactive to Pending
在断言中断源时,中断从非活动过渡到挂起。此时,GIC向PE断言中断信号(如果中断被启用并且具有足够的优先级)。
- Pending to Active
当PE通过读取CPU接口中的一个IAR来响应中断时,中断从Pending转到Active。此读取通常是在发生中断异常后执行的中断处理例程的一部分。然而,软件也可以轮询IAR。此时,GIC取消对PE的中断信号。
- Active to Active and Pending
如果外围设备重新断言中断信号,中断将从Active到Active & Pending。
- Active and Pending to Pending
当PE写入CPU接口中的一个EOIR时,中断从Active and Pending变为 Pending。这表明PE已经完成了处理中断的第一个实例。此时,GIC将向PE重新断言中断信号。
三、亲和性路由
Affinity routing :大概意思就是亲和性/匹配性的相关路由吧 = =
GICv3使用亲和路由来识别已连接的PE,并将中断路由到特定的PE或PE组。PE的亲和度表示为四个8-bit字段:
<affinity level 3>.<affinity level 2>.<affinity level 1>.<affinity level 0>
下图显示了关联级别层次结构的一个示例:
在Aff level0处,有一个Redistributor。每个Redistributor都连接到一个CPU口。
Redistributor控制SGI、PPI和LPI。亲和力方案与ARMv8-A中使用的方案与MPIDR_EL1中的PE亲和力相匹配。设计必须确保MPIDR_EL1所指示的亲和值与连接到PE的Redistributor的GICR_TYPER所指示的亲和值相同。不同affinity级别的确切含义是由特定的处理器和SoC来定义的。举个例子:
. . .
. . .
所有可能的节点都不太可能存在于一个单一的实现中。例如,一个移动设备的SoC可以有一个类似于这样的布局:
0.0.0.[0:3] Cores 0 to 3 of a Cortex-A53 processor
0.0.1.[0:1] Cores 0 to 1 of a Cortex-A57 processor
在ARMv8-A中,AArch64状态支持四个级别的亲和力。AArch32状态和ARMv7只能支持三个级别的亲和力。这意味着使用AArch32状态的设计仅限于亲和级别3(0.x.y.z)上的单个节点。GICD_TYPER.A3V表示中断控制器是否能支持多个3级节点。
GICD_TYPER.A3V =0,aff3=0,即:0.x.y.z;
GICD_TYPER.A3V =1,aff3可以不为0,即:x.x.y.z;
注意:尽管每个1级节点在0级上最多可以托管256个Redistributor,但实际上它很可能是16个或更少。这是因为对SGI的目标PEs的编码方式。(Aff3好像也是取0-15。)
四、安全模型
GICv3架构支持ARM TrustZone技术。必须为每个INTID分配一个组和安全设置。GICv3支持三种组合,如下图所示:
Group 0的中断总是被标记为FIQ。
根据PE的当前安全状态和异常级别,Group 1的中断被标记为IRQ或FIQ。
这些规则旨在补充ARMv8-A安全状态和异常级别的路由控制。下图显示了一个简化的软件堆栈,以及当在EL0执行时发出不同类型的中断信号时会发生什么:
在本例中,IRQ被路由到EL1 (SCR_EL3.IRQ0)和FIQs路由到EL3 (SCR_EL3.FIQ1) 。根据上表6中描述的规则,在EL1或EL0执行时,当前安全状态的组1中断被视为IRQ。其他安全状态的中断触发FIQ,异常被带到EL3。这就允许在EL3处执行的软件来执行必要的上下文切换。
4.1 对软件的影响
在配置中断控制器时,软件控制INTID到中断组Group的分配。只有在安全状态下执行的软件才能分配INTID到中断组。通常,只有在安全状态下执行的软件才能访问安全中断(Group 0和Secure Group 1)的设置和状态。可以启用从非安全状态到安全中断设置和状态的访问。这使用GICD_NSACRn和GICR_NSACR寄存器对每个INTID进行单独控制。
注意:在重置时,INTID属于的中断组根据具体实现来定义。
注意:LPI总是被视为 Non-secure Group 1中断。
4.2 对单一安全状态的支持
在ARMv8-A和GICv3中,支持两种安全状态是可选的。实现可以选择只实现一个安全状态或两个安全状态。在支持两个安全状态的GICv3实现中,可以禁用一个安全状态。这是由GICD_CTLR.DS控制的。
GICD_CTLR.DS == 0 支持两种安全状态
GICD_CTLR.DS == 1 只支持一个安全状态。
在只实现单一安全状态的实现上,这一位是RAO/WI。
注:RAO : Read As One WI :Write Ignored
当只支持一个安全状态时,只有两个中断组,就是Group 0和Group 1。
注意:如果软件设置为GICD_CTLR.DS=1,它只能通过复位来清除。
五、编程模型
GICv3中断控制器的寄存器接口被分为三组:·
- Distributor (GICD_*)
Distributor寄存器是由 memory-mapped内存映射的,并包含影响连接到中断控制器的所有PE的全局设置。Distributor提供了一个编程接口:·
-
SPI的中断优先级和分发。·
-
使能和禁用SPI。·
-
设置每个SPI的优先级级别。
-
每个SPI的路由信息。·
-
将每个SPI设置为电平触发或边沿触发。·
-
生成基于消息的SPI。·
-
控制SPI的active和pending状态。·
-
控制在每个安全状态(亲和路由或传统模式)中使用的程序员模型。
-
Redistributors (GICR_*)
对于每个连接的PE,都有一个Redistributor。
Distributors提供了一个编程接口:
-
使能和禁用SGIs和PPIs。·
-
设置SGIs和PPIs的优先级。·
-
将每个PPI设置为电平触发或边沿触发。·
-
将每个SGI和PPI分配给一个中断组。·
-
控制SGIs和PPIs的状态。·
-
在内存中的数据结构(支持相关的中断属性和lpi的pending状态)的基地址控制。·
-
对连接的PE的电源管理支持·
-
CPU interfaces (ICC_*_ELn)
每个Redistributor连接了一个CPU接口,CPU接口提供的编程接口:
-
通用控制和配置,以启用中断处理。·
-
响应中断。·
-
执行优先级下降(priority drop)和停用(deactivation)中断。·
-
为PE设置中断优先级掩码。·
-
定义PE的抢占策略。·
-
确定PE的等待中断的最高优先级 HPPI(highest priority pending interrupt)
在GICv3中,CPU接口寄存器作为系统寄存器(ICC_*_ELn)被访问。在使用这些寄存器之前,软件必须先启用系统寄存器接口。这是由ICC_SRE_ELn寄存器中的SRE位控制的,其中“n”指定了异常级别(EL1- EL3)。
注意:在GICv1和GICv2中,CPU接口寄存器被内存映射(GICC_*)。
注意:软件可以通过读PE的ID_AA64PFR0_EL1来检查GIC系统寄存器支持。