Chapter 8: GICv4.1 虚拟中断支持
本章描述 GICv4.1 虚拟中断处理和优先级排序的基本方面:
-
关于 GICv4.1 虚拟中断支持 。
-
CPU interface 的变更 。
-
ITS 命令 。
-
vPEID 宽度 。
-
门铃 。
-
vPE 驻留和定位数据结构 。
-
基于寄存器的 vLPI 失效 。
-
vSGI 的直接注入 。
8.1 关于 GICv4.1 虚拟中断支持
GICv4.1 扩展了对 SGI 虚拟中断直接注入的支持。它通过以下变更使直接注入对软件来说更简单、更高效:
-
跟踪所有活动 vPE 的待处理和配置表的结构。
-
虚拟中断配置的基于寄存器的失效选项。
-
简化不再使用时分配给 GIC 的内存回收的修改。
GICv4.1 中传统模式支持已过时,ARE 位为 RES1。
8.2 CPU interface 的变更
GICv4.1 引入了 CPU interface 的变更。
ID_AA64PFR0_EL1.GIC==b0011 表示支持 GICv4.1。
将 vSGI 传递给 ID_AA64PFR0_EL1.GIC==b0001 的 PE 是 CONSTRAINED UNPREDICTABLE:
-
中断被忽略。
-
中断被传递。
ICH_HCR_EL2.vSGIEOICount 控制 vSGI 的停用是否增加 ICH_HCR_EL2.EOIcount。
8.3 ITS 命令
在任何 ITS 命令中指定超出实现范围的 vPEID 是 CONSTRAINED UNPREDICTABLE,有两种选择:
-
生成命令错误。
-
ITS 忽略未实现的 vPEID 位。
在大多数命令中,指定超出配置 vPEID 大小的 vPEID 会生成命令错误。
8.4 vPEID 宽度
GICv4.1 允许 vPEID 宽度在 1 到 16 位之间。GICD_TYPER2 中的 VIL 和 VID 字段一起报告实现的 vPEID 宽度。
软件在分配 Redistributor vPE 配置表和 ITS vPE 表时可以配置较小的 vPEID 宽度。
8.5 门铃
GICv4.0 支持的 门铃 机制在 GICv4.1 中被称为 个人门铃。门铃中断针对 vPE 当前映射到的 Redistributor,基于 vPE 的先前 VMAPP 或 VMOVP 命令。
8.5.1 个人门铃
GICv4.1 中对个人门铃的支持是 IMPLEMENTATION DEFINED,由 GITS_TYPER.nID 报告。连接到单个 GIC 的所有 ITS 具有相同的 GITS_TYPER.nID 值。
当 GITS_TYPER.nID==1 时,VMAPTI 和 VMAPI 中的 Dbell_pINTID 字段被视为 1023。
当来自 ITS 的 vLPI 变为待处理时,如果满足以下所有条件,则生成个人门铃中断:
-
GITS_TYPER.nID==0
-
目标 vPE 未调度。
-
ITS 为 EventID/DeviceID 组合的映射提供了个人门铃 pINTID。
虚拟 SGI 不能触发个人门铃,触发个人门铃的虚拟中断是否也触发默认门铃是 IMPLEMENTATION DEFINED。
8.5.2 默认门铃
GICv4.1 为每个 vPEID 提供新的默认门铃,作为 VMAPP 命令的一部分指定。
当 EventID 或 DeviceID 映射到虚拟中断时,可以在 VMAPI 或 VMAPTI 命令中指定门铃 INTID。如果未指定门铃,则使用 vPE 的默认门铃(如果已指定)。
当满足以下所有条件时,生成默认门铃中断:
-
单独启用的虚拟中断变为待处理,或虚拟中断在待处理时变为启用。
- GIC 是否在 vPE 上次调度时考虑来自 GICR_VPENDBASER 的组启用是 IMPLEMENTATION DEFINED。对于从未调度过的 vPE,组启用被视为 1。
-
vPE 未调度。
-
当该 vPE 上次变为非调度时,GICR_VPENDBASER.doorbell 被写为 0b1
- 创建 vPE 时,它被视为变为非调度且 GICR_VPENDBASER.doorbell 被写为 0b1。
注意 在某些情况下,GICR_VPENDBASER.doorbell 即使写为 0b1 也表现为 0b0,请参见寄存器描述。
-
ITS 为 vPEID 的映射提供了默认门铃。
-
自 vPE 上次变为非驻留以来,此 vPE 的默认门铃尚未被确认。
如果 vPE 的默认门铃待处理,但 vPE 没有单独启用和待处理的中断,则默认门铃的待处理状态是否被清除是 IMPLEMENTATION DEFINED。
如果虚拟中断被单独禁用或属于禁用的组,则不生成默认门铃中断。这与 GICv4.0 不同,在 GICv4.0 中门铃生成独立于 vLPI 的启用状态。
GICR_VPENDBASER.doorbell 允许软件向 IRI 指示是否为 vPE 生成默认门铃。它不影响个人门铃的生成。 在变为非调度和变为调度之间,vPE 的默认门铃最多设置为待处理一次。如果满足除虚拟中断到达之外的所有其他条件,vPE 的默认门铃可能会推测性地设置为待处理。这不会覆盖默认门铃在驻留之间最多仅设置为待处理一次的要求。将 vPE 设置为调度会清除其默认门铃的待处理状态。
8.6 vPE 驻留和定位数据结构
vPE 配置表存储每个 vPE LPI 配置和待处理表的位置。每个 Redistributor 上的 GICR_VPROPBASER 寄存器指向 vPE 配置表,vPEID 索引该表。通过将其 vPEID 写入 GICR_VPENDBASER 来调度 vPE,从 vPE 配置表中选择一个条目。系统可以包含多个 vPE 配置表副本。此结构如图 8-1 所示。

图像文本
vLPI
Configuration
table
vPE Configuration table
vLPI
Valid entry Pending
Redistributor Invalid entry table
Invalid entry
GICR_VPROPBASER Valid entry
vLPI
Configuration
table
vLPI
Pending
table
vPEID
8.6.1 vPE 配置表
vPE 配置表的格式是 IMPLEMENTATION DEFINED。GICR_VPROPBASER.Z 指示表是否包含全零。如果 vPE 配置表在初始分配时不包含全零,则行为是 UNPREDICTABLE。当 GICR_VPROPBASER.Z==0 时,内存内容不为零并包含有效数据。
GICR_VPROPBASER.Valid 指示 vPE 配置表是否有效。如果当任何指向该表的 Redistributor 具有 GICR_VPROPBASER.Valid==1 时,GIC 以外的任何代理写入 vPE 配置表,则行为是 UNPREDICTABLE。当没有具有 GICR_VPROPBASER.Valid==1 的 Redistributor 指向 vPE 配置表时,任何 Redistributor 中都没有该 vPE 配置表的缓存副本。
当 GICR_VPROPBASER.Valid 从 1 写入 0 时,寄存器中的所有其他读/写字段变为 UNKNOWN。在将 GICR_VPROPBASER.Valid 从 1 写入 0 后,当 GICR_CTLR.RWP==0 时,该 Redistributor 不会再访问 vPE 配置表。
当同一 CommonLPIAff 组中的另一个 Redistributor 由于先前将 GICR_VPROPBASER.Valid 从 1 写入 0 而具有 GICR_CTLR.RWP==1 时,可以将 GICR_VPROPBASER.Valid 从 1 写入 0。如果当同一 CommonLPIAff 组中的任何 Redistributor 由于先前将 Valid 从 1 写入 0 而具有 GICR_CTLR.RWP==1 时,将 GICR_VPROPBASER.Valid 从 0 写入 1,结果是 UNPREDICTABLE。
当 GICR_CTLR.RWP==1 是由于在该 Redistributor 上先前将 GICR_VPROPBASER.Valid 从 1 写入 0 时,写入 GICR_VPROPBASER 会导致 UNPREDICTABLE 行为。
注意 vPE 配置表作为通过 ITS 发出的 VMAPP 命令的副作用而填充。它不打算由软件直接访问。
8.6.2 驻留和映射限制
如果目标 Redistributor 具有 GICR_VPROPBASER.Valid==0,则 V==1 的 VMAPP 命令具有以下 CONSTRAINED UNPREDICTABLE 效果之一:
-
映射被丢弃。
-
使用来自具有 GICR_VPROPBASER.Valid==1 的 UNKNOWN Redistributor 的 vPE 配置表进行映射。
如果目标 Redistributor 具有 GICR_VPROPBASER.Valid==0,则 VMOVP 命令具有以下 CONSTRAINED UNPREDICTABLE 效果之一:
-
映射未移动。
-
映射被移动。
-
映射被丢弃。
如果指定的 vPEID 超出 vPE 配置表的范围,则 V==1 的 VMAPP 命令具有以下 CONSTRAINED UNPREDICTABLE 效果之一,除非命令导致命令错误:
-
命令被忽略。
-
vPEID 被视为 UNKNOWN 合法值。
如果指定的 vPEID 超出 vPE 配置表的范围,则 VMOVP 命令具有以下 CONSTRAINED UNPREDICTABLE 效果之一,除非命令导致命令错误:
-
命令被忽略。
-
vPEID 被视为 UNKNOWN 合法值。
如果有任何针对 Redistributor 的 ITS vPEID 映射,则将 GICR_VPROPBASER.Valid 从 1 清除为 0 的效果是 UNPREDICTABLE。
注意 Arm 强烈建议在清除 GICR_VPROPBASER.Valid 之前从 Redistributor 移除所有 vPE 映射。
如果 vPEID 同时在多个 Redistributor 上调度,则效果是 UNPREDICTABLE。
如果在该 vPEID 没有当前 ITS 映射时在任何 Redistributor 上调度 vPEID,则发生以下 CONSTRAINED UNPREDICTABLE 效果之一:
-
GICR_VPENDBASER.vPEID 被视为具有 UNKNOWN 有效值,除了直接读取寄存器的所有目的。
-
GICR_VPENDBASER.Valid 被视为设置为 0,除了直接读取寄存器的所有目的。
-
vPEID 被视为使用 UNKNOWN 配置进行映射。
vPEID 可以在其在 ITS 中映射到的 Redistributor 上调度,或在同一 CommonLPIAff 组内的任何其他 Redistributor 上调度。在不同 CommonLPIAff 组的 Redistributor 上调度 vPEID 具有以下 CONSTRAINED UNPREDICTABLE 效果之一:
-
待处理中断未传递。
-
传递非待处理的中断。
-
中断可能使用错误的配置。
-
门铃中断的保证可能不被遵守。
如果在为 vPEID 发出 VMOVP 时该 vPEID 在任何 Redistributor 上调度,结果是 UNPREDICTABLE。
8.7 基于寄存器的 vLPI 失效
可以使用 GICR_INVLPIR 寄存器使特定 LPI 的缓存配置数据失效,或使用 GICR_INVALLR 寄存器使所有 LPI 失效,如下所示:
-
写入 GICR_INVLPIR.V == 0 或 GICR_INVALLR.V == 0 在物理 INTID 空间上执行失效。
-
写入 GICR_INVLPIR.V == 1 或 GICR_INVALLR.V == 1 在由 GICR_INVLPIR.vPEID 或 GICR_INVALLR.vPEID 字段分别标识的虚拟 INTID 空间上执行失效。
当写入 GICR_INVLPIR.V == 1 时,当发生以下任何情况时,失效操作无效果:
-
GICR_INVLPIR.INTID 字段超出该 vPE 支持的 LPI 范围。
-
GICR_INVLPIR.INTID 字段不是 LPI。
为未映射到该 Redistributor 或同一 CommonLPIAff 组内另一个 Redistributor 的 vPEID 发出基于寄存器的失效操作具有以下 CONSTRAINED UNPREDICTABLE 效果之一:
-
操作被忽略。
-
失效完成,影响 UNKNOWN 的 Redistributor 子集。
-
失效完成,影响所有 Redistributor。
当写入 GICR_INVLPIR 或 GICR_INVALLR 时,GICR_SYNCR.Busy 跟踪在同一 Redistributor 上发出的失效:
-
GICR_SYNCR.Busy == 1 直到失效完成。
-
当 GICR_SYNCR.Busy == 0 时,失效完成且失效效果在所有 Redistributor 上可见,除非另有规定。
当 GICR_SYNCR.Busy==1 时写入 GICR_INVLPIR 或 GICR_INVALLR 具有以下 CONSTRAINED UNPREDICTABLE 效果之一:
-
写入被忽略。
-
执行写入指定的失效。
基于寄存器的失效效果仅保证在 GICR_SYNCR 记录其完成后对 ITS 命令可见。当受影响的中断有未完成的基于寄存器的失效时发出 ITS 命令具有以下 CONSTRAINED UNPREDICTABLE 效果之一:
-
失效效果在 ITS 命令之前应用。
-
失效被忽略。
当受中断影响的未完成 ITS 命令存在时为中断发出基于寄存器的失效具有以下 CONSTRAINED UNPREDICTABLE 效果之一:
-
失效效果在 ITS 命令之前应用。
-
失效效果在 ITS 命令之后应用。
-
失效被忽略。
GICR_INVLPIR、GICR_INVALLR 和 GICR_SYNCR 寄存器在 GICv4.1 中是强制性的。
8.8 vSGI 的直接注入
引入了新机制允许通过 ITS 直接注入 SGI。此机制仍需要在发送 PE 上对 hypervisor 进行陷阱,但消除了在接收 PE 上对 hypervisor 进行陷阱的需要。这些控制有限制:
-
ITS 控制必须仅在具有该 vPEID 映射的 ITS 上使用。
- 当多个 ITS 具有 vPEID 的映射时,可以使用任何具有映射的 ITS。
-
Redistributor 控制必须仅在当前目标 Redistributor 上或同一 CommonLPIAff 组内的 Redistributor 上使用。vPEID 不需要当前调度,只需映射。
- 当多个 ITS 具有 vPEID 的映射时,可以使用任何具有映射的 ITS。
不遵循这些指导原则可能导致 UNPREDICTABLE 行为。
没有控制来查询 vSGI 的当前配置。软件必须保留自己的 vSGI 当前配置副本以模拟 GICR_IxxxR0 SGI 配置字段的读取。通过直接注入接收的 vSGI 没有活动状态。
8.8.1 生成 vSGI
当 GITS_CTLR.Enabled==1 且 GITS_CTLR.Quiescent==0 时,对 GITS_SGIR 的写入会导致使用写入中的 vPEID 和 vINTID 生成虚拟中断。如果 vPEID 未在任何 ITS 上映射,则写入被静默丢弃。如果 vPEID 未在此 ITS 上映射但在不同的 ITS 上映射,则中断是传递还是丢弃是 CONSTRAINED UNPREDICTABLE。虚拟 SGI 没有优先级移位。
8.8.2 存储 vSGI 状态和配置
虚拟 LPI 待处理表中 IMPLEMENTATION DEFINED 区域的最后 128 位被重新定义用于存储 SGI 配置和状态。此空间的格式为:
表 8-1 虚拟 LPI 待处理表
| 31 | 24 23 | 16 | 15 | 8 7 | 0 | 从待处理表 开始的偏移 | |—|— Enable RES0 |—|—|— Pending Group |—|— +0x3F0 +0x3F4 | | PRI_7 | PRI_6 PRI_5 | PRI_4 | PRI_3 | PRI_2 PRI_1 | PRI_0 | +0x3F8 | | PRI_15 | PRI_14 PRI_13 | PRI_12 | PRI_11 | PRI_10 PRI_9 | PRI_8 | +0x3FC |
-
Pending[n]:vSGI n 的待处理状态:
-
0 - 非待处理。
-
1 - 待处理。
-
-
Enable[n]:vSGI n 的启用状态:
-
0 - 禁用。
-
1 - 启用。
-
-
Group[n]:vSGI n 的组:
-
Group 0。
-
Group 1。
-
PRI_
8.8.3 模拟 GICR_I[C|S]PENDR0
写入 GICR_VSGIR 查询属于指定 vPE 的虚拟 SGI 的待处理状态。GICR_VSGIPENDR.Busy 确定查询何时完成,如下所示:
-
GICR_VSGIPENDR.Busy == 1 直到查询完成。
-
当 GICR_VSGIPENDR.Busy == 0 时,属于该 vPE 的 vSGI 的待处理状态在 GICR_VSGIPENDR.Pending 中报告。
在以下情况下,GICR_VSGIRPEND.Pending 返回 UNKNOWN 值:
-
当 GICR_VSGIPENDR.Busy == 1 时。
-
写入无效的或未映射到此 CommonLPIAff Redistributor 组的 vPEID。
当 GICR_VSGIPENDR.Busy == 1 时写入 GICR_VSGIR 具有以下 CONSTRAINED UNPREDICTABLE 效果之一:
-
写入被忽略。
-
写入导致新的查找发生。
VSGI 命令允许模拟对 GICR_ISPENDR0 的写入。可以使用 GITS_SGIR 模拟对 GICR_ISPENDR0 的写入。