PLIC 规范
RISC-V Platform-Level Interrupt Controller Specification
这个文档包含了 RISC-V 平台级中断控制器 (PLIC) 规范,它定义了一个专门设计用于在 RISC-V 系统上下文中工作的中断控制器。PLIC 多路复用各种设备在 HART 上下文的外部中断行中断,具有用于中断优先级的硬件支持。
本规范定义了常规 PLIC 架构和操作参数。PLIC 支持高达 1023 个中断(0 保留)和 15872 个上下文,但实际的中断数量和上下文取决于 PLIC 实现。但是,具体实现中每个寄存器的偏移量需要遵循标准。声称符合标准的 PLIC 应遵循以下部分中提到的实现。
所谓上下文是指在特定 RISC-V 处理器实例中的特定 HART 中的特定权限模式。例如,在具有双路超线程的 4 核系统中,您有 8 个 HART,并且每个 HART 可能至少有两种特权模式:M 模式和 S 模式。(引用)
PLIC 如何组织上下文(HART 和特权模式)的中断超出了 RISC-V PLIC 规范范围,但它必须在厂家的 PLIC 规范中规定。
RISC-V PLIC 操作参数
本规范中定义了通用 PLIC 操作参数寄存器块,它们是:
- 中断优先级配置寄存器:每个中断源的中断优先级。
- 中断等待位寄存器:每个中断源的中断等待(待处理)状态。
- 中断使能寄存器:设置启用每个上下文的中断源。
- 优先级阈值寄存器:每个上下文的中断优先级阈值。
- 中断请求寄存器:可读取每个上下文的中断源 ID。
- 中断完成寄存器:中断完成后向相关寄存器写入信息。
这些寄存器都是 32 位宽。
中断优先级
如果 PLIC 支持中断优先级,则可以通过写入其中断优先级配置寄存器来为每个 PLIC 中断源分配优先级。优先级值为 0 被保留为禁用中断。优先级 1 是最低优先级,而最大优先级取决于 PLIC 实现。全局中断的优先级相同时,中断源 ID 小的具有更高优先级。
中断优先级配置寄存器组相对于 PLIC 基地址的偏移是 0,组中寄存器的个数与中断源个数相同,第 n 个寄存器中的数字即为 n 号中断源的优先级。
等待(待处理)中断位
某一中断源的等待状态可以从等待寄存器组中读出,读取方法是将所有等待寄存器连起来视作一个元素大小为 1 位的数组,第 n 号中断源的待处理位存储在第 n / 32
个寄存器的第 n % 32
位中。(其中第 0 个寄存器的位 0 表示不存在中断源 0,被硬连线为 0。)
- 当 IP 位为 1 时,表示当前该外部中断源存在等待响应的中断。该位可通过内存存储指令 (SW 指令) 置 1。在对应中断源采样逻辑采样到有效电平或脉冲中断后也会将该位置 1。
- 当 IP 位为 0 时,表示当前该外部中断源没有等待响应的中断。该位可通过内存存储指令 (SW 指令)清 0。当中断被响应后,PLIC 也会将对应中断的 IP 位清除。
中断等待寄存器组相对于 PLIC 基地址的偏移是 0x001000。
中断使能
通过在使能寄存器中设置相应的位,可以启用各个全局中断。使能寄存器的访问方式与等待寄存器相同。(其中第 0 个寄存器的位 0 表示不存在中断源 0,被硬连线为 0。) PLIC 具有 15872 个上下文的中断使能寄存器组。
- 当 IE 位为 1 时,表示中断对该目标使能。
- 当 IE 位为 0 时,表示中断对该目标屏蔽。
中断使能寄存器组相对于 PLIC 基地址的偏移是 0x002000,且首先是上下文 0 的所有中断源的使能位,随后是按顺序上下文 1 到上下文 15871 的所有中断使能位。内存布局如下:
0x002000: Interrupt Source #0 to #31 Enable Bits on context 0
...
0x00207F: Interrupt Source #992 to #1023 Enable Bits on context 0
0x002080: Interrupt Source #0 to #31 Enable Bits on context 1
...
0x0020FF: Interrupt Source #992 to #1023 Enable Bits on context 1
0x002100: Interrupt Source #0 to #31 Enable Bits on context 2
...
0x00217F: Interrupt Source #992 to #1023 Enable Bits on context 2
0x002180: Interrupt Source #0 to #31 Enable Bits on context 3
...
0x0021FF: Interrupt Source #992 to #1023 Enable Bits on context 3
...
0x1F1F80: Interrupt Source #0 to #31 on context 15871
...
0x1F1F80: Interrupt Source #992 to #1023 on context 15871
我们的开发板 D1 只有单核单线程,2 种中断的特权模式,因此有 2 个上下文。虽然只支持最多 256 个中断源,但是由于要和 PLIC 标准所规定的内存布局一致,因此 1 号上下文的使能寄存器组(PLIC Superuser Mode Interrupt Enable Register n
)的偏移依然需要从 0x2080 开始。
优先级阈值
PLIC 提供基于上下文的中断阈值寄存器,用于每个上下文的中断优先级阈值的设置。阈值寄存器是一个 WARL 字段。PLIC 将屏蔽优先级小于或等于阈值的所有 PLIC 中断。例如,阈值为 0 意味着允许所有非零优先级中断。
WARL 字段:指这个寄存器可以写任意值,但只有在值合法的时候才会被真正写入。
中断优先级阈值寄存器组相对于 PLIC 基地址的偏移是 0x200000,并且每个寄存器要求 4K 对齐(实际来说,就是每个寄存器地址是前一个寄存器加 0x1000)。
内存布局如下:
0x200000: Priority threshold for context 0
0x201000: Priority threshold for context 1
0x202000: Priority threshold for context 2
0x203000: Priority threshold for context 3
...
0x3FFF000: Priority threshold for context 15871
中断响应过程
当 PLIC 对特定中断目标存在有效中断请求,且优先级大于该中断目标的中断阈值时,会向该中断目标发起中断请求。
当该中断目标收到中断请求,且可响应该中断请求时,需要向 PLIC 发送中断响应消息。中断响应机制如下:
- 中断目标(即上下文,某一 HART 的某一特权级)向其对应的中断响应/完成寄存器发起一个读操作。该读操作将返回一个 ID,表示当前 PLIC 仲裁出的中断 ID。中断目标根据所获得的 ID 进行下一步处理。如果获得的中断 ID 为 0,表示没有有效中断请求,中断目标结束中断处理。
- 当 PLIC 收到中断目标发起的读操作,且返回相应 ID 后,会将该 ID 对应的中断源等待位清 0,且在中断处理完成之前屏蔽该中断源的后续采样。
PLIC 可以随时执行响应过程,并且响应操作不受优先级阈值寄存器的设置的影响(此时相当于手动轮询所有可中断外设,而不是真正的中断)。
中断响应寄存器组是基于上下文的,相对于 PLIC 基地址的偏移是 0x200000,并且每个寄存器要求 4K 对齐后+4(实际来说,就是每个寄存器地址是前一个寄存器加 0x1000,且第一个寄存器偏移为 0x200004)
中断完成
完成中断处理程序后,中断目标向中断响应/完成寄存器发起写操作,写入本次完成的中断 ID。如果中断类型为电平中断,需要在此之前清除外设中断源的有效中断信息。
PLIC 收到该中断完成请求后,更新中断响应/完成寄存器,解除 ID 对应的中断源采样屏蔽,结束整个中断处理过程。
PLIC 不检查完成的中断号是否与该目标最后一个响应的中断号相同。如果完成的中断号与该目标的已开启中断号不匹配,则会被忽略。
中断完成寄存器是基于上下文的,并且与中断响应过程中的寄存器地址相同。