由 riscv64-interrupt-plic-aplic-research.md 生成

RISC-V 64 中断控制器调研:PLIC 与 AIA(APLIC / IMSIC)——Bringup 中断 Bug 的根因与排查

元数据内容
文档类型技术调研报告
版本v1.0
状态公开资料调研;未进行目标硬件实测与基准复现
密级公开资料
作者Qoder(基于 RISC-V 官方规范、Linux 内核与上游项目源码、设备树 binding 与厂商公开资料整理)
生成日期2026-10-08
研究截点2026-10-08
目标读者Bringup / 固件 / 内核驱动 / 虚拟化工程师,性能与调试工具开发者,RISC-V 平台选型与技术管理者
调研问题① PLIC 的规范语义与编程模型是什么,为什么 claim/complete 协议最容易在 bringup 阶段踩坑;② AIA 的 APLIC 与 IMSIC 相对 PLIC 有什么本质差异(投递模型、虚拟化、CSR);③ 两代中断控制器在 Linux、固件、QEMU 与虚拟化中的软件接口与现状;④ 国内平台(香山、SpacemiT 等)落在哪一代、有什么独特实现;⑤ bringup 中断 bug 的根因分类与系统化排查方法
覆盖范围PLIC v1.0.0 规范语义(gateway、priority、pending、enable、threshold、claim、completion);AIA v1.0 规范(Smaia/Ssaia、IMSIC、APLIC、CSRs、MSLevel、VSLevel、IPIs);Linux irqchip 驱动(irq-sifive-plic、irq-riscv-aplic-、irq-riscv-imsic-);设备树 binding(sifive,plic-1.0.0、riscv,aplic、riscv,imsics、riscv,cpu-intc);OpenSBI 的 APLIC/IMSIC 初始化;QEMU virt 的 aia 模式;内核 spurious 机制;国内平台与虚拟化实践(香山 ChiselAIA、SpacemiT K1/K3、hvisor);社区实践(T-Head 两格设备树、Zephyr PLIC 边沿规范化)
排除范围未公开的芯片内部实现与流片细节;真实硬件上的性能与功耗实测;安全认证结论;采购建议;PLIC 网关在电平/边沿下“一周期”级时序细节(本次未能从规范正文确证,报告回避断言)

版本历史

版本日期内容
v1.02026-10-08首次调研:PLIC v1.0.0 与 AIA v1.0 规范语义逐章核读;Linux/OpenSBI/QEMU 软件路径与国内平台证据;给出 bringup 中断 bug 五类根因、排查矩阵与验收建议

术语与缩略语

术语本报告含义
PLIC平台级中断控制器(Platform-Level Interrupt Controller),RISC-V 第一代外部中断控制器事实标准,规范版本 v1.0.0
AIA高级中断架构(Advanced Interrupt Architecture),RISC-V 第二代中断标准,由 Smaia、Ssaia、IMSIC、APLIC 组成
APLIC高级 PLIC(Advanced PLIC);AIA 中承接有线中断、以 direct 或 MSI 两种模式向 hart 投递
IMSIC传入 MSI 控制器(Incoming MSI Controller);每 hart 一个,用内存消息中断文件承载外部中断身份
Smaia / SsaiaM 态 / S 态高级中断 CSR 扩展;mtopei、stopei、siselect 等 CSR 的来源
GatewayPLIC 中位于中断源与核心之间的网关:接收源信号、置位 pending、在完成消息回达前不再转发该源请求
ContextPLIC 的目标上下文,等于“hart × 特权级”;每个 context 有独立的 enable、threshold、claim 寄存器
claim / completePLIC 协议的成对操作:claim 读取胜者身份并原子清 pending;complete 写回身份告知网关服务完成
pending中断待处理状态位;在 PLIC 中是尖峰位,在 IMSIC 中对应 eip 位
priorityPLIC 源优先级;规范规定数值越大优先级越高,0 保留为“永不中断”
thresholdPLIC 阈值;屏蔽优先级“小于或等于”阈值的源,0 表示全部放行
MSI消息信号中断(Message Signaled Interrupt);以内存写代替独立中断线,AIA 的投递基础
identity中断身份号;MSI 写的数据字段(data)承载,0 恒为无效值
EIID外部中断身份(External Interrupt Identity);APLIC 与 IMSIC 之间传递的中断编号
topi / claimi / topeiAPLIC 的最高待处理身份 / claim 触发寄存器;IMSIC 的 topei 读操作具备 claim 语义
eidelivery / eithresholdIMSIC 中断文件的投递使能与阈值;阈值非零时“身份大于等于阈值者不参与投递”
GEILEN每 hart 支持的 guest 中断文件数量参数(Guest External Interrupt Number)
CSR控制状态寄存器;AIA 的 M/S/VS 级操作经 mtopei、stopei、siselect 等 CSR 暴露
H 扩展RISC-V 虚拟化扩展(Hypervisor Extension);guest 中断文件与 vs 级 CSR 的语境
SBI监督二进制接口(Supervisor Binary Interface);M 态固件向上层提供的统一服务接口
Bonding / binding设备树绑定文档;描述 compatible、interrupt-cells、msi-parent 等属性的官方约束
msi-parent设备树属性:指定设备 MSI 写投递到哪个 MSI 控制器(IMSIC)
hwprobeLinux 的 RISC-V 能力探测接口;内核据此向用户态报告硬件扩展组合
spurious伪中断/未处理中断;内核统计窗口内未落入任何处理器即触发风暴防护
quirk驱动中针对特定平台实现差异或硅缺陷的兼容分支
Multi-MSI单设备以多个向量共享一段 MSI 地址的机制;Linux AIA 驱动当前不支持

可靠性标记

【C】 表示规范原文、官方文档或一手资料可直接核查的事实,不代表本报告已实测;【C*】 表示稳定的通用工程原理;【S】 表示厂商或组织的单方声明,未交叉验证;【P】 表示分析、估算、建议或条件性情景;【?】 表示本次证据不足。正文中的“判断”“建议”“估算”同样限定结论性质。

版本规则: 除明确注明外,PLIC 结论以 v1.0.0 规范为准,AIA 结论以 v1.0 规范(revision 20230605–20260222)为准;Linux 驱动与 binding 以研究截点的主线版本为准;厂商公布实现参数(文件数、身份范围等)按“宣称值”处理。硬件与软件行为随时可能随上游演进变化,结论以研究截点为准。

1. 核心判断(TL;DR)

2. 问题、范围与方法

本报告回答五个问题:PLIC 的规范语义与为什么 claim/complete 易踩坑;AIA 的 APLIC/IMSIC 相对 PLIC 的本质差异;两代控制器在 Linux/固件/QEMU/虚拟化中的软件接口与现状;国内平台的落地代际与独特实现;bringup 中断 bug 的根因分类与排查方法。

方法上采用“规范优先、上游优先、一手优先”的证据层级:ISA 与控制器规范原文、Linux 内核源码与设备树 binding、OpenSBI/QEMU 源码文档为第一层;厂商与项目官方仓库、发行方文档为第二层;社区邮件列表与第三方分析为第三层,仅用于线索与交叉印证。所有引用编号与“参考来源”台账一一对应;对未能从规范正文确证的细节(例如网关电平/边沿的一周期级行为)明确回避断言。

调研问题主要证据类型代表性来源
Q1 PLIC 规范语义与踩坑点规范逐章原文(v1.0.0)[S01][S02][S03][S06][S07][S08]
Q2 AIA 投递模型差异AIA 规范(IMSIC/APLIC/CSR 章)[S12][S13][S14][S15][S16]
Q3 软件与固件现状驱动源码、binding、OpenSBI、QEMU[S09][S10][S20][S23][S28][S30]
Q4 国内落地厂商 binding、开源仓库、项目文档[S24][S25][S32][S33][S34]
Q5 bringup 根因与排查规范、驱动、内核机制、社区实践[S11][S20][S31][S36]

3. 全球技术基线

3.1 PLIC:第一代事实标准及其语义陷阱

PLIC v1.0.0 规范把系统描述为三段:中断源经各自 gateway 进入核心,核心对每个“hart × 特权级”上下文维护独立的使能与阈值,胜出者拉高目标上下文的外部中断线。寄存器面是 32 位 MMIO,靠原子存取保证选主语义:priority 位于 0x0(每源 4 字节)、pending 位于 0x1000、enable 位于 0x2000(每 context 步长 0x80)、threshold 与 claim 位于 0x200000(每 context 步长 0x1000),规范上限为 1023 个中断源与 15871 个上下文 [S02]。完整数据通路与生命周期的读法见图 1。

区域起始偏移步长语义要点
priority0x04 字节/源数值越大优先级越高;0 保留为“永不中断”
pending0x100032 源/字尖峰位;对已使能源先置 enable 再 claim 可清除
enable0x20000x80/context源 n 对应 bit n;bit0 硬连 0(源 0 不存在)
threshold 与 claim0x2000000x1000/context低半阈值、高半 claim/complete;32 位原子访问

三个最反直觉的语义:其一,priority 的 0 不是“最低优先级”而是“禁用”;其二,threshold 屏蔽的是“小于或等于”阈值的源,写 0 才全部放行;其三,claim 操作不受 threshold 影响,只受使能位与优先级仲裁约束,无待处理时返回身份 0——把返回值 0 当作有效中断处理是新手驱动最常见的崩溃点 [S03][S06][S07]。completion 同样有陷阱:规范明确“PLIC 不检查完成身份是否与上次 claim 一致”,且处理完成后必须向网关发送完成消息,否则该源的后续请求不再进入转发链路——这正是“中断只来一次”这类现象的规范级根因 [S08]。

3.2 AIA:第二代标准的投递模型

AIA v1.0 的动机是消除 PLIC 的两个结构性缺陷:组播投递与软件竞争 claim。规范引言明确:高级 PLIC 支持“把每个被信号化的中断只发送给软件选定的单一 hart,而不是多个 hart”,并且“把到来的有线中断转换成送往各 hart IMSIC 单元的 MSI 写” [S16]。组成上,AIA 由 M/S 态 CSR 扩展(Smaia、Ssaia)、每 hart 一个的 IMSIC、以及 APLIC 构成 [S12]。投递模型的全景见图 2。

IMSIC 的中断文件承载全部语义:每 hart 包含各特权级文件与 GEILEN 个 guest 文件,每文件可容纳 63 至 2047 个中断身份;投递条件是“文件内存在既 pending 又 enable 的身份”并满足 eidelivery 与 eithreshold——eithreshold 非零阈值 X 时,“身份 X 及更高者不参与投递”(数值越小越优先);MSI 是 32 位自然对齐的内存写,落点在 4KiB 页内,数据字段承载 identity,而 identity 0 恒为无效;topei 的读操作本身即 claim,会清除对应 pending 位 [S13]。这套设计使“中断=内存写”,天然适配 PCIe MSI、虚拟化与多核扩展。

APLIC 负责把有线中断接入模型:domaincfg 的 DM 位(WARL)决定域内投递模式;direct 模式下 target 寄存器给出 hart 索引与优先级并直接拉起该 hart 的外部中断线,MSI 模式下 target 寄存器转而描述 guest 中断文件选择,命中源由 APLIC 生成 MSI 写投递;sourcecfg 把每个源配置为 Inactive、Detached、Edge0/1 或 Level0/1,inactive 源的 pending 与 enable 位只读为 0;topi 读给出最高待处理身份,claimi 读在返回身份的同时清除对应 pending,MSI 模式则依托“发送成功即自动清 pending”的协议 [S14]。M 态经 mtopei 与 mtopi 操作,S 态经 siselect 与 sireg 间接访问再落到 stopi 与 stopei,guest 侧由 vs 级 CSR 与虚拟中断文件承接 [S15][S17][S18];IPI 也可以直接写目标中断文件完成,这是虚拟化免陷入 IPI 的基础 [S19]。

3.3 软件与固件的分流器

Linux 侧两条路径并存。PLIC 驱动以 irq-sifive-plic.c 为核心,兼容档覆盖多家平台(含 spacemit,k1-plic、starfive、sophgo、canaan、eswin 等),并对两类实现差异内置 quirk:T-Head C900 与 Andes nceplic100 需要“两格中断描述”(第二格描述触发类型)且由驱动软件模拟电平/边沿,CP100 的 claim 竞争缺陷需要特殊绕行 [S09][S10]。需要强调:两格描述是这些平台的规范变体而非驱动发明的 quirk,linux-riscv 邮件列表的共识是“这不是 quirk,而是 PLIC 规范的一个特性分支” [S11]。AIA 侧由三种文件分工:irq-riscv-aplic-main.c 负责域复位(关闭全部本地使能、把全部源置为 inactive)与休眠恢复顺序,irq-riscv-aplic-msi.c 生成 MSI 写并对电平型中断经 setipnum 回写重触发,irq-riscv-imsic-state.c 与 irq-riscv-imsic-platform.c 管理中断文件状态与 MSI 载荷、亲和迁移与 PCI 枚举挂接 [S20][S21][S22][S23]。设备树 binding 规定:riscv,aplic 的 compatible 含 riscv,aplic、qemu,aplic 与 spacemit,k3-aplic,中断描述固定两格;riscv,imsics 必须声明为 MSI 控制器且给出 num-ids;cpu-intc 的外部中断格值固定为 9 [S24][S25][S26]。编号层面,Linux 的 csr.h 已把 mtopei、stopei、siselect、hvien、vstopi 等 AIA CSR 全部落位,说明内核的 CSR 面已经完整 [S27]。

固件与仿真器决定了“谁来初始化”。OpenSBI 的 fdt_irqchip_imsic.c 与 fdt_irqchip_aplic.c 只在 M 态准备 IMSIC/APLIC(冷初始化与核间映射),不替 S 态做初始化与委托 [S28][S29]。QEMU virt 机器的 aia 参数有 none、aplic、aplic-imsic 三档且默认 none(即维持 PLIC),KVM 下 kernel-irqchip=split 会强制由 QEMU 仿真 APLIC,且“无论选择哪种 AIA 模式都不提供 M 态仿真” [S30]。这意味着在 QEMU 上验证 AIA 驱动必须显式指定模式,并且对 M 态职责的覆盖天然不完整。

3.4 内核级观测与风暴防护

当中断无主时,内核的防护机制会把它变成可见事件:某 IRQ 在 100000 次中断窗口中超过 99900 次未落入任何处理函数,内核即判定其卡死,打印 nobody cared 与“Disabling IRQ #N”并停用该中断,随后以 HZ/10 的间隔轮询尝试恢复 [S31]。这套机制把“电平未清、边沿抖动、设备树触发类型配错”这类中断源问题在 dmesg 中显式化。跨栈视角还有一个佐证:Zephyr 曾长期把 PLIC 边沿支持藏在私有配置里、寄存器偏移放在设备树非标字段,最终被修正为规范化固定偏移与显式选项,说明电平与边沿语义在不同软件栈间的漂移是系统性问题 [S36]。

图 1:PLIC 数据通路与 claim/complete 协议全景(数据来源:PLIC v1.0.0 规范 [S01][S02][S03][S06][S07][S08] 与 Linux PLIC 驱动 [S09] 综合绘制)。

图 1:PLIC 数据通路与 claim/complete 协议全景
图 1:PLIC 数据通路与 claim/complete 协议全景

图 2:AIA(APLIC 与 IMSIC)投递模型与 CSR 接口面(数据来源:AIA v1.0 规范 [S12][S13][S14][S16] 与 Linux csr.h [S27] 综合绘制)。

图 2:AIA(APLIC 与 IMSIC)投递模型与 CSR 接口面
图 2:AIA(APLIC 与 IMSIC)投递模型与 CSR 接口面

4. 国内发展、差距与机会

平台代际上,国内 RISC-V 正处于两代并存的分流期。尚在 PLIC 阵营的包括:Milk-V Jupiter(K1,spacemit,k1-plic)与 VisionFive 2(JH7110,starfive 兼容档)、SG2042 与 Lichee Pi 4A(TH1520)——后两者都回退到 thead,c900-plic 兼容档,意味着两格中断描述与驱动的边沿软件模拟对它们同样适用;此外 EIC7700、K230、CV1800B 等 SoC 也都在 PLIC 兼容表中 [S09][S10]。进入 AIA 阵营的以 SpacemiT K3 为代表:其绑定明确给出 spacemit,k3-aplic 与 spacemit,k3-imsics 两个 compatible,且平台定位 RVA23,是国内首批把 APLIC 与 IMSIC 作为产品级配置的路径 [S24][S25]。

开源实现层面,香山的 ChiselAIA 是国内少有的完整 AIA 硬件开源实现:IMSIC 默认提供 M、S 加 5 个 VS 共 7 个中断文件、身份范围 1–255,经 setipnum 类寄存器投递,并对超过 8 位的身份访问做硬件截断;为实现规范要求的访问隔离(S 级不得访问 M 级中断文件),其内存布局把 M 级文件集中连续排布以便用单个 PMP 表项保护。仓库同时说明 APLIC 的 direct 投递模式尚未支持 [S32][S33]。虚拟化侧,hvisor 给出了完整的 AIA 使用范式:以 IRQ=aia 打开后,guest 中断按 APLIC target 配置以 MSI 方式投送到虚拟中断文件,guest 的 IPI 只需直写虚拟文件、无需 hypervisor 模拟,guest 对 APLIC 的寄存器访问则由 vaplic 模拟一并承接 [S34]。

差距与机会同样清晰。差距方面:其一,虚拟化纵深仍有空洞——KVM RISC-V 的嵌套虚拟化补丁仍在推进(校验 Ssaia、G-stage 模拟未完成,嵌套 guest 暂不可运行),这意味着 AIA 的 guest 中断文件优势在主线虚拟化栈中尚未完全兑现 [S35];其二,硬件实现与规范存在局部落差(香山 APLIC 的 direct 模式缺位),跨平台移植时不能假设“AIA 全功能” [S32];其三,调试与观测工具对 AIA 的适配(例如针对中断文件状态的用户态观测)仍不成熟,PLIC 时代的对账习惯(读 pending 位、数 claim 次数)在 MSI 模型下需要重建方法论 [S13][S14]。机会在于:把 PLIC 时代积累的“设备树核对、claim/complete 审计、风暴处置”经验工程化为一套可复用的 bringup 中断验收清单,并把 AIA 迁移(老 PLIC 平台到新 AIA 平台的驱动与固件适配、虚拟化场景的 MSI 配置验证)做成标准化服务——这正是当前国内工程能力与需求之间的空位。

5. 关键机制深挖

5.1 PLIC 的网关模型与 claim/complete 协议

接口与规范依据: PLIC 的软件接口面是一组 32 位 MMIO 寄存器(priority、pending、enable、threshold、claim/completion),全部以对齐的 32 位原子存取访问;其行为依据来自 PLIC v1.0.0 规范的对应章节,Linux 侧的实现由 irq-sifive-plic.c 承载(版本以研究截点的主线分支为准),核心逻辑包括上下文映射、claim/complete 回调与按兼容档分流的两类 quirk [S02][S07][S08][S09]。

协议闭环: 源信号经 gateway 置位 pending 后进入核心仲裁;核心只从“已使能且优先级高于该上下文阈值”的候选中选优——同优先级取最小身份号;胜者被拉线到目标上下文;处理器的 claim 读取原子返回身份并清 pending;服务完成后必须 complete 写回,网关才恢复对该源的转发 [S03][S07][S08]。规范对 claim 与 threshold 的关系做了反直觉的说明:claim 不受阈值影响,阈值只影响“是否拉线”,不影响“claim 能否取到”——把这两件事混为一谈会在中断嵌套与阈值动态调整场景中产生难以定位的“丢中断”错觉 [S06][S07]。

失效边界: priority=0 使源永久静默;threshold 屏蔽小于或等于阈值的源;未 complete 使该源在网关处阻塞;claim 返回 0 表示无待处理;complete 写错身份不会报错但会破坏网关状态机;两格描述平台上第二格触发类型配错会把电平设备当边沿处理,造成 EOI 后立即重触发 [S03][S04][S06][S07][S08][S10]。

验证条件与复现: 可用两类最小实验复现协议语义——其一,claim 后故意不 complete,观测该源“只来一次”;其二,把 threshold 调高到目标源之下,观测“拉线消失但 claim 仍可返回”的现象(对应规范说明)。生产验收则是压测下 pending 位与中断计数长期对账无残留,且驱动对 claim 返回 0 有显式分支 [S07][S08]。

工程取舍与开销: 用 threshold 做上下文级中断开关的实现成本最低,但它与 enable 位是两套正交机制,混用会引入时序窗口(阈值写回与新中断到达竞争);软件模拟电平/边沿的平台在每次 EOI 时可能需要翻转 enable 位,其每次中断的可观测开销高于纯硬件平台,性能敏感场景应优先选择原生支持电平语义的控制器 [S05][S06][S09]。

5.2 AIA:APLIC 双重投递模式与 IMSIC 消息文件

接口与实现依据: AIA 的软件接口分两层——MMIO 层(APLIC 的域寄存器、IMSIC 的 4KiB 页)与 CSR 层(mtopei/stopei 直接访问,siselect/sireg 间接访问,hvien/hvip 与 vs 级 CSR 服务虚拟化);语义依据为 AIA v1.0 规范的 APLIC、IMSIC、CSRs、MSLevel、VSLevel 与 IPIs 各章,Linux 实现分布于 aplic-main、aplic-msi、imsic-state、imsic-platform 四个文件,M 态初始化由 OpenSBI 的 fdt_irqchip 两个文件实现 [S13][S14][S15][S17][S18][S20][S21][S28][S29]。

投递机制: APLIC 的 DM 位在域级一锤定音:direct 模式把 target 寄存器解释为“hart 索引加优先级”并直接拉起目标 hart 的外部中断线;MSI 模式把 target 寄存器解释为“guest 中断文件选择”,命中源由 APLIC 生成 MSI 写,经 IMSIC 页落为中断文件中的 pending 位 [S14]。IMSIC 的投递闸门是 eidelivery 与 eithreshold:阈值非零时“身份大于等于阈值者不参与投递”,且数值越小越优先,这一语义与 PLIC 的 threshold 恰好相反(PLIC 屏蔽的是数值小的低优先级源)[S13][S06]。软件侧的复位与恢复顺序同样是协议的一部分:驱动把全部源先置 inactive、关闭全部本地使能后再配置;休眠恢复时必须先恢复 sourcecfg 再恢复 target 与 pending/enable 位;IMSIC 使能时先写 EITHRESHOLD 再写 EIDELIVERY、禁用时反序,以避免使能瞬间的投递竞态 [S20][S22]。

失效边界: identity 0 恒无效,把 topi/claimi 返回 0 当有效身份会破坏状态机;claimi 与 topei 的读操作带清 pending 副作用,误读即丢中断;MSI 模式发送成功自动清 pending,若再按 PLIC 习惯执行 complete 是不必要的(协议中不存在该写);inactive 源的 pending 与 enable 位只读为 0,软件配置顺序颠倒会把中断静默;MSI 目标从一块 IMSIC 向量迁到另一块的更新非原子,“设备可能观察到中间态”;Multi-MSI 在 Linux AIA 驱动中尚未支持 [S13][S14][S20][S23]。

验证与测试路径: APLIC 内置 genmsi 自发测试路径(带 busy 位)可独立验证 MSI 写链路;QEMU aia=aplic 与 aia=aplic-imsic 两个模式可对同一驱动做对照复现;guest 场景则可以用 hvisor 的 IPI 直写路径验证虚拟文件投递,用 vstopi 读取验证 claim 语义 [S14][S30][S34]。

权衡与代价: MSI 模式换来的收益是彻底消除多 hart claim 竞争与组播风暴,代价是引入 MSI 写路径的状态机复杂度(目标迁移原子性、电平重触发需软件经 setipnum 回写、PCI 枚举要求 MSI 域先于设备域建立)[S21][S23];direct 模式语义简单、接近 PLIC 直觉,但生态实现少(香山 APLIC 即暂未支持),跨平台选用时需以实际兼容表为准,而非以“AIA 规范应然”推导 [S32]。

5.3 Bringup 中断问题的五类根因与排查路径

接口与依据: 排查以三层接口为依据——设备树 binding 规定的属性与格子语义、驱动按兼容档维护的 quirk 表、以及规范章节对协议语义的定义;三者任何一层与实际硬件不一致,都会以“中断不来、只来一次、或风暴被关”的形式暴露 [S10][S11][S24][S25][S26]。

① 设备树与映射类。 典型错误包括:两格中断描述(需 T-Head/Andes 兼容档)与一格描述混用导致第二格被误解析为中断号;context 编号与步长映射错误,enable 与 threshold 写到了别的上下文;用 -1 表示“上下文不存在”的平台在软件里被当成有效索引;riscv,ndev 数量与实际源数不符导致尾部源丢失;AIA 平台缺 msi-parent 迫使驱动转入 direct 路径或直接探测失败;外部中断格子值(1、5、9)写错把外部中断接到错误本地号。验证手段是 dtc 反编译后与手册逐项对账、确认 /proc/interrupts 对应行存在且计数增长 [S10][S24][S25][S26]。

② 协议语义类。 PLIC 侧:claim 后未 complete 使该源在网关阻塞(“只来一次”);priority 写 0 被误当最低优先级(实为禁用);threshold 配置把目标源屏蔽;claim 返回 0 未容错;把 claim 当作受 threshold 影响来预测行为。AIA 侧:eithreshold 非零把高身份永久屏蔽;EIDELIVERY 与 EITHRESHOLD 使能顺序颠倒;把 claimi/topei 当纯读操作触发清 pending 副作用;MSI 模式按 PLIC 习惯画蛇添足地 complete。验证手段是把 pending/enable 位、驱动状态与规范语义逐条对账,用 ftrace 观察处理路径是否闭合 [S03][S06][S07][S08][S13][S14][S20][S22]。

③ 平台 quirk/errata 类。 C900 与 nceplic100 平台的中断触发语义由驱动软件模拟(EOI 时按需翻转 enable 位),行为与规范原文不完全一致;CP100 存在 claim 竞争类硅缺陷需要特别读法绕开;香山 IMSIC 对超 8 位身份的硬件截断意味着不能假设身份空间任意扩展;Linux AIA 驱动尚未支持 Multi-MSI,多向量设备在此路径上会异常。判别特征是“仅特定平台复现、换 QEMU 或换核不复现”。验证方式是按兼容档比对驱动分支、用 QEMU 对应模式做最小复现,并读芯片手册确认触发语义 [S09][S23][S32][S33]。

④ 固件与运行模式类。 OpenSBI 只为 M 态准备 APLIC/IMSIC——S 态初始化与委托不在其职责内,固件与内核都“以为对方会配”时外部中断会静默地不来;QEMU 默认 aia=none(PLIC),验证 AIA 必须显式选择 aia=aplic 或 aia=aplic-imsic;KVM 下 kernel-irqchip=split 强制 QEMU 仿真 APLIC,与真机 KVM 路径不同;QEMU 不提供 M 态仿真,任何依赖 M 态 IMSIC/APLIC 行为的测试都不可在 QEMU 闭环。验证手段是读取固件启动日志与移交的 FDT、核对 QEMU 命令行、区分 PLIC 与 AIA 两条驱动路径的加载状态 [S28][S29][S30]。

⑤ 中断风暴与伪中断类。 电平未清、边沿抖动、触发类型配错都会让一个源持续断言;内核在 100000 次窗口中超过 99900 次未处理即判定卡死,打印 nobody cared 并停用该 IRQ,再以 HZ/10 轮询尝试恢复。处置顺序是先清源再开 IRQ,临时可用 irqpoll 轮询代偿,根治靠修正触发类型或电平语义。跨栈证据是 Zephyr 的 PLIC 边沿支持曾为非标实现(寄存器偏移放设备树、边沿开关藏配置),最终才规范化为固定偏移——同一症状在不同栈上反复出现,说明该类别值得在验收清单中单列 [S31][S36]。

整体排查路径(见图 3):上电即挂优先查设备树与固件;稳定复现的协议行为查语义与 quirk;运行期突现并被内核关闭查风暴类。三类证据链的公共底座是 dtc、/proc/interrupts、dmesg、ftrace 与 QEMU 对照。

成本与取舍: QEMU 最小复现成本最低,但其 M 态缺位与 split 模型失真意味着它不能替代真机验证(尤其涉及固件职责与真实电平行为时);先静态对账(DT 与 binding)再动态观测(计数器与 trace)的顺序,能把无效实验的机时开销压到最低 [S30][S31]。

图 3:Bringup 中断问题根因排查矩阵——从现象到行动的就诊路径(数据来源:规范、驱动源码与平台文档综合 [S10][S20][S30][S31])。

图 3:Bringup 中断问题根因排查矩阵
图 3:Bringup 中断问题根因排查矩阵

能力成熟度对比矩阵

本矩阵以设备树接口面与驱动实现为观察角度、以规范依据与可验证性为判断标准(驱动与 binding 版本以研究截点主线为限),对比 PLIC、APLIC direct 与 APLIC 加 IMSIC(MSI)三种形态;其中“失效边界与限制”列写明各形态在 bringup 中最常见的失败模式,“开销与代价”列从工程成本视角给出取舍参考,具体验证条件见各节说明与第 7 节矩阵。

能力维度PLIC v1.0.0APLIC(direct 模式)APLIC + IMSIC(MSI 模式)
投递模型组播候选,软件 claim 竞争单 hart 定向,直接拉起外部中断线单 hart 定向,MSI 写投递至中断文件
目标选择context 使能位矩阵target=hart 索引加优先级target=guest 文件选择加外部中断身份
身份空间至多 1023 源域内源数由平台声明每文件 63 至 2047 身份,identity 0 无效
完成语义必须 complete 写回,否则网关阻塞claimi 读即清 pendingMSI 发送成功自动清 pending
虚拟化支持无内建 guest 机制可绑定 guest 文件(依赖 MSI)GEILEN 个 guest 文件,vstopi/vstopei 接口
Linux 支持长期成熟,quirk 与兼容档最多与 IMSIC 同框架实现同左,且 msi-parent 存在时优先于 direct
观测与调试pending 位与 claim 计数直观对账通用计数加 topi/claimi 副作用中断文件状态可读,但 MSI 链路需重建方法论
典型平台K1、JH7110、SG2042、TH1520 等香山(direct 暂缺)K3、QEMU aia=aplic-imsic
失效边界与限制电平/边沿语义靠平台约定,两格变体引发配置错位目标静态绑定,生态实现稀少迁移非原子、Multi-MSI 未支持、M 态责任在固件
开销与代价每次中断含组播与仲裁;软件模拟平台 EOI 有额外翻转开销硬件简单,但改目标需重配且无消息链路免仲裁收益大,换来 MSI 路径状态机与迁移原子性成本

6. 演进方向与情景

演进的技术轴很清晰:投递从“组播候选加软件竞争”走向“单播定向加消息化”——PLIC 用 32 位 MMIO 与 claim 仲裁解决“多源对多 hart”的接线问题,AIA 用 APLIC 的 target 固定化与 IMSIC 的 MSI 写把“谁被中断”变成软件可编程的静态映射,从而把竞争、组播风暴与虚拟化 guest 文件的一等公民支持同时解决 [S13][S14][S16]。配套的软件轴同样收敛:CSR 面已在 Linux csr.h 落位、binding 已把 riscv,aplic 与 riscv,imsics 纳入标准、OpenSBI 已承担 M 态初始化、QEMU 已提供三档 aia 模式,全栈“接口齐备、实现分流”的格局已经形成 [S27][S24][S25][S28][S30]。国内侧的对应信号是 K3 以 k3-aplic 与 k3-imsics 进入产品配置、香山以 ChiselAIA 补齐硬件实现、hvisor 给虚拟化范式打样 [S24][S25][S32][S34]。

情景推演(判断,非预测):情景 A“PLIC 长尾”表现为存量消费级与嵌入式平台继续以 PLIC 交付,性价比与成熟度压倒迁移动力,两格变体与 quirk 维护继续存在;情景 B“AIA 成新默认”表现为新发布的中高端与 RVA23 平台普遍以 APLIC 加 IMSIC 出货,发行版内核的 AIA 路径成为主验证路径;情景 C“混合期拉长”表现为同一厂商同代产品线中 PLIC 与 AIA 并存(K1 到 K3 的演进即是样本),驱动与调试方法必须双轨并行 [S09][S10][S24][S25]。判别信号建议盯三个:新平台绑定中的 compatible 组合、主线虚拟化栈对 AIA guest 文件的兑现程度(嵌套虚拟化补丁是直接风向标)、以及发行版内核对 aia 模式的选择策略 [S25][S30][S35]。

对工程师的含义:PLIC 语义(claim/complete、priority、threshold)仍是未来数年必须精通的存量技能,而 AIA 的迁移能力(MSI 链路配置、guest 文件与 CSR、迁移原子性)正在成为增量技能的分水岭;两者共享的设备树核对与风暴处置方法论,是跨代际可复用的最大公约数 [S07][S14][S31]。

7. 建议与验收

面向 bringup 一线,建议按“先静态后动态、先对照后真机”推进六件事:其一,任何中断问题先做设备树静态审计——dtc 反编译核对中断格子数、context 编号、riscv,ndev、msi-parent 与外部中断格值;其二,在 PLIC 平台上审计 claim 与 complete 的配对路径与返回值 0 容错,并把 threshold 与 priority 的当前值纳入启动日志;其三,在 AIA 平台上核对三条顺序契约——复位顺序(域清零、本地使能全关、源置 inactive)、恢复顺序(sourcecfg 先于 target 与 pending/enable)、IMSIC 使能顺序(EITHRESHOLD 先于 EIDELIVERY、禁用反序)[S20][S22];其四,为风暴场景准备标准剧本:dmesg 定位源、清源再开 IRQ、irqpoll 临时代偿、修正触发类型 [S31];其五,虚拟化与 guest 场景以 MSI 配置与迁移窗口为重点验证对象,警惕迁移中间的中间态 [S23][S34];其六,建立 QEMU 双模式对照基线(aia=aplic 与 aia=aplic-imsic)并明确其不可替代真机的边界 [S30]。下面矩阵给出每条建议对应的可执行验收条件与工具证据。

建议—验收矩阵

建议验收条件(可执行验证)工具与证据
设备树静态审计先行dtc 反编译后格子数、context、riscv,ndev、msi-parent 与手册逐项一致;对应 IRQ 行存在且计数增长dtc、/proc/interrupts [S10][S24][S25][S26]
QEMU 双模式对照同一镜像在 aia=aplic 与 aia=aplic-imsic 下行为差异可解释;缺陷可最小复现QEMU virt 命令行 [S30]
PLIC claim 与 complete 配对审计压测下 pending 无残留;人为跳过 complete 可稳定复现“只来一次”;返回 0 有显式分支ftrace、计数器对账 [S07][S08]
AIA 顺序契约核对休眠唤醒后各源中断全部恢复;顺序颠倒可稳定复现丢中断驱动日志、syscore 路径 [S20][S22]
风暴处置剧本演练人为制造未清源后内核出现 nobody cared,按剧本可定位并恢复;irqpoll 代偿生效dmesg、/proc/interrupts [S31]
虚拟化 MSI 与迁移验证guest 中断可达;迁移窗口内不丢中断或已记录中间态风险hvisor/KVM、MSI 追踪 [S23][S34][S35]

8. 不确定性与研究限制

本报告的结论基于公开规范与源码,未进行真机实测与压力复现,因此“行为”层面的表述属于规范与代码推理。具体限制包括:其一,PLIC 网关在电平与边沿下的“一周期”级时序细节未能从规范正文确证,本报告回避相关断言;其二,驱动与 binding 行为以研究截点的主线版本为准,上游演进可能使具体函数与顺序契约变化;其三,国内平台的实现细节(如香山 APLIC 的 direct 支持进度)来自项目自述,未做交叉验证;其四,虚拟化栈状态(KVM RISC-V 的 AIA 与嵌套支持)处于演进中,LWN 报道的补丁状态不等于主线行为;其五,QEMU 仿真与真机存在结构性差异(M 态缺位、split 中断芯片模型),本文对“QEMU 正常真机挂”类问题给出的是排查方向而非确定性归因。主张与证据的强度对照如下。

主张—证据矩阵

主张证据强度限制或反例
claim 不受 threshold 影响PLIC 规范 claim 章原文强(规范原文)软件模拟平台可能引入行为偏差 [S07][S09]
两格中断描述是规范变体而非 quirklinux-riscv 邮件列表讨论共识中(开发者观点,未见规范文本)仅适用于 Andes/T-Head 变体 [S10][S11]
APLIC 把每个中断只投递给单一 hartAIA 规范引言原文强(规范原文)direct 模式仍依赖软件正确配置 target [S16]
香山 APLIC 暂不支持 direct 模式ChiselAIA 仓库自述中(单方声明,未实测)后续版本可能补齐 [S32]
KVM RISC-V 嵌套虚拟化尚不可用第三方报道的补丁进展中(转述,非主线状态)状态随时间变化 [S35]
网关电平/边沿一周期级行为本次未从规范正文确证弱(回避断言)报告不做该断言 [S01]

参考来源

以下台账与正文引用编号一一对应;链接均为公开可核查来源(规范官网、上游源码托管、官方文档与仓库),证据层级见第 2 节方法说明。

编号来源与链接说明
[S01]docs.riscv.org/reference/plic/v1.0.0/introduction.html 与 github.com/riscv/riscv-plic-specPLIC v1.0.0 规范入口(引言与操作参数;上游仓库)
[S02]docs.riscv.org/reference/plic/v1.0.0/plic-memory-map.htmlPLIC 内存映射章(寄存器偏移、步长、上下文上限)
[S03]docs.riscv.org/reference/plic/v1.0.0/plic-priority.htmlPLIC 优先级章(数值语义、0 保留值、同优先级仲裁)
[S04]docs.riscv.org/reference/plic/v1.0.0/plic-interrupts.htmlPLIC 中断源章(源 0、pending 语义与清除条件)
[S05]docs.riscv.org/reference/plic/v1.0.0/plic-enables.htmlPLIC 使能位章(位映射与 bit0 硬连 0)
[S06]docs.riscv.org/reference/plic/v1.0.0/plic-thresholds.htmlPLIC 阈值章(小于等于屏蔽、0 全放行)
[S07]docs.riscv.org/reference/plic/v1.0.0/plic-claims.htmlPLIC claim 章(原子返回、返回 0、与阈值无关)
[S08]docs.riscv.org/reference/plic/v1.0.0/plic-completion.htmlPLIC completion 章(写回身份、不校验一致、网关完成消息)
[S09]elixir.bootlin.com/linux/latest/source/drivers/irqchip/irq-sifive-plic.cLinux PLIC 驱动(兼容档、两格变体、EDGE 与 CP100 quirk、上下文映射)
[S10]Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml(Linux 内核树)PLIC 绑定:compatible 全表、riscv,ndev、interrupts-extended、格子数变体、-1 语义
[S11]lists.infradead.org/pipermail/linux-riscv/2022-November/022072.htmllinux-riscv 邮件列表:两格中断描述的规范变体讨论
[S12]docs.riscv.org/reference/aia/v1.0/ 与 github.com/riscv/riscv-aiaAIA v1.0 规范入口(组成:Smaia、Ssaia、IMSIC、APLIC;修订历史)
[S13]docs.riscv.org/reference/aia/v1.0/IMSIC.htmlAIA 规范 IMSIC 章(中断文件、投递条件、MSI 写格式、topei 语义)
[S14]docs.riscv.org/reference/aia/v1.0/AdvPLIC.htmlAIA 规范 APLIC 章(domaincfg、sourcecfg、target 双模式、topi、claimi、genmsi)
[S15]docs.riscv.org/reference/aia/v1.0/CSRs.htmlAIA 规范 CSR 章(mvi、svi、hvi、siselect 间接访问面)
[S16]docs.riscv.org/reference/aia/v1.0/intro.htmlAIA 规范引言(动机:单一 hart 投递、有线转 MSI)
[S17]docs.riscv.org/reference/aia/v1.0/MSLevel.htmlAIA 规范 MSLevel 章(mtopi、mtopei、mvien 对 SEIP 的控制)
[S18]docs.riscv.org/reference/aia/v1.0/VSLevel.htmlAIA 规范 VSLevel 章(guest 级 CSR 与虚拟中断文件接口)
[S19]docs.riscv.org/reference/aia/v1.0/IPIs.htmlAIA 规范 IPIs 章(经 IMSIC 的中断文件实现核间中断)
[S20]elixir.bootlin.com/linux/latest/source/drivers/irqchip/irq-riscv-aplic-main.cLinux APLIC 主驱动(复位序列、msi-parent 优先、恢复顺序注释)
[S21]elixir.bootlin.com/linux/latest/source/drivers/irqchip/irq-riscv-aplic-msi.cLinux APLIC MSI 实现(MSI 写生成、电平重触发经 setipnum 回写)
[S22]elixir.bootlin.com/linux/latest/source/drivers/irqchip/irq-riscv-imsic-state.cLinux IMSIC 状态管理(EITHRESHOLD/EIDELIVERY 顺序、向量使能与可见性)
[S23]elixir.bootlin.com/linux/latest/source/drivers/irqchip/irq-riscv-imsic-platform.cLinux IMSIC 平台层(MSI 载荷、亲和迁移两步交换、Multi-MSI 限制)
[S24]Documentation/devicetree/bindings/interrupt-controller/riscv,aplic.yaml(Linux 内核树)APLIC 绑定(compatible 含 spacemit,k3-aplic、msi-parent 与 direct 二选一)
[S25]Documentation/devicetree/bindings/interrupt-controller/riscv,imsics.yaml(Linux 内核树)IMSIC 绑定(msi-controller、num-ids、含 spacemit,k3-imsics)
[S26]Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.yaml(Linux 内核树)本地中断控制器绑定(外部中断格子值 9)
[S27]elixir.bootlin.com/linux/latest/source/arch/riscv/include/asm/csr.hLinux csr.h:AIA CSR 编号实证(mtopei、stopei、siselect、hvien、vstopi 等)
[S28]github.com/riscv-software-src/opensbi(lib/utils/fdt/fdt_irqchip_imsic.c)OpenSBI IMSIC 初始化(compatible riscv,imsics;仅 M 态)
[S29]github.com/riscv-software-src/opensbi(lib/utils/fdt/fdt_irqchip_aplic.c)OpenSBI APLIC 初始化(compatible riscv,aplic;核映射与 M 态使能)
[S30]qemu.org/docs/master/system/riscv/virt.htmlQEMU virt 文档(aia=none/aplic/aplic-imsic、split 强制仿真、无 M 态仿真)
[S31]elixir.bootlin.com/linux/latest/source/kernel/irq/spurious.c内核伪中断与风暴防护(100k 窗口判定、停用 IRQ、轮询恢复)
[S32]github.com/OpenXiangShan/ChiselAIA香山 AIA 硬件实现(IMSIC 与 APLIC;direct 模式未支持的自述)
[S33]docs.xiangshan.cc/projects/user-guide/zh-cn/kunminghu-v2/interruption-controller/香山昆明湖-v2 用户手册中断控制器页(中断文件数、身份范围、截断与 PMP 隔离)
[S34]hvisor.syswonder.org/chap04/subchap02/RISC-AIA.htmlhvisor AIA 章(MSI 投送、guest IPI 免陷、vaplic 模拟)
[S35]lwn.net/Articles/1055170/KVM RISC-V 嵌套虚拟化进展(校验 Ssaia;嵌套尚不可用)
[S36]github.com/zephyrproject-rtos/zephyr/issues/63466 与 pull/63273Zephyr PLIC 边沿支持与寄存器偏移规范化(跨栈语义漂移佐证)

附录:研究方法

本报告以“规范优先、上游优先、一手优先”为采集原则:PLIC 与 AIA 的语义结论全部回溯到规范对应章节;软件行为结论回溯到 Linux/OpenSBI/QEMU 的主线源码或绑定文档;国内平台结论回溯到厂商绑定、开源仓库与项目官方文档。社区邮件列表与第三方报道仅用于交叉印证,且在图 3 与主张—证据矩阵中标注证据强度。全部结论以研究截点为限:未做真机实测、未复现压力场景、未穷尽厂商 errata;对证据不足的细节(网关一周期级时序)明确回避断言,并在第 8 节列出。