RISC-V 的 PLIC(Platform-Level Interrupt Controller,平台级中断控制器)负责收集各外设的全局中断请求,经优先级仲裁后分发到指定的 Hart Context(硬件线程上下文)。其核心特点是采用软件主动 Claim/Complete 握手协议(拉取模型),而非传统 x86 PIC 的推送模型。
一、PLIC 关键硬件组成
组件 | 说明 |
|---|---|
Interrupt Gateway(中断闸口) | 每个中断源一个,将设备电平/边沿信号转为标准请求,同一时刻只允许一个未完成的请求进入 PLIC,直到收到 Complete 才放行下一个 |
Pending 寄存器 (IP) | 标记哪些中断源已锁存请求(bitmap,ID 1~1023,ID 0 保留表示无中断) |
Priority 寄存器 | 每中断源一个优先级值,0=禁用,值越大优先级越高 |
Enable 矩阵 (IE) | 按 Hart Context 分别配置每个中断源是否对该核使能 |
Threshold 寄存器 | 每 Hart Context 一个阈值,只有 Priority > Threshold 的中断才发给该核 |
Claim/Complete 寄存器 | 每 Hart Context 一个 MMIO 寄存器,读→Claim(取中断ID),写→Complete(写回中断ID) |
二、中断分发与仲裁流程(完整生命周期)
设备触发 → Gateway → PLIC 置 Pending → 仲裁筛选 → 置 MEIP/SEIP → Hart陷入 → Claim读ID → 调ISR → Complete写ID → Gateway放行新请求① 中断到达与锁存
外设拉中断信号 → 对应 Gateway 向 PLIC Core 发请求 → PLIC 将该中断源Pending 位(IP)置 1,Gateway 锁定该源(阻止同源重复进入)。
② 仲裁与分发(硬件过滤)
PLIC 对每个 Hart Context 独立评估所有 Pending 中断:
中断在该 Context 的IE 位 = 1(已使能)
中断Priority > 该 Context 的 Threshold
若有多个满足条件,选优先级最高者;优先级相同选ID 最小
通过筛选的最高优先级中断 → PLIC 对该 Hart 置位mip.MEIP(或 sip.SEIP),通知 Hart 有外部中断待处理。
⚠️ PLIC 本身不做中断嵌套,也不自动向多核广播选中——同一中断若多个 Context 都使能,可同时发给多个核(软件需通过 affinity 绑定避免多核争抢)。
③ Hart 陷入与 Claim(软件拉取)
Hart 检测到 MEIP=1 且 mie.MEIE=1 → 进入 Trap → 跳到中断入口。OS 必须读本 Context 的 Claim 寄存器:
// 读 Claim 寄存器 → 返回最高优先级 Pending 中断 ID,无则返回 0 uint32_t irq_id = *(volatile uint32_t*)(PLIC_BASE + 0x200004 + ctx_id * 0x1000); // 副作用:PLIC 自动清除该 irq_id 对应的 Pending 位(从仲裁队列移除) if (irq_id != 0) { do_irq_handler(irq_id); // 根据 ID 调对应设备 ISR }这是原子操作,自动清 Pending
返回 0 说明该 Context 无待处理中断(可能已被别的核 Claim 或未达到阈值)
④ 中断完成 Complete(握手)
ISR 处理完后,将获得的irq_id写回同一 Claim/Complete 地址:
// 写回中断 ID → 通知 Gateway 该中断已服务完 *(volatile uint32_t*)(PLIC_BASE + 0x200004 + ctx_id * 0x1000) = irq_id; // Gateway 解除锁定,允许该设备再次向 PLIC 发新请求PLIC 不校验 ID 是否匹配上次 Claim(但会忽略未使能源的 Complete)。Gateway 收到 Complete 后解除阻塞,同一设备的新中断可再次进入 PLIC。
⑤ 批量处理(可选优化)
高效的中断处理可在 ISR 中用循环不断 Claim 直到返回 0,一次性处理多个 Pending 中断再退出 Trap,减少陷入/退出的开销:
while ((irq_id = read_claim(ctx)) != 0) { handle_irq(irq_id); write_complete(ctx, irq_id); }三、多核分发与注意事项
中断亲和性(Affinity):通过配置各 Context 的 IE 矩阵决定某中断送给哪个/哪些 Hart。典型做法是一个设备中断只使能在一个 Hart 上(1:1 绑定),避免多核同时 Claim 竞争。
SMP 场景:若同一中断源在多个 Context 使能,多个 Hart 都会收到 MEIP,但只有第一个成功 Claim 的 Hart 拿到非零 ID,其余读回 0。
电平触发注意:对于电平触发的设备,必须在 ISR 中清除设备端中断条件后再写 Complete,否则设备保持电平断言,Gateway 会立即重新请求 → 无限重入。
Threshold 用法:可动态调高阈值进入临界区屏蔽低优中断,不影响其他核。
如果你需要看具体 SoC(如 QEMU virt、SiFive FU540、K210 等)的 PLIC 寄存器基地址和初始化代码示例,也可以告诉我。