概述
LPI全称是Locality-specific Peripheral Interrupts(LPIs),GICv3有两种方式支持LPIs:
1)使用ITS把从设备发送的EventID转换成LPI INTID
2)直接转发LPI INTID到Redistributors(GICR_SETLPIR)
如果一个实现支持LPIs,则默认至少需要支持8192个LPIs,因此每一个LPI的配置和pending信息都是以table的形式保存在memory中(不是寄存器中),这些tables的基地址保存在Redistributors的寄存器中。(Arm建议在Redistributors中缓存部分tables来减少latency和memory traffic的目的)
下面两幅图分别是有ITS和没有ITS时实现LPIs的示意图:
LPI space
GICv>3中有一个全局的物理LPI space,可以被各个Redistributors共享。软件可以通过GICR_PROPBASER寄存器来设置这个全局的物理LPI space:
要注意的是物理LPI space的大小受限于GICD_TYPER.IDbits。
对于一个给定的Redistributor,如果支持物理LPIs,则LPI的配置和状态信息保存在memory的两个table中:
- LPI Configuration tables
- LPI Pending tables
其中LPI的优先级和enable位域在LPI的配置表中控制,LPI配置表的地址保存在GICR_PROPBASER寄存器中。(注意在GICR_CTLR.EnableLPIs == 1时,更新GICR_PROPBASER会导致异常)GICR_PROPBASER.IDBits用于设置ID空间,因此LPI配置表和LPI pending table的项目数也就确定了。
LPI的pending信息则保存在LPI pending table中,每个redistributor都有一个独立的pending table。LPI pending table的地址保存在GICR_PENDBASER寄存器中。
如果GICR_CTLR.EnableLPIs == 0,会在Redistributor接口上disable LPI,LPI也不会再变为pending,这点和SGI、PPI、SPI是有区别的。
GICv4中引入了虚拟LPI的配置和pending表,基地址分别保存在GICR_VPROPBASER和GICR_VPENDBASER寄存器中。虚拟LPI的enable则是由GICR_VPENDBASER.Valid来控制。
LPI配置表
GIC支持不同的Redistributors指向不同的LPI Configuration Table,GICR_TYPER.CommonLPIAff表示哪些Redistributor的GICR_PROPBASER需要有相同的值,也就是指向相同的LPI Configuration Table。
为了避免不可以预测的结果,软件必须在下面的情况下保证所有LPI Configuration table都是相同的:
- 任何一个Redistributor的GICR_CTLR.EnableLPIs从0设置为1
- 如果支持的是direct LPI,GICR_CTLR.EnableLPIs == 1的情况下,写入任何Redistributor的GICR_INVLPIR和GICR_INVALLR寄存器
- 如果支持ITS,ITS执行INV和INVALL命令
LPI Configuration Table保存的是LPI的配置信息,包括:
- GICR_PROPBASER指定的4KB对齐的物理地址,这个地址是LPI Configuration Table的基地址
- 对于LPI N对应的table entry的地址是(base_address + (N-8192))
软件写入LPI Configuration Table以后,需要触发INV或INVALL命令(有ITS)或者写入寄存器GICR_INVALLR或GICR_INVLPIR(无ITS)来保证配置生效。
LPI配置项
LPI配置表是由若干个8bits的条目组成的,每一个LPI对应一个8bits的条目:
Caching
Redistributor可以caching LPI Configuration Table,但是需要遵循下面的规则:
- 可以有一个或者多个cache,cache的结构和大小由具体实现确定
- 一个LPI Configuration table条目可以在任何时间allocate到cache中
- 缓存的LPI Configuration Table条目不保证一直保留在cache中
- 缓存的LPI Configuration Table条目不保证和memory中的内容是一致的
- LPI配置修改后,只有在执行invalidation操作后才能保证可见性
如果没有Redistributor的GICR_CTLR.EnableLPIs == 1,则GIC没有cached LPI Configuration Table条目。
LPI Pending Tables
软件使用GICR_PENDBASER寄存器控制LPI pending tables,这个寄存器存储了物理LPIs的LPI pending table的基地址。
每一个Redistributor维护的LPI Pending table是互相独立的,每一个LPI都有一个bit表示pending状态,0表示没有pending,1表示pending。
如果LPI Pending table的内容全是0的话(包括开始的1KB),就表示没有pending的LPIs。
LPI Pending table的最前面的1KB的内容是由实现决定的,并且这1KB的内容必须在初始化时保证都为0,否则会导致不可预测的结果。
在正常运行过程中,Redistributor负责维护LPI pending table,如果GICR_CTLR.EnableLPIs==1时,软件操作LPI pending table,结果是未知的。如果GICR_CTLR.EnableLPIs==0,在GICR_CTLR.RWP ==0之前写入LPI Pending table,也会导致不可预测的结果。
当GICR_CTLR.EnableLPIs变为1时,Redistributor必须要从LPI pending table中读取物理LPI的pending状态。如果GICR_PENDBASER.PTZ == 1,软件需要保证LPI Pending Table只包含0值,包括开始的1KB。在这种情况下硬件不需要再读取LPI pending table。
如果GICR_CTLR.EnableLPIs清0后,并且GICR_CTLR.RWP为0后,GIC不会再读写LPI Pending Table,所有caching的LPI Pending Table都会invalidated。但是清除GICR_CTLR.EnableLPIs不一定会导致LPI Pending Table更新到memory中。
对于虚拟LPI,当GICR_CTLR.EnableLPIs == 1 && GICR_VPENDBASER.Valid == 1,则Redistributor必须要从LPI Pending Table读取虚拟LPI的pending状态。
Virtual LPI Configuration tables and virtual LPI Pending tables
GICv4使用和物理LPIs类似的机制管理虚拟LPIs。
直接转发LPI INTID
如果系统没有实现ITS,则必须要包含下面几个寄存器:
- GICR_INVLPIR
- GICR_INVALLR
- GICR_SYNCR
- GICR_SETLPIR
- GICR_CLRLPIR