Linux 内核 QAIC 驱动深度解析:Qualcomm Cloud AI(AIC100/AIC080)加速卡的硬件架构、NNC 协议与 uAPI 实战指南
本文基于 Linux 内核的 QAIC 驱动文档 及其子页面(QAIC 驱动说明、AIC100 硬件文档、AIC080 文档),结合 drivers/accel/qaic/ 下的实际源码,系统讲解 Qualcomm Cloud AI 系列 PCIe 加速卡(AIC100/AIC080/AIC200)在内核中的支持方式:硬件组成与 BAR 布局、无闪存启动流程、MHI 通道划分、DMA Bridge 的 FIFO 与信号量同步机制、NNC 协议分工、中断风暴缓解策略、完整的 uAPI IOCTL 集与模块参数。读完后你可以掌握该加速卡从 PCI 枚举、固件加载到工作负载提交/执行/等待的完整软件路径,并能在内核中定位对应实现。
一、产品定位与产品族
QAIC(Qualcomm AI Card)驱动是 AIC100 家族 AI 加速器产品的内核态驱动(KMD)。该系列是 PCIe 适配器卡,板载一颗专用 SoC ASIC,目标是高效运行 AI 深度学习推理(inference)工作负载,而非训练。核心规格:
- PCIe 接口支持 Gen4 速度、8 条 lane(x8);
- 单颗 SoC 最多可配 16 个 NSP(Neural Signal Processor)用于运行工作负载;
- 每颗 SoC 含一颗 ARM A53 管理 CPU(即 QSM);
- 卡上最多 32 GB DDR;
- 单系统可插多张 AIC100 卡扩展整体性能;卡是多用户设备,支持多用户并发执行工作负载。
文档树中的三个页面分别描述产品族:
| 文档 | 内容 |
|---|---|
| aic100.rst | AIC100 完整硬件/协议/启动流程文档(含 SA9000P,Snapdragon Ride 的一部分) |
| aic080.rst | AIC080 是 AIC100 的衍生型号:NSP 数量与主频降低以适配资源受限方案,PCIe Product ID 为 0xa080,其余文档全部适用 |
| qaic.rst | KMD 侧:中断处理、NNC 协议分工、uAPI、客户端隔离、模块参数 |
从源码结构看,驱动还覆盖了第三个器件 ID:qaic_drv.c 定义了 PCI_DEVICE_ID_QCOM_AIC080 = 0xa080、PCI_DEVICE_ID_QCOM_AIC100 = 0xa100、PCI_DEVICE_ID_QCOM_AIC200 = 0xa110,并为 AIC200 配置了独立的 BAR 掩码与 MHI/DBC BAR 索引(aic200_config),即 AIC200 是同一 KMD 支持下的新家族(qaic.h 中的 enum aic_families 也包含 FAMILY_AIC200)。
PCIe 身份标识与复位能力
- AIC100 使用标准 Qualcomm VID 0x17cb;所有 AIC100 SKU 共用 DID 0xa100(AIC080 为 0xa080)。
- AIC100 不实现 FLR(function level reset)——复位管理不能依赖 PCIe FLR,这一点对驱动的状态恢复设计(见 SSR 章节)有直接约束。
- AIC100 实现 MSI 但不实现 MSI-X:正常工作偏好 17 个 MSI(1 个给 MHI,16 个给 DMA Bridge),在无法预留 32 个 MSI 的场景可回退到 1 个 MSI(单 MSI 模式的详细行为见本文第九节)。
BAR 布局
AIC100 提供 3 个 64 位 BAR:
| BAR | 大小 | 用途 |
|---|---|---|
| 第 1 个 BAR | 4K | 暴露 MHI 接口给主机 |
| 第 2 个 BAR | 2M | 暴露 DMA Bridge 接口给主机(16 个 DBC × 每 DBC 4KB) |
| 第 3 个 BAR | 随配置可变,默认 64K | 当前无用途 |
从主机视角看,AIC100 有 5 个关键硬件组件:MHI(Modem Host Interface)、QSM(QAIC Service Manager)、NSP、DMA Bridge、DDR。
- MHI:主机与 QSM 通信的机制;除经 DMA Bridge 传输的工作负载数据外,与设备的所有交互都走 MHI。MHI 框架本身见 Documentation/mhi/index.rst。
- QSM:由板上 ARM A53 运行,执行卡片主固件与管理任务,每卡一个。
- NSP:即 Qualcomm Hexagon(Q6)DSP,带 HVX 与 HMX。每个 NSP 同一时刻只能跑一个工作负载,但一个工作负载可以分配到多个 NSP;由于没有硬件时间片,AIC100 最多支持 16 个并发工作负载,工作负载“调度”由主机负责。
- DMA Bridge:自研 DMA 引擎,管理数据进出工作负载的通道;每卡 1 个,含 16 条通道(DBC),每条通道是一对请求/响应 FIFO。
- DDR:卡上 DDR 存放工作负载、工作负载数据,QSM 也用它做设备管理;NSP 按 QSM 的授权访问 DDR 分区。主机不能直接访问 DDR,必须通过 QSM 请求搬运数据。
高层使用流程
AIC100 定位是多用户可编程加速器,典型推理场景的使用步骤(摘自 aic100.rst “High-level Use Flow”):
- 将工作负载编译为面向 NSP 的 ELF;
- 向 QSM 请求把 ELF 及附属物加载进设备 DDR;
- 向 QSM 请求把该工作负载激活到一组空闲 NSP 上;
- 通过 DMA Bridge 向工作负载送入输入、取回输出;
- 不再需要时向 QSM 请求去激活,NSP 回到空闲;
- 后续不再使用这些制品时,请求从 DDR 卸载,释放给其他用户。
二、无闪存(flashless)启动流程
AIC100 采用源自 Qualcomm MSM 的无闪存启动流程,固件全部由主机推送:
- 上电后 ROM 中的 PBL(Primary Bootloader)枚举 PCIe 链路,初始化 MHI 的 BHI(Boot Host Interface)组件;
- 主机经 BHI 告知 PBL SBL(Secondary Bootloader)镜像位置,PBL 从主机拉取、校验并执行 SBL;
- SBL 初始化大部分硬件(含 DDR)、把启动日志 offload 给主机、与主机做时间戳同步,并使用 Sahara 协议从主机获取运行期固件镜像;
- SBL 校验运行期固件后释放 NSP 复位并跳入 QSM;
- QSM 通过 MHI 通知主机设备进入 QSM 阶段(MHI 术语中的 AMSS),此时设备完全可用。
源码对应:drivers/accel/qaic/sahara.c 与 sahara.h 实现主机侧 Sahara 传输,mhi_controller.c 负责 MHI 控制器与设备复位(定义 MAX_RESET_TIME_SEC 25)。
三、MHI 通道定义
AIC100 为不同用途定义了如下 MHI 通道(完整表格见 aic100.rst):
| 通道名 | 通道 ID | 归属阶段 | 用途 |
|---|---|---|---|
| QAIC_LOOPBACK | 0 & 1 | AMSS | 环回测试,收到的数据原样送回主机 |
| QAIC_SAHARA | 2 & 3 | SBL | SBL 经此从主机获取运行期固件 |
| QAIC_DIAG | 4 & 5 | AMSS | 通过 DIAG 协议与 QSM 通信 |
| QAIC_SSR | 6 & 7 | AMSS | 通知子系统重启事件、offload SSR crashdump |
| QAIC_QDSS | 8 & 9 | AMSS | Qualcomm 调试子系统 |
| QAIC_CONTROL | 10 & 11 | AMSS | NNC 协议主通道,主机与 QSM 管理工作负载 |
| QAIC_LOGGING | 12 & 13 | SBL | SBL 把启动日志发给主机 |
| QAIC_STATUS | 14 & 15 | AMSS | 上报 RAS 事件 |
| QAIC_TELEMETRY | 16 & 17 | AMSS | 读取/设置功率、温度等属性 |
| QAIC_DEBUG | 18 & 19 | AMSS | 未使用 |
| QAIC_TIMESYNC | 20 & 21 | SBL | 启动阶段时间戳同步 |
| QAIC_TIMESYNC_PERIODIC | 22 & 23 | AMSS | 周期性时间戳同步 |
| IPCR | 24 & 25 | AMSS | AF_QIPCRTR 客户端/服务器 |
四、DMA Bridge(DBC):寄存器、FIFO 与同步原语
4.1 通道与寄存器
激活工作负载时 QSM 会为该网络分配一条 DMA Bridge 通道(DBC),该通道为该工作负载独占,不与其他工作负载共享。每条 DBC 由一对 FIFO 构成:请求 FIFO 与响应 FIFO。
每条 DBC 在硬件中有 4 个寄存器:
| 偏移 | 寄存器 | 访问方向 | 含义 |
|---|---|---|---|
| 0x0 | 请求 FIFO head | 主机只读 | 设备已消费的最新项 |
| 0x4 | 请求 FIFO tail | 主机读/写 | 主机递增以向 FIFO 添加新项 |
| 0x8 | 响应 FIFO head | 主机读/写 | 主机已消费的最新项 |
| 0xc | 响应 FIFO tail | 主机只读 | 设备递增以向 FIFO 添加新项 |
寄存器值是 FIFO 内索引,元素地址 = FIFO 基址 + 寄存器值 × 元素大小。DBC 寄存器经第二个 BAR 暴露,每条 DBC 在 BAR 中占 4KB——这与 qaic.h 中的定义一致:QAIC_DBC_BASE = SZ_128K、QAIC_DBC_SIZE = SZ_4K,QAIC_DBC_OFF(i) = i*4K + 128K。
真正的 FIFO 由主机内存承载:向 QSM 发送激活请求时,主机必须捐出一段连续内存给该 DBC(设备内部映射限制要求单块连续内存同时承载两个 FIFO,请求 FIFO 占段首、响应 FIFO 占段尾)。qaic.h 中的 struct dma_bridge_chan 即每条 DBC 的内核表示,包含 req_q_base/rsp_q_base(FIFO 主机侧基址)、dma_addr(总线地址)、dbc_base(BAR 内寄存器基址)以及轮询/中断相关字段(irq、poll_work)。
4.2 请求元素结构与四步处理
请求 FIFO 元素(文档给出的 C 结构):
struct request_elem {
u16 req_id;
u8 seq_id;
u8 pcie_dma_cmd;
u32 reserved;
u64 pcie_dma_source_addr;
u64 pcie_dma_dest_addr;
u32 pcie_dma_len;
u32 reserved;
u64 doorbell_addr;
u8 doorbell_attr;
u8 reserved;
u16 reserved;
u32 doorbell_data;
u32 sem_cmd0;
u32 sem_cmd1;
u32 sem_cmd2;
u32 sem_cmd3;
};
关键字段:
- req_id:请求 ID;请求与响应元素中相同 req_id 指向同一条命令;
- seq_id:请求内序列号,DMA Bridge 忽略;
- pcie_dma_cmd:Bit(7) force-MSI 标志(该请求完成时强制产生 MSI,需 QSM 配置 DMA Bridge 检查此位);Bit(4) 完成码标志(完成后生成响应元素);Bit(3) 链表传输(0)/块传输(1);Bit(1:0) 传输类型:0 不传输、1 到设备、2 从设备、3 非法;
- pcie_dma_source_addr / pcie_dma_dest_addr / pcie_dma_len:块传输地址/目标/长度;
pcie_dma_len为 32 位,单次传输上限 4GB; - doorbell_addr / doorbell_attr / doorbell_data:请求完成后要敲的“门铃”;attr 的 Bit(7) 使能写、Bit(1:0) 编码长度(0=32 位、1=16 位、2=8 位、3=保留),地址须自然对齐;
- sem_cmd0..3:信号量命令,Bit(31) 使能、Bit(30) 到设备 DMA fence、Bit(29) 从设备 DMA fence、Bit(26:24) 命令码(0 NOP、1 init、2 加、3 减、4 等待等于、5 等待大于等于、6 "P":等待大于 0 后减 1、7 保留)、Bit(22) 同步模式(0 post sync 在 DMA 之后执行信号量操作,1 pre sync 作为 DMA 的门槛,每条请求至多一个 pre sync)、Bit(20:16) 信号量索引、Bit(11:0) 操作数值。
一条请求按 4 步处理:
- 若指定,pre-sync 信号量条件必须成立;
- 若使能,执行 DMA 传输;
- 若指定,post-sync 信号量条件必须成立;
- 若使能,写门铃。
借助信号量与 NSP 上运行的工作负载配合,可实现数据流水线同步:主机可以为工作负载预排多批输入请求,DMA Bridge 只在工作负载准备好接收下一批输入时真正把数据拷进工作负载内存。
4.3 响应元素与中断
请求全部处理完毕后,若 pcie_dma_cmd 指定了完成码,则生成响应元素:
struct response_elem {
u16 req_id;
u16 completion_code;
};
completion_code 为 0 表示成功,非 0 为错误。DMA Bridge 会在某条 DBC 响应 FIFO 活动向主机发 MSI:硬件带中断风暴缓解算法,仅在响应 FIFO 从空变为非空时产生 MSI(除非 force-MSI 使能并触发)。主机收到 MSI 后应排空响应 FIFO,并自行处理排空与设备继续插入元素之间的竞争。
五、NNC 协议:KMD 与 UMD 的分工
NNC(Neural Network Control)是主机向 QSM 请求管理工作负载的协议,走 QAIC_CONTROL MHI 通道。
5.1 消息与事务
每条 NNC 请求打包成一个消息;消息是一系列事务(transactions)的序列;passthrough 类型事务可包含称作命令(commands)的元素。格式要求:小端编码、字段自然对齐,因存在 64 位元素而必须保持 64 位对齐。
- 消息 = 头 + 事务序列;
- QSM → 主机方向消息最大 4K;主机 → QSM 方向最大 64K(单个 MHI 包最大尺寸),并支持续传机制:消息 N+1 可标记为消息 N 的延续,用于超大的 DMA xfer 事务。
事务类型:
| 事务 | 作用 |
|---|---|
| passthrough | 用户态把不透明载荷直接发给 QSM,即 NNC 命令;载荷的 QSM 消息要求由用户态负责 |
| dma_xfer | DMA 传输:描述 QSM 应按“地址+大小”元组搬进设备的对象 |
| activate | 把工作负载激活到 NSP 上;主机须提供 DBC 使用的内存 |
| deactivate | 去激活活动工作负载,NSP 回到空闲 |
| status | 查询 QSM 的 NNC 实现(版本、是否使用 CRC) |
| terminate | 释放某用户的资源 |
| dma_xfer_cont | 上一条 DMA 传输的续传(高碎片化无法单消息描述时补更多区段) |
| validate_partition | 查询某 partition 标识是否有效 |
每条消息带 user id 与 partition id:user id 让 QSM 跟踪资源并在用户消失(如进程崩溃)时释放;partition id 标识消息适用的 QSM 资源分区。消息可以带 CRC:在 QSM 通过 status 事务报告“不需要 CRC”之前都应当带 CRC;SA9000P 上的 QSM 出于 black channel safing 要求必须带 CRC。
5.2 KMD/UMD 边界与 terminate
NNC 实现被拆分在 KMD(QAIC)与 UMD 之间(摘自 qaic.rst):
- QAIC 负责 NNC 线上协议的编解码,以及需要内核态知识才能处理的协议元素(例如把主机内存映射为设备 IOVA);它理解消息结构和全部事务,但不理解命令(passthrough 事务的载荷);
- 小端与 64 位对齐由 QAIC 在其能力范围内强制执行;对 passthrough 载荷,QAIC 依赖 UMD 自行满足格式要求;
- terminate 事务对 QAIC 尤为关键:QAIC 不知道加载到设备上的资源(那发生在 NNC 命令层),因此无法回滚用户态活动。为保证进程崩溃或出 bug 时用户资源被完全释放,QAIC 在用户消失时用 terminate 通知 QSM。
版本协商:QSM 可报告其支持的 NNC 协议版本,形式为 Major.Minor。Major 变化意味着影响消息格式或事务(影响 QAIC);Minor 变化意味着只影响命令(不影响 QAIC)。
5.3 客户端隔离
AIC100 支持多客户端:一个客户端可消费多条 DBC,多个客户端也可各自消费一条或多条 DBC。由于工作负载可能含敏感信息,只有工作负载属主客户端才应能操作其 DBC:
- 客户端由其
open()关联的实例标识; - 客户端只能使用其自行分配的内存和被分配给其工作负载的 DBC;
- 访问其他客户端资源的尝试会被拒绝。
内核侧对应 qaic.h 的 struct qaic_user(含唯一 handle、kref 引用计数与 SRCU),qaic_drv.c 的 qaic_open 在设备 QAIC_ONLINE 时才分配用户句柄(ida_alloc(&qaic_usrs)),否则返回 -ENODEV。
六、uAPI:accel 设备与 9 个 IOCTL
QAIC 为每个物理 PCIe 设备创建一个 accel 设备,该 accel 设备与 PCIe 设备在 Linux 中的生命周期一致。PCIe 设备并非随时可接受用户态请求:QAIC 通过 KOBJ_ONLINE/OFFLINE uevent 通告设备何时可接受请求(ONLINE)、何时因复位或其他状态迁移而停止接受请求(OFFLINE)。
驱动特定 IOCTL 定义在 include/uapi/drm/qaic_accel.h,编号与结构如下(语义来自 qaic.rst):
| IOCTL | 编号 | 语义 |
|---|---|---|
| DRM_IOCTL_QAIC_MANAGE | 0x00 | 向 QSM 发送 NNC 请求;阻塞直到收到响应或超时 |
| DRM_IOCTL_QAIC_CREATE_BO | 0x01 | 分配可收/发数据给工作负载的 buffer object,返回 GEM handle;BO 在切片(见 ATTACH_SLICE_BO)前不可用 |
| DRM_IOCTL_QAIC_MMAP_BO | 0x02 | 把已分配的 BO 准备为可 mmap 进用户进程 |
| DRM_IOCTL_QAIC_ATTACH_SLICE_BO | 0x03 | 为 BO 做“切片”:描述 BO 的哪些部分发往工作负载何处。需要一组面向 DMA Bridge 的 DMA 传输,因此把 BO 锁定到某条 DBC |
| DRM_IOCTL_QAIC_EXECUTE_BO | 0x04 | 提交一组已切片 BO 到设备;非阻塞,成功仅表示已入队,不代表已执行 |
| DRM_IOCTL_QAIC_PARTIAL_EXECUTE_BO | 0x05 | 同 EXECUTE_BO,但允许为本次调用收缩 BO:BO 通常有 N 个输入,若只有子集可用,则只发送 BO 的前 M 字节以减少传输开销。需动态重算切片,因此入队前有额外处理开销 |
| DRM_IOCTL_QAIC_WAIT_BO | 0x06 | 等待某个 BO 被设备处理完成;阻塞直到 BO 处理完可重新入队,或超时 |
| DRM_IOCTL_QAIC_PERF_STATS_BO | 0x07 | 收集最近一次 BO 执行的性能统计,用于构建 BO 处理的端到端时间线 |
| DRM_IOCTL_QAIC_DETACH_SLICE_BO | 0x08 | 移除此前 ATTACH_SLICE_BO 附上的切片信息(其逆操作);调用时 BO 必须空闲;detach 后 BO 不能再执行,直到再次 attach。attach/detach 组合允许一个 BO 服务多个工作负载 |
内核中的实现入口见 qaic.h 声明的 qaic_create_bo_ioctl、qaic_attach_slice_bo_ioctl、qaic_execute_bo_ioctl、qaic_partial_execute_bo_ioctl、qaic_wait_bo_ioctl、qaic_perf_stats_bo_ioctl、qaic_detach_slice_bo_ioctl 等,实现在 qaic_data.c;QAIC_MANAGE_MAX_MSG_LENGTH 在 uapi 头中定义为 SZ_4K,与“QSM→主机方向消息最大 4K”对应。内核侧 BO 结构 struct qaic_bo 持有 sg_table、切片列表、nr_slice_xfer_done、perf_stats(req_received_ts/req_submit_ts/req_processed_ts 三个纳秒时间戳与 queue_level_before),正是 PERF_STATS 数据面的来源。
七、模块参数
QAIC 支持以下模块参数(文档见 qaic.rst,源码位置见右列):
| 参数 | 类型/默认值 | 生效时机 | 说明 | 源码位置 |
|---|---|---|---|---|
datapath_polling |
bool,默认 0(关) | 必须在 QAIC 驱动初始化时设置 | 用轮询线程处理数据面事件,替代设备中断;适用于多 MSI 损坏的平台 | qaic_drv.c |
mhi_timeout_ms |
uint,默认 2000 | 必须在设备探测时设置 | MHI 操作超时(毫秒) | mhi_controller.c |
control_resp_timeout_s |
uint,默认 60 | 必须在向 QSM 发请求时设置 | QSM 对 NNC 消息的响应超时(秒) | qaic_control.c |
wait_exec_default_timeout_ms |
uint,默认 5000 | 必须在 wait_exec ioctl 调用前设置;ioctl 调用内显式指定的值对当次调用覆盖默认 | DRM_IOCTL_QAIC_WAIT_BO 的默认超时(毫秒) |
qaic_data.c |
datapath_poll_interval_us |
uint,默认 100 | 下一个轮询周期生效 | 数据面轮询开启时的轮询间隔(微秒) | qaic_data.c |
timesync_delay_ms |
uint,默认 1000 | — | 相邻两次 timesync 操作的时间间隔(毫秒) | qaic_timesync.c |
八、中断风暴缓解与单 MSI 回退
8.1 IRQ 风暴缓解
AIC100 DMA Bridge 硬件虽有 IRQ 风暴缓解机制,但特定条件下风暴仍会发生:当工作负载非常快且主机响应迅速——主机排空响应 FIFO 的速度能跟上设备插入元素的速度时,FIFO 会频繁地在“空→非空”间切换,从而以工作负载的处理速率产生 MSI。文档给出的实例:lprnet(车牌识别网络)工作负载可产生超过每秒 10 万个 MSI,多数系统长期承受这种中断开销会因中断控制器打扰 CPU 触发某种看门狗而崩溃。
QAIC 的软件缓解策略(qaic.rst):
- 收到 IRQ 时先禁用该中断线,阻止中断控制器继续打扰 CPU;
- 排空 FIFO;
- 进入“last chance”轮询算法:QAIC 睡眠一段时间,观察工作负载是否还有新活动;期间中断线保持禁用;
- 若检测到无活动,退出轮询模式并重新使能中断线。
效果:同一 lprnet 用例从 /proc/interrupts 统计的每秒约 10 万 IRQ 降到 5 分钟内约 64 次 IRQ,主机保持稳定,工作负载吞吐性能不变(在运行间噪声范围内)。
8.2 单 MSI 模式
多 MSI 并非所有系统都支持得很好(2023 年前后),虚拟化环境更差:有的 hypervisor 会遮蔽 PCIe MSI 能力结构,而支持 MultiMSI 需要大内存开销的 vIOMMU。因此驱动支持仅能分配 1 个 MSI 的回退:该 MSI 由 MHI 与所有 DBC 共享;设备检测到只配置了 1 个 MSI 时,会把 DBC 的中断全部导向原本给 MHI 用的那个中断。代价是每来一个中断,所有 DBC 和 MHI 的中断处理器都会醒来;但 DBC 的线程化 irq handler 只在检测到有工作要干时才启动(MHI 的线程 handler 则总是启动)。
注意一个交互细节:若 DBC 被配置为强制 MSI 中断(请求元素 pcie_dma_cmd 的 force-MSI 位),可绕过上述软件 IRQ 风暴缓解——由于 MSI 被共享、永不禁用,FIFO 中每新增一个条目都会触发一个新中断。
九、SSR、RAS 与 Telemetry
9.1 子系统重启(SSR)
SSR 是限制错误影响面的机制:AIC100 多用户并发运行时,某个用户的工作负载崩溃不应波及其他工作负载。某工作负载崩溃时:
- QSM 经 QAIC_SSR MHI 通道通知主机,通知按 DBC 标识受影响工作负载;
- 随后进入多阶段恢复流程清理两侧状态,把 DBC/NSP 恢复到可用状态;
- SSR 发生时该工作负载的所有状态丢失:处理中或未处理的输入全部丢失;已加载制品仍留在卡上 DDR,但主机需要重新激活工作负载才能恢复。
受 SSR 影响的 DBC 依次经历如下状态迁移(与 qaic.h 的 enum dbc_states 一致):
DBC_STATE_BEFORE_SHUTDOWN——受影响 NSP 发现于不可恢复错误条件;DBC_STATE_AFTER_SHUTDOWN——NSP 处于复位中;DBC_STATE_BEFORE_POWER_UP——NSP 调试信息已收集完毕、可供主机取走(可选);此时 QSM 重启 NSP;DBC_STATE_AFTER_POWER_UP——NSP 已重启、完全可用、处于空闲。
SSR 还有可选的 crashdump 收集特性:启用后主机可以收集崩溃 NSP 的内存转储并经 dev_coredump 子系统导出到用户态;也可以拒绝设备的 crashdump 收集请求。内核实现见 qaic_ssr.c(struct qaic_device 中的 ssr_dbc 用哨兵 U32_MAX 表示无 SSR 进行中)。
9.2 RAS 与 Telemetry
- RAS(Reliability, Accessibility, Serviceability):AIC100 预期部署在应用 RAS 理念的服务系统中。PCIe AER 是 RAS 的一部分,但 AER 不允许设备报告内部错误细节,因此 AIC100 实现了自定义 RAS 机制:RAS 事件发生时,QSM 经 QAIC_STATUS MHI 通道上报带细节的事件;系统管理员可据此判断设备是否需要额外服务。内核侧对应 qaic_ras.c,错误计数(correctable / uncorrectable / uncorrectable-non-fatal)维护在
struct qaic_device的ce_count/ue_count/ue_nf_count中。 - Telemetry:QSM 可上报(部分还可由主机控制)设备物理属性,例如温度限制、温度读数、功率读数,经 QAIC_TELEMETRY 通道通信。实现见 qaic_timesync.c 等相邻模块与通道管理。
十、内核源码地图与编译配置
Kconfig 项为 DRM_ACCEL_QAIC("Qualcomm Cloud AI accelerators",tristate),依赖 DRM_ACCEL、PCI、HAS_IOMEM、MHI_BUS,并 select CRC32 与 WANT_DEV_COREDUMP(后者对应 SSR crashdump 的 dev_coredump 导出能力);选 M 时模块名为 qaic。模块参数即第七节所列 6 个。
| 源码文件 | 职责 |
|---|---|
| qaic_drv.c | PCI 探测/移除、每器件配置表(AIC080/AIC100/AIC200 的 BAR 掩码与 MHI/DBC BAR 索引)、open/close 用户管理、datapath_polling 参数 |
| mhi_controller.c | MHI 控制器、设备复位、Sahara 引导;mhi_timeout_ms 参数 |
| qaic_control.c | QAIC_CONTROL 通道上的 NNC 消息收发、control_resp_timeout_s 参数 |
| qaic_data.c | DBC 请求/响应 FIFO 管理、数据面 IOCTL 与轮询;两个数据面参数 |
| qaic_ssr.c / qaic_ras.c | SSR 状态机、crashdump;RAS 事件处理 |
| qaic_timesync.c | 主机/设备时间戳同步(timesync_delay_ms) |
| sahara.c | 无闪存启动的 Sahara 固件传输 |
| qaic_sysfs.c / qaic_debugfs.c | DBC 状态等 sysfs 属性、调试接口 |
| qaic.h | 核心数据结构:qaic_device、dma_bridge_chan、qaic_bo、bo_slice、DBC/设备状态枚举 |
设备状态机 dev_states(QAIC_OFFLINE / QAIC_BOOT / QAIC_ONLINE)正是 uAPI 章节所述 KOBJ_ONLINE/OFFLINE uevent 的内核侧来源:qaic_open 仅当 dev_state == QAIC_ONLINE 时放行用户,否则 -ENODEV。
小结
QAIC 文档树 + 驱动源码共同描述了一条清晰的边界:主机侧内核(QAIC KMD)只管 PCIe/MHI 传输、DBC 数据面、NNC 事务层与用户隔离,工作负载语义全部下沉到 UMD 与 QSM 固件。实践要点:
- 使用
datapath_polling=1应对多 MSI 不可靠(尤其虚拟化)平台,配合datapath_poll_interval_us调节轮询粒度; - 调优超时时注意各参数的“生效时机”约束(初始化期、探测期、调用前);
- 多客户端共享一张卡时,客户端隔离基于 open 实例 + user id,进程崩溃由 terminate 事务兜底释放资源;
- 排查故障时按 MHI 通道分工定位:控制走 QAIC_CONTROL、错误恢复走 QAIC_SSR、RAS 走 QAIC_STATUS、固件获取走 QAIC_SAHARA、时间戳走 QAIC_TIMESYNC。
相关文档入口:Compute Accelerators 总览、MHI 框架文档;用户态组件(编译器、UMD、Sahara loader/kickstart)在 aic100.rst “Userspace components” 一节中列出了上游开源项目指引。
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