Linux 内核 amdxdna 驱动:AMD NPU(XDNA 架构)硬件结构、资源调度与负载运行全流程解析
AMD NPU 是集成在 AMD 客户端 APU 中的多用户 AI 推理加速器,由 Linux 内核的 amdxdna 驱动管理,可高效运行 CNN、LLM 等机器学习负载。本篇技术指南基于内核文档 AMD NPU 展开,完整梳理 NPU 的硬件组成(XDNA Array、共享 L2、微控制器、Mailbox、PCIe EP)、空间/时间混合调度机制、工作负载运行流程、DMA 与错误处理路径,并结合 amdxdna 驱动源码 说明驱动如何实现设备识别、固件加载、SVA/PASID 隔离与客户端用量统计,读完后你可以理解“一个 NPU 二进制如何从编译产物走到硬件执行并返回完成信号”的完整链路。
一、硬件组成:XDNA Array 与共享 L2 内存
AMD XDNA Array:2D 计算阵列
AMD NPU 基于 AMD XDNA 架构构建,核心是 XDNA Array——由 AMD AI Engine 技术构建的 2D 计算/存储阵列:
- 每一列由 4 行计算 tile + 1 行存储 tile 组成;
- 每个计算 tile 内含一个 VLIW 处理器,并带有独立的程序与数据内存;
- 存储 tile 充当 L2 内存;
- 2D 阵列可以在列边界处切分,形成空间上相互隔离的分区(spatial partition),分区可绑定到一个工作负载上下文;
- 每一列还拥有专用 DMA 引擎,负责在主机 DDR 与存储 tile(L2)之间搬运数据。
不同平台的阵列规模不同:
| NPU 平台 | 阵列拓扑 | 计算列数 | L2 总容量 | 最大并发负载上下文 |
|---|---|---|---|---|
| AMD Phoenix / Hawk Point | 4x5 | 5 列 | 2560 KB | 6 个 |
| AMD Strix Point | 4x8 | 8 列 | 4096 KB | 16 个 |
单行存储 tile 构成一个软件管理的片上 L2 内存池,DMA 引擎在主机 DDR 与存储 tile 之间移动数据。
微控制器:NPU 固件的执行者
NPU 内部微控制器运行 NPU 固件,职责包括:
- 命令处理;
- XDNA Array 分区建立;
- XDNA Array 配置;
- 工作负载上下文管理;
- 工作负载编排(orchestration)。
固件使用两类隔离上下文服务请求:
- ERT(Execution Runtime Task):每个工作负载上下文对应一个专用的隔离非特权上下文实例,负责处理该负载的用户通道请求,并在负载上下文中执行用户提供的
ctrlcode; - MERT(Management ERT):唯一的隔离特权上下文,专门服务来自 amdxdna 驱动的管理命令。
Mailbox:特权通道与用户通道
微控制器与 amdxdna 驱动之间通过**邮箱(mailbox)**通信,分为两类通道:
| 通道 | 用途 | 服务者 | 绑定关系 |
|---|---|---|---|
| 特权通道 | 上下文建立、遥测、查询、错误处理、用户通道建立等管理任务 | MERT | 绑定到单个 mailbox |
| 用户通道 | 向 NPU 提交工作 | 该上下文的 ERT 实例 | 每个工作负载上下文独享一个 mailbox |
PCIe EP:主机侧视角
NPU 对 x86 主机 CPU 呈现为一个 PCIe Endpoint,带多个 BAR 和若干 MSI-X 中断向量。NPU 使用专用的高带宽 SoC 级 fabric 读写主机内存;每个 ERT 实例拥有独立的 MSI-X 中断,MERT 拥有单个 MSI-X 中断。
BAR 数量随设备而异,按功能可归类为:
- PSP BAR:暴露 AMD PSP(Platform Security Processor,平台安全处理器)功能;
- SMU BAR:暴露 AMD SMU(System Management Unit,系统管理单元)功能;
- SRAM BAR:暴露 mailbox 的环形缓冲区;
- Mailbox BAR:暴露 mailbox 控制寄存器(head、tail、ISR 寄存器等);
- Public Register BAR:暴露公共寄存器。
不同设备中 BAR 的组合方式不同,例如:
- AMD Phoenix 设备:PSP、SMU、Public Register BAR 均位于 PCIe BAR index 0;
- AMD Strix Point 设备:Mailbox 与 Public Register BAR 位于 index 0,而 PSP 的寄存器分布在 index 0(Public Register BAR)和 index 4(PSP BAR)两处。
源码中可以看到驱动按 (device_id, rev_id) 选择设备信息结构:amdxdna_pci_drv.c 定义了 PCI 设备表(0x1502、0x17f0、0x17f2、0x17f3、0x1B0B、0x1B0C),其中 0x17f0 的三个 rev(0x10/0x11/0x20)分别映射到 dev_npu4_info、dev_npu5_info、dev_npu6_info,0x17f2/0x1B0B 与 0x17f3/0x1B0C 则分别对应 NPU3 的 PF(物理功能)与 VF(虚拟功能)信息,这与上文“具体设备 BAR 布局不同”的说明相互印证。
二、进程隔离硬件与混合调度
进程隔离硬件
XDNA Array 可被动态切分为多个隔离的空间分区,每个分区包含一列或多列,由微控制器编程列隔离寄存器完成切分。每个空间分区关联一个 PASID,同样由微控制器写入,因此 NPU 内多个空间分区可以并发地访问主机内存并受 PASID 保护。NPU 固件自身则依赖微控制器 MMU 强制的隔离上下文来分别服务用户通道与特权通道请求。
从源码结构看,驱动侧通过 IOMMU SVA 绑定获得每个客户端的 PASID:amdxdna_pci_drv.c 中的 amdxdna_sva_init() 调用 iommu_sva_bind_device() 并 iommu_sva_get_pasid() 取回 PASID,失败则解绑并返回 -ENODEV——这是“每个工作负载上下文独占 PASID 保护”的内核侧落点。
空间与时间混合调度
AMD XDNA 架构支持对 2D 阵列进行空间 + 时间(时分)混合调度:空间分区可随负载需求动态建立与拆除。一个空间分区可以独占绑定一个工作负载上下文,另一个分区则可能被临时(时间上)共享给多个上下文;对于临时共享的分区,微控制器会随时把其 PASID 更新为当前绑定上下文,从而在时分复用下依然保持隔离。
Resource Solver:列资源分配器
Resource Solver 是 amdxdna 驱动中负责在多个负载间分配 2D 阵列的组件:
- 每个负载在元数据中声明运行 NPU 二进制所需列数;
- Solver 结合负载给出的提示(hints)与自身启发式策略,决定 2D 阵列的(重)分区策略以及空间/时间共享下的列映射;
- 最终的“上下文—列”绑定决策由固件(FW)强制执行。
源码实现位于 aie2_solver.c。其内部以 partition_node 描述一个分区(起始列 start_col、列数 ncols、是否独占 exclusive、共享请求数 nshared),与文档中“独占/临时共享”的语义一一对应。此外 Solver 还承担 QoS 检查与 DPM(动态功耗管理)档位选择:qos_meet() 依据负载的 gops、fps、latency 参数计算所需服务能力,set_dpm_level() 遍历 cu_clk_list 中的各级频率,选出能满足所有会话的最低/合适档位(无 QoS 参数时直接取最高档)。
三、应用二进制:overlay 与 ctrlcode
一个 NPU 应用负载由 NPU 编译器生成的两个独立二进制组成:
- AMD XDNA Array overlay:用于配置 NPU 空间分区。overlay 包含计算 tile 的流开关(stream switch)配置指令与 ELF,由绑定该负载的空间分区所关联的 ERT 实例加载到分区上;
ctrlcode:用于编排已加载到空间分区上的 overlay。它由运行在保护模式下、处于该负载上下文中的 ERT 在微控制器上执行,由一系列名为XAie_TxnOpcode的操作码序列构成。
特殊主机缓冲区
文档还描述了两种特殊缓冲区:
- Per-context Instruction Buffer:每个工作负载上下文使用一块 64 MB 的常驻主机缓冲区,被内存映射到服务该负载的 ERT 实例中;负载的
ctrlcode会拷贝进这块内存。该缓冲区与其他输入/输出缓冲区一样受 PASID 保护,同时也会映射到负载的用户空间; - Global Privileged Buffer:驱动另外分配一块全局缓冲区,用于 MERT 错误记录等维护任务。它使用全局 IOMMU 域,只有 MERT 可以访问。
四、运行一个 NPU 负载的高层流程
文档给出了在工作负载跑起来之前的 11 个步骤,这里按执行主体分组复述:
准备阶段(编译)
- 将负载编译为 overlay 与
ctrlcode二进制。
上下文建立阶段(用户态 + 驱动 + 固件)
- 用户态在驱动中打开上下文(context)并提供 overlay;
- 驱动向 Resource Solver 查询为该负载预置一组列;
- 驱动请求 MERT 在设备上按所需列创建上下文;
- MERT 创建 ERT 实例,并把 Instruction Buffer 映射进 ERT 内存;
- 用户态把
ctrlcode拷贝到 Instruction Buffer。
提交与执行阶段
- 用户态创建命令缓冲区(command buffer),其中包含指向输入、输出与指令缓冲区的指针,随即将命令缓冲区提交给驱动并睡眠等待完成;
- 驱动通过 Mailbox 把命令发送给 ERT;
- ERT 执行指令缓冲区中的
ctrlcode; ctrlcode执行过程中触发到/自主机 DDR 的 DMA,同时 XDNA Array 在并行运行;- ERT 到达
ctrlcode末尾时,触发 MSI-X 中断向驱动发送完成信号,驱动随即唤醒等待中的负载。
这条链路与源码结构吻合:驱动通过 amdxdna_mailbox.c 实现 mailbox 收发,amdxdna_ctx.c 管理工作负载上下文,amdxdna_cbuf.c 处理命令缓冲区,而 DMA 与列分配的底层差异则分别由 aie2_solver.c、aie2_ctx.c(第二代 XDNA)与 aie4_* 系列文件(第四代,含 UMQ 用户邮箱队列与 SR-IOV)承载。
五、启动流程:经 PSP 安全加载 NPU 固件
amdxdna 驱动通过 PSP 安全加载签名的 NPU 固件并启动 NPU 微控制器,随后等待位于 BAR 0 上特殊位置的 alive 信号。SoC 挂起(suspend)期间 NPU 会断电,恢复(resume)后重新加载 NPU 固件并再次执行握手。
源码中可以直接看到驱动声明的固件清单:amdxdna_pci_drv.c 通过 MODULE_FIRMWARE() 声明了 amdnpu/1502_00/npu.sbin、amdnpu/17f0_10/npu.sbin、amdnpu/17f0_11/npu.sbin、amdnpu/17f0_20/npu.sbin 及其对应的 npu_7.sbin 变体——这些设备 ID(1502/17f0)与上文 PCIe 设备表一致,说明固件按设备型号分目录存放。驱动的版本演进也记录在源码注释中(当前为 0.10,从“支持 BO 用量查询”演进到“支持 AIE4 UMQ”)。
编译依赖:该驱动是 DRM 加速子系统的一部分,Kconfig 定义了 DRM_ACCEL_AMDXDNA(“AMD AI Engine”),依赖 AMD_IOMMU、DRM_ACCEL、PCI、HAS_IOMEM、X86_64,并选择 DRM_SCHED、DRM_GEM_SHMEM_HELPER、FW_LOADER、HMM_MIRROR;选 M 时生成 amdxdna 内核模块。HMM_MIRROR 与 AMD_IOMMU 依赖正是 SVA/PASID 用户内存保护与主机缓冲区映射(见上节 Instruction Buffer)的基础。
六、用户态组件:编译器与 UMD
NPU 生态的用户态组件包括:
- Peano:基于 LLVM 的开源单核编译器,面向 AMD XDNA Array 计算 tile(对应开源仓库
llvm-aie); - IRON:面向 AMD XDNA Array NPU 的开源阵列编译器,底层使用 Peano(对应开源仓库
mlir-aie); - XRT 运行时栈:开源用户态驱动运行时,与 amdxdna 内核驱动对接(
Xilinx/XRT); - XRT 的 NPU shim:面向 NPU 的开源 shim 层(
amd/xdna-driver)。
即典型链路为:编译器(Peano/IRON)生成 overlay + ctrlcode → XRT + xdna-driver shim 通过 DRM 接口调用 amdxdna 内核驱动 → 驱动经 MERT/ERT 与 mailbox 调度硬件执行。
七、DMA 操作、错误处理与遥测
DMA 操作
DMA 指令编码在 ctrlcode 中,对应 XAIE_IO_BLOCKWRITE 操作码。当 ERT 执行该操作码时,即在主机 DDR 与 L2 内存之间发起 DMA 搬运——这解释了为何 DMA 不需要用户态直接参与:搬运由 ERT 在执行 ctrlcode 序列的过程中自动触发。
错误处理
错误处理路径为:
- MERT 检测到 XDNA Array 中的错误后,暂停对应工作负载上下文的执行,并通过特权通道向驱动发送异步消息;
- 驱动向 MERT 发送缓冲区指针,让 MERT 捕获与出错上下文绑定的分区的寄存器状态;
- 驱动读取该缓冲区内容,解码错误。
这与第二节的 Global Privileged Buffer(仅 MERT 可访问、位于全局 IOMMU 域)共同构成维护/错误记录的数据通路。
遥测
MERT 可上报多种遥测信息,文档列举了:
- L1 中断计数器;
- DMA 计数器;
- Deep Sleep 计数器;
- 等等。
八、DRM 客户端用量统计(fdinfo)
amdxdna 驱动实现了 DRM client usage stats 规范(见内核文档 :ref:drm-client-usage-stats``)。文档给出了示例输出:
pos: 0
flags: 0100002
mnt_id: 29
ino: 939
drm-driver: amdxdna_accel_driver
drm-client-id: 3219
drm-pdev: 0000:c5:00.1
amdxdna_accel_driver-heap-alloc: 60 KiB
amdxdna_accel_driver-internal-alloc: 67588 KiB
amdxdna_accel_driver-external-alloc: 0
drm-total-memory: 67632 KiB
drm-shared-memory: 0
其中驱动自有的三个键值对含义是:
heap-alloc:客户端 heap 分配(client->heap_usage);internal-alloc:驱动内部 BO 分配(total_int_bo_usage);external-alloc:外部 BO 分配(total_bo_usage - internal_usage)。
源码落点在 amdxdna_pci_drv.c:fdinfo 输出函数从 struct amdxdna_client(定义于 amdxdna_pci_drv.h)读取 heap_usage、total_bo_usage、total_int_bo_usage 三个计数器,经 drm_fdinfo_print_size() 打印。计数维护在 GEM 路径上:amdxdna_gem.c 的 amdxdna_gem_add_bo_usage()/amdxdna_gem_del_bo_usage() 在 BO 发布/回收时增减统计。此外驱动还实现了 AMD_IOCTL_AMDXDNA_GET_ARRAY 形式的跨客户端 BO 用量聚合查询(amdxdna_drm_get_bo_usage(),见 amdxdna_gem.c),可一次性得到所有客户端的 total/internal/heap 用量汇总,便于用户态监控整个 NPU 的内存压力。
九、小结:从文档视角建立 NPU 内核栈心智模型
- 硬件层:XDNA Array(VLIW 计算 tile 列 + L2 存储 tile + 每列 DMA)是算力与内存载体;微控制器固件(MERT/ERT)是控制大脑;mailbox + MSI-X 是主机与固件的通信骨架;PASID + 列隔离寄存器提供进程级空间隔离。
- 驱动层:amdxdna 作为 DRM accel 驱动负责设备识别(PCI ID 表)、PSP 固件加载与 alive 握手、SVA/PASID 绑定、Resource Solver 列分配、上下文与命令缓冲区管理、错误解码与遥测上报,以及 DRM client usage stats。
- 应用层:Peano/IRON 编译出 overlay 与
ctrlcode,XRT + xdna-driver shim 经 DRM 接口提交负载;执行期由 ERT 运行ctrlcode,通过XAIE_IO_BLOCKWRITE触发 DDR↔L2 的 DMA,最后以 MSI-X 完成信号唤醒用户态。
阅读入口建议:文档本体 amdnpu.rst 与加速子系统总览 accel/index.rst;驱动源码 drivers/accel/amdxdna,重点关注 amdxdna_pci_drv.c(设备表/固件/fdinfo)、aie2_solver.c(资源求解)、amdxdna_ctx.c(上下文)、amdxdna_cbuf.c(命令缓冲区)、amdxdna_mailbox.c(邮箱通信)与 aie_psp.c(PSP 固件加载)。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00