The GICv3 architecture supports the ARM TrustZone technology. Each INTID must be assigned a group and security setting.
每一个中断都需要配置安全态和分组。
中断安全态及中断分组gicv3 为了兼容 armv8 引入了支持2种安全状态(secure state),根据 secure 状态,分为安全中断和非安全中断。也可以配置成只支持一种安全状态。显而易见,下图中前两组是安全中断,NSG1 是非安全中断。
中断安全态由 GICD_CTLR 寄存器的 DS bit,表示是否支持2种安全模式。该位为0表示支持2种安全态,为1表示只支持一种安全态,此时只有两个中断分组,分别是 group0 & 1,需要注意的是 DS 位被 置1 后只有处理器复位才能清除该标志。开启两个安全态时会在中断 configure, ack, priority drop, deactivation 中进行安全态检查。
When GICD_CTLR.DS == 0, LPIs are always Non-secure Group 1 interrupts.When GICD_CTLR.DS == 1, LPIs are always Group 1 interrupts.When GICD_CTLR.DS == 0• The GIC supports two Security states, Secure state and Non-secure state.• The GIC supports three interrupt groups:— Group 0.— Secure Group 1.— Non-secure Group 1.这个时候 Group 0 中断始终是安全态的,非安全态下无法访问 Group 0 相关的寄存器。When GICD_CTLR.DS == 1:• The GIC supports only a single Security state. This can be either Secure state or Non-secure state.• The GIC supports two interrupt groups:— Group 0.— Group 1.不同安全态下访问该寄存器的视图是不一样的:
当系统支持多个中断安全态时从 安全态 访问该寄存器:
当系统支持多个中断安全态时从 非安全态 访问该寄存器:
当系统支持1个中断安全态时从 安全或者非安全态 访问该寄存器:
gicv3 将 cpu interface 从gic中抽离,放入到了cpu中,cpu interface 通过 gic stream 接口与gic IRI 进行通信。当gic要发送中断时gic 通过 gic stream 接口给 cpu interface 发送中断命令,cpu interface 收到中断命令后,根据中断线映射配置,决定是通过 IRQ 还是 FIQ 管脚向 cpu 发送中断。中断线映射根据中断 group 以及当前 cpu 所处的 el 以及 seucre 状态来决定。
Group 0 interrupts are always signaled as FIQs. Group 1 interrupts are signaled as either IRQs or FIQs depending on the current Security state and Exception level of the PE.
可以看到 group0 的中断均为 fiq, el3 时触发的中断均为 fiq,另外可以发现 cpu 在某个安全态下运行,发生了非本安全态的中断都是 fiq。这是因为通常我们会把 fiq 路由到 el3 去处理,此时 el3 的组件会完成两个安全态上下文的切换,把中断分发给相应的安全或非安全 OS 处理。fiq 路由到 el3,可由 SCR_EL3.FIQ==1 完成。
GICv3 编程模型Interrupt Controller 中的 Distributor, Redistributor, CPU Interface 需要按照不同顺序配置。Distributor 是所有CPU都对应的,这个只要在第一个CPU启动时配置就可以了,对于 Redistributor 和 CPU Interface 是 PER-CPU 对应的,所以在SECONDARY CPU 启动时候需要配置各自的组件。
部分寄存器是内存映射的 (memory-mapped),有些是直接系统寄存器访问 (system register access)。
部分寄存器在支持 legacy 操作时采用内存映射,在 GICv3 模式下使用系统寄存器访问。
CPU interface 支持采用系统寄存器访问的方式。
In GICv3 the CPU Interface registers are accessed as System registers (ICC_*_ELn). Software must enable the System register interface before using these registers. This is controlled by the SRE bit in the ICC_SRE_ELn registers, where “n” specifies the Exception level (EL1-EL3).
使能亲和性路由和各个 group 中断。GICD_CTLR
Enable Affinity routing (ARE bits)Enables group interrupt Individual PE settings redistributor 设置唤醒即可。GICR_WAKER
Clear GICR_WAKER .ProcessorSleep to 0Poll GICR_WAKER .ChildrenAsleep until it reads 0 cpu interface 配置使能系统寄存器访问,设置中断屏蔽优先级,抢占配置,设置中断 EOI 模式,使能对应的中断。
Enable System register access ICC_SRE_ELnSet priority mask and binary point registers ICC_PMR_EL1 and ICC_BPRn_EL1The Priority Mask sets the minimum priority an interrupt must have in order to be forwarded to the PE. The Binary Point register is used for priority grouping and preemption.Set EOI mode ICC_CTLR_EL1 and ICC_CTLR_EL3Enable signaling of each interrupt group
The signalling of each interrupt group must be enabled before interrupts of that group will be forwarded by the CPU interface to the PE. To enable signaling software must write to ICC_IGRPEN1_EL1 register for Group 1 interrupts and ICC_IGRPEN0_EL1 registers for Group 0 interrupts. ICC_IGRPEN1_EL1 is banked by Security state. This means that ICC_GRPEN1_EL1 controls Group 1 for the current Security state. At EL3, software can access both Secure Group 1 interrupt enables and Non-secure Group 1 interrupt enables using ICC_IGRPEN1_EL3. 处理器设置
为了让处理器能够处理中断,处理器自身也要做相应的配置。
Routing controls。SCR_EL3 and HCR_EL2,分别可以配置中断到 EL3 还是 EL2 处理。路由选择决定了中断被哪个 el 所处理,即采用哪个异常级的中断向量表。Interrupt masks。除了 GIC 会进行中断屏蔽外,处理器本身 PSTATE 的 DAIF 也可以进行屏蔽。Vector table。VBAR_ELn
以上三者除了 PSTATE 复位会有值外其他寄存器都是 UNKNOWN,因此必须初始化。
SPI PPI SGI configuration前面把基本的环境都配置好了,对于每个中断而言,还有各自的属性需要配置。
SPI 使用 GICD_*,PPI 和 SGI 使用 GICR_*。这里属性就是中断优先级、中断分组、触发类型、使能,对于 SPI 还有目标PE。
从上面的配置过程看,关闭或者不响应某个中断可以从各个层面去控制。
在 distributor 处可以关闭某个 group 的中断,注意这里是全局关某个 group,GICD_CTLR。
在 cpu interface 处也可以关闭该 interface 某个 group 的中断,ICC_IGRPEN0_EL1 & ICC_IGRPEN1_EL1 or ICC_IGRPEN1_EL3。
对于每个中断,同样有单独的使能寄存器。(GICD_ISENABLERn, GICD_ICENABLER, GICR_ISENABLER0, GICR_ICENABLER0)。
当然 PE 层面也可以实现屏蔽,这是全局屏蔽。DAIF。