这里对ITS再作简要介绍。在GICv3中,外设通过写GITS_TRANSLATER,根据所写内容解析出device_id和event_id,根据device_id找到设备所对应的Device Table,根据event id找到ITT,并最终在Collection Table中找到中断所要发送的GICR上。
其中通过ITS命令MAPD/MAPTI/MAPC建立起内存的各种表之间的关系。
ITS驱动是通过ACPI表获取ITS信息,并分配ITS所需要的Device Table/Collection Table内存并设置对应的寄存器,同时分配LPI中断所需要的LPI配置表和LPI pending表。最后为ITS分配并设置irq_domain。
ITS驱动初始化步骤如下:
其中主要是通过函数its_acpi_probe()识别并使能ITS,函数allocate_lpi_tables()分配LPI配置表和pending表。其中函数its_acpi_probe()详细如下:
它执行操作如下:
- 映射ITS寄存器,分配its_node,并设置ITS物理地址和虚拟地址
- 分配ITS命令列队,并设置命令队列的基地址
- 设置ITS的GITS_TRANSLATER地址
- 分配ITS表(Device Table)
- 分配Collection Table表,每个CPU一个表
- 设置命令队列并使能ITS
- 分配并设置irq_domain
其中ITS所对应的irq_domain = its_domain_ops设置如下所示:
(1).alloc = its_irq_domain_alloc 分配nr_irqs个中断,设置irq_chip
它分配nr_irqs个中断,并设置irq_chip为its_irq_chip,各成员函数介绍如下。
序号 | 函数名 | 描述 |
1 | .irq_mask=its_mask_irq | 屏蔽中断。对于GICv3,将LPI configure表EN位设置为0 |
2 | .irq_unmask=its_unmask_irq | 使能中断。对于GICv3,将LPI configure表EN位设置为1,并发INV |
3 | .irq_eoi=irq_chip_eoi_parent | 空 |
4 | .irq_set_affinity= its_set_affinity | 设置亲和性。通过ITS命令MOVI设置中断亲和性 |
5 | .irq_compose_msi_msg=its_irq_compose_msi_msg | 设置MSI IOVA地址 |
6 | .irq_set_irqchip_state=its_irq_set_irqchip_state | 设置或清除IRQCHIP状态。设置采用INT命令,清除采用CLEAR命令 |
(2).activate = its_irq_domain_activate 激活中断,建立起ite
对于ITS命令,在驱动中起了非常重要的作用,以下对ITS命令作简要归纳。
命令 | 命令参数 | 描述 |
CLEAR | DeviceID, EventID | 将EventID和DeviceID定义的event转化为ICID和pINTID,并发送到合适的Redistributor移除pending状态 |
DISCARD | DeviceID, EventID | 将EventID和DeviceID定义的event转化为ICID和pINTID,并发送到合适的Redistributor移除pending状态。它也保证与特定的EventID相关的Redistributor的任何缓存与内存中配置保持一致。DISCARD移除了ITT中DeviceID和EventID的映射,保证特定EventID的请求被丢弃。 |
INT | DeviceID, EventID | 将EventID和DeviceID定义的event转化为ICID和pINTID,并发送到合适的Redistributor设置pending状态 |
INV | DeviceID, EventID | 指定ITS必须保证与特定EventID相关的Redistributor的任何缓存与内存中LPI配置表保持一致 |
INVALL | ICID | 指定ITS必须保证由ICID定义的中断collection的任何缓存与所有Redistributor内存中LPI配置表保持一致 |
INVDB 仅GICv4.1 | vPEID | 仅GICv4.1。指定ITS必须保证vPEID的默认doorbell相关的任何缓存与所有Redistributor内存中LPI配置表保持一致 |
MAPC | ICID, RDbase | 将ICID定义的collection表映射到RDbase定义的Redistributor |
MAPD | DeviceID,ITT_addr,Size | 将DeviceID相关的设备表项映射到由ITT_addr和Size定义的ITT |
MAPI | DeviceID,EventID, ICID | 将EventID和DeviceID定义的event映射到ICID和pINTID=EventID的ITT项 |
MAPTI | DeviceID,EventID, pINTID, ICID | 将EventID和DeviceID定义的event映射到它相关的ITE,ITE由DeviceID相关的ITT中ICID和pINTID定义 |
MOVALL | RDbase1, RDbase2 | 让RDbase1指定的Redistributor上所有的中断移到RDbase2指定的Redistributor上 |
MOVI | DeviceID,EventID, ICID | 更新DeviceID和EventID定义的event的ITT表项的ICID域。它也将DeviceID和EventID定义的event转化为ICID和pINTID,并在合适的Redistributor移除pending状态,如果它被设置,将中断移到新的ICID定义的Redistributor,并使用新的ICID更新event相关的ITE |
SYNC | RDbase | 保证RDbase指定的Redistributor的物理中断相关的所有未完成ITS操作在执行任何更多ITS命令之前全局可见。跟随SYNC的执行,所有之前命令必须应用于后续写入GITS_TRANSLATE。 |
VINVALL | vPEID | 保证与vPEID相关的任何缓存的Redistributor信息与内存中相关的LPI配置表保持一致 |
VMAPI | DeviceID, EventID,Dbell_pINTID, vPEID | 将由DeviceID和EventID定义的event映射到ITT表项,该表项vPEID, vINTID=EventID, Dbell_pINTID,一个doorbell |
VMAPP GICv4.0 | vPEID,RDbase,VPT_addr, VPT_size | 将vPEID定义的vPE表项映射到目标RDbase,包括相关的虚拟LPI pending表(VPT_addr, VPT_size) |
VMAPP GICv4.1 | vPEID,RDbase, VCONF_addr,VPT_addr, VPT_size, PTZ, Alloc, Default_Doorbell_pINTID | 映射vPEID定义的vPE,包括相关的虚拟LPI配置和pending表。可选的指定默认doorbell。 |
VMAPTI | DeviceID, EventID, vINTID, Dbell_pINTID,vPEID | 使用vPEID,vINTID,Dbell_pINTID和doorbell将DeviceID和EventID定义的event映射到ITT表项 |
VMOVI | DeviceID, EventID, vPEID | 为DeviceID和EventID定义的event更新ITT表项的vPEID域。将DeviceID和EventID定义的event转化为vPEID和pINTID,让合适的Redistributor移除pending状态,如果有设置,将中断发送到新vPEID定义的Redistributor,使用新的vPEID更新event相关的ITE |
VMOVP GICv4.0 | vPEID, RDbase, SequenceNumber, ITSList | 更新vPEID定义的vPE表项到由RDbase定义的目标Redistributor。软件必须使用SequenceNumber和ITSList在超过一个ITS的情况下同步VMOVP命令的执行 |
VMOVP GICv4.1 | vPEID, RDbase, SequenceNumber, ITSList, Default_Doorbell_pINTID | 将vPEID定义的vPE映射更新到RDbase定义的目标Redistributor |
VSGI 仅GICv4.1 | vPEID, Priority, G, C, E, vPEID | 仅GICv4.1。对于vPEID定义的vPE,设置配置或更新由vINTID定义的中断状态 |
VSYNC | vPEID | 保证在任何更多ITS命令被执行之前所有未完成的ITS操作被全局可见。VSYNC接下来的执行,所有之前的命令必须应用到后续写GITS_TRANSLATER。 |
这里对重要的ITS命令作介绍。
- MAPD命令
每个DeviceID都有自己的ITT用于保持EventID到INTID的映射。软件使用MAPD命令用于将DeviceID映射到ITT。
MAPD <DeviceID>, <ITT_Address>, <Size>
- MAPT/MAPTI命令
不同的EventID被映射到不同的INTID,INTID必须被映射到collection,而每个collection被映射到一个Redistributor。软件使用MAPT/MAPTI命令将INTID映射到一个collection。
当EventID=INTID时,使用MAPT如下:
MAPT <DeviceID>, <EventID>, <Collection ID>
当EventID!=INTID时,使用MAPTI如下:
MAPTI <DeviceID>, <EventID>, <INTID>, <Collection ID>
- MAPC命令
软件使用MAPC命令将collection映射到一个Redistributor。
MAPC <Collection ID>, <Target Redistributor>
其中对于Target Redistributor的识别,依赖于GITS_TYPER.PTA。当GITS_TYPER.PTA=0时,Redistributor可以通过处理器ID识别;当GITS_TYPER.PTA=1时,Redistributor可以通过物理地址识别。
- MOVI命令
软件使用MOVI命令将DeviceID和EventID表示的中断重新映射到一个CollectionID。
MOVI <DeviceID>, <EventID>, <CollectionID>
- CLEAR命令
软件使用CLEAR命令清除DeviceID和EventID表示的中断的pending状态。
CLEAR <DeviceID>, <EventID>
- INT命令
软件使用INT命令设置DeviceID和EventID表示的中断的pending状态。
INT <DeviceID>, <EventID>
- MOVALL命令
软件使用MOVALL命令将RDbase1表示的Redistributor上所有中断移到RDbase2表示的Redistributor上。
MOVALL <RDbase1>, <RDbase2>
- INV命令
软件使用INV命令保证DeviceID和EventID表示的中断所对应的LPI配置表项与Redistributor中的缓冲保持一致。
INV <DeviceID>, <EventID>
- INVALL命令
软件使用INVALL命令保证CollectionID所对应的LPI配置表项与Redistributor中缓冲保持一致。
INVALL <CollectionID>
- SYNC命令
软件使用SYNC命令保证Redistributor上未完成的物理中断对应的ITS操作完成。
SYNC <RDbase>