Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第 5 章:本地性特定外设中断和 ITS

本章描述了_本地性特定外设中断_(LPI)和_中断转换服务_(ITS)。包含以下章节:

  • LPI

  • 中断转换服务

  • ITS 命令

  • 通用 ITS 伪代码函数

  • ITS 命令错误编码

  • ITS 电源管理

5.1 LPI

本地性特定外设中断(LPI)是边沿触发的基于消息的中断,如果实现了_中断转换服务_(ITS),则可以使用 ITS 将中断路由到特定的 Redistributor 和连接的 PE。GICv3 为 LPI 提供两种类型的支持。LPI 可以通过以下任一方式支持:

  • 使用 ITS 将来自设备的 EventID 转换为 LPI INTID。有关 EventID 的更多信息,请参见_中断转换服务_。

  • 通过使用 GICR_SETLPIR 直接将 LPI INTID 转发到 Redistributor。

实现必须只支持这些方法中的一种。

注意

在支持 LPI 但不包含 ITS 的实现中,以下寄存器是强制性的:

  • GICR_INVLPIR。

  • GICR_INVALLR。

  • GICR_SYNCR。

在确实包含 ITS 的实现中,对这些寄存器的支持是 IMPLEMENTATION DEFINED 的。

这些寄存器控制不包含 ITS 的系统中的物理 LPI:

  • GICR_SETLPIR。

  • GICR_CLRLPIR。

在包含 LPI 的实现中,至少支持 8192 个 LPI。因此,每个中断的配置和每个中断的挂起信息保存在内存中的表中,而不是寄存器中,这些表由保存在 Redistributor 中的寄存器指向。

注意

  • Arm 期望实现将在 Redistributor 中缓存表的部分内容,以减少延迟和内存流量。这些缓存的形式是 IMPLEMENTATION DEFINED 的。

  • LPI 表的地址在 Non-secure 物理地址空间中。

图 5-1 显示了在包含至少一个 ITS 的实现中 LPI 的生成。

Image text

Message-based interrupts
Distributor ITS [a]
GITS_TRANSLATER
LPIs
PE PE PE PE PE
x.y.0.0 x.y.0.1 x.y.0.2 x.y.n.0 x.y.n.1
Cluster C0 Cluster Cn
Redistributor CPU interface

a. GIC 中可能有零个、一个或多个 ITS。

图 5-1 在带有 ITS 的实现中触发 LPI

注意 在图 5-1 中,ITS 到 Redistributor 的通道是 IMPLEMENTATION DEFINED 的。

图 5-2 显示了在没有 ITS 的实现中 LPI 的生成。 5.1 LPI

Message-based interrupts

Image text

Distributor
LPIs
PE PE PE PE PE
x.y.0.0 x.y.0.1 x.y.0.2 x.y.n.0 x.y.n.1
Cluster C0 Cluster Cn
Redistributor CPU interface

***图 5-2 在没有 ITS 的实现中触发 LPI*** 当 GICD_CTLR.DS == 0 时:
  • 只有在为 Non-secure 状态启用亲和性路由时才支持 LPI。

  • LPI 总是 Non-secure Group 1 中断。

当 GICD_CTLR.DS == 1 时:

  • 只有在启用亲和性路由时才支持 LPI。

  • LPI 总是 Group 1 中断。

有一个单一的全局物理 LPI 空间,以便 LPI 可以在所有 Redistributor 之间移动。软件使用 GICR_PROPBASER.IDbits 编程单一全局物理 LPI 空间的大小。

注意 物理 LPI 空间的大小受实现支持的最大大小限制,该大小在 GICD_TYPER.IDbits 中定义。

对于给定的 Redistributor,LPI 配置和状态在内存中的两个表中维护,在以下章节中描述:

  • LPI Configuration 表

  • LPI Pending 表。 如果 Redistributor 支持物理 LPI,它具有:

  • 在 LPI Configuration 表中编程的 LPI 优先级和使能位。LPI Configuration 表的地址由 GICR_PROPBASER 定义。如果在 GICR_CTLR.EnableLPIs == 1 时更新 GICR_PROPBASER,效果是 UNPREDICTABLE 的。有关更多信息,请参见_LPI Configuration 表_。

  • LPI Pending 表中 LPI 挂起位的内存支持存储。此表特定于特定的 Redistributor。LPI Pending 表的地址由 GICR_PENDBASER 定义。如果在 GICR_CTLR.EnableLPIs == 1 时更新 GICR_PENDBASER,效果是 UNPREDICTABLE 的。

GICR_PROPBASER.IDBits 设置 ID 空间的大小,从而设置 LPI Configuration 表和相应 LPI Pending 表中的条目数量。

通过写入 GICR_CTLR.EnableLPIs 来启用物理 LPI。

注意

当在 Redistributor 接口禁用 LPI 时,即当 GICR_CTLR.EnableLPIs == 0 时,LPI 无法变为挂起。在这种情况下尝试使 LPI 挂起没有效果,LPI 会丢失。这与禁用 SGI、PPI 和 SPI 不同,后者只阻止向 CPU 接口发出中断信号。

GICv4 引入了等效的表来处理虚拟 LPI,地址在 GICR_VPROPBASER 和 GICR_VPENDBASER 中引用。

在 GICv4 中,通过写入 GICR_VPENDBASER.Valid 来启用虚拟 LPI。

5.1.1 LPI Configuration 表

LPI 配置是全局的。GIC 是否支持指向 LPI Configuration 表的不同副本的 Redistributor 是 IMPLEMENTATION DEFINED 的。

GICR_PROPBASER 是否可以在不同的 Redistributor 上设置为不同的值是 IMPLEMENTATION DEFINED 的。GICR_TYPER.CommonLPIAff 指示哪些 Redistributor 在 GICR_CTLR.EnableLPIs == 1 时必须将 GICR_PROPBASER 设置为相同的值。

实现可以将所有需要具有相同值的 GICR_PROPBASER 副本视为访问公共状态。

在需要使用公共 LPI Configuration 表的 Redistributor 上,当 GICR_CTLR.EnableLPIs == 1 时,在 GICR_PROPBASER 的不同副本中设置不同的值会导致 UNPREDICTABLE 行为。

如果在不同的 Redistributor 上将 GICR_PROPBASER 编程为不同的值,则 GIC 读取 LPI Configuration 表时使用哪个或哪些 GICR_PROPBASER 副本是 IMPLEMENTATION DEFINED 的。但是,使用的副本将对应于 GICR_CTLR.EnableLPIs == 1 的 Redistributor。

为避免不可预测的行为,软件必须确保所有 LPI Configuration 表的副本都相同,并且所有更改都是全局可观察的,在以下情况下:

  • 在任何 Redistributor 上将 GICR_CTLR.EnableLPIs 从 0 写为 1。

  • 在任何 GICR_CTLR.EnableLPIs == 1 的 Redistributor 上写入 GICR_INVLPIR 和 GICR_INVALLR,如果支持直接 LPI。

  • 在包含至少一个 ITS 的实现中,ITS 执行 INV 和 INVALL 命令。

内存中的 LPI Configuration 表存储包含每个 LPI 配置信息的条目,其中:

  • GICR_PROPBASER 指定一个 4KB 对齐的物理地址。这是 LPI Configuration 表基地址。

  • 对于任何 LPI N,表条目的位置由 (base address + (N – 8192)) 定义。

要更改中断的配置,软件写入 LPI Configuration 表,然后发出 INV 或 INVALL 命令。在不包含 ITS 的实现中,软件写入 GICR_INVALLR 或 GICR_INVLPIR。 5.1 LPI

LPI Configuration 表为每个 LPI 包含一个 8 位条目。图 5-3 显示了 LPI Configuration 表条目格式。

7 2 1 0
Priority
RES1
Enable 图 5-3 LPI Configuration 表条目

表 5-1 显示了 LPI Configuration 表条目位分配。

表 5-1 LPI Configuration 表条目位分配

名称功能
[7:2] PriorityLPI 的优先级。这些是 LPI 优先级的最高有效位。优先级的位 [1:0] 为 0。当 GICD_CTLR.DS == 0 时,此值根据_第 4-75 页上软件访问中断优先级_中指定的安全和优先级规则进行移位。这意味着 LPI 优先级总是在优先级范围的下半部分。优先级值范围是 128-254。如果 GICD_CTLR.DS == 1,此字段中的值不会移位。在 GICv4 中,Virtual LPI Configuration 表的行为就像 GICD_CTLR.DS == 1,因此优先级不会移位。注意 实现可能支持少于 8 位的优先级。未实现的位将被视为 RES0。
有关中断优先级的更多信息,请参见第 4-68 页上的_中断优先级_。
[1]-RES1。
[0]EnableLPI 使能。此位控制是否启用 LPI:0 LPI 未启用。1 LPI 已启用。

缓存

当 GICR_CTLR.EnableLPI == 1 时,Redistributor 可以缓存来自 GICR_PROPBASER 指向的 LPI Configuration 表的信息,受所有以下规则约束:

  • 是否存在一个或多个缓存是 IMPLEMENTATION DEFINED 的。如果存在至少一个缓存,则结构和大小是 IMPLEMENTATION DEFINED 的。

  • LPI Configuration 表条目可能在任何时候分配到缓存中。

  • 缓存的 LPI Configuration 表条目不保证保留在缓存中。

  • 缓存的 LPI Configuration 表条目不保证与内存保持不一致。

  • 在适当的无效操作完成之前,不保证 LPI 配置的更改是可见的:

    • 如果实现了一个或多个 ITS,则使用 INV 或 INVALL 命令执行无效。SYNC 命令完成 INV 和 INVALL 命令。
  • 如果没有实现 ITS,则通过写入 GICR_INVALLR 或 GICR_INVLPIR 执行无效。

如果没有 GICR_CTLR.EnableLPIs == 1 的 Redistributor,GIC 就没有缓存的 LPI Configuration 表条目。

5.1.2 LPI Pending 表

软件使用有效 LPI INTID 的实现范围,通过写入 GICR_PENDBASER 来配置 LPI Pending 表。此寄存器提供物理 LPI 的 LPI Pending 表的基地址。

当 GICR_CTLR.EnableLPIs == 1 时,每个 Redistributor 在单独的 LPI Pending 表中维护条目,指示每个 LPI 的挂起状态:

0 LPI 未挂起。1 LPI 挂起。

对于给定的 LPI:

  • LPI Pending 表中相应的字节是 (base address + (N / 8))。

  • 字节中的位位置是 (N MOD 8)。

仅包含零的 LPI Pending 表,包括前 1KB,表示没有挂起的 LPI。

LPI Pending 表的前 1KB 是 IMPLEMENTATION DEFINED 的。但是,如果 LPI Pending 表的前 1KB 和表的其余部分仅包含零,则必须表示没有挂起的 LPI。

LPI Pending 表的前 1KB 内存在初始分配时必须仅包含零,并且这必须对 Redistributor 可见,否则效果是不可预测的。

在正常操作期间,LPI Pending 表仅由 Redistributor 维护。

如果在 GICR_CTLR.EnableLPIs == 1 时软件写入 LPI Pending 表,行为是 UNPREDICTABLE 的。当 GICR_CTLR.EnableLPIs 清零为 0 时,如果在 GICR_CTLR.RWP 读取为 0 之前写入 LPI Pending 表,行为是 UNPREDICTABLE 的。

按照 GICR_TYPER.CommonLPIAff 的指示,需要共享公共 LPI Configuration 表的 Redistributor 可能将 GICR_PENDBASER 的 OuterCache、Shareability 或 InnerCache 字段视为访问公共状态。

在系统中,在 GICR_CTLR.EnableLPIs == 1 的不同 Redistributor 上将 GICR_PENDBASER 的 OuterCache、Shareability 或 InnerCache 字段编程为不同的值是不可预测的。

对于物理 LPI,当 GICR_CTLR.EnableLPIs 更改为 1 时,Redistributor 必须从物理 LPI Pending 表读取物理 LPI 的挂起状态。

注意

如果 GICR_PENDBASER.PTZ == 1,软件保证 LPI Pending 表仅包含零,包括前 1KB。在这种情况下,硬件可能不会读取表的任何部分。

如果 GICR_CTLR.EnableLPIs 清零为 0,则当 GICR_CTLR.RWP 读取为 0 时,GIC 不再访问 LPI Pending 表,并且 LPI Pending 表的任何缓存都被无效。不保证清零 GICR_CTLR.EnableLPIs 会导致在内存中更新 LPI Pending 表。

注意

如果实现了一个或多个 ITS,Arm 强烈建议在将 GICR_CTLR.EnableLPIs 清零为 0 之前将所有 LPI 映射到另一个 Redistributor。

对于虚拟 LPI,当 GICR_CTLR.EnableLPIs ==1 且 GICR_VPENDBASER.Valid 更改为 1 时,Redistributor 必须从虚拟 LPI Pending 表读取虚拟 LPI 的挂起状态。

注意

  • 如果 GICR_VPENDBASER.IDAI == 0,软件保证 LPI Pending 表由同一 GIC 实现写出,这意味着硬件可以依赖表的前 1KB,可能不会读取整个表。

  • 如果当 GICR_CTLR.EnableLPIs == 1 时 GICR_PROPBASER.IDbits 小于 0b1101,GIC 仍可能访问 LPI Pending 表的 IMPLEMENTATION DEFINED 区域。

5.1.3 Virtual LPI Configuration 表和 virtual LPI Pending 表

GICv4 使用相同的内存表概念来保存虚拟 LPI 的配置和挂起信息。这些表的格式与物理 LPI 相同。

5.2 中断转换服务

中断转换服务(ITS)转换来自设备的输入 EventID,由其 DeviceID 标识,并确定:

  1. 此输入的相应 INTID。

  2. 目标 Redistributor,并通过它确定该 INTID 的目标 PE。

对于 GICv3,ITS 为转换为物理 LPI 的事件执行此功能。LPI 可以通过 ITS 或直接写入 GICR_SETLPIR 转发到 Redistributor。实现必须只支持这些方法中的一种。

对于 GICv4,ITS 还为直接注入为虚拟 LPI 的中断以及对于 GICv4.1,虚拟 SGI 执行此功能。

ITS 对物理 SGI、SPI 或 PPI 没有影响。

ITS 转换的流程如下:

  1. DeviceID 选择_设备表_中描述使用哪个_中断转换表_(ITT)的_设备表条目_(DTE)。

  2. EventID 选择 ITT 中描述以下内容的_中断转换条目_(ITE):

    • 对于物理中断:

      • 输出物理 INTID。

      • 中断集合编号,ICID。

    • 对于虚拟中断,在 GICv4 中:

      • 输出虚拟 INTID。

      • vPEID。

      • 如果 vPE 未被调度,则使用的门铃。

  3. 对于物理中断,ICID 选择_集合表_(CT)中的 Collection 表条目,描述目标 Redistributor,因此是中断路由到的目标 PE。

  4. 对于虚拟中断,在 GICv4 中,vPEID 选择 vPE 表条目,描述当前托管中断路由到的目标 vPE 的 Redistributor。

转换过程中使用的表在以下章节中更详细地描述:

  • ITS 表

  • 设备表

  • 中断转换表

  • 集合表

  • vPE 表

这些表使用_ITS 命令_中描述的 ITS 命令创建和维护。GICv3 和 GICv4 不支持对表的直接访问,必须使用 ITS 命令配置表。

5.2.1 ITS 表

当 GIC 提供一组寄存器允许发现以下功能时,软件为 ITS 私有表提供内存:

  • 所需的私有表数量。

  • 每个表中每个条目的大小。

  • 每个表的类型。

注意

所有 ITS 表都在 Non-secure 物理地址空间中。

ITS 表的状态和配置存储在内存中的一组表中。在启用 ITS 之前,此内存由软件分配。 GITS_BASER 指定 ITS 表的基地址和大小,必须在启用 ITS 之前提供。

ITS 表具有平坦结构或两级结构。结构由 GITS_BASER 确定:

  • 0 平坦表。在这种情况下,为表分配一个连续的内存块。表的格式是 IMPLEMENTATION DEFINED 的。

    • 如果在 ITS 新分配使用时用于 ITS 表的内存不包含零,则行为是 UNPREDICTABLE 的。
  • 1 两级表。在这种情况下,1级表中的每个条目都是 64 位,格式如下:

    • 位 [63] - Valid:

      • 如果此位清零为 0,PhysicalAddress 字段不指向 2 级表的基地址。

      • 如果此位设置为 1,PhysicalAddress 字段指向 2 级表的基地址。

    • 位 [62:52] - RES 0。

    • 位 [51:N] - 2 级表的 PhysicalAddress。N 是指定页面大小所需的位数:

      • 2 级表的大小由 GITS_BASER.Page_Size 确定。
    • 位 [N-1:0] - RES 0。N 是指定页面大小所需的位数。

    • 1 级表由适当的 ID 索引,使得 1 级条目 = ID/(Page Size / Entry Size)。

注意 这允许软件确定必须为给定的 CollectionID、DeviceID 或 vPEID 分配的 2 级表。

对于 1 级表条目,当 Valid == 0 时:

  • 如果 Type 字段指定除 Collection 表之外的有效表类型,ITS 丢弃对 2 级表的任何写入。

  • 如果 Type 字段指定 Collection 表,且 ICID 大于或等于 GITS_TYPER.HCC 指示的数量,ITS 丢弃对 2 级表的任何写入。

2 级表的格式是 IMPLEMENTATION DEFINED 的。

如果以下情况,行为是 UNPREDICTABLE 的:

  • 在 ITS 新分配使用时用于 2 级表的内存不包含零。

  • 多个 Valid == 1 的 1 级表条目指向同一个 2 级表。

注意 作为从断电事件恢复 ITS 状态的一部分,描述表的寄存器可以指向以前由 ITS 填充的表,因此可能包含除零之外的值。ITS 电源管理的详细信息是 IMPLEMENTATION DEFINED 的。请参见_ITS 电源管理_。

图 5-4 显示了这些表在转换过程中如何使用。

Image text

Device
table
Interrupt Redistributor A
Source
vPE table
(GICv4 only) Virtual
pending table
Interrupt
translation
table
Redistributor B
Collection
table Pending table
pINTID (direct LPI support)
DeviceID
vPEID
CollectionID
vINTID
EventID
pINTID

**图 5-4 ITS 表**

当 GITS_CTLR.Enabled 从 0 写为 1 时,如果满足以下任何条件,行为是 UNPREDICTABLE 的:

  • GITS_CBASER.Valid == 0。

  • 对于 Type 字段指示设备的任何 GITS_BASER 寄存器,GITS_BASER.Valid == 0。

  • 对于 Type 字段指示集合且 GITS_TYPER.HCC == 0 的任何 GITS_BASER 寄存器,GITS_BASER.Valid == 0。

  • 在 GICv4 中,对于 Type 字段指示 vPE 的任何 GITS_BASER 寄存器,GITS_BASER.Valid == 0。

软件访问私有 ITS 表

如果 GITS_BASER.Indirect == 0,如果首次分配给 ITS 时用于 ITS 表的内存不包含全零,则行为是 UNPREDICTABLE 的。

如果 GITS_BASER.Indirect == 1,如果首次分配供 ITS 使用时用于 2 级表的内存不包含全零,则行为是不可预测的。

当 GITS_CTLR.Enabled == 0 且 GITS_CTLR.Quiescent == 1 时:

  • 实现将不会访问任何 GITS_BASER 寄存器指向的表。

当 GITS_CTLR.Enabled == 1 或 GITS_CTLR.Quiescent == 0 时:

  • 实现将不会访问任何 GITS_BASER.Valid == 0 的 GITS_BASER 寄存器指向的表。

  • 对于 GITS_BASER.Valid == 1 且 GITS_BASER.Indirect == 0 的 GITS_BASER 寄存器指向的表,如果软件写入该表,行为是 UNPREDICTABLE 的。

  • 对于 GITS_BASER.Valid == 1 且 GITS_BASER.Indirect == 1 的 GITS_BASER 寄存器指向的表:

    • 如果软件写入任何 2 级表条目,行为是 UNPREDICTABLE 的。

    • ITS 不会缓存有效位清零为 0 的 1 级表中的任何条目。

  • 如果软件写入有效位设置为 1 的任何 1 级表条目,行为是 UNPREDICTABLE 的。

  • 将 1 级表条目的有效位从 0 更改为 1 的写入必须在软件将依赖于该条目的命令添加到 ITS 命令队列之前全局可见。否则,命令是否成功或是否被忽略是未知的。

5.2.2 中断集合

在 GICv3 中,ITS 将其生成的所有物理 LPI 视为_集合_的成员。与集合关联的数据可以保存在 ITS 中、外部内存中或两者中。如果任何 GITS_BASER.Type == 0b100,ITS 支持保存在内存中的集合:

  • 当 ITS 支持保存在内存中的集合时,支持的集合总数由软件分配的内存确定:

  • 如果 GITS_BASER.Indirect == 0,可以使用以下公式计算内存中支持的集合数量:

((number of pages * page size) / entry size) 此公式的相关值在 GITS_BASER.Size、GITS_BASER.PageSize 和 GITS_BASER.EntrySize 中指示。

  • 如果 GITS_BASER.Indirect == 1,可以使用以下公式计算内存中支持的集合数量:

(((number of pages in level 1 table * page size) /8) * (page size/entry size))。此公式的相关值在 GITS_BASER.Size、GITS_BASER.PageSize 和 GITS_BASER.EntrySize 中指示。

注意

间接表允许稀疏分配,因此支持范围内的所有 ICID 可能不可用。

  • 当集合同时保存在 ITS 和外部内存中时,集合总数由 GITS_TYPER.CCT 指示。

当 GITS_TYPER.HCC!= 0 时:

  • 范围 {0… GITS_TYPER.HCC-1} 中标识符的集合保存在 ITS 中。

  • 如果支持,标识符范围大于 GITS_TYPER.HCC 中指示的集合保存在外部内存中。

当 GITS_TYPER.HCC == 0 时:

  • ITS 必须支持外部内存中的集合,所有集合都保存在外部内存中。

支持的集合最大数量受 ICID 大小限制:

  • 如果 GITS_TYPER.CIL == 0,ICID 是 16 位。

  • 如果 GITS_TYPER.CIL == 1,ICID 由 GITS_TYPER.CIDbits 报告。

5.2.3 设备表

设备表_提供_设备表条目(DTE)的表。每个 DTE 描述 DeviceID 和 ITT 基地址之间的映射,该地址指向 ITS 可用于存储 EventID 转换的内存。ITS 使用 ITT 存储指定 DeviceID 的每个 EventID 的转换。DeviceID 是分配给可以创建一系列 EventID 的每个设备的唯一标识符。例如,Arm 期望来自 PCIe 根复合体的 16 位 Requester ID 作为 DeviceID 呈现给 ITS。

DeviceID 为表提供索引值。 表 5-2 显示了可能分配给每个 DTE 的位数示例。

表 5-2 DTE 条目

位数分配注释
1Valid布尔值
40ITT Address基物理地址
5ITT RangeLog2(ITT 支持的 EventID 宽度)减一。

5.2.4 中断转换表

中断转换表(ITT)特定于可以创建编号事件的每个设备。ITT 中的每个条目称为_中断转换条目_(ITE)。

在 GICv3 中,ITE 仅为物理中断定义。

在 GICv4 中,ITE 为物理中断和虚拟中断定义,并提供以下区别:

  • 物理 LPI 的条目和使用 ICT 进行路由信息。

  • 虚拟 LPI 的条目和使用_vPE 表_。

必须为 ITT 分配从 ITT Address 开始的连续物理地址空间。大小为 2^(DTE.ITT Range + 1)* GITS_TYPER.ITT_entry_size。

如果内存在 ITS 新分配使用时不包含全零,则行为是 UNPREDICTABLE 的。

如果多个 ITT 在内存中重叠,行为是 UNPREDICTABLE 的。

ITS 对 ITT 的访问使用为设备表指定的相同 Shareability 和 Cacheability 属性。

对于物理中断,每个 ITE 描述输入 EventID 与以下内容之间的映射:

  • 发送到目标 PE 的_输出物理 INTID_(pINTID)。

  • 标识集合表中条目的 ICID,确定 LPI 的目标 PE。有关集合表的更多信息,请参见_集合表_。

对于虚拟中断,每个 ITE 描述如前面列表中所述的 EventID 映射,以及:

  • 发送到目标 vPE 的_输出虚拟 INTID_(vINTID)。

  • 标识 vPE 表中条目以确定当前主机 Redistributor 的_虚拟 PE 编号_(vPEID)。有关 vPE 表的更多信息,请参见_vPE 表_。

  • 如果在目标 vPE 当前未在物理 PE 上调度时转换虚拟中断,则发送到物理 PE 的物理 LPI。

EventID 为表提供索引值。

表 5-3 显示了可能存储在 ITE 中的位数示例。

表 5-3 ITE 条目

位数分配注释
1Valid布尔值,指示中断是物理还是虚拟。
1Interrupt_Type布尔值,指示中断是物理还是虚拟。
LPI 编号空间的大小aInterrupt_Number根据中断类型的 pINTID 或 vINTID。
表 5-3 ITE 条目(续)
位数分配注释
LPIInterrupt_Number在 GICv4 中,pINTID 用作门铃。在 GICv3 中,以及
编号空间的大小aHypervisorID在 GICv4 中当不需要门铃时,编程值为 1023。
16ICID中断集合 ID,仅用于物理中断。
16vPEIDvPE ID,仅用于虚拟中断。

a. 有关 LPI 编号空间大小的信息,请参见_INTID_。

5.2.5 集合表

集合表(CT)提供_集合表条目_(CTE)的表。仅对于物理 LPI,每个 CTE 描述以下内容之间的映射:

  • ITT 生成的 ICID。

  • 以 GITS_TYPER.PTA 定义格式的目标 Redistributor 的地址。

每个 ITS 有一个 CT,可以保存在寄存器中或内存中,或两者的组合。有关更多信息,请参见 GITS_BASER.Type 和 GITS_TYPER.HCC。

TableID 为表提供索引值。它从 ICID 派生。

表 5-4 显示了可能分配给每个 CT 的位数示例。

表 5-4 CT 条目

位数分配注释
1Valid布尔值
RDbase 标识符的大小RDbaseGIC 支持 RDbase 的两种格式,请参见 RDbase

5.2.6 vPE 表

vPE 表由 vPE 表条目组成,提供从 ITS 生成的 vPEID 到以下内容的映射:

  • 以 GITS_TYPER.PTA 定义格式的目标 Redistributor。

  • 与目标 vPE 关联的虚拟 LPI Pending 表的基地址。

由 GITS_BASER 定义的内存区域保存 vPE 表并指示表中每个条目的大小。

vPE 表描述与 ITS 关联的所有 vPE。表 5-5 显示了实现可能在 vPE 表中存储的位数示例。 16 位 vPEID 为表提供索引值。

表 5-5 vPE 表条目

位数分配注释
1Valid布尔值
RDbase 标识符的大小RDbaseGIC 支持 RDbase 的两种格式。
地址的VPT_addrVPT_addr 在 VM 不
大小驻留在 Redistributor 中时定位 LPI Pending 表。当 vPE 在与 RDbase 关联的 GICR_* 寄存器中调度时,它用作 GICR_VPENDBASER 中的地址。
5Size支持的 vINTID 范围的大小(减一)。

5.2.7 ITS 的控制和配置

使用内存映射接口控制和配置 ITS,其中:

  • 可以从 GITS_IIDR 和 GITS_PIDR2 读取版本。

  • GITS_TYPER 指定 ITS 支持的功能。

  • GITS_CTLR 控制 ITS 的操作。

  • GITS_TRANSLATER 接收 EventID 信息。如何提供 DeviceID 是 IMPLEMENTATION DEFINED 的。有关更多详细信息,请参见_ITS 命令_。

  • GITS_BASER 寄存器提供有关架构 ITS 内存结构的类型、大小和访问属性的信息。

  • GITS_CBASER、GITS_CREADR 和 GITS_CWRITER 存储 ITS 命令队列接口的地址信息。

每个 ITS 都有一个使能位,GITS_CTLR.Enabled。

5.2.8 ITS 命令接口

图 5-5 显示了 ITS 如何提供 ITS 命令队列使用的基地址和大小。

Image text

ITS
GITS_CBASER
- Base address and
size of command
queue
-
-
GITS_CREADR
Command 1 Next command to be
processed by the ITS
Command 2
Command 3
- GITS_CWRITERNext empty location
-
-

**图 5-5 ITS 命令队列**

GITS_CBASER、GITS_CREADR 和 GITS_CWRITER 定义 ITS 命令队列。

  • GITS_CBASER 使用以下字段:

    • Valid。此字段指示 ITS 命令队列的内存分配。

    • Cacheability。此字段指示对 ITS 命令队列的访问的可缓存性属性。

    • Shareability。此字段指示对 ITS 命令队列的访问的可共享性属性。

    • Physical address。此字段提供包含 ITS 命令队列的内存的基物理地址。

    • Size。此字段指示 ITS 命令队列的物理内存的 4KB 页数。

  • GITS_CREADR 指定 ITS 读取下一个要执行的命令的基地址偏移。

  • GITS_CWRITER 指定软件写入下一个命令的下一个空闲条目的基地址偏移。

ITS 命令队列条目的大小为 32 字节。这意味着每个 4KB 页面支持 128 个条目。

ITS 命令队列使用小端内存顺序模型。

在 ITS 命令队列中:

  • 基地址总是对齐到 64KB。

  • 大小以 4KB 的倍数表示。

  • 队列回绕的地址总是对齐到 4KB,是(基地址 +(大小 * 4KB))。

注意

所有地址都是 Non-secure 物理地址。 当第一个命令完成时,ITS 开始处理下一个命令。读指针 GITS_CREADR 随着 ITS 处理命令而前进。如果 GITS_CREADR 到达 GITS_CBASER 中指定的内存顶部,则指针回绕到 GITS_CBASER 中指定的基地址。GITS_CWRITER 由软件控制。

当 GITS_CWRITER 和 GITS_CREADR 指定相同的基地址偏移值时,ITS 命令队列为空。

当 GITS_CWRITER 指向缓冲区中 GITS_CREADR 后 32 字节的地址时,ITS 命令队列已满。

当 GITS_CREADR.Stalled == 1 时,不处理后续命令。

INT ITS 命令在执行时生成中断,这可以在特定命令序列完成时生成中断,请参见_ITS 命令_。

5.2.9 与 ITS 命令输出的转换排序

每个命令队列条目看起来是原子执行的,因此转换请求要么看到命令之前的 ITS 状态,要么看到命令之后的 ITS 状态。

SYNC 或 VSYNC 命令完成后发起的转换请求使用与命令执行后状态一致的 ITS 状态进行转换。

在没有 SYNC 或 VSYNC 命令的情况下,架构未定义 ITS 命令和转换请求的排序。

5.2.10 INTID 映射规则的限制

如果软件:

  • 将多个 EventID-DeviceID 组合映射到相同的物理 LPI INTID。

  • 将具有相同物理 LPI INTID 的门铃中断分配给不同的物理 PE。这仅适用于 GICv4。

  • 将 EventID-DeviceID 组合和单独的门铃中断映射到相同的物理 LPI INTID,除非它们针对相同的物理 PE。这适用于所有版本的 GICv4。

  • 将多个 EventID-DeviceID 组合映射到相同的虚拟 LPI INTID-vPEID。这仅适用于 GICv4。

  • 将 EventID-DeviceID 组合和默认门铃中断映射到相同的物理 LPI INTID。这仅适用于 GICv4.1。

  • 将默认门铃和单独门铃映射到相同的物理 LPI INTID。这仅适用于 GICv4.1。

则 GIC 的行为是不可预测的。

注意 从概念上讲,限制是软件不应该将多个 EventID-DeviceID 组合映射到给定虚拟机内的相同 vLPI。但是,ITS 不知道哪些 vPE 属于同一虚拟机。

5.3 ITS 命令

表 5-6 提供了所有 ITS 命令的摘要。

表 5-6 ITS 命令

命令 命令参数描述
CLEAR DeviceID, EventID将由 EventID 和 DeviceID 定义的事件转换为 ICID 和 pINTID,并指示适当的 Redistributor 移除挂起状态。
DISCARD DeviceID, EventID转换由 EventID 和 DeviceID 定义的事件,并指示适当的 Redistributor 移除中断的挂起状态。它还确保与特定 EventID 关联的 Redistributor 中的任何缓存与内存中保存的配置一致。DISCARD 从 ITT 中移除 DeviceID 和 EventID 的映射,并确保静默丢弃具有特定 EventID 的传入请求。
INT DeviceID, EventID将由 EventID 和 DeviceID 定义的事件转换为 ICID 和 pINTID,并指示适当的 Redistributor 设置中断挂起。
INV DeviceID, EventID指定 ITS 必须确保与指定 EventID 关联的 Redistributor 中的任何缓存与内存中保存的 LPI Configuration 表一致。
INVALL ICID指定 ITS 必须确保与 ICID 定义的中断集合关联的任何缓存与所有 Redistributor 的内存中保存的 LPI Configuration 表一致。
INVDB GICv4.1 only vPEID仅 GICv4.1。指定 ITS 必须确保与 vPEID 的默认门铃关联的任何缓存与所有 Redistributor 的内存中保存的 LPI Configuration 表一致。
MAPC ICID, RDbase将由 ICID 定义的集合表条目映射到由 RDbase 定义的目标 Redistributor。
MAPD DeviceID, ITT_addr, Size将与 DeviceID 关联的设备表条目映射到其关联的 ITT,由 ITT_addr 和 Size 定义。
MAPI DeviceID, EventID, ICID将由 EventID 和 DeviceID 定义的事件映射到具有 ICID 和 pINTID=EventID 的 ITT 条目。注意 • pINTID≥0x2000 用于有效的 LPI INTID。 • 这等价于 MAPTI DeviceID, EventID, EventID, ICID
MAPTIa DeviceID, EventID, pINTID, ICID将由 EventID 和 DeviceID 定义的事件映射到其关联的 ITE,由与 DeviceID 关联的 ITT 中的 ICID 和 pINTID 定义。注意 pINTID≥0x2000 用于有效的 LPI INTID。 注意 pINTID≥0x2000
MOVALL RDbase1, RDbase2指示由 RDbase1 指定的 Redistributor 将其所有中断移动到由 RDbase2 指定的 Redistributor。
表 5-6 ITS 命令(续)
命令 命令参数描述
MOVI DeviceID, EventID, ICID更新由 DeviceID 和 EventID 定义的事件的 ITT 条目中的 ICID 字段。它还将由 EventID 和 DeviceID 定义的事件转换为 ICID 和 pINTID,并指示适当的 Redistributor 将中断的挂起状态(如果已设置)移动到由新 ICID 定义的 Redistributor,并更新与事件关联的 ITE 以使用新的 ICID。
SYNC RDbase确保在执行任何进一步的 ITS 命令之前,与 RDbase 指定的 Redistributor 的物理中断关联的所有未完成的 ITS 操作都被全局观察。在 SYNC 执行后,所有先前命令的效果必须应用于对 GITS_TRANSLATER 的后续写入。有关更多信息,请参见第 5-97 页上的_与 ITS 命令输出的转换排序_。
VINVALLb vPEID确保与 vPEID 关联的任何缓存的 Redistributor 信息与内存中保存的关联 LPI Configuration 表一致。
VMAPIb DeviceID, EventID, Dbell_pINTID, vPEID将由 DeviceID 和 EventID 定义的事件映射到具有 vPEID、vINTID=EventID 和 Dbell_PINTID(门铃规定)的 ITT 条目。注意 • vINTID≥0x2000 用于有效的 LPI INTID。 • 这等价于 VMAPTI DeviceID, EventID, EventID, pINTID, vPEID • Dbell_pINTID 必须是 1023 或 Dbell_pINTID≥0x2000 用于有效的 LPI INTID。
VMAPP GICv4.0b 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 Configuration 和 Pending 表。可选择指定默认门铃。
VMAPTIbc DeviceID, EventID, vINTID, Dbell_pINTID, vPEID将由 DeviceID 和 EventID 定义的事件映射到具有 vPEID 和 vINTID 以及 Dbell_pINTID(门铃规定)的 ITT 条目。注意 • vINTID≥0x2000 用于有效的 LPI INTID。 • Dbell_pINTID 必须是 1023 或 Dbell_pINTID≥0x2000 用于有效的 LPI INTID。
VMOVIb DeviceID, EventID, vPEID更新由 DeviceID 和 EventID 定义的事件的 ITT 条目中的 vPEID 字段。将由 EventID 和 DeviceID 定义的事件转换为 vPEID 和 pINTID,并指示适当的 Redistributor 将中断的挂起状态(如果已设置)移动到由新 vPEID 定义的 Redistributor,并更新与事件关联的 ITE 以使用新的 vPEID。
VMOVP GICv4.0b vPEID, RDbase, SequenceNumber, ITSList将由 vPEID 定义的 vPE 表条目更新到由 RDbase 指定的目标 Redistributor。软件必须使用 SequenceNumber 和 ITSList 来同步多个 ITS 上 VMOVP 命令的执行。

Arm IHI 0069G 表 5-6 ITS 命令(续)

命令命令参数描述
VMOVPvPEID, RDbase, SequenceNumber,将为 vPEID 定义的 vPE 映射更新到由 RDbase 定义的目标 Redistributor。
GICv4.1ITSList, Default_Doorbell_pINTID
VSGI forvPEID, Priority, G, C, E, vPEID仅 GICv4.1。对于由 vPEID 定义的 vPE,设置配置或
GICv4.1 onlyb更新由 vINTID 定义的中断状态。
VSYNCbvPEID确保在执行任何进一步的 ITS 命令之前,指定的 vPEID 的所有未完成的 ITS 操作都被全局观察。在 VSYNC 执行后,所有先前命令的效果必须应用于对 GITS_TRANSLATER 的后续写入。
  • a. 此命令以前称为 MAPVI。

  • b. 此命令仅存在于 GICv4 中。

  • c. 此命令以前称为 VMAPVI。

实现支持的 EventID 和 DeviceID 位数可从 GITS_TYPER 发现。未实现的位是 RES0。

注意

  • LPI 的 INTID 在 8192 - 最大数量的范围内。最大数量是 IMPLEMENTATION DEFINED 的。请参见_INTID_。

  • 以下参数名称已从与此 GIC 规范相关的初步信息中使用的名称更改:

    • Device 已更改为 DeviceID。

    • ID 已更改为 EventID。

    • pID 已更改为 pINTID。

    • vID 已更改为 vINTID。

    • pCID 已更改为 ICID。

    • target address 已更改为 RDbase。

    • VCPU 已更改为 vPE。

  • 集合目标地址 RDbase 的格式由 GITS_TYPER.PTA 指示。

5.3.1 ITS 命令参数中的 IMPLEMENTATION DEFINED 大小

一些 ITS 命令包括以下类型的具有 IMPLEMENTATION DEFINED 大小的参数:

DeviceID

关联设备表支持的设备标识符最大数量由可用位数确定,如 GITS_TYPER.Devbits 指定。

EventID EventID 受最大 MAPD Size 字段限制,该字段受 GITS_TYPER.ID_bits 限制。 ICID 支持的集合数量是 IMPLEMENTATION DEFINED 的:

• 对于不支持外部内存中集合表的实现,GITS_TYPER.HCC 指示集合数量。

• 对于确实支持外部内存中集合表的实现,支持的集合数量受分配的集合表大小限制: — 支持的集合总数计算如下:GITS_TYPER.HCC +(集合表大小/条目大小)当 GITS_TYPER.CIL == 1 时,集合的最大数量受 GITS_TYPER.CIDbits 限制。 pINTID pINTID 受 GICR_PROPBASER.IDbits 限制,该限制受 GICD_TYPER.IDbits 限制。这也适用于 Dbell_pINTID。

RDbase

RDbase 与 Redistributor 关联,以两种格式之一指定:

  • 当 GITS_TYPER.PTA == 1 时的 RD_base 基物理地址。

注意 地址可以达到 52 位大小,必须 64KB 对齐。RDbase 字段由地址的位 [51:16] 组成。

  • 当 GITS_TYPER.PTA == 0 时,GICR_TYPER.Processor_Number 中指示的 PE 编号。

  • vINTID vINTID 可以受 GICR_VPROPBASER.IDbits 限制,该限制受 GICD_TYPER.IDbits 限制。

vPEID vPEID 受 vPE 表大小限制。

5.3.2 命令错误

如果 ITS 在提供给命令的数据中检测到错误,则结果行为是 CONSTRAINED UNPREDICTABLE 选择:

  • 忽略命令:

    • 不执行更改中断处理的操作。

    • GITS_CREADR 递增以指向下一个命令,必要时回绕。

    • 如果 GITS_TYPER.SEIS 设置为 1,则生成系统错误。

注意

如何记录系统错误以及如何向 PE 报告是 IMPLEMENTATION DEFINED 的。

  • 停止 ITS 命令队列:

    • GITS_CREADR 不递增,继续指向触发错误的条目。

    • — GITS_CREADR.Stalled 设置为 1。

    • 软件可以通过向 GITS_CWRITER.Retry 写入 1 来重启命令处理。

    • 如果 GITS_TYPER.SEIS 设置为 1,则生成系统错误。

      • 注意

如何记录系统错误以及如何向 PE 报告是 IMPLEMENTATION DEFINED 的。

  • 将数据视为有效数据:

    • 生成错误的数据被视为具有合法值,并相应地处理命令。

    • GITS_CREADR 递增以指向下一个命令,必要时回绕。

    • 如果 GITS_TYPER.SEIS 设置为 1,则生成系统错误。

注意

如何记录系统错误以及如何向 PE 报告是 IMPLEMENTATION DEFINED 的。

有关更多信息,请参见_ITS 命令错误编码_。

5.3.3 CLEAR

此命令将由 EventID 和 DeviceID 定义的事件转换为 ICID 和 pINTID,并指示适当的 Redistributor 移除挂起状态。

图 5-6 显示了 CLEAR 命令的格式。

63323187 07 0DW
DeviceIDRES00x040
RES0EventID1
RES02
RES03

图 5-6 CLEAR 命令格式

在图 5-6 中:

  • EventID 标识要清除挂起状态的与设备关联的中断。

  • DeviceID 指定请求设备。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

命令及其参数为:

CLEAR DeviceID, EventID

如果以下任何情况适用,则发生命令错误:

  • DeviceID 超过 ITS 支持的最大值。

  • DeviceID 指定的设备未使用 MAPD 映射到中断转换表。

  • EventID 超过 ITT 允许的最大值。此值在发出 MAPD 命令时由 Size 字段指定。

  • 设备的 EventID 未使用 MAPI 或 MAPTI 映射到集合。

  • 设备的 EventID 映射到未使用 MAPC 映射到 RDbase 的集合。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

以下伪代码描述了 CLEAR 命令的操作:

// ITS.CLEAR // =========
ITS.CLEAR(ITSCommand cmd)
    if DeviceOutOfRange(cmd.DeviceID)
    then if GITS_TYPER.SEIS == '1'
    then IMPLEMENTATION_DEFINED "SError CLEAR_DEVICE_OOR";
UNPREDICTABLE;

dte = ReadDeviceTable(UInt(cmd.DeviceID));

if !dte.Valid then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError CLEAR_UNMAPPED_DEVICE";
        UNPREDICTABLE;
    if IdOutOfRange(cmd.EventID, dte.ITT_size) then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError CLEAR_ID_OOR";
            UNPREDICTABLE;
        InterruptTableEntry ite = ReadTranslationTable(dte.ITT_base, UInt(cmd.EventID));
        if !ite.Valid then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError CLEAR_UNMAPPED_INTERRUPT";
                UNPREDICTABLE;
            success = ClearPendingState(ite);
            if !success then
                if GITS_TYPER.SEIS == '1' then
                    IMPLEMENTATION_DEFINED "SError CLEAR_ITE_INVALID";
                    UNPREDICTABLE;
                IncrementReadPointer();
                return;

5.3.4 DISCARD

此命令转换由 EventID 和 DeviceID 定义的事件,并指示适当的 Redistributor 移除中断的挂起状态。它还确保与特定 EventID 关联的 Redistributor 中的任何缓存与内存中保存的配置一致。DISCARD 从 ITT 中移除 DeviceID 和 EventID 的映射,并确保静默丢弃具有特定 EventID 的传入请求。

图 5-7 显示了 DISCARD 命令的格式。

63323187 0DW
DeviceIDRES00x0F0
RES0EventID1
RES02
RES03

图 5-7 DISCARD 命令格式

在图 5-7 中:

  • EventID 标识要丢弃的与设备关联的中断。

  • DeviceID 指定请求设备。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

命令及其参数为:

DISCARD DeviceID, EventID

如果以下任何情况适用,则发生命令错误:

  • DeviceID 超过 ITS 支持的最大值。

  • DeviceID 指定的设备未使用 MAPD 映射到 ITT。

  • EventID 超过 ITT 允许的最大值。此值在发出 MAPD 命令时由 Size 字段指定。

  • 设备的 EventID 未使用 MAPI 或 MAPTI 映射到集合。

  • 设备的 EventID 映射到未使用 MAPC 映射到 RDbase 的集合。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

在 GICv4.1 中,当为映射到虚拟 LPI 的 EventID 和 DeviceID 发出此命令,且关联的 vPEID 未映射到该 ITS 上的 Redistributor 时:

  • 它移除 ITS 上 EventID 和 DeviceID 的映射。

  • 如果 vPE 在至少一个其他 ITS 上映射,是否清除挂起状态是 IMPLEMENTATION DEFINED 的。

  • 如果 vPE 在任何 ITS 上都未映射,则不清除挂起状态。

如果没有为其发出 V=1 的 VMAPP,或者已通过 V=0 的 VMAPP 取消映射,则 vPEID 被归类为_未映射_。

以下伪代码描述了 DISCARD 命令的操作:

// ITS.DISCARD // ===========
ITS.DISCARD(ITSCommand cmd)
    if DeviceOutOfRange(cmd.DeviceID)
    then if GITS_TYPER.SEIS == '1'
    then IMPLEMENTATION_DEFINED "SError DISCARD_DEVICE_OOR";
UNPREDICTABLE;

DeviceTableEntry dte = ReadDeviceTable(UInt(cmd.DeviceID));

if !dte.Valid then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError DISCARD_UNMAPPED_DEVICE";
        UNPREDICTABLE;
    if IdOutOfRange(cmd.EventID, dte.ITT_size) then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError DISCARD_ID_OOR";
            UNPREDICTABLE;
        InterruptTableEntry ite = ReadTranslationTable(dte.ITT_base, UInt(cmd.EventID));
        if ite.Valid then success = ClearPendingState(ite);
        if !success then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError DISCARD_ITE_INVALID";
                UNPREDICTABLE;
        else if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError DISCARD_UNMAPPED_INTERRUPT";
            UNPREDICTABLE;

ite.Valid = FALSE; WriteTranslationTable(dte.ITT_base, UInt(cmd.EventID), ite);

IncrementReadPointer(); return;

5.3.5 INT

此命令将由 EventID 和 DeviceID 定义的事件转换为 ICID 和 pINTID,并指示适当的 Redistributor 设置中断挂起。

图 5-8 显示了 INT 命令的格式。

63323187 0DW
DeviceIDRES00x030
RES0EventID1
RES02
RES03

图 5-8 INT 命令格式 在图 5-8 中:

  • EventID 标识与设备关联的中断源。然后 ITS 将其转换为 LPI INTID。

  • DeviceID 指定请求设备。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

命令及其参数为:

INT DeviceID, EventID

如果以下任何情况适用,则发生命令错误:

  • DeviceID 超过 ITS 支持的最大值。

  • DeviceID 指定的设备未使用 MAPD 映射到 ITT。

  • EventID 超过 ITT 允许的最大值。此值在发出 MAPD 命令时由 Size 字段指定。

  • EventID 未使用 MAPI 或 MAPTI 映射到集合。

  • 设备的 EventID 映射到未使用 MAPC 映射到 RDbase 的集合。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

以下伪代码描述了 INT 命令的操作:

// ITS.INT // ======= ITS.INT(ITSCommand cmd)
if DeviceOutOfRange(cmd.DeviceID) then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError INT_DEVICE_OOR";
        UNPREDICTABLE;
    DeviceTableEntry dte = ReadDeviceTable(UInt(cmd.DeviceID));
    if !dte.Valid then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError INT_UNMAPPED_DEVICE";
            UNPREDICTABLE;
        if IdOutOfRange(cmd.EventID, dte.ITT_size) then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError INT_ID_OOR";
                UNPREDICTABLE;
            InterruptTableEntry ite = ReadTranslationTable(dte.ITT_base, UInt(cmd.EventID));
            if !ite.Valid then
                if GITS_TYPER.SEIS == '1' then
                    IMPLEMENTATION_DEFINED "SError INT_UNMAPPED_INTERRUPT";
                    UNPREDICTABLE;
                boolean success = SetPendingState(ite);
                if !success then
                    if GITS_TYPER.SEIS == '1' then
                        IMPLEMENTATION_DEFINED "SError INT_ITE_INVALID";
                        UNPREDICTABLE;
                    IncrementReadPointer();
                    return;

5.3.6 INV

此命令指定 ITS 必须确保与指定 EventID 关联的 Redistributor 中的任何缓存与内存中保存的 LPI Configuration 表一致。

在 GICv4.1 中,INV 是否影响默认门铃的生成和优先级是 IMPLEMENTATION DEFINED 的。

注意 无论中断是否映射为物理中断还是虚拟中断,INV 命令都执行相同的功能。

图 5-9 显示了 INV 命令的格式。

63323187 0DW
DeviceIDRES00x0C0
RES0EventID1
RES02
RES03

图 5-9 INV 命令格式

在图 5-9 中:

  • EventID 标识与设备关联的中断源。然后 ITS 将其转换为 LPI INTID。

  • DeviceID 指定请求设备。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。 命令及其参数为:

INV DeviceID, EventID

如果以下任何情况适用,则发生命令错误:

  • DeviceID 超过 ITS 支持的最大值。

  • DeviceID 指定的设备未使用 MAPD 映射到 ITT。

  • EventID 超过 ITT 允许的最大值。此值在发出 MAPD 命令时由 Size 字段指定。

  • EventID 未使用 MAPI 或 MAPTI 映射到集合。

  • 设备的 EventID 对应于物理 LPI 并映射到未使用 MAPC 映射到 RDbase 的集合。

  • 设备的 EventID 对应于与未使用 VMAPP GICv4.0 或 VMAPP GICv4.1 映射到 Redistributor 的 vPE 关联的虚拟 LPI。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

以下伪代码描述了 INV 命令的操作:

// ITS.INV // ======= ITS.INV(ITSCommand cmd)
if DeviceOutOfRange(cmd.DeviceID) then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError INV_DEVICE_OOR";
        UNPREDICTABLE;
    DeviceTableEntry dte = ReadDeviceTable(UInt(cmd.DeviceID));
    if !dte.Valid then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError INV_UNMAPPED_DEVICE";
            UNPREDICTABLE;
        if IdOutOfRange(cmd.EventID, dte.ITT_size) then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError INV_ID_OOR";
                UNPREDICTABLE;
            InterruptTableEntry ite = ReadTranslationTable(dte.ITT_base, UInt(cmd.EventID));
            if !ite.Valid then
                if GITS_TYPER.SEIS == '1' then
                    IMPLEMENTATION_DEFINED "SError INV_UNMAPPED_INTERRUPT";
                    UNPREDICTABLE;
                invalidateByITE(ite);
                IncrementReadPointer();
                return;

5.3.7 INVALL

此命令指定 ITS 必须确保与 ICID 定义的中断集合关联的任何缓存与所有 Redistributor 的内存中保存的 LPI Configuration 表一致。

在 GICv4.1 中,INVALL 是否影响默认门铃的生成和优先级是 IMPLEMENTATION DEFINED 的。

图 5-10 显示了 INVALL 命令的格式。

Image text

63 16 15 8 7 0 DW
RES0 0x0D 0
RES0 1
RES0 ICID 2
RES0 3

**图 5-10 INVALL 命令格式**

在图 5-10 中:

  • ICID 指定中断集合。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

命令及其参数为:

INVALL ICID

如果以下任何情况适用,则发生命令错误:

  • ICID 指定的集合超过 ITS 支持的最大数量。

  • ICID 指定的集合未使用 MAPC 映射到 RDbase。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

以下伪代码描述了 INVALL 命令的操作:

// ITS.INVALL // ==========
ITS.INVALL(ITSCommand cmd)
    if (CollectionOutOfRange(cmd.ICID))
    then if GITS_TYPER.SEIS == '1'
    then IMPLEMENTATION_DEFINED "SError INVALL_COLLECTION_OOR";
UNPREDICTABLE;

CollectionTableEntry cte = ReadCollectionTable(UInt(cmd.ICID));

if !cte.Valid then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError INVALL_UNMAPPED_COLLECTION";
        UNPREDICTABLE;
    // This invalidates any caches containing the configuration data
    for all interrupts in the
    // collection. Over invalidation is permitted.
    InvalidateCollectionCaches(UInt(cmd.ICID));
    IncrementReadPointer();
    return;

5.3.8 INVDB 仅 GICv4.1

在 GICv4.1 中,ITS 命令 INVDB 分配用于无效默认门铃的配置:

图 5-11 显示了仅 GICv4.1 的 INVDB 命令格式。

Image text

63 48 47 32 31 16 15 8 7 0 DW
RES0 0x2E 0
RES0 vPEID RES0 1
RES0 2
RES0 3

**图 5-11 INVDB 命令编码** 其中:
  • vPEID = vPE 的 vPEID。
// ITS.INVDB // ========= ITS.INVDB(ITSCommand cmd)
if VCPUOutOfRange(cmd.VCPUID) then
    if GITS_TYPER.SEIS == 1 then
        IMPLEMENTATION_DEFINED "SError INVDB_VCPU_OOR";
        UNPREDICTABLE;
    VCPUTableEntry vte = ReadVCPUTable(UInt(cmd.VCPUID));
    if vte.Valid then InvalidateInterruptDoorbellCaches(VCPUID, vte);
    IncrementReadPointer();
    return;

INVDB 由 VSYNC 命令同步。

INVDB 命令完成后,在任何 Redistributor 中都没有与指定 vPE 的默认门铃关联的缓存。

如果以下任何情况适用,则发生命令错误:

  • 使用超过 ITS 配置的最大 vPEID 的 vPEID 发出 INVDB:INVDB_VCPU_OOR (0x01_2E11)。

如果以下任一点为真,具有有效 vPEID 的 INVDB 表现为 NOP:

  • vPEID 未在 ITS 上映射。

  • vPEID 没有默认门铃。

5.3.9 MAPC

此命令将由 ICID 定义的集合表条目映射到由 RDbase 定义的目标 Redistributor。

图 5-12 显示了 MAPC 命令的格式。

63625150168 157 0DW
RES00x090
RES01
VRES0RDbaseICID2
RES03

图 5-12 MAPC 命令格式

在图 5-12 中:

  • V 指定集合的 RDbase 是否有效。

  • RDbase 指定集合中中断转发到的目标 Redistributor。请参见_ITS 命令参数中的 IMPLEMENTATION DEFINED 大小_。

  • ICID 指定要映射的中断集合。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

如果 GITS_TYPER.PTA == 1 并且指定了物理地址,则目标地址必须 64KB 对齐,意味着只需要位 [47:16]。有关更多信息,请参见_ITS 命令参数中的 IMPLEMENTATION DEFINED 大小_。此外,当 V 清零为 0 时,此字段必须写为零,但硬件可能忽略该值。

命令及其参数为: MAPC ICID, RDbase, V

当 V 为 1 时:

  • 如果有中断映射到指定的集合且集合当前映射到 Redistributor,则行为是不可预测的,除非 MAPC 之后跟随 MOVALL,以便将集合的挂起状态从旧目标 Redistributor 移动到新目标 Redistributor。MOVALL 可能由不同的 ITS 发出:

    • 当多个集合从同一源重新映射到同一目的地时,如果在所有 MAPC 全局可观察之前发出 MOVALL,则行为是不可预测的。

    • 如果在 MOVALL 全局可观察之前,在 MAPC 之后发出影响属于重新映射集合的中断的任何 ITS 命令,则行为是不可预测的。

  • 如果 RDbase 未指定有效的 Redistributor,则行为是不可预测的。

当 V 为 0 时:

  • MAPC 移除指定中断集合的映射。映射到此集合的中断被忽略。

  • 如果有中断映射到指定的集合,则行为是不可预测的,限制是来自该设备的进一步转换请求被忽略。

如果以下情况适用,则发生命令错误:

  • ICID 指定的集合超过 ITS 支持的最大数量。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

注意

当软件使用 MAPC 命令将集合从目标 Redistributor A 移动到目标 Redistributor B 时,必须在发出伴随的 MOVALL 命令之前向 Redistributor A 发出 SYNC 命令。否则,来自集合的中断仍可能被与 Redistributor A 关联的 PE 接受。

以下伪代码描述了 MAPC 命令的操作:

// ITS.MAPC // ======== ITS.MAPC(ITSCommand cmd)
if CollectionOutOfRange(cmd.ICID) then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError MAPC_COLLECTION_OOR";
        UNPREDICTABLE;
    CollectionTableEntry cte;
    cte.Valid  = cmd.V == '1';
    cte.RDbase = cmd.RDbase;
    WriteCollectionTable(UInt(cmd.ICID), cte);
    IncrementReadPointer();
    return;

5.3.10 MAPD

此命令将与 DeviceID 关联的设备表条目映射到其关联的 ITT,由 ITT_addr 和 Size 定义。

图 5-13 显示了 MAPD 命令的格式。

63625251323187 50 4DW
DeviceIDRES00x080
RES0Size1
VRES0ITT_addrRES02
RES03

图 5-13 MAPD 命令格式 在图 5-13 中:

  • DeviceID 指定使用 ITT 的设备。

注意 有关将设备映射到 ITT 的更多信息,请参见_中断转换表_。

  • V 指定 ITT_addr 和 Size 字段是否有效。

  • ITT_addr 指定 ITT 物理地址的位 [51:8]。

  • Size 是一个 5 位数字,指定设备支持的位数减一。size 字段启用对此 DeviceID 的转换请求的 EventID 范围检查。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

如果以下任何情况适用,则行为是 UNPREDICTABLE 的:

  • DeviceID 已存在映射且映射的 ITT 包含有效的 EventID 映射。

  • 当 V == 1 时,指定的 ITT 不包含全零。

命令及其参数为:

MAPD DeviceID, ITT_addr, Size, V

ITT 条目的格式是 IMPLEMENTATION DEFINED 的。典型的示例条目大小为 8 字节,允许以 32 个中断的倍数向设备分配标识符。

当 V 为 1 时:

  • MAPD 将 DeviceID 与 ITT 的 256 字节对齐地址关联。

  • 当 V 为 0 时:

  • MAPD 移除指定 DeviceID 的映射。来自该设备的转换请求被忽略。

  • MAPD 移除指定 DeviceID 的映射,来自该设备的中断请求被丢弃。在 DeviceID 再次映射到 ITT 之前,DeviceID 的后续转换不会生成 LPI 或 VLPI。

如果以下任何情况适用,则发生命令错误:

  • DeviceID 超过 ITS 支持的最大设备数量。

  • 当 V 设置为 1 时,Size 超过 GITS_TYPER.ID_bits 设置允许的最大值。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

注意 ITS 对 ITT 的访问使用为设备表指定的相同 Shareability 和 Cacheability 属性,请参见_设备表_。

以下伪代码描述了 MAPD 命令的操作:

// ITS.MAPD // ======== ITS.MAPD(ITSCommand cmd)
    if DeviceOutOfRange(cmd.DeviceID)
    then if GITS_TYPER.SEIS == '1'
    then IMPLEMENTATION_DEFINED "SError MAPD_DEVICE_OOR";
UNPREDICTABLE;
if SizeOutOfRange(cmd.Size) then

if GITS_TYPER.SEIS == '1' then IMPLEMENTATION_DEFINED "SError MAPD_ITTSIZE_OOR"; UNPREDICTABLE;
// If a device is Re-mapped software must perform the following actions
// to ensure the LPI configuration is up to date:
// 1. Ensure that the device is quiescent and that all interrupts have
//     been handled.
// 2. Remap the device with the new (empty) ITT
//
DeviceTableEntry dte;

5.3.11 MAPI

此命令将由 EventID 和 DeviceID 定义的事件映射到具有 ICID 和 pINTID = EventID 的 ITT 条目。

注意

  • pINTID ≥0x2000 用于有效的 LPI INTID。

  • 这等价于 MAPTI DeviceID, EventID, EventID, ICID

图 5-14 显示了 MAPI 命令的格式。

633231168 157 0DW
DeviceIDRES00x0B0
RES0EventID1
RES0ICID2
RES03

图 5-14 MAPI 命令格式

在图 5-14 中:

  • EventID 标识要映射的与设备关联的中断。

  • DeviceID 指定请求设备。

  • ICID 指定包含指定中断的中断集合。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

如果 EventID-DeviceID 组合已存在映射,则行为是 UNPREDICTABLE 的。

命令及其参数为:

MAPI DeviceID, EventID, ICID

如果以下任何情况适用,则发生命令错误:

  • DeviceID 超过 ITS 支持的最大值。

  • DeviceID 指定的设备未使用 MAPD 映射到 ITT。

  • ICID 超过 ITS 支持的最大中断集合数量。有关更多信息,请参见_集合表_。

  • EventID 超过 ITT 允许的最大值。此值在发出 MAPD 命令时由 Size 字段指定。 • EventID 未指定有效的 LPI 标识符。请参见_INTID_。在这种情况下,ITS 必须采取_命令错误_中描述的操作。以下伪代码描述了 MAPI 命令的操作:

// ITS.MAPI // ======== ITS.MAPI(ITSCommand cmd)
if DeviceOutOfRange(cmd.DeviceID) then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError MAPI_DEVICE_OOR";
        UNPREDICTABLE;
    if CollectionOutOfRange(cmd.ICID) then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError MAPI_COLLECTION_OOR";
            UNPREDICTABLE;
        DeviceTableEntry dte = ReadDeviceTable(UInt(cmd.DeviceID));
        if !dte.Valid then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError MAPI_UNMAPPED_DEVICE";
                UNPREDICTABLE;
            if IdOutOfRange(cmd.EventID, dte.ITT_size) then
                if GITS_TYPER.SEIS == '1' then
                    IMPLEMENTATION_DEFINED "SError MAPI_ID_OOR";
                    UNPREDICTABLE;
                if LPIOutOfRange(cmd.EventID) then
                    if GITS_TYPER.SEIS == '1' then
                        IMPLEMENTATION_DEFINED "SError MAPI_ID_OOR";
                        UNPREDICTABLE;
                    InterruptTableEntry ite = ReadTranslationTable(dte.ITT_base, UInt(cmd.EventID));

ite.Valid = TRUE; ite.Type = physical_interrupt; ite.OutputID = cmd.EventID; ite.DoorbellID = ZeroExtend(INTID_SPURIOUS); // Don’t generate a doorbell ite.ICID = cmd.ICID;

WriteTranslationTable(dte.ITT_base, UInt(cmd.EventID), ite);

IncrementReadPointer();

return;

5.3.12 MAPTI

此命令将由 EventID 和 DeviceID 定义的事件映射到其关联的 ITE,由与 DeviceID 关联的 ITT 中的 ICID 和 pINTID 定义。

图 5-15 显示了 MAPTI 命令的格式。

633231168 157 0DW
DeviceIDRES00x0A0
pINTIDEventID1
RES0ICID2
RES03

图 5-15 MAPTI 命令格式 在图 5-15 中:

  • EventID 标识要映射的与设备关联的中断。

  • pINTID 是呈现给软件的物理中断的 INTID。

  • DeviceID 指定请求设备。

  • ICID 指定包含指定物理中断的中断集合。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

如果 EventID-DeviceID 组合已存在映射,则行为是 UNPREDICTABLE 的。

命令及其参数为:

MAPTI DeviceID, EventID, pINTID, ICID

如果以下任何情况适用,则发生命令错误:

  • DeviceID 超过 ITS 支持的最大值。

  • DeviceID 指定的设备未使用 MAPD 映射到 ITT。

  • 集合数量超过 ITS 支持的最大集合数量。有关更多信息,请参见_集合表_。

  • EventID 超过 ITT 允许的最大值。此值在发出 MAPD 命令时由 Size 字段指定。

  • pINTID 未指定有效的 LPI INTID。有关 LPI INTID 范围的信息,请参见_INTID_。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

以下伪代码描述了 MAPTI 命令的操作:

// ITS.MAPTI // =========

ITS.MAPTI(ITSCommand cmd)

if DeviceOutOfRange(cmd.DeviceID) then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError MAPTI_DEVICE_OOR";
        UNPREDICTABLE;
    if CollectionOutOfRange(cmd.ICID) then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError MAPTI_COLLECTION_OOR";
            UNPREDICTABLE;
        DeviceTableEntry dte = ReadDeviceTable(UInt(cmd.DeviceID));
        if !dte.Valid then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError MAPTI_UNMAPPED_DEVICE";
                UNPREDICTABLE;
            if IdOutOfRange(cmd.EventID, dte.ITT_size) then
                if GITS_TYPER.SEIS == '1' then
                    IMPLEMENTATION_DEFINED "SError MAPTI_ID_OOR";
                    UNPREDICTABLE;
                if LPIOutOfRange(cmd.pINTID) then
                    if GITS_TYPER.SEIS == '1' then
                        IMPLEMENTATION_DEFINED "SError MAPTI_PHYSICALID_OOR";
                        UNPREDICTABLE;
                    InterruptTableEntry ite = ReadTranslationTable(dte.ITT_base, UInt(cmd.EventID));

ite.Valid = TRUE; ite.Type = physical_interrupt; ite.OutputID = cmd.pINTID; ite.DoorbellID = ZeroExtend(INTID_SPURIOUS); // Don’t generate a doorbell ite.ICID = cmd.ICID;

WriteTranslationTable(dte.ITT_base, UInt(cmd.EventID), ite);

IncrementReadPointer();

return;

5.3.13 MOVALL

此命令指示由 RDbase1 指定的 Redistributor 将其所有中断移动到由 RDbase2 指定的 Redistributor。

注意 中断到集合的映射和集合到 Redistributor 的映射通常不受此命令影响。软件必须确保可能受此命令影响的任何中断都针对 RDbase2 指定的 Redistributor,否则系统行为是 UNPREDICTABLE 的。特别是,实现可能选择将所有受影响的集合重新映射到 RDbase2。

图 5-16 显示了 MOVALL 命令的格式。

6351503231168 157 0DW
RES00x0E0
RES01
RES0Rdbase 1RES02
RES0Rdbase 2RES03

图 5-16 MOVALL 命令格式

在图 5-16 中:

  • RDbase1 指定当前与中断关联的 Redistributor。请参见_ITS 命令参数中的 IMPLEMENTATION DEFINED 大小_。

  • RDbase2 指定中断要移动到的 Redistributor。请参见_ITS 命令参数中的 IMPLEMENTATION DEFINED 大小_。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

命令及其参数为:

MOVALL RDbase1, RDbase2

如果 RDbase1 和 RDbase2 未指定有效的 Redistributor,则行为是不可预测的。这些字段的格式由 GITS_TYPER.PTA 指定。

针对禁用 LPI 的 RD 的 MOVALL 是 CONSTRAINED UNPREDICTABLE 的,可选择:

  • 清除所有移动的 LPI 的挂起状态。

  • 作为 NOP,挂起状态在源 RD 上保持不变。

以下伪代码描述了 MOVALL 命令的操作:

// ITS.MOVALL // ==========
ITS.MOVALL(ITSCommand cmd) rd1 = cmd.RD1base;
rd2 = cmd.RD2base;
if rd1 != rd2
    then MoveAllPendingState(rd1, rd2);

IncrementReadPointer();

return;

5.3.14 MOVI

此命令更新由 DeviceID 和 EventID 定义的事件的 ITT 条目中的 ICID 字段。它还将由 EventID 和 DeviceID 定义的事件转换为 ICID 和 pINTID,并指示适当的 Redistributor 将中断的挂起状态(如果已设置)移动到由新 ICID 定义的 Redistributor,并更新与事件关联的 ITE 以使用新的 ICID。

图 5-17 显示了 MOVI 命令的格式。

633231168 157 0DW
DeviceIDRES00x010
RES0EventID1
RES0ICID2
RES03

图 5-17 MOVI 命令格式

在图 5-17 中:

  • EventID 标识要重定向的与设备关联的中断。

  • DeviceID 指定请求设备。

  • ICID 指定要包含指定物理中断的新中断集合。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

命令及其参数为:

MOVI DeviceID, EventID, ICID

如果以下任何情况适用,则发生命令错误:

  • DeviceID 超过 ITS 支持的最大值。

  • DeviceID 指定的设备未使用 MAPD 映射到 ITT。

  • ICID 超过 ITS 支持的最大中断集合数量。

  • ICID 未使用 MAPC 映射到 RDbase。

  • EventID 未使用 MAPI 或 MAPTI 映射到集合。

  • EventID 对应于虚拟 LPI。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

注意 如果在使用 MOVI 将中断从集合 A 移动到集合 B 后,软件再次将同一中断从集合 B 移动到集合 C,则必须在第二个 MOVI 之前为与集合 A 关联的 Redistributor 使用 SYNC 命令以确保正确行为。

当发出的 MOVI 针对未映射的集合或映射到禁用 LPI 的 Redistributor 的集合时,行为是 CONSTRAINED UNPREDICTABLE 的,可选择:

  • 清除移动的 LPI 的挂起状态。

  • 源 RD 上的挂起状态保持不变。

以下伪代码描述了 MOVI 命令的操作:

// ITS.MOVI // ========

ITS.MOVI(ITSCommand cmd)

if DeviceOutOfRange(cmd.DeviceID) then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError MOVI_DEVICE_OOR";
        UNPREDICTABLE;
    if CollectionOutOfRange(cmd.ICID) then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError MOVI_COLLECTION_OOR";
            UNPREDICTABLE;
        DeviceTableEntry dte = ReadDeviceTable(UInt(cmd.DeviceID));
        if !dte.Valid then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError MOVI_UNMAPPED_DEVICE";
                UNPREDICTABLE;
            if IdOutOfRange(cmd.EventID, dte.ITT_size) then
                if GITS_TYPER.SEIS == '1' then
                    IMPLEMENTATION_DEFINED "SError MOVI_ID_OOR";
                    UNPREDICTABLE;
                InterruptTableEntry ite = ReadTranslationTable(dte.ITT_base, UInt(cmd.EventID));
                if !ite.Valid then
                    if GITS_TYPER.SEIS == '1' then
                        IMPLEMENTATION_DEFINED "SError MOVI_UNMAPPED_INTERRUPT";
                        IncrementReadPointer();
                        return;
                    if ite.Type == virtual_interrupt then
                        if GITS_TYPER.SEIS == '1' then
                            IMPLEMENTATION_DEFINED "SError MOVI_ID_IS_VIRTUAL";
                            UNPREDICTABLE;
                        CollectionTableEntry cte1 = ReadCollectionTable(UInt(ite.ICID));
                        if !cte1.Valid then
                            if GITS_TYPER.SEIS == '1' then
                                IMPLEMENTATION_DEFINED "SError MOVI_UNMAPPED_COLLECTION";
                                UNPREDICTABLE;
                            CollectionTableEntry cte2 = ReadCollectionTable(UInt(cmd.ICID));
                            if !cte2.Valid then
                                if GITS_TYPER.SEIS == '1' then
                                    IMPLEMENTATION_DEFINED "SError MOVI_UNMAPPED_COLLECTION";
                                    IncrementReadPointer();
                                    return;
                                bits(32) rd1 = cte1.RDbase;
                                bits(32) rd2 = cte2.RDbase;
                                if rd1 != rd2 then
                                    // Move the move the pending state to rd2
                                    if set taking care of any races where the
                                    // interrupt has been forwarded to the processor
                                    MovePendingState(rd1, rd2, ite.OutputID);

5.3.15 SYNC

此命令确保在执行任何进一步的 ITS 命令之前,与 RDbase 指定的 Redistributor 的物理中断关联的所有未完成的 ITS 操作都被全局观察。在 SYNC 执行后,所有先前命令的效果必须应用于对 GITS_TRANSLATER 的后续写入。

图 5-18 显示了 SYNC 命令的格式。

6351503231168 157 0DW
RES00x050
RES01
RES0RDbaseRES02
RES03

图 5-18 SYNC 命令格式 在图 5-18 中:

  • RDbase 指定目标 Redistributor 的物理地址。目标地址的格式由 GITS_TYPER.PTA 确定。有关更多信息,请参见_ITS 命令参数中的 IMPLEMENTATION DEFINED 大小_。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

命令及其参数为:

SYNC RDbase

以下伪代码描述了 SYNC 命令的操作:

// Wait for the external effects of any virtual commands to be observable by all redistributors
// and ensure the internal effects of any previous commands affect any subsequent interrupt
// requests or commands
WaitForVirtualCompletion(rd_base);

IncrementReadPointer();

return;

5.3.16 VINVALL

此命令确保与 vPEID 关联的任何缓存的 Redistributor 信息与内存中保存的关联 LPI Configuration 表一致。

此命令仅在 GICv4 中提供。

图 5-19 显示了 VINVALL 命令的格式。

634847323187 0DW
RES00x2D0
RES0vPEIDRES01
RES02
RES03

图 5-19 VINVALL 命令格式

在图 5-19 中:

  • vPEID 指定 vPE。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

命令及其参数为:

VINVALL vPEID

如果以下任何情况适用,则发生命令错误:

  • vPEID 超过 ITS 支持的最大数量,如 GITS_BASER 定义。

  • vPEID 指定的 PE 未使用 VMAPP GICv4.0 映射到 Redistributor。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。 以下伪代码描述了 VINVALL 命令的操作:

// ITS.VINVALL // ===========
ITS.VINVALL(ITSCommand cmd)
    if VCPUOutOfRange(cmd.VCPUID) then
if GITS_TYPER.SEIS == '1' then
    IMPLEMENTATION_DEFINED "SError VINVALL_VCPU_OOR";
    UNPREDICTABLE;
VCPUTableEntry vte = ReadVCPUTable(UInt(cmd.VCPUID));
if !vte.Valid then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError VINVALL_VCPU_INVALID";
        UNPREDICTABLE;
    InvalidateVCPUCaches(UInt(cmd.VCPUID));
    IncrementReadPointer();
    return;

5.3.17 VMAPI

此命令将由 DeviceID 和 EventID 定义的事件映射到具有 vPEID、vINTID=EventID 和 Dbell_PINTID(门铃规定)的 ITT 条目。

注意

  • vINTID ≥0x2000 用于有效的 LPI INTID。

  • 这等价于 VMAPTI DeviceID, EventID, EventID, pINTID, vPEID。

  • Dbell_pINTID 必须是 1023 或 Dbell_pINTID ≥0x2000 用于有效的 LPI INTID。

此命令仅在 GICv4 中提供。

图 5-20 显示了 VMAPI 命令的格式。

Image text

63 48 47 32 31 8 7 0 DW
DeviceID RES0 0x2B 0
RES0 vPEID EventID 1
Dbell_pINTID RES0 2
RES0 3

**图 5-20 VMAPI 命令格式**

在图 5-20 中:

  • EventID 标识要呈现给 VM 的与设备关联的中断。

  • DeviceID 指定请求设备。

  • vPEID 指定 vPE。

  • Dbell_pINTID 指定如果 vPE 未调度时呈现给 hypervisor 的 ID。

    • 注意

如果 Dbell_pINTID 指示伪造中断,则不生成物理中断。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

如果 EventID-DeviceID 组合已存在映射,则行为是 UNPREDICTABLE 的。

命令及其参数为:

VMAPI DeviceID, EventID, Dbell_pINTID, vPEID 如果以下任何情况适用,则发生命令错误:

  • DeviceID 超过 ITS 支持的最大值。

  • vPEID 超过 ITS 支持的最大数量,如 GITS_BASER 定义。

  • DeviceID 指定的设备未使用 MAPD 映射到 ITT。

  • EventID 超过 ITT 允许的最大值。此值在发出 MAPD 命令时由 Size 字段指定。

  • EventID 未指定有效的 LPI INTID。有关有效 LPI INTID 的信息,请参见_INTID_。

  • Dbell_pINTID 未指定有效的门铃 INTID,其中有效 INTID 为: — 1023。

    • 在 LPI 支持的范围内。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

以下伪代码描述了 VMAPI 命令的操作:

// ITS.VMAPI // =========
ITS.VMAPI(ITSCommand cmd)
    if DeviceOutOfRange(cmd.DeviceID)
    then if GITS_TYPER.SEIS == '1'
    then IMPLEMENTATION_DEFINED "SError VMAPI_DEVICE_OOR";
UNPREDICTABLE;
if VCPUOutOfRange(cmd.VCPUID) then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError VMAPI_VCPU_OOR";
        UNPREDICTABLE;
    DeviceTableEntry dte = ReadDeviceTable(UInt(cmd.DeviceID));
    if !dte.Valid then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError VMAPI_UNMAPPED_DEVICE";
            UNPREDICTABLE;
        if IdOutOfRange(cmd.EventID, dte.ITT_size) then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError VMAPI_ID_OOR";
                UNPREDICTABLE;
            if LPIOutOfRange(cmd.EventID) then
                if GITS_TYPER.SEIS == '1' then
                    IMPLEMENTATION_DEFINED "SError VMAPI_ID_OOR";
                    UNPREDICTABLE;
                if LPIOutOfRange(cmd.Dbell_pINTID) then
                    if GITS_TYPER.SEIS == '1' then
                        IMPLEMENTATION_DEFINED "SError VMAPI_PHYSICALID_OOR";
                        UNPREDICTABLE;
                    InterruptTableEntry ite = ReadTranslationTable(dte.ITT_base, UInt(cmd.EventID));

ite.Valid = TRUE; ite.Type = virtual_interrupt; ite.OutputID = cmd.EventID; ite.DoorbellID = cmd.Dbell_pINTID; ite.VCPUID = cmd.VCPUID;

WriteTranslationTable(dte.ITT_base, UInt(cmd.EventID), ite);

IncrementReadPointer();

return;

5.3.18 VMAPP GICv4.0

此命令将由 vPEID 定义的 vPE 表条目映射到目标 RDbase,包括关联的虚拟 LPI Pending 表(VPT_addr,VPT_size)。

图 5-21 显示了 GICv4.0 的 VMAPP 命令格式。

636251503231168 157 50 4DW
RES00x290
RES0vPEIDRES01
VRES0RDbaseRES02
RES0VPT_addrRES0VPT_ size3

图 5-21 VMAPP GICv4.0 命令格式 在图 5-21 中:

  • vPEID 指定 vPE。

  • V 指定 vPE 的 RDbase 和 VPT_addr 是否有效。

  • RDbase 指定拥有 vPE 并且 ITS 为该 PE 定向命令的目标 Redistributor。请参见_ITS 命令参数中的 IMPLEMENTATION DEFINED 大小_。

  • VPT_addr 指定 vPE 的虚拟 LPI Pending 表物理地址的位 [51:16]。

注意 目标地址必须 64KB 对齐,意味着只需要位 [51:16]。物理地址的位 [15:0] 为 0。

  • VPT_size 指定 vPE 支持的 vINTID 位数减一。

  • DW 是 32 字节或四个双字的 ITS 命令包中的双字偏移。

命令及其参数为:

VMAPP vPEID, RDbase, VPT_addr, VPT_size, V

当 V 为 0 时:

  • VMAPP 移除指定 vPE 的映射。映射到此 vPE 的中断被丢弃。

当 V 为 1 时:

  • 如果 RDbase 未指定有效的 Redistributor,则行为是 UNPREDICTABLE 的。

如果以下任何情况适用,则发生命令错误:

  • vPEID 超过 ITS 支持的最大数量,如 GITS_BASER 定义。

  • Size 超过 GITS_TYPER.ID_bits 设置允许的最大值。

在这种情况下,ITS 必须采取_命令错误_中描述的操作。

注意 如果系统包含多个 ITS,Arm 强烈建议当另一个 ITS 上有同一 vPEID 的未完成 VMOVP 时,软件不要发出 VMAPP,因为这可能产生竞争条件。

以下伪代码描述了 VMAPP 命令的操作:

// ITS.VMAPP // =========
ITS.VMAPP(ITSCommand cmd)
    if VCPUOutOfRange(cmd.VCPUID) then
if GITS_TYPER.SEIS == '1' then IMPLEMENTATION_DEFINED "SError VMAPP_VCPU_OOR"; UNPREDICTABLE;

VCPUTableEntry vte;
// Common to GICv4.0 and GICv4.1
vte.Valid = cmd.V == '1';
vte.RDbase = cmd.RDbase;

if HasGIC41Ext() then
    // GICv4.1

    if ((Uint(cmd.VPT_size) < 14) || ((Uint(GICD_TYPER.bits) > 23)) then
        if ConstrainUnpredictableBool() then
            (c, cmd.VPT_size) = ConstrainUnpredictableInteger(14, 24);
            assert (c == Constraint_UNKNOWN);

    // Record configuration in vPE Configuration Table,
    // held by Redistributors
    WriteVPEConfigurationTable(UInt(cmd.VCPUID), cmd.RDbase,
        cmd.VCONF_addr, cmd.VPT_addr,
        cmd.Default_Doorbell_pINTID, cmd.VPT_size,
        cmd.V, cmd.Alloc, cmd.PTZ);

    // The ITS could record the size of the VPT to detect out of range
    // INTIDs, or it could rely on the Redistributors doing this.
else
    // GICv4.0
    if SizeOutOfRange(cmd.VPT_size) then
        if GITS_TYPER.SEIS == '1' then IMPLEMENTATION_DEFINED "SError
            VMAPP_VPTSIZE_OOR";
        UNPREDICTABLE;
    vte.VPT_base = cmd.VPT_addr:Zeros(16);
    vte.VPT_size = cmd.VPT_size;

WriteVCPUTable(UInt(cmd.VCPUID), vte);

IncrementReadPointer();

return;

5.3.19 VMAPP GICv4.1

在 GICv4.1 中修改了 VMAPP 命令,以允许指定 vPE 的 LPI 配置和挂起表位置。

图 5-22 显示了 GICv4.1 的 VMAPP 命令格式。

Image text

63 52 51 48 47 32 31 16 15 9 8 7 0 DW
RES0 VCONF_addr RES0 P All 0x29 0
T oc
Z
RES0 vPEID Default_Doorbell_pINTID 1
V RES0 RDbase RES0 2
RES0 VPT_addr RES0 VPT_size 3

**图 5-22 VMAPP GICv4.1 命令编码**

在图 5-22 中:

  • RDbase = 标识目标 Redistributor。当 V==0 时为 RES0。

  • VCONF_addr = vPE 虚拟配置表地址的位 [51:16],位 [15:0] 为 0。当 V==0 时为 RES0。

  • VPT_addr = vPE 虚拟挂起表地址的位 [51:16],位 [15:0] 为 0。当 V==0 时为 RES0。

  • VPT_size = vPE 的 vINTID 位数。当 V==0 时为 RES0。

  • Default_Doorbell_pINTID 是 vPE 的默认门铃。当 V==0 时为 RES0。

  • Alloc = 表示这是否为该 vPEID 的第一次映射或最后一次取消映射。

  • PTZ = 表示 VPT_addr 是否指向归零的内存,当 V!=1 或 Alloc!=1 时忽略。

命令及其参数为:

VMAPP vPEID, RDbase, VPT_addr, VPT_size, V

当 V 为 0 时:

  • VMAPP 移除指定 vPE 的映射。

当 V 为 1 时:

  • 如果 RDbase 未指定有效的 Redistributor,则行为是 UNPREDICTABLE。

如果发生以下任何情况,会出现命令错误:

  • vPEID 超过 ITS 支持的最大数量,由 GITS_BASER 定义。

  • Size 超过 GITS_TYPER.ID_bits 设置允许的最大值。

  • V==1 的 VMAPP 指定的 Default_Doorbell_pINTID 值不是 1023 且超出已实现的 LPI 范围。报告的命令错误码为 0x01_2906 (VMAPP_PHYSICALID_OOR)。

在这种情况下,ITS 必须执行 命令错误 中描述的操作。

注意 如果系统包含多个 ITS,Arm 强烈建议软件不要在另一个 ITS 上为相同 vPEID 存在未完成的 VMOVP 时发出 VMAPP,因为这可能会造成竞争条件。

描述该命令操作的伪代码,请参见 VMAPP GICv4.0

V 和 Alloc 字段的使用

GICv4.1 引入了 vPE 配置表,它与记录虚拟 LPI 配置和挂起表位置的 Redistributor 相关联。该表使用 VMAPP 命令填充。

VMAPP 命令中的 Alloc 字段在创建或销毁 vPE 时使用,用于指示何时应更新 vPE 配置表项。

{V, Alloc}=={0, 1} 的 VMAPP 清理并使 GIC 中保存的与 vPEID 关联的任何缓存虚拟挂起表和虚拟配置表失效。Alloc 字段的无效使用可能导致 UNPREDICTABLE 行为,包括 IRI 的持续访问。

对于 V==1 的 VMAPP,VPT_size 决定了 vINTID 命名空间的大小,从中派生虚拟配置和挂起表的大小。

对于 V==1 的 VMAPP,如果 VPT_size 大于支持的 INTID 大小,则使用以下 CONSTRAINED UNPREDICTABLE 值之一:

  • 指定的值。

  • 范围内的 UNKNOWN 值。

V==1、Default_Doorbell_pINTID==1023 的 VMAPP 表示无默认门铃。

V==1 且指定以下 Default_Doorbell_pINTID 值之一的 VMAPP 会导致 UNPREDICTABLE 行为:

  • 该值用于有效的 EventID 或 DeviceID 映射。

  • 该值用于现有有效 vPE 的默认门铃。

Alloc==0 的 VMAPP 表示至少有一个 ITS 中存在该 vPEID 的现有映射。如果不是这样,结果行为是 UNPREDICTABLE。

{V, Alloc}=={1, 1} 的 VMAPP 表示这是任何 ITS 中该 vPEID 的第一次映射。在任何其他时间设置 {V, Alloc}=={1, 1} 会导致 UNPREDICTABLE 行为。

{V, Alloc}=={0, 1} 的 VMAPP 表示这是任何 ITS 中该 vPEID 的最后一次映射。在任何其他时间设置 {V, Alloc}=={0, 1} 会导致 UNPREDICTABLE 行为。

当发出 {V, Alloc}=={1, 1} 的 VMAPP 时,虚拟 LPI 配置表和虚拟 LPI 挂起表被分配给 IRI,并保持分配给 IRI 直到完成 {V, Alloc}=={0, 1} 的 VMAPP。表 5-7 总结了 V 和 Alloc 字段组合的效果。

表 5-7 V 和 Alloc 字段组合的效果

VAlloc描述
00取消映射命令,至少还有另一个 ITS 具有有效映射。
01取消映射命令,没有其他 ITS 具有有效映射。
10映射命令,至少有另一个 ITS 已经具有此映射。
11映射命令,还没有其他 ITS 具有此映射。

注意 与 Alloc 无效使用相关的 UNPREDICTABLE 行为可能包括 IRI 在释放后继续读取或写入与 vPEID 关联的内存结构。Arm 强烈建议避免这些情况。

{V, Alloc}=={0, x} 的 VMAPP 是自同步的。这意味着在其所有效果完成之前,ITS 命令队列不会显示该命令为已消费。

当实现多个 ITS 时,对不同 ITS 上的相同 vPEID 发出 V==1 的 VMAPP,使用不同的 VCONF_addr、VPT_addr 或 VPT_size 值,会导致 UNPREDICTABLE 行为。

当实现多个 ITS 时,发出 {V, Alloc}=={1, 0} 的 VMAPP,其中 Default_Doorbell_pINTID 或 RDbase 与当前配置的值不匹配,会导致 UNPREDICTABLE 行为。

当 {V, Alloc}!={1, 1} 时,PTZ 位被忽略。

当 {V, Alloc, PTZ}=={1, 1, 0} 时:

  • 指定虚拟挂起表的 IMPLEMENTATION DEFINED 区域必须包含全零或已被相同实现的 GIC 填充。否则行为是 UNPREDICTABLE。

  • IRI 将加载挂起状态和 SGI 配置。

当 {V, Alloc, PTZ}=={1, 1, 1} 时,指定的虚拟挂起表必须包含全零,否则行为是 UNPREDICTABLE。这包括 SGI 和 IMPLEMENTATION DEFINED 区域。

5.3.20 VMAPTI

此命令将由 DeviceID 和 EventID 定义的事件映射到具有 vPEID 和 vINTID 以及门铃条款 Dbell_pINTID 的 ITT 项中。

注意

  • vINTID ≥0x2000 用于有效的 LPI INTID。

  • Dbell_pINTID 必须是 1023 或 Dbell_pINTID ≥0x2000 用于有效的 LPI INTID。

此命令仅在 GICv4 中提供。

图 5-23 显示了 VMAPTI 命令的格式。

Image text

63 48 47 32 31 16 15 8 7 0 DW
DeviceID RES0 0x2A 0
RES0 vPEID EventID 1
Dbell_pINTID vINTID 2
RES0 3

**图 5-23 VMAPTI 命令格式**

在图 5-23 中:

  • vPEID 指定 vPE。

  • DeviceID 指定 vPE 拥有的设备。

  • vINTID 指定呈现给控制 DeviceID 指定设备的 vPE 的 INTID。

  • Dbell_pINTID 指定当 vPE 未被调度时呈现给 PE 的 pINTID。

注意 如果 Dbell_pINTID 为 1023,则不生成物理中断。

  • DW 是 32 字节或四个双字 ITS 命令包内的双字偏移量。

如果 EventID-DeviceID 组合存在现有映射,则行为是 UNPREDICTABLE。

命令及其参数为:

VMAPTI DeviceID, EventID, vINTID, Dbell_pINTID, vPEID

如果发生以下任何情况,会出现命令错误:

  • DeviceID 超过 ITS 支持的最大值。

  • vPEID 超过 ITS 支持的最大数量,由 GITS_BASER 定义。

  • DeviceID 指定的设备未使用 MAPD 映射到 ITT。

  • EventID 超过 ITT 允许的最大值。该值由发出 MAPD 命令时的 Size 字段指定。

  • vINTID 未指定有效的 LPI INTID,参见 INTIDs

  • Dbell_pINTID 未指定有效的门铃 INTID,其中有效的 INTID 为: — 1023。

    • 在 LPI 支持的范围内。

在这种情况下,ITS 必须执行 命令错误 中描述的操作。

以下伪代码描述了 VMAPTI 命令的操作:

// ITS.VMAPTI // ==========
ITS.VMAPTI(ITSCommand cmd)
    if DeviceOutOfRange(cmd.DeviceID)
    then if GITS_TYPER.SEIS == '1'
    then IMPLEMENTATION_DEFINED "SError VMAPTI_DEVICE_OOR";
UNPREDICTABLE;
if VCPUOutOfRange(cmd.VCPUID) then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError VMAPTI_VCPU_OOR";
        UNPREDICTABLE;
    DeviceTableEntry dte = ReadDeviceTable(UInt(cmd.DeviceID));
    if !dte.Valid then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError VMAPTI_UNMAPPED_DEVICE";
            UNPREDICTABLE;
        if IdOutOfRange(cmd.EventID, dte.ITT_size) then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError VMAPTI_ID_OOR";
                UNPREDICTABLE;
            if LPIOutOfRange(cmd.vINTID) then
                if GITS_TYPER.SEIS == '1' then
                    IMPLEMENTATION_DEFINED "SError VMAPTI_vINTID_OOR";
                    UNPREDICTABLE;
                if DoorbellOutOfRange(cmd.Dbell_pINTID) then
                    if GITS_TYPER.SEIS == '1' then
                        IMPLEMENTATION_DEFINED "SError VMAPTI_DOORBELL_OOR";
                        UNPREDICTABLE;
                    InterruptTableEntry ite = ReadTranslationTable(dte.ITT_base, UInt(cmd.EventID));
                    if ite.Valid then
                        if GITS_TYPER.SEIS == '1' then
                            IMPLEMENTATION_DEFINED "SError VMAPTI_ALREADY_MAPPED";
                            UNPREDICTABLE;
                        ite.Valid = '1';
                        ite.Type = virtual_interrupt;
                        ite.OutputID = cmd.vINTID;
                        ite.VCPUID = cmd.VCPUID;
                        ite.DoorBellOutputID = cmd.Dbell_pINTID;
                        WriteTranslationTable(dte.ITT_base, UInt(cmd.EventID), ite);
                        IncrementReadPointer();
                        return;

5.3.21 VMOVI

此命令将由 DeviceID 和 EventID 定义的事件移动到由新的 vPEID 定义的新 vPE。事件保持与现有 ITT 项中相同的 vINTID。

此命令仅在 GICv4 中提供。

图 5-24 显示了 VMOVI 命令的格式。

Image text

63 48 47 32 31 16 15 8 7 0 DW
DeviceID RES0 0x2E 0
RES0 vPEID EventID 1
RES0 2
RES0 3

**图 5-24 VMOVI 命令格式**

在图 5-24 中:

  • vPEID 指定新的 vPE。

  • DeviceID 指定设备。

  • EventID 标识要移动的事件。

  • DW 是 32 字节或四个双字 ITS 命令包内的双字偏移量。

命令及其参数为:

VMOVI DeviceID, EventID, vPEID

如果发生以下任何情况,会出现命令错误:

  • DeviceID 超过 ITS 支持的最大值。

  • vPEID 超过 ITS 支持的最大数量,由 GITS_BASER 定义。

  • DeviceID 指定的设备未使用 MAPD 映射到 ITT。

  • EventID 超过 ITT 允许的最大值。该值由发出 MAPD 命令时的 Size 字段指定。

  • EventID 未映射到现有的 ITT 项。

  • EventID 映射到物理 LPI 而不是虚拟 LPI。

  • 源或目标 vPE 未使用 VMAPP 映射到 Redistributor。

在这种情况下,ITS 必须执行 命令错误 中描述的操作。

以下伪代码描述了 VMOVI 命令的操作:

// ITS.VMOVI // ==========
ITS.VMOVI(ITSCommand cmd)
    if DeviceOutOfRange(cmd.DeviceID) then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError VMOVI_DEVICE_OOR";
            UNPREDICTABLE;
        if VCPUOutOfRange(cmd.VCPUID) then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError VMOVI_VCPU_OOR";
                UNPREDICTABLE;
            DeviceTableEntry dte = ReadDeviceTable(UInt(cmd.DeviceID));
            if !dte.Valid then
                if GITS_TYPER.SEIS == '1' then
                    IMPLEMENTATION_DEFINED "SError VMOVI_UNMAPPED_DEVICE";
                    UNPREDICTABLE;
                if IdOutOfRange(cmd.EventID, dte.ITT_size) then
                    if GITS_TYPER.SEIS == '1' then
                        IMPLEMENTATION_DEFINED "SError VMOVI_ID_OOR";
                        UNPREDICTABLE;
                    InterruptTableEntry ite = ReadTranslationTable(dte.ITT_base, UInt(cmd.EventID));
                    if !ite.Valid then
                        if GITS_TYPER.SEIS == '1' then
                            IMPLEMENTATION_DEFINED "SError VMOVI_UNMAPPED_INTERRUPT";
                            UNPREDICTABLE;
                        if ite.Type == physical_interrupt then
                            if GITS_TYPER.SEIS == '1' then
                                IMPLEMENTATION_DEFINED "SError VMOVI_ID_IS_PHYSICAL";
                                UNPREDICTABLE;
                            VCPUTableEntry vte1 = ReadVCPUTable(UInt(ite.VCPUID));
                            VCPUTableEntry vte2 = ReadVCPUTable(UInt(cmd.VCPUID));
                            if !vte1.Valid then
                                if GITS_TYPER.SEIS == '1' then
                                    IMPLEMENTATION_DEFINED "SError VMOVI_ITEVCPU_INVALID";
                                    UNPREDICTABLE;
                                if !vte2.Valid then
                                    if GITS_TYPER.SEIS == '1' then
                                        IMPLEMENTATION_DEFINED "SError VMOVI_CMDVCPU_INVALID";
                                        UNPREDICTABLE;
                                    bits(32) rd1 = vte1.RDbase;
                                    Address vpt1 = vte1.VPT_base;
                                    bits(32) rd2 = vte2.RDbase;
                                    Address vpt2 = vte2.VPT_base;

ite.VCPUID = cmd.VCPUID;

// From this point new interrupts sent to the new VCPU move the pending
// state to rd2 if set taking care of any races where the interrupt
// has been forwarded to the processor
MoveVirtualPendingState(rd1, vpt1, vpt2, ite.OutputID);

IncrementReadPointer();

return;

5.3.22 VMOVP GICv4.0

此命令将由 vPEID 定义的 vPE 表项更新到目标 RDbase。软件必须使用 SequenceNumber 和 ITSList 来同步跨多个 ITS 的 VMOVP 命令的执行。

此命令仅在 GICv4 中提供。

软件必须确保此命令不会与在目标 Redistributor 上调度的 vPEID 一起执行,否则系统行为是 UNPREDICTABLE。

图 5-25 显示了 VMOVP 命令的格式。

Image text

63 51 50 32 31 16 15 8 7 0 DW
RES0 Sequence Number RES0 0x22 0
RES0 vPEID RES0 ITSList 1
RES0 RDbase RES0 2
RES0 3

**图 5-25 VMOVP 命令格式**

在图 5-25 中:

  • vPEID 指定 vPE。

  • RDbase 指定中断转发到的 Redistributor。参见 ITS 命令参数中的 IMPLEMENTATION DEFINED 大小

  • Sequence Number 指定 ITS 列表中包含的每个 ITS 使用的同步点的标识。当 GITS_TYPER.VMOVP == 0 时,Sequence Number 指定 ITSList 中包含的所有 ITS 使用的同步点的标识。

    • 当 GITS_TYPER.VMOVP == 1 时,Sequence Number 为 RES0。

    • 更多信息,参见 VMOVP 用法

  • ITSList 指定包含在同步操作中的 ITS 实例,其中:

    • ITS 列表中的每个位标识一个 ITS,其中位 [n] 对应于 ITS n。

    • 如果相应的位设置为 1,则包含 ITS。

当 GITS_TYPER.VMOVP == 0 时,ITSList 指定同步操作中包含哪些 ITS。ITSList 的每个位对应一个 ITS,例如 ITSList 的位 [0] 对应 ITS 0,位 [1] 对应 ITS 1。

当 GITS_TYPER.VMOVP ==1 时,ITSList 为 res0。

  • DW 是 32 字节或四个双字 ITS 命令包内的双字偏移量。

命令及其参数为:

VMOVP, vPEID, RDbase, SequenceNumber, ITSList

如果发生以下任何情况,会出现命令错误:

  • 如果 vPEID 指定的 PE 未使用 VMAPP GICv4.0 映射到 Redistributor。

  • vPEID 超过 ITS 支持的最大数量,由 GITS_BASER 定义。

在这种情况下,ITS 必须执行 命令错误 中描述的操作。

以下伪代码描述了 VMOVP 命令的操作:

// ITS.VMOVP // ========= ITS.VMOVP(ITSCommand cmd)
if VCPUOutOfRange(cmd.VCPUID) then
    if GITS_TYPER.SEIS == '1' then
        IMPLEMENTATION_DEFINED "SError VMOVP_VCPU_OOR";
        UNPREDICTABLE;
    VCPUTableEntry vte = ReadVCPUTable(UInt(cmd.VCPUID));
    if !vte.Valid then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError VMOVP_VCPU_INVALID";
            UNPREDICTABLE;

vte.RDbase = cmd.RDbase;

if HasGIC41Ext() then UpdateVPEConfigurationTable(UInt(cmd.VCPUID), cmd.RDbase, cmd.Default_Doorbell_pINTID);

WriteVCPUTable(UInt(cmd.VCPUID), vte);

IncrementReadPointer();

return;

VMOVP 用法

当多个 ITS 控制同一个 vPE 的中断时,必须在不同的 ITS 之间协调移动这个 vPE。这由软件使用这里详述的两种方法之一来控制:

当 GITS_TYPER.VMOVP == 0 时:

  • 必须为控制正在移动的 vPE 中断的每个 ITS 发出 VMOVP 命令。这些命令中的每一个都必须具有公共序列号。该序列号不能用于其他 VMOVP 命令,直到先前使用该序列号的所有命令都已被所有 ITS 处理。

  • 为每个 ITS 发出的 VMOVP 命令包含受移动 vPE 影响的所有 ITS 的列表。这是 ITS 列表。

  • 每个 ITS 必须以与其他 ITS 相同的顺序接收序列号。

当 GITS_TYPER.VMOVP == 1 时:

  • VMOVP 命令只能在控制正在移动的 vPE 中断的 ITS 中的一个上发出。

  • 实现负责传播更新的映射。

不遵循此方法会导致 UNPREDICTABLE 行为。

注意 如果系统包含多个 ITS,Arm 强烈建议软件不要在另一个 ITS 上为相同 vPEID 存在未完成的 VMOVP 时发出 VMAPP,因为这可能会造成竞争条件。

5.3.23 VMOVP GICv4.1

在 GICv4.1 中修改了 VMOVP 命令,以允许为 vPE 分配默认门铃。

Image text

52 51 48 47 32 31 16 15 0 DW
RES0 Sequence Number RES0 0x22 0
RES0 vPEID RES0 ITSList 1
DB RES0 RDbase RES0 2
RES0 Default_Doorbell_pINTID 3

**图 5-26 GICv4.1** VMOVP **命令编码**

在图 5-26 中:

  • Default_Doorbell_pINTID 是 vPE 的默认门铃。

  • DB 表示是否将 vPE 标记为在目标上需要默认门铃。

Default_Doorbell_pINTID==1023 的 VMOVP 意味着无默认门铃。对于具有有效 Default_Doorbell_pINTID(除 1023 外)的 VMOVP,默认门铃的挂起状态将转移到新目标。

Default_Doorbell_pINTID==1023 的 VMOVP 会清除旧目标上默认门铃的挂起状态(如果先前指定了一个)。即使门铃使用的 INTID 发生改变,默认门铃的挂起状态也会被转移。移动 vPE 不会改变生成默认门铃的规则。

当发出 VMOVP 时,如果 DB==1,则 vPE 被标记为在新目标上请求默认门铃生成。当 DB==0 时,vPE 被标记为在新目标上不请求默认门铃生成。

如果发生以下任何情况,会出现命令错误:

  • vPEID 指定的 PE 未使用 VMAPP 映射到 Redistributor。

  • vPEID 超过 ITS 支持的最大数量,由 GITS_BASER 定义。

  • VMOVP 指定的 Default_Doorbell_pINTID 值超出已实现的 LPI 范围(除 1023 外)。报告的命令错误码为 0x01_2206(VMOVP_PHYSICALID_OOR)。

在这种情况下,ITS 必须执行 命令错误 中描述的操作。

GICv4.1 中的 VMOVP 用法

GICv4.1 中的 VMOVP 用法与 GICv4.0 中相同。更多信息参见 VMOVP 用法

5.3.24 仅适用于 GICv4.1 的 vSGI

vSGI 命令设置指定 vSGI 的配置并可选地清除其挂起状态。

图 5-27 显示了 vSGI 命令的格式。

63 4832 47 36 3532 47 36 3531 20 24 23:20 19:31 20 24 23:20 19:31 20 24 23:20 19:8 15:11 9 108 15:11 9 108 15:11 9 108 15:11 9 107 0DW
RES0vINTIDRES0PriRES0RES0GCE0x230
RES0vPEIDRES01
RES02
RES03

图 5-27 vSGI 命令编码

其中:

  • E 是使能配置。

    • 当 C==1 时忽略。
  • G 是组配置。

    • 当 C==1 时忽略。
  • C 表示是否清除挂起状态。

  • Pri 是优先级配置。

    • 当 C==1 时忽略。
  • vINTID 是 vSGI 的 INTID。

命令及其参数为:

vSGI vPEID, vINTID, Enable, Priority, Group, Clear

如果发生以下任何情况,会出现命令错误:

  • vPEID 超过 ITS 支持的最大数量,由 GITS_BASER 定义。

  • vINTID 不在 vSGI 的范围内(0-15)。

在这种情况下,ITS 必须执行 命令错误 中描述的操作。

以下伪代码描述了 vSGI 命令的操作:

// ITS.vSGI
// =========
ITS.vSGI(ITSCommand cmd)
    if VCPUOutOfRange(cmd.VCPUID) then
        if GITS_TYPER.SEIS == '1' then
            IMPLEMENTATION_DEFINED "SError vSGI_VCPU_OOR";
            UNPREDICTABLE;
        if SGIOutOfRange(cmd.vINTID) then
            if GITS_TYPER.SEIS == '1' then
                IMPLEMENTATION_DEFINED "SError vSGI_vINTID_OOR";
                UNPREDICTABLE;
            VCPUTableEntry vte = ReadVCPUTable(UInt(cmd.VCPUID));
            if !vte.Valid then
                if GITS_TYPER.SEIS == '1' then
                    IMPLEMENTATION_DEFINED "SError vSGI_VCPU_INVALID";
                    UNPREDICTABLE;
                if cmd.C == '1' then
                    ClearVirtualSGIPendingState(UInt(cmd.VCPUID), vte, UInt(cmd.vINTID));
                else
                    SetVirtualSGIConfiguration(UInt(cmd.VCPUID), vte, UInt(cmd.vINTID), UInt(cmd.E), UInt(cmd.Pri), UInt(cmd.G));
                IncrementReadPointer();
                return;

5.4 通用 ITS 伪代码函数

本节的一些伪代码函数中出现以下术语:

中断翻译

导致 ITS 尝试在特定表中设置特定挂起位的操作。挂起中断

在特定表中设置特定挂起位。

本节中的伪代码函数基于以下假设:

  • 每个 ITS 函数必须作为原子操作执行。实现必须确保观察到的行为与严格原子实现的行为一致。

  • 当伪代码向特定 Redistributor 发出一系列读写操作时,这些操作必须按照生成的顺序执行。

  • 当伪代码向特定 Redistributor 发出写入时,操作不需要等待写入完成。

  • 当伪代码向内存发出写入以更新表时,操作不需要等待这些写入完成。向内存的写入可能永远不会对外部观察者可见。但是,任何此类写入的效果必须按任何后续 ITS 操作的顺序进行,包括处理中断翻译。除了标准规则(内存必须表现得好像对每个位置的写入按程序顺序发生)外,没有其他排序规则。

  • 因为每个 ITS 函数都作为原子操作执行,所以在该函数之后发生的任何新中断翻译都必须受到该函数效果的影响。

  • Redistributor LPI 配置和 LPI 挂起表的缓存效果在伪代码中明确指定。

  • 中断翻译可能设置挂起位,挂起位保持设置状态直到被 PE 处理。当中断挂起时,它可能会受到由后续 ITS 函数更新的中断翻译的影响。

注意 伪代码中使用的一些变量名与正文中使用的不同。受影响变量的列表,参见 伪代码术语 B-910。

以下伪代码使指定翻译的 Redistributor 中 LPI 配置的任何关联缓存失效。

// InvalidateByITE
// ===============
boolean InvalidateByITE(InterruptTableEntry ite)
if ite.Type == physical_interrupt then
    CollectionTableEntry cte = ReadCollectionTable(UInt(ite.ICID));
    if !cte.Valid then
        return FALSE;
    InvalidateInterruptCaches(ite.ICID, ite.OutputID);
else

VCPUTableEntry vte = ReadVCPUTable(UInt(ite.VCPUID));
if !vte.Valid then
    return FALSE;
InvalidateVirtualInterruptCaches(ite.VCPUID, ite.OutputID);
return TRUE;
以下伪代码描述了移动挂起中断。

以下伪代码描述了移动挂起中断。

// MovePendingState()
// ==================

MovePendingState(bits(32) rd1, bits(32) rd2, bits(32) ID)
    if IsPending(GICR_PENDBASER[rd1], ID) then
        // The interrupt is pending in the source redistributor

        // Make sure the interrupt is released or taken by the processor for
        // example by sending a clear and waiting for the response
        EnsureInterruptNotPendingOnProcessor(rd1, ID);

        if IsPending(GICR_PENDBASER[rd1], ID) then
            // The CPU released the interrupt and it is still pending
            // Note: the following must be done without any possibility of the
            // source redistributor re-forwarding the interrupt to the processor
            ClearPendingStateLocal(GICR_PENDBASER[rd1], ID);
            SetPendingStateLocal(GICR_PENDBASER[rd2], ID);

以下伪代码描述了移动挂起虚拟中断。

// MoveVirtualPendingState()
// =========================

MoveVirtualPendingState(bits(32) rd_base, Address vpt1, Address vpt2, bits(32) ID)
    if IsPending(vpt1, ID) then
        // The interrupt is pending in the source redistributor

        // Make sure the interrupt is released or taken by the processor for example by sending a
        // VClear and waiting for the response
        EnsureVirtualInterruptNotPendingOnProcessor(rd_base, vpt1, ID);

        if IsPending(vpt1, ID) then
            // The CPU released the interrupt and it is still pending
            // Note: the following must be done without any possibility of the source redistributor
            // re-forwarding the interrupt to the processor
            ClearVirtualPendingStateLocal(vpt1, ID);
            SetVirtualPendingStateLocal(vpt2, ID);
    return;

以下伪代码描述了使与 vPE 关联的默认门铃的配置数据缓存失效。

// Invalidates any caching of configuration for the default
// doorbell associated with a vPE
InvalidateInterruptDoorbellCaches(UInt VCPUID, VCPUTableEntry vte);

// Sets the configuration of the specified vSGI
SetVirtualSGIConfiguration(UInt VCPUID, VCPUTableEntry vte, UInt Intid,
                           UInt Enable, UInt Priority, UInt Group);

// Clears the pending state of the specified vSGI
ClearVirtualSGIPendingState(UInt VCPUID, VCPUTableEntry vte, UInt Intid);

// Returns TRUE if the ITS supports GICv4.1
Boolean HasGIC41Ext();

以下伪代码描述了移动挂起虚拟中断。

// MoveVirtualPendingState() // =========================
// The names of the Banked core registers.

enumeration RName {RName_0usr, RName_1usr, RName_2usr, RName_3usr, RName_4usr, RName_5usr,
                   RName_6usr, RName_7usr, RName_8usr, RName_8fiq, RName_9usr, RName_9fiq,
                   RName_10usr, RName_10fiq, RName_11usr, RName_11fiq, RName_12usr, RName_12fiq,
                   RName_SPusr, RName_SPfiq, RName_SPirq, RName_SPsvc,
                   RName_SPabt, RName_SPund, RName_SPmon, RName_SPhyp,
                   RName_LRusr, RName_LRfiq, RName_LRirq, RName_LRsvc,
                   RName_LRabt, RName_LRund, RName_LRmon,
                   RName_PC};

array bits(8) _Memory[0..0xFFFFFFFF];

数组总是显式声明的,没有常量数组的记号。数组总是包含至少一个元素,因为:
•      枚举总是包含至少一个符号常量。
•      整数范围总是包含至少一个整数。

数组通常不会直接出现在伪代码中。在伪代码中在语法上看起来像数组的项目通常是类似数组的函数,如 R[i]、MemU[address, size] 或 Elem[vector, i, size]。这些函数打包和抽象了通常在访问底层数组时执行的额外操作,如寄存器组、内存保护、字节序相关的字节排序、独占访问管理和高级 SIMD 元素处理。

以下伪代码描述了使与 vPE 关联的默认门铃的配置数据缓存失效。

// Invalidates any caching of configuration for interrupts which are
// members of the collection specified by "collection"

InvalidateCollectionCaches(integer collection);

5.4.1 ITS 辅助函数

本小节描述 ITS 辅助函数。这些函数是行为未架构化且为 IMPLEMENTATION DEFINED 的行为的占位符函数。

这些函数由分层路径名表示,例如 shared/gic/its/its_helper:

  • shared/gic/its/its_helper/Address

  • shared/gic/its/its_helper/ClearPendingState

  • shared/gic/its/its_helper/ClearPendingStateLocal

  • shared/gic/its/its_helper/CollectionOutOfRange

  • shared/gic/its/its_helper/CollectionTableEntry

  • shared/gic/its/its_helper/DeviceOutOfRange

  • shared/gic/its/its_helper/DeviceTableEntry

  • shared/gic/its/its_helper/EndOfCommand

  • shared/gic/its/its_helper/EnsureInterruptNotPendingOnProcessor

  • shared/gic/its/its_helper/EnsureVirtualInterruptNotPendingOnProcessor

  • shared/gic/its/its_helper/IdOutOfRange

  • shared/gic/its/its_helper/IncrementReadPointer

  • shared/gic/its/its_helper/InterruptTableEntry

  • shared/gic/its/its_helper/InterruptType

  • shared/gic/its/its_helper/InterruptType

  • shared/gic/its/its_helper/InvalidateInterruptCaches

  • shared/gic/its/its_helper/InvalidateInterruptConfigurationCaches

  • shared/gic/its/its_helper/InvalidateVCPUCaches

  • shared/gic/its/its_helper/InvalidateVirtualConfigurationCaches

  • shared/gic/its/its_helper/InvalidateVirtualInterruptCaches

  • shared/gic/its/its_helper/IsPending

  • shared/gic/its/its_helper/IsPending

  • shared/gic/its/its_helper/LPIOutOfRange

  • shared/gic/its/its_helper/MoveAllPendingState

  • shared/gic/its/its_helper/ReadCollectionTable

  • shared/gic/its/its_helper/ReadDeviceTable

  • shared/gic/its/its_helper/ReadTranslationTable

  • shared/gic/its/its_helper/ReadVCPUTable

  • shared/gic/its/its_helper/RetargetVirtualInterrupt

  • shared/gic/its/its_helper/SetPendingState

  • shared/gic/its/its_helper/SetPendingStateLocal

  • shared/gic/its/its_helper/SizeOutOfRange

  • shared/gic/its/its_helper/VCPUOutOfRange

  • shared/gic/its/its_helper/VCPUTableEntry

  • shared/gic/its/its_helper/WaitForCompletion

  • shared/gic/its/its_helper/WaitForVirtualCompletion

  • shared/gic/its/its_helper/WriteCollectionTable

  • shared/gic/its/its_helper/WriteDeviceTable

  • shared/gic/its/its_helper/WriteTranslationTable

  • shared/gic/its/its_helper/WriteVCPUTable

下面是这些函数的详细实现:

shared/gic/its/its_helper/DeviceTableEntry

// DeviceTableEntry
// ================

type DeviceTableEntry is (
    boolean Valid,
    Address ITT_base,
    bits(5) ITT_size
)

shared/gic/its/its_helper/EndOfCommand

// EndOfCommand()
// ================

// 终止当前命令的处理而不递增读指针。
// 这意味着命令将再次运行。

EndOfCommand();

shared/gic/its/its_helper/EnsureInterruptNotPendingOnProcessor

// EnsureInterruptNotPendingOnProcessor()
// ======================================

// 当由 ID 指定的物理中断在连接到由 rd1 指定的 redistributor 的
// CPU 接口上不再挂起时返回

EnsureInterruptNotPendingOnProcessor(bits(32) rd1, bits(32) ID);

shared/gic/its/its_helper/EnsureVirtualInterruptNotPendingOnProcessor

// EnsureVirtualInterruptNotPendingOnProcessor()
// ==========================================

// 当由 ID 指定的虚拟中断在连接到由 rd1 指定的 redistributor 的
// CPU 接口上不再挂起时返回

EnsureVirtualInterruptNotPendingOnProcessor(bits(32) rd1, Address vpt, bits(32) ID);

shared/gic/its/its_helper/IdOutOfRange

// IdOutOfRange()
// ============================

// 如果提供的值具有超出已实现大小或超出 ITT_size 的位,则返回 TRUE

boolean IdOutOfRange(bits(32) ID, bits(5) ITT_size);

shared/gic/its/its_helper/IncrementReadPointer

// IncrementReadPointer()
// ===================

// 递增 GITS_CREADR,如果适当则回绕

IncrementReadPointer();

shared/gic/its/its_helper/InterruptTableEntry

// InterruptTableEntry()
// =====================

type InterruptTableEntry is (
boolean Valid,
InterruptType Type,
bits(32) OutputID,
bits(32) DoorbellID,
bits(16) ICID,
bits(16) VCPUID
)

shared/gic/its/its_helper/InterruptType

// InterruptType
// ====================

enumeration InterruptType { virtual_interrupt, physical_interrupt };

shared/gic/its/its_helper/InvalidateCollectionCaches

//InvalidateCollectionCaches() // =========================

// 使由 "collection" 指定的集合成员中断的任何配置缓存失效

InvalidateCollectionCaches(integer collection);

shared/gic/its/its_helper/InvalidateInterruptCaches

// InvalidateInterruptCaches()
// =============================

// 使由 interruptID 指定的物理中断的任何配置缓存失效,
// 该中断是由 collection 指定的集合的成员

InvalidateInterruptCaches(bits(16) collection, bits(32) interruptID);

shared/gic/its/its_helper/InvalidateInterruptConfigurationCaches

// InvalidateInterruptConfigurationCaches()
// ===================================

InvalidateInterruptConfigurationCaches(bits(32) ID, integer collection);

shared/gic/its/its_helper/InvalidateVCPUCaches

// InvalidateVCPUCaches()
// ==========================

// 使由 vcpu_id 指定的 vPE 的任何配置缓存失效

InvalidateVCPUCaches(integer vcpu_id);

shared/gic/its/its_helper/InvalidateVirtualConfigurationCaches

// InvalidateVirtualConfigurationCaches
// ================================

InvalidateVirtualConfigurationCaches(bits(32) ID, bits(16) VCPU);

shared/gic/its/its_helper/InvalidateVirtualInterruptCaches

// InvalidateVirtualInterruptCaches()
// =====================================

// 使由 vcpu_id 指定的 vPE 的由 interruptID 指定的虚拟中断的
// 任何配置缓存失效

InvalidateVirtualInterruptCaches(bits(16) vcpu_id, bits(32) interruptID);

shared/gic/its/its_helper/IsPending

// IsPending()
// ========================

// 如果由 interruptID 指定的虚拟中断在由 base 指定的 LPI 挂起表中挂起,
// 则返回 TRUE

boolean IsPending(Address base, bits(32) interruptID);

shared/gic/its/its_helper/IsPending

// IsPending()

// ========================
// 如果提供的值具有超出已实现范围的位或如果提供的值超过
// 相应 GITS_BASERn 中配置的最大大小,则返回 TRUE

boolean VCPUOutOfRange(bits(16) vcpu);

shared/gic/its/its_helper/LPIOutOfRange

//LPIOutOfRange()

// ==========================

// 如果提供的值大于 GICD_TYPER.IDbits 允许的值或不在 LPI 范围内
// 且不是 1023,则返回 TRUE

boolean LPIOutOfRange(bits(32) ID);

shared/gic/its/its_helper/MoveAllPendingState

// MoveAllPendingState()
// ===================

// 将所有中断的挂起状态从由 rd1 指定的 Redistributor
// 移动到由 rd2 指定的 Redistributor

MoveAllPendingState(bits(32) rd1, bits(32) rd2);

shared/gic/its/its_helper/ReadCollectionTable

// ReadCollectionTableEntry()
// =========================

// 从内存读取集合表项

CollectionTableEntry ReadCollectionTable(integer index);

shared/gic/its/its_helper/ReadDeviceTable

// ReadDevicePointer()
// ==========================

// 从内存读取设备表项

DeviceTableEntry ReadDeviceTable(integer index);

shared/gic/its/its_helper/ReadTranslationTable

// ReadTranslationTable()
// =======================
// 从内存读取 VCPU 表项

VCPUTableEntry ReadVCPUTable(integer index);

shared/gic/its/its_helper/ReadVCPUTable

//ReadVCPUTable() // ===========================

// 从内存读取 VCPU 表项

VCPUTableEntry ReadVCPUTable(integer index);

shared/gic/its/its_helper/RetargetVirtualInterrupt

// RetargetVirtualInterrupt()
// =======================

RetargetVirtualInterrupt(integer device, bits(32) ID, integer vcpu);

shared/gic/its/its_helper/SetPendingState

// SetPendingState()
// =================

boolean SetPendingState(InterruptTableEntry ite)

     if ite.Type == physical_interrupt then
         CollectionTableEntry cte = ReadCollectionTable(UInt(ite.ICID));

         if !cte.Valid then
             return FALSE;

         bits(32) rd_base = cte.RDbase;

         SetPendingStateLocal(GICR_PENDBASER[rd_base], ite.OutputID);

     else
         VCPUTableEntry vte = ReadVCPUTable(UInt(ite.VCPUID));

         if !vte.Valid then
             return FALSE;

         bits(32) rd_base = vte.RDbase;
         Address vpt = vte.VPT_base;

         SetVirutalPendingStateLocal(vpt, ite.OutputID);

         if (GICR_VPENDBASER[rd_base].Valid == '1' &&
             GICR_VPENDBASER[rd_base].PhysicalAddress != vpt<47:16>) then
             if ite.DoorbellID != ZeroExtend(INTID_SPURIOUS, 32) then
                 // Not resident so set the doorbell interrupt pending as well
                 SetPendingStateLocal(GICR_PENDBASER[rd_base], ite.DoorbellID);

     return TRUE;

shared/gic/its/its_helper/SetPendingStateLocal

// SetPendingStateLocal()
// =======================

// 为拥有由 PendBase 指定的 LPI 挂起表的 Redistributor
// 设置由 INTID 指定的物理中断的挂起状态

SetPendingStateLocal(PBType PendBase, bits(32) INTID);

// SetVirtualPendingStateLocal()
// =======================

// 在由 base 指定的 LPI 挂起表中设置由 INTID 指定的虚拟中断的挂起状态

SetPendingStateLocal(Address base, bits(32)INTID);

shared/gic/its/its_helper/SizeOutOfRange

// SizeOutOfRange()
// =====================

// 如果提供的值超过 GITS_TYPER.ID_bits 允许的最大值,则返回 TRUE

boolean SizeOutOfRange(bits(5) ITT_size);

shared/gic/its/its_helper/VCPUOutOfRange

// VCPUOutOfRange()
// =======================

shared/gic/its/its_helper/VCPUTableEntry

//VCPUTableEntry() // ==================

type VCPUTableEntry is ( boolean Valid, bits(32) RDbase, Address VPT_base, bits(5) VPT_size )

shared/gic/its/its_helper/WaitForCompletion

// WaitForCompletion()
// ============================

// 当任何物理命令的所有外部效果对所有 Redistributor 都可观察
// 且任何先前命令的内部效果影响任何后续中断请求或命令时返回

WaitForCompletion(bits(32) RDbase);

shared/gic/its/its_helper/WaitForVirtualCompletion

// WaitForVirtualCompletion()
// =======================

WaitForVirtualCompletion(bits(32) RDbase);

shared/gic/its/its_helper/WriteCollectionTable

//WriteCollectionTable() // =========================

// 将集合表项写入内存

WriteCollectionTable(integer index, CollectionTableEntry cte);

shared/gic/its/its_helper/WriteDeviceTable

// WriteDeviceTable()
// ========================

// 将设备表项写入内存

WriteDeviceTable(integer index, DeviceTableEntry dte);

shared/gic/its/its_helper/WriteTranslationTable

// WriteTranslationTable()
// ================================

// 将 ITT 表项写入内存

WriteTranslationTable(Address base, integer index, InterruptTableEntry cte);

shared/gic/its/its_helper/WriteVCPUTable

// WriteVCPUTable()
// ===============================

// 将 VCPU 表项写入内存

WriteVCPUTable(integer index, VCPUTableEntry vte);

5.5 ITS 命令错误编码

当 ITS 支持系统错误时,即当 GITS_TYPER.SEIS == 1 时,ITS 命令错误可以报告给软件。如何记录和报告这些错误是 IMPLEMENTATION DEFINED。

表 5-8 显示了 ITS 命令错误编码。

表 5-8 ITS 命令错误编码表 5-8 ITS 命令错误编码
编码 错误助记符 命令错误描述
0x01_0801 MAPD_DEVICE_OOR MAPD 0x01_0802 MAPD_ITTSIZE_OOR超出范围
0x01_0903 MAPC_COLLECTION_OOR MAPC超出范围
0x01_0B01 MAPI_DEVICE_OOR MAPI 0x01_0B03 MAPI_COLLECTION_OOR 0x01_0B04 MAPI_UNMAPPED_DEVICE 0x01_0B05 MAPI_ID_OOR未映射设备 超出范围
0x01_0A01 MAPTI_DEVICE_OOR MAPTI 0x01_0A03 MAPTI_COLLECTION_OOR 0x01_0A04 MAPTI_UNMAPPED_DEVICE 0x01_0A05 MAPTI_ID_OOR 0x01_0A06 MAPTI_PHYSICALID_OOR未映射设备 超出范围
0x01_0101 MOVI_DEVICE_OOR MOVI 0x01_0103 MOVI_COLLECTION_OOR 0x01_0104 MOVI_UNMAPPED_DEVICE 0x01_0105 MOVI_ID_OOR 0x01_0107 MOVI_UNMAPPED_INTERRUPT 0x01_0108 MOVI_ID_IS_VIRTUAL 0x01_0109 MOVI_UNMAPPED_COLLECTION未映射设备 超出范围 未映射中断 指定了 vINTID 未映射中断集合
0x01_0F01 DISCARD_DEVICE_OOR DISCARD 0x01_0F04 DISCARD_UNMAPPED_DEVICE 0x01_0F05 DISCARD_ID_OOR 0x01_0F07 DISCARD_UNMAPPED_INTERRUPT 0x01_0F10 DISCARD_ITE_INVALID超出范围 未映射设备 超出范围 未映射中断 无效翻译表项

表 5-8 ITS 命令错误编码(续)

编码 错误助记符 命令错误描述
0x01_0C01 INV_DEVICE_OOR INV 0x01_0C04 INV_UNMAPPED_DEVICE 0x01_0C05 INV_ID_OOR 0x01_0C07 INV_UNMAPPED_INTERRUPT 0x01_0C10 INV_ITE_INVALID超出范围 未映射设备 超出范围 未映射中断 无效翻译表项
0x01_0D03 INVALL_COLLECTION_OOR INVALL 0x01_0D09 INVALL_UNMAPPED_COLLECTION超出范围 未映射中断集合
0x01_0301 INT_DEVICE_OOR INT 0x01_0304 INT_UNMAPPED_DEVICE 0x01_0305 INT_ID_OOR 0x01_0307 INT_UNMAPPED_INTERRUPT 0x01_0310 INT_ITE_INVALID超出范围 未映射设备 超出范围 未映射中断 无效翻译表项
0x01_0501 CLEAR_DEVICE_OOR CLEAR 0x01_0504 CLEAR_UNMAPPED_DEVICE 0x01_0505 CLEAR_ID_OOR 0x01_0507 CLEAR_UNMAPPED_INTERRUPT 0x01_0510 CLEAR_ITE_INVALID超出范围 未映射设备 超出范围 未映射中断 无效翻译表项
0x01_2906 VMAPP_PHYSICALID_OOR VMAPP GICv4.0或 VMAPP GICv4.1 0x01_2911 VMAPP_VCPU_OOR 0x01_2912 VMAPP_VPTSIZE_OOR超出范围

表 5-8 ITS 命令错误编码(续)

编码 错误助记符 命令错误描述
0x01_2b01 VMAPI_DEVICE_OOR VMAPI 0x01_2b11 VMAPI_VCPU_OOR 0x01_2b04 VMAPI_UNMAPPED_DEVICE 0x01_2b05 VMAPI_ID_OOR 0x01_2b06 VMAPI_PHYSICALID_OOR超出范围 未映射设备 超出范围
0x01_2a01 VMAPTI_DEVICE_OOR VMAPTI 0x01_2a11 VMAPTI_VCPU_OOR 0x01_2a04 VMAPTI_UNMAPPED_DEVICE 0x01_2a05 VMAPTI_ID_OOR 0x01_2a13 VMAPTI_VIRTUALID_OOR 0x01_2a06 VMAPTI_PHYSICALID_OOR未映射设备 超出范围
0x01_2d11 VINVALL_VCPU_OOR VINVALL 0x01_2d14 VINVALL_VCPU_INVALID指定了无效的 vPE
0x01_2511 VSYNC_VCPU_OOR VSYNC 0x01_2514 VSYNC_VCPU_INVALID超出范围 指定了无效的 vPE
0x01_2206 VMOVP_PHYSICALID_OOR VMOVP GICv4.0或 VMOVP GICv4.1 0x01_2211 VMOVP_VCPU_OOR 0x01_2214 VMOVP_VCPU_INVALID超出范围 指定了无效的 vPE
0x01_2101 VMOVI_DEVICE_OOR VMOVI 0x01_2103 VMOVI_VCPU_OOR 0x01_2104 VMOVI_UNMAPPED_DEVICE 0x01_2105 VMOVI_ID_OOR 0x01_2106 VMOVI_PHYSICALID_OOR 0x01_2107 VMOVI_UNMAPPED_INTERRUPT 0x01_2115 VMOVI_ID_IS_PHYSICAL 0x01_2116 VMOVI_ITEVCPU_INVALID 0x01_2117 VMOVI_CMDVCPU_INVALID超出范围 未映射设备 超出范围
未映射中断 指定了 pINTID 无效翻译表项 指定了无效的 vPE
0x01_2311 VSGI_VCPU_OOR 仅适用于 GICv4.1 的 VSGIvPEID 超出 ITS 配置范围。
0x01_2E11 INVDB_VCPU_OOR 仅适用于 GICv4.1 的 INVDB超出范围

5.6 ITS 电源管理

本小节描述了启用和禁用 ITS 的软件序列。包含以下部分:

  • 启用 ITS

  • 禁用 ITS

5.6.1 启用 ITS

在上电时,ITS 被重置为静止状态,其中 GITS_CTLR.Quiescent == 1 且 GITS_CTLR.Enabled == 0。要启用 ITS,软件必须:

  1. 确保支持设备、中断翻译、中断集合或虚拟 CPU 表所需的任何内存结构都已初始化或恢复。

  2. 确保 ITS 命令队列已配置。

  3. 将 GITS_CTLR.Enabled 设置为 1。

  4. 使用适当的 ITS 命令根据需要配置 ITS。有关 ITS 命令的更多信息,参见 ITS 命令

5.6.2 禁用 ITS

要禁用 ITS,软件必须:

  1. 确保所有针对正在关闭的 ITS 的中断都被重定向或禁用。

  2. 通过将 GITS_CTLR.Enable 清零为 0 来禁用 ITS。禁用的 ITS 完成所有未完成的操作,然后将 GITS_CTLR.Quiescent 设置为 1。

  3. 通过轮询直到 GITS_CTLR.Quiescent == 1 来确保 ITS 处于静止状态。

当 GITS_CTLR.Enable == 0 时,对 GITS_TRANSLATER 的写入访问被忽略。当 GITS_CTLR.Quiescent == 1 时,所有操作都已完成且内存支持的状态已提交。然后 ITS 可以断电到 IMPLEMENTATION DEFINED 状态。