AMDGPU/KFD IV(Interrupt Vector)信息结构及实现
1. IV(Interrupt Vector)机制简介
IV(Interrupt Vector,中断向量)是 AMDGPU/KFD 驱动与 GPU 硬件之间传递中断事件的标准数据结构。每当 GPU 发生异常、事件或信号(如 VM fault、SQ interrupt、doorbell、SDMA trap 等),硬件会将事件相关信息打包为 IV 条目,写入 IH(Interrupt Handler)环形缓冲区。驱动通过解析 IV 条目,精确获取事件类型、来源、所属进程等关键信息,实现高效的事件分发和处理。
2. IV条目结构定义
IV 条目本质上是一个 uint32_t entry[8]
数组,每个元素通过位运算和掩码提取不同字段。SOC15 架构下,字段定义如下(见 soc15_int.h):
// entry[0]
#define SOC15_CLIENT_ID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[0]) & 0xff)
#define SOC15_SOURCE_ID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[0]) >> 8 & 0xff)
#define SOC15_RING_ID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[0]) >> 16 & 0xff)
#define SOC15_VMID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[0]) >> 24 & 0xf)
#define SOC15_VMID_TYPE_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[0]) >> 31 & 0x1)// entry[3]
#define SOC15_PASID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[3]) & 0xffff)
#define SOC15_NODEID_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[3]) >> 16 & 0xff)// entry[4~7]
#define SOC15_CONTEXT_ID0_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[4]))
#define SOC15_CONTEXT_ID1_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[5]))
#define SOC15_CONTEXT_ID2_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[6]))
#define SOC15_CONTEXT_ID3_FROM_IH_ENTRY(entry) (le32_to_cpu(entry[7]))
字段说明
-
client_id:事件所属硬件模块(如 GFX、VMC、SDMA 等)。
-
source_id:事件类型(如 SQ_INTERRUPT_MSG、VMC_FAULT、SDMA_TRAP 等)。
-
ring_id:事件发生的 ring(队列)编号。
-
vmid:虚拟内存空间 ID,标识事件属于哪个虚拟地址空间。
-
vmid_type:VMID 类型标志。
-
pasid:Process Address Space ID,标识事件属于哪个用户进程。
-
nodeid:节点 ID,多 GPU/多 NUMA 场景下使用。
-
context_id0~3:事件上下文信息,具体内容随事件类型变化,包含错误类型、波前号、SIMD号、WGP号、trap code等。
3. IV条目解析与使用流程
3.1 硬件写入 IV 条目
-
GPU 发生事件时,硬件将事件相关信息编码为 IV 条目,写入 IH ring 的下一个位置。
-
IV 条目内容由硬件协议定义,驱动需按协议解析。
3.2 驱动遍历 IH ring
-
驱动收到中断后,遍历 IH ring,依次读取每个 IV 条目(如
uint32_t ih_ring_entry[8]
)。 -
使用宏(如
SOC15_CLIENT_ID_FROM_IH_ENTRY
等)从条目中提取各字段。
3.3 事件分发
-
驱动根据 IV 条目的
source_id
、client_id
、pasid
、vmid
等字段,判断事件类型和归属。 -
分发到对应的事件处理函数(如 VM fault handler、doorbell handler、SQ interrupt handler 等)。
-
通过
pasid
精确定位到对应的 KFD/AMDGPU 进程,实现进程级别的异常处理和信号分发。
3.4 上下文信息解析
-
对于复杂事件(如 SQ interrupt),还需解析
context_id0~3
字段,获取波前号、SIMD号、错误类型等详细信息。 -
这些信息用于调试、异常定位和高层业务处理。
典型代码示例
void kfd_handle_iv_entry(uint32_t *ih_ring_entry)
{uint8_t client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);uint8_t source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry);uint8_t ring_id = SOC15_RING_ID_FROM_IH_ENTRY(ih_ring_entry);uint8_t vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);uint16_t pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry);uint32_t ctx_id0 = SOC15_CONTEXT_ID0_FROM_IH_ENTRY(ih_ring_entry);uint32_t ctx_id1 = SOC15_CONTEXT_ID1_FROM_IH_ENTRY(ih_ring_entry);// 根据 source_id 分发事件switch (source_id) {case SOC15_INTSRC_SQ_INTERRUPT_MSG:handle_sq_interrupt(pasid, ctx_id0, ctx_id1);break;case SOC15_INTSRC_VMC_FAULT:handle_vm_fault(pasid, vmid, ctx_id0);break;// ...其他事件类型}
}
4. IV结构的扩展性和机制优势
IV结构具有扩展性:
- IV 条目结构支持多事件类型和多硬件模块,便于未来扩展。
- 通过 context_id0~3 字段可灵活携带丰富的上下文信息,适应复杂业务需求。
- 支持多 GPU/多 NUMA 场景下的节点标识(nodeid)。
IV机制优势:
- 高效:硬件直接写入环形缓冲区,驱动批量解析,减少中断开销。
- 精准:通过 pasid/vmid 实现进程级别事件定位,提升多租户和虚拟化支持。
- 灵活:支持多种事件类型和丰富上下文信息,便于调试和业务扩展。
- 安全:事件分发精确到进程,防止跨进程干扰和资源泄漏。
IV(Interrupt Vector)是 AMDGPU/KFD 驱动与 GPU 硬件之间传递中断事件的标准结构。通过环形缓冲区机制,硬件将事件信息打包为 IV 条目,驱动通过宏和位运算解析各字段,实现高效、精准的事件分发和处理。