1、GIC的电源管理功能
从gic3开始,cpu interface放到了PE中,因此cpu interface和PE是同一个power domain。
而属于gic的其他组件,如redistributor,distributor,是另外一个power domain。
因此就有如下一种情况,PE和cpu interface的电源给断掉了,而gic的电源并没有断掉。此时gic给cpu interface发送数据,cpu interface是不会响应的。
在这种情况下,gic提供了power管理功能。
一、GICR_WAKER寄存器
gic中,提供了如下的 GICR_WAKER 寄存器,来支持power功能。
其寄存器描述如下:
二、断电cpu interface和PE
在cpu interface和PE要断电之前,软件要保证,通知redistributor,cpu interface和PE要进入low-power状态。
软件,要往GICR_WAKER寄存器的ProcessorSleep字段,写入1,表示PE要进入到low-power状态。cpu interface之后将自己置为low-power状态之后,就将ChildrenAseep字段,设置为1。
当GICR_WAKER.ChildrenAsleep为1之后,redistributor,不会在将中断,发送给cpu interface,distributor在中断仲裁时,也不会考虑该PE。
三、唤醒cpu interface和PE
当gic要唤醒cpu interface和PE时,也是操作这个 GICR_WAKER寄存器。
将processorsleep,写入0,然后去唤醒该cpu,最后读取childrenasleep,判断PE是否唤醒成功,
2、gicv3的中断分组
GICv3架构中,对中断进行了分组。分成了以下三个组:
- group0,用于EL3处理的中断
- secure group1:用于secure EL1处理的中断
- non-secure group1:用于non-secure的EL2和non-secure的EL1。
对于redistributor的set命令,带有Mod和Grp参数。
Mod与Grp共同表示,中断所属的组。其组合如下图所示:
对于每一组中断,有一个系统寄存器,来控制该组中断是否有效。
- ICC_IGRPEN0_EL1:针对group0的中断
- ICC_IGRPEN1_EL1:针对group1的中断,该寄存器分为non-secure和secure访问,不同的secure下,是访问当前(状态)secure下的寄存器
而每个中断的分组,由以下两个寄存器来决定:
- GICR_IGROUPR: interrupt group registers
- GICR_IGRPMODR:interrupt group modifier registers
每个中断,占寄存器中的1个bit,使用中断号进行索引。
当gic给cpu interface通过set命令发送中断,cpu能够响应该组中断,会回发activate命令,认可该中断。
如果cpu不能响应该组中断,会回发release响应。如下图所示:
gic给cpu interface通过set命令发送中断,中断号为93,优先级为0x40,Mod和Grp均为1,表示non-secure的group1。
cpu interface不能响应该中断,回发release响应。
3、GICv3软中断
软中断(software generated interrupts),用来多个核之间的通信(inter-processor communication)。软件通过写SGI寄存器来产生。(我觉得我的bug就是出现在这里的)
- 软件写ICC_SGI1R_EL1产生对应当前secure状态的group1软中断
- 软件写ICC_ASGI1R_EL1产生secure状态的group1软中断
- 软件写ICC_SGI0R_EL1产生secure状态的group0软中断 这三个寄存器的位域是一样的,如下图:
- Aff3.Aff2.Aff1:表示软中断目的CPU的属性层次。
- TargetList:表示要发给哪些CPU。
- INTID:表示软中断号
- IRM:软中断发送,是按照属性层次发送,还是发起其他所有的cpu
- RS:range selector,和TargetList结合,表示发送哪些CPU
例如,IRM为0,INTID为1,Aff3.Aff2.Aff1为0.0.0,TargetList为0xf,RS为0,就表示,软中断发送给属性层次为0.0.0.[0-3]的cpu。 GICv3对软中断的中断号,进行了规定,只能是0-15。(0xf和0结合了个寂寞)
一、cpu interface SGI命令
软件写SGI寄存器后,cpu interface会通过gic stream接口,发送SGI命令。
- SGT:表示写的哪一个SGI寄存器 0b00: ICC_SGI0R_EL1 0b01: ICC_SGI1R_EL1 0b10: ICC_ASGI1R_EL1 0b11: Reserved
- NS: 当前的secure状态,0表示secure,1表示non-secure
- IRM: SGI寄存器的IRM bit
- A3V: aff3是否有效,如果有效,需要发送A3数据。
- RSV: range selector域是否有效
- SGInum: 软中断中断号
- A3,A2,A1: 对应Aff3.Aff2.Aff1
- TargetList: 对应SGI寄存器中的TargetList
- Range Selecto: 对应SGI寄存器中的RS域
比如,往ICC_SGI0R_EL1寄存器写0xffffef_ffffffff,那么cpu interface会发送如下波形:
二、A3V
GICv3中,使用属性层次对CPU进行编号,属性层次最多有4层,最高层为Aff3,这一层可以通过cpu interface系统寄存器来控制,是否使能。
ICC_CTLR_EL3和ICC_CTLR_EL1的A3V表示cpu interface是否支持Aff3,而GICD_TYPER.A3V表示gic ip是否支持Aff3。
三、关于range selector的理解。
gicv3的spec对range selector的解释如下:
gic3中,使用属性层次,来对CPU进行标识,这样可以精确的将中断发送指定的cpu。属性层次最高有4层,为aff3.aff2.aff1.aff0。每一个属性层次,用8bit来表示。如下图所示:
SGI中断,是可以同时发送给多个cpu的中断,通过TargetList来表示要发送给哪一些CPU。
而TargetList只有16个bit,也就是只能发送给16个cpu,但是Aff0最多可以表示256个cpu,那怎么发送给其他的cpu的了?
这个时候range selector就派上用场了,RS域共4个bit,可以表示16个范围,16×16=256,刚好表示256个cpu。所以spec里面,说TargetList[n]表示的aff0的值为RS*16 + n。 比如要给65-68号CPU发送软中断,首先判断这些cpu属于的range,为5,那么给这些CPU发送软中断,RS为5,TargetList为0x1E。
四、GIC的SGI认可响应
当GIC收到cpu interface发的SGI命令,需要回SGI认可响应。