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_idclient_idpasidvmid 等字段,判断事件类型和归属。

  • 分发到对应的事件处理函数(如 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 条目,驱动通过宏和位运算解析各字段,实现高效、精准的事件分发和处理。IV 机制是多进程、多租户、高性能 GPU 驱动不可或缺的基础设施。