USER GUIDE / PROCESSOR & BUS / PLIC / INTERRUPT HANDLING
中断处理
中断处理
PLIC 中断操作
概述

图 1 展示了通过 PLIC 进行中断处理的流程。该流程可分为 3 个主要部分:中断仲裁、中断响应和中断完成。
中断仲裁
当网关收到中断信号时,若 IP 位为 0 且该中断源优先级大于 0,则会向 PLIC 核转发中断请求。此外,如果网关此前已经发送过中断请求,则必须等待来自中断目标的中断完成消息。只有当前一个来自同一中断源的中断请求被中断处理程序完全服务后,网关才会转发新的中断请求。
当 PLIC 核接收到中断请求后,会对来自已使能中断源(IE=1)的请求进行优先级仲裁。优先级最高的中断将被响应;若有多个中断具有相同最高优先级,则中断 ID 较小者优先。
随后,若最高优先级中断的优先级严格高于中断目标的阈值,则 PLIC 核会向中断目标发送中断通知(Interrupt Notification)。
中断响应
收到中断通知后,若全局中断已使能(即 mstatus 寄存器中的 MIE 位为 1),目标端会向 PLIC 核发送中断认领(Interrupt Claim)消息。同时,对应中断源的 IP 位会被清除。
中断完成
中断处理程序完成中断服务后,目标端必须向对应网关发送中断完成(Interrupt Completion)消息,随后网关才能转发新的中断请求。该过程通过将中断 ID 回写到 PLIC_CLAIM 寄存器实现。
中断加速
RISC-V 硬件本身不支持中断嵌套和尾链处理。但在本实现中,可针对来自 PLIC 的中断实现这些加速机制,如图 2 所示。进入中断服务子程序之前的主要步骤包括:认领中断、记录嵌套优先级、保存上下文以及重新使能全局中断。进入中断服务子程序后的主要步骤包括:中断完成、尾链检查和上下文恢复。
上述步骤均由硬件自动完成,从而加快中断处理过程。
在本实现中,中断嵌套或尾链仅允许发生在 PLIC 中断之间。异常和其他类型的中断可以抢占 PLIC 中断,但这可能导致不可预期的结果。
PLIC 中断处理期间,硬件会自动实现 PLIC 中断栈与用户栈之间的隔离,并支持基于 PLIC 中断的任务切换。异常、其他类型的中断以及 NMI 不支持嵌套或上下文自动压栈,也不支持自动栈隔离。但在处理这些情况时,建议软件统一使用中断栈。

- Claim 操作由硬件自动完成。
- 系统维护了一个中断级别列表,用于记录当前嵌套的优先级层级,并据此判断 PLIC 中断嵌套和尾链是否发生。
- 为了减小代码体积并缩短取指时间,设计中提供了一段指令 ROM 用于存放上下文保存指令。完成上下文保存后,值为 32’hffffffff 的 EXC_RETURN 会存入链接寄存器(Link Register)。当 PLIC 中断服务完成后,执行 RET 指令会触发从 ISR 返回的异常,从而使目标端自动出栈。
- 要允许中断嵌套或尾链,在进入服务例程之前应重新使能全局中断。
- 上述完整操作均由硬件自动完成。
- 当 PLIC 中断从 ISR 返回时,记录嵌套优先级的列表会被更新,随后使用更新后的列表判断是否可以发生 PLIC 中断尾链。
- 为了减小代码体积并缩短取指时间,设计中提供了一段指令 ROM 用于存放上下文恢复指令。
与中断加速相关的 CSR 寄存器
机器中断控制寄存器(mintctrl,0x7c3)
该 CSR 寄存器保存中断的配置信息。
| 位 | 名称 | 说明 | RW |
|---|---|---|---|
| 31:16 | NESTED_NUM | 当前 PLIC 中断之间的最大嵌套深度(不包括被 NMI 或异常抢占的情况)等于最大中断优先级减 1。该值仅由硬件更新:当用户程序被 PLIC 中断打断时置为 1;当某个 PLIC 中断处理程序被另一个 PLIC 中断抢占时,该值递增。 | R |
| 15:4 | Reserved | 写入无影响,读取为零。 | R |
| 3 | MSP | 指示是否启用 PLIC 中断栈与用户栈之间的隔离。 0:始终使用用户栈,指令 ROM 中与中断栈相关的指令按 NOP 处理。此时硬件中只有一个栈指针 sp,用于保存中断上下文。 1:在中断处理程序中使用中断栈,硬件同时提供用户栈指针 psp 和中断栈指针 msp。 该位会根据中断处理过程中的具体情况更新,同时相应更新 sp 寄存器的值。 | R/W |
| 2 | MIE | 指示是否执行指令 ROM 中用于设置全局 MIE 的指令,默认执行。 0:不执行,全局中断使能 MIE 保持原值。 1:执行,将全局中断使能位置位。 | R/W |
| 1 | TAIL_CHAIN | 指示是否启用中断尾链功能。尾链功能的前提是 ACC_MODE=1。 0:禁用 PLIC 中断尾链功能。 1:启用 PLIC 中断尾链功能。 | R/W |
| 0 | ACC_MODE | PLIC 中断加速模式,默认启用 PLIC 中断嵌套。即当 ACC_MODE=1 时,PLIC 中断之间可以发生中断嵌套。需要注意的是,当 ACC_MODE=1 时,软中断、定时器中断以及其他所有中断都由 PLIC 按 PLIC 中断的方式完成仲裁并分发到内核。在 ACC_MODE=1 的情况下,PLIC 中断源 ID 与异常原因码之间满足映射关系:mcause.code = source_id + 32,即所有中断均被视为用户定义中断。 0:禁用 PLIC 中断加速功能。 1:启用 PLIC 中断加速功能。 | R/W |
主堆栈寄存器(msp,0x7c4)
| 位 | 名称 | 说明 | RW |
|---|---|---|---|
| 31:0 | MSP | 该栈指针用于 PLIC 中断处理程序中的上下文保存与恢复。当 PLIC 中断处理程序内部再次发生 PLIC 中断时,它保存的是硬件执行完指令 ROM 中指令之后的 PLIC 中断栈指针(即硬件已自动保存部分上下文之后的值)。当从 PLIC 中断处理程序返回时,它保存的是处理程序退出时的栈指针(SP)。 | R/W |
进程堆栈寄存器(psp,0x7c5)
| 位 | 名称 | 说明 | RW |
|---|---|---|---|
| 31:0 | PSP | 用户栈的栈指针。当用户程序被 PLIC 中断打断时,硬件在执行完指令 ROM 中的指令之后(即硬件已自动保存部分上下文之后),会自动将 PSP 更新为用户栈顶。 | R/W |