LPIs
locality- specific peripheral interrupt(lpi)是一种基于消息的边沿触发的中断。在具体的架构实现中,它可以使用interrupt translation service(its)将自身路由到特定的gicr以及连接的核上。gicv3提供了两种支持lpi的方式
- 通过its将来自外设的事件id转化为lpi的中断id
- 通过gicr_setlpir寄存器将lpi的中断id直接发给gicr
在具体的架构实现中,如果包含了lpi功能,则最少需要支持8192个lpi中断。由于lpi中断数量较多,所以并不能像sgi、ppi、spi一样将配置信息与pending信息保存在寄存器中。lpi的配置信息与pending状态信息都是保存在内存中,而它们的基地址则是保存在gicr中。
当架构中有安全与非安全两种模式时,lpi总是非安全group1类型的中断。如果架构只支持一种安全模式,则lpi总是group1类型的中断。
由于整个架构中只有唯一的全局物理lpi空间,所以lpi可以在所有的gicr上路由。
LPI Configuration tables
lpi的配置是全局的。gic是否支持gicr指向不同的lpi配置表的副本,是具体实现中来决定的。为了避免系统产生不可预测的行为,软件保证所有lpi配置表的副本都是一致的。
lpi配置表的每一个表项,代表了一个lpi的配置信息。配置表的基地址要求4KB对齐。在改变某一个lpi的配置,即修改了lpi配置表内容后,需要执行INV和INVALL指令。如果架构中不包含ITS,则需要软件去写gicr_invallr寄存器或者gicr_invlpir寄存器。
在lpi配置表中,每一个表项有8bits。具体分配如下
lpi优先级的低2位永远为0。enable位为1时表示该lpi被启用。
gicr可以cache存储来自lpi配置表中信息。它遵循以下规则:
- cache数量和大小都是由架构实现时具体决定的,至少有一个cache
- 一个lpi配置表项可能在任何时刻分配到cache中
- 一个cached表项不一定保留在cache中
- 对lpi配置表的更改在使用作废指令之前不一定可见
LPI Pending tables
软件通过gicr_pendbaser寄存器来配置LPIpending表。该寄存器提供了lpi pending表的基地址信息。
每一个gicr都会在单独的lpi pending表中维护自己拥有的表项。
如果表中所有数据全为0,包括表前1KB地址空间,则表明当前没有lpi处于pending状态。表开头1KB地址空间的作用是由架构实现具体决定的。但是需要保证在初始化时,该地址空间内全为0,并且对gicr都为可见的,否则会产生不可预测的影响。
当gicr_ctlr的lpi使能位被打开时,对lpi pending表的写操作会造成不可预测的后果。
在虚拟的lpi中也有对应的虚拟lpi pending表。与上述的物理lpi pending表有相同的概念,区别在于虚拟lpi pending表的基地址由对应的gicr_vpendbaser寄存器提供。
ITS
its将来自外设(由deviceID进行区分)的event ID进行转换:
- 该event ID对应的中断ID
- 该中断ID的目标gicr
在gicv3架构中,its将外设的事件转化为对应的lpi中断。lpi可以通过its转发到目标gicr上,或者可以通过gicr_setlpir寄存器直接在gicr上产生一个lpi。具体的实现中只能支持这两种方法中的一个。
在gicv4架构中,its还支持直接注入虚拟lpi中断
its对于sgi、ppi、spi都是无效的。
its的转换流程如下所示:
- 根据device ID在外设表(device table)中选择对应的表项(device table entry DTE)。该表项描述了要使用哪一个中断转换表(interrupt translation table ITT)
- 根据event ID在上述确定的ITT中找到对应的表项(interrupt translation entry ITE)。该表项描述了对应的中断ID以及interrupt collection number(ICID)
- 根据ICID在collection table(CT)中选择对应的表项。该表项描述了目标的gicr
这些表是通过its命令来创建并维护的。架构规定不能直接访问这些表的地址,并且这些表必须通过its命令进行配置。
ITS Table
为了让软件给its私有的表提供地址空间,gic提供了一组寄存器用于配置以下信息:
- 需要的its私有表的数量
- 每个表的表项大小
- 每个表的类型
所有的its表都处于非安全的物理地址空间
its表的状态与配置信息都存放在一组内存中的表内。这段地址空间需要在使能its之前由软件对其进行分配。gits_baser寄存器指明了its表的基地址与大小。its表拥有两种结构:
- 一级表:一段连续的地址空间被分配作为its表
- 二级表:level1表项为64位长。第63位为valid位用于控制该表项是否指向level2表。62到52位为保留位,为0。第51到第N位代表level2表的基地址,N由page size决定(gits_baser.page_size)。第N到0位为保留位,为0。
下图展示了its表是如何执行转换操作的
Interrupt collections
在gic v3架构中,its认为产生的所有物理lpi都是集合的成员。与集合相关的数据可以保存在ITS中,也可以保存在外部存储器中,或者同时保存在两者中。
The Device table
设备表的每一个表项DTE描述了一个设备ID和一个ITT基地址之间的映射关系。its使用itt来存储指定设备ID的每个event ID的转换。设备ID是分配给每个设备的唯一标识符,可以创建一系列的event ID
The Interrupt translation table
中断转换表itt是特定于每个可创建被编号事件的设备。itt中每一个表项被称为ite
The collection table
集合表提供了一个中断集合项CTE的表格。对于物理lpi来说,每一个cte描述了itt产生的icid与目标gicr之间的映射关系。
Command interface
its是由存储在内存中的命令队列来控制的。它是一个循环buffer,由以下三个寄存器定义
- gits_cbaser:该寄存器定义了命令队列的基地址和他的大小。命令队列必须是64KB对齐,并且大小必须是4KB的倍数。命令队列的每一个条目是32bytes。该寄存器还定义了命令队列的cacheability以及shareability属性
- gits_creadr:这个寄存器指向its将要执行的下一条命令
- gits_cwriter:这个寄存器指向下一条写入命令的队列条目