RISC-V 把同步异常和异步中断统一纳入 trap 机制。指令访问异常、系统调用属于同步异常;软件、定时器和外部中断则由相应 pending/enable 条件触发。平台级外设常通过 PLIC 汇聚,但采用 AIA/IMSIC 的新平台路径不同,因此“RISC-V 中断就是 PLIC”并不准确。
特权级与入口寄存器
每个特权级有对应 trap vector、cause、epc 和 status 寄存器,例如 S 模式使用 stvec、scause、sepc 和 sstatus。trap 到达哪个特权级取决于委托配置和中断路由。运行 Linux 的系统通常还涉及 M 模式固件(如 OpenSBI)与 S 模式内核的分工,不能只看驱动源码推断完整链路。
PLIC 路径里发生什么
在典型 PLIC 平台上,每个中断源有 pending 状态和优先级,每个 target context 有 enable 位图与 threshold。外设拉起中断后,PLIC 选择优先级高于阈值且已使能的来源;hart 收到外部中断并进入 trap,软件读取 claim 寄存器获得中断号。处理完成后,将该编号写回 complete。若设备侧中断条件没有清除,完成后仍可能再次触发。
claim/complete 只处理控制器侧仲裁。驱动 ISR 仍要读取设备状态寄存器,区分多个可能来源,并按设备要求清除或屏蔽中断。电平触发设备尤其要避免“只 complete、不清设备”的中断风暴。
Linux 中的映射层
设备树描述 interrupt parent、specifier 与触发类型,irqchip 驱动建立 IRQ domain,把硬件中断号映射为 Linux IRQ。设备驱动通过 request_irq() 或 devm_request_threaded_irq() 注册处理函数。硬中断部分应只完成必须立即处理的工作,可能睡眠或较慢的操作放在线程化 handler、workqueue 或其他合适上下文。
1 | cat /proc/interrupts |
/proc/interrupts 计数增长说明 Linux 处理了对应 IRQ,但不能证明每次设备事件都被正确消费。还要同时检查设备寄存器、丢事件统计、CPU 亲和性和 handler 执行时间。QEMU virt 上的结果也不能直接代表具体 SoC 的中断拓扑。
常见故障顺序
- 确认设备侧是否真的产生中断,极性和触发类型是否一致。
- 检查设备树 interrupt specifier、父控制器和 irqchip 是否完成初始化。
- 检查
/proc/interrupts是否出现并增长,handler 是否返回正确状态。 - 若出现风暴,确认设备状态清除顺序、屏蔽逻辑和电平信号是否仍保持有效。
- 多核系统再检查 affinity、负载与线程化 handler 的调度条件。
证据边界
本文以传统 PLIC 路径解释主要概念,没有覆盖 AIA、虚拟化中断注入和所有厂商扩展。具体寄存器与路由必须以目标平台设备树、特权规范和 irqchip 驱动为准。
参考:RISC-V Privileged Architecture · RISC-V PLIC specification · Linux generic IRQ handling · 不懂 RISC-V 中断,难以吃透嵌入式底层编程