外部中断与平台级中断控制器(PLIC)

外部中断

外部中断主要用于处理与外设相关的中断,如 GPIO、UART、DMA 等。PLIC 接收所有外设的中断信号,根据程序配置的优先级、阈值和上下文规则,在相应的硬件线程上触发外部中断。程序需要从 PLIC 的 MMIO 寄存器中进一步读取具体的中断外设源信息。

mip.MEIP 位对程序是只读的,只能由 PLIC 写入或清除。 mip.SEIP 可读写, M 态程序可以将该位置 1 ,而是否产生 S 态外部中断由该位的值和 PLIC 相应的信号逻辑或的结果决定,二者中任一为 1 即产生中断; csrrcsrrscsrrc 指令在该位上的行为略有不同,具体可见规范。 sip.SEIP (对 S 态程序)是只读的。对于用户态中断的 xip.UEIP 位可以设计类似的约束条件。

PLIC

目前的 PLIC 规范 支持至多 1024 个(外设)中断源和 15872 套上下文,每个中断源至多可配置 2^32 种优先级,每套上下文至多可配置 2^32 种优先级阈值,以及在每套上下文中可配置每个中断源是否使能。

中断触发条件

  1. 中断源产生中断等待信号;
  2. 在某套上下文中,该中断源被使能;
  3. 该中断源的优先级高于该上下文的优先级阈值;

上述条件均满足时,PLIC 会在硬件线程中触发外部中断,硬件线程编号与中断的特权级由上下文的设计决定。

上下文

上下文指的是特定处理器中,特定硬件线程上的特定特权级,如果 CPU 中有三个硬件线程和两个可以处理中断的特权级( M 和 S ),那么就存在六套 PLIC 上下文(在某个硬件线程上触发某个特权级的外部中断)。在该场景下,不妨按以下方法对上下文编号:

硬件线程 1硬件线程 2硬件线程 3
运行在 M 态上下文 1上下文 3上下文 5
运行在 S 态上下文 2上下文 4上下文 6

设某个中断源符合上下文 1 、2 和 6 的中断触发条件,那么 PLIC 会在硬件线程 1 上同时触发 MEI 和 SEI,在硬件线程 3 上触发 SEI ;在硬件线程 2 上,该中断源不会触发外部中断。

中断领取与完成

PLIC 中每套上下文具有一个领取/完成(claim/complete)寄存器。程序读取该寄存器时,PLIC 会返回该上下文中优先级最高、等待信号有效且被使能的中断源编号(该中断源的优先级可以低于上下文阈值),清除该中断源的等待位,并全局屏蔽该中断源的中断有效信号。 程序向该寄存器中写入一个中断编号以通知 PLIC 该中断处理完成,若相应中断源在其上下文中被使能,则 PLIC 解除相应的屏蔽,否则忽略本次写入。

PLIC 对于领取/完成寄存器的读写是“无记忆”的,写入的中断编号与领取的编号可以不同。如果一个中断源在两个上下文中被使能,可以在第一个上下文领取该中断并屏蔽其信号,在第二个上下文中完成该中断并解除屏蔽。

N 扩展下的 PLIC 设计

PLIC 的设计基本能够与 N 扩展兼容,只需为每个硬件线程的 U 态额外分配一套上下文,并将相应的中断信号与 xip.UEIP 位进行相应的连接逻辑即可。

每个上下文的领取/完成寄存器地址均与 4KB 边界对齐,故内核可以将 U 态对应上下文的地址直接映射到用户进程地址空间,这样用户进程可以直接完成领取/完成操作;中断源优先级和使能位对应的地址空间应当仅由内核访问和控制。

如何实现对外部中断的管理和复用,使其在多进程环境下仍然能够正常运行,见用户态中断的管理章节。