RISC-V 平台级中断控制器规范
介绍
该规范描述了根据 RISC-V 平台级中断控制器(PLIC)规范(已从 RISC-V Privileged Spec v1.11-draft 中移除)中定义的通用 PLIC 架构的操作参数,以在 RISC-V 系统的上下文中运行。PLIC 将各种设备中断多路复用到 Hart 上下文的外部中断线上,并具有对中断优先级的硬件支持。
PLIC 支持最多 1023 个中断(0 为保留值)和 15872 个上下文,但实际中断和上下文的数量取决于 PLIC 的实现。
然而,实现必须遵循 PLIC 操作参数中每个寄存器的偏移量。
自称为 PLIC-Compliant 标准 PLIC 的实现应遵循下面各节中提到的实现方法。
中断目标和 Hart 上下文
中断目标通常是 hart 上下文,其中 hart 上下文是给定 hart 上的给定特权模式(尽管还有其他可能的中断目标,例如 DMA 引擎)。例如,在具有 2 路 SMT 的 4 核系统中,您有 8 个 hart,每个 hart 可能至少有两种特权模式:机器模式和管理模式(参考)。并非所有 hart 上下文都需要成为中断目标,特别是,如果处理器内核不支持将外部中断委派给低权限模式,则低权限 hart 上下文将不会成为中断目标。PLIC 生成的中断通知分别出现在 M/S 模式的 mip/sip 寄存器的 meip/seip 位中。
如果外部中断已委托给低权限模式,则通知仅出现在低权限 xip 寄存器中。每个处理器内核都必须定义一个策略,说明内核上的多个 hart 上下文如何处理同时发生的活动中断。对于单个 hart 上下文堆栈的简单情况,一个用于
在每个受支持的特权模式下,较高特权上下文的中断可以抢占较低特权上下文的中断处理程序的执行。多线程处理器内核可以同时在不同的 hart 上下文中运行多个独立的中断处理程序。处理器核心还可以提供仅用于中断处理的 hart 上下文以减少中断服务延迟,并且这些可能会抢占同一核心上其他 hart 的中断处理程序。PLIC 独立处理每个中断目标,不考虑包含多个中断目标的组件使用的任何中断优先级方案。因此,PLIC 不提供中断抢占或嵌套的概念,因此这必须由托管多个中断目标上下文的内核来处理。
中断路由
中断网关负责将全局中断信号转换为通用中断请求格式,并控制中断请求流向 PLIC 内核。每个中断源最多有一个中断请求可以在任何时候在 PLIC 内核中挂起,通过设置源的 IP 位来指示。网关仅在收到服务于同一源的先前中断请求的中断处理程序已完成的通知后,才将新的中断请求转发到 PLIC 内核。
如果全局中断源使用电平敏感中断,网关会将中断电平的第一个断言转换为中断请求,但此后网关不会再转发额外的中断请求,直到收到中断完成消息。在接收到中断完成消息时,如果中断是电平触发的并且中断仍然有效,则新的中断请求将被转发到 PLIC 内核。一旦转发到 PLIC 内核,网关就无法收回中断请求。如果一个电平敏感的中断源在 PLIC 内核接受请求之后和中断被服务之前取消断言中断,则中断请求仍然存在于 PLIC 内核的 IP 位中,并将由处理程序提供服务,然后处理程序必须 确定中断设备不再需要服务。
如果全局中断源是边沿触发,网关会将第一个匹配的信号边沿转换为中断请求。根据设备和中断处理程序的设计,在发送中断请求和接收其处理程序完成通知之间,网关可能会忽略其他匹配边沿或增加挂起中断的计数器。在任何一种情况下,下一个中断请求都不会被转发到 PLIC 核心,直到接收到先前的完成消息。如果网关有挂起的中断计数器,当中断请求被 PLIC 内核接受时,计数器将递减。与专用线中断信号不同,消息信号中断 (MSI) 通过系统互连通过描述哪个中断被断言的消息包。消息被解码以选择中断网关,然后相关网关处理 MSI,类似于边沿触发中断。
中断通知
每个中断目标在 PLIC 内核中都有一个外部中断挂起 (EIP) 位,指示相应的目标有一个挂起的中断等待服务。EIP 中的值可能会因 PLIC 内核中的状态变化而发生变化,由中断源、中断目标或其他代理操作 PLIC 中的寄存器值引起。EIP 中的值作为中断通知传送到目标目标。如果目标是 RISC-V hart 上下文,中断通知将根据 hart 上下文的特权级别到达 meip/seip 位。(在简单的系统中,中断通知将是连接到实现 hart 的处理器的简单线路。在更复杂的平台中,通知可能作为消息通过系统互连进行路由。)
PLIC 硬件只支持中断的多播,这样所有启用的目标都将收到给定活动中断的中断通知。(多播提供快速响应,因为最快的响应者要求中断,但如果多个 harts 捕获一个只有一个可以成功要求的中断,则在高中断率情况下可能会造成浪费。软件可以将 PLIC IE 位作为每个中断处理程序的一部分进行调制,以提供替代策略,例如中断关联或循环单播。)
根据平台架构和用于传输中断通知的方法,目标可能需要一些时间才能接收到这些通知。PLIC 保证最终将 EIP 中的所有状态更改传递给所有目标,前提是 PLIC 核心中没有干预活动。
(中断通知中的值只能保证包含在过去某个时间点有效的 EIP 值。特别是,当第一个目标的通知仍在运行时,第二个目标可以响应并要求中断,这样当第一个目标试图要求中断时,它发现它在 PLIC 内核中没有活动中断。)
中断标识符 (ID)
全局中断源分配有小的无符号整数标识符,从值 1 开始。中断 ID 0 保留表示“无中断”。当两个或多个中断源具有相同的分配优先级时,中断标识符也用于打破平局。 较小的中断 ID 值优先于较大的中断 ID 值。
中断流程
下图显示了通过 PLIC 处理中断时在代理之间流动的消息。
- 全局中断从它们的源发送到中断网关,该网关处理来自每个源的中断信号
- 中断网关然后向 PLIC 内核发送单个中断请求,后者将这些请求锁存在内核中断挂起位 (IP) 中
- 如果目标启用了任何挂起中断,并且挂起中断的优先级超过每个目标阈值,则 PLIC 核心将中断通知转发到一个或多个目标
- 当目标接受外部中断时,它会发送一个中断声明请求,以从 PLIC 内核中检索为该目标挂起的最高优先级全局中断源的标识符。
- PLIC 内核然后清除相应的中断源挂起位。
- 目标服务中断后,它向关联的中断网关发送中断完成消息
- 中断网关现在可以将同一源的另一个中断请求转发给 PLIC。
RISC-V PLIC 操作参数
通用 PLIC 操作参数寄存器块在本规范中定义,它们是:
- 中断优先级寄存器:每个中断源的中断优先级。
- 中断挂起位寄存器:每个中断源的中断挂起状态。
- 中断使能寄存器:每个上下文的中断源的使能。
- 优先级阈值寄存器:每个上下文的中断优先级阈值。
- 中断请求寄存器:获取每个context中断源ID的寄存器
- 中断完成寄存器:向关联网关发送中断完成消息的寄存器。
下图为PLIC操作参数框图,
内存映射
PLIC 内存映射的基地址是特定于平台实现的。本章中指定的内存映射寄存器的宽度为 32 位。使用 LW 和 SW 指令以原子方式访问这些位。
1 | base + 0x000000: Reserved (interrupt source 0 does not exist) |
以下部分描述了 PLIC 操作参数的控制寄存器块
中断优先级
中断优先级是小的无符号整数,具有平台特定的支持级别的最大数量。保留优先级值0表示“永不中断”,中断优先级随着整数值的增加而增加。每个全局中断源都有一个关联的中断优先级,保存在内存映射寄存器中。不同的中断源不需要支持同一组优先级值。一个有效的实现可以硬连接所有输入优先级。中断源优先级寄存器应该是 WARL 字段,以允许软件确定每个优先级规范(如果有)中读写位的数量和位置。为了简化支持的优先级值的发现,每个优先级寄存器必须支持寄存器内可变位中值的任意组合,即,如果寄存器中有两个可变位,则这些位中的所有四种值组合必须作为 有效的优先级。
如果 PLIC 支持中断优先级,则可以通过写入其 32 位内存映射优先级寄存器来为每个 PLIC 中断源分配一个优先级。保留优先级值 0 表示“永不中断”并有效地禁用中断。优先级 1 是最低的活动优先级,而最高优先级取决于 PLIC 实现。相同优先级的全局中断之间的关系由中断 ID 打破;ID 最低的中断具有最高的有效优先级。
PLIC 内存映射区域内中断源优先级块的基址固定为 0x000000。
PLIC 寄存器块名称 | 功能 | 以字节为单位的寄存器块大小 | 描述 |
---|---|---|---|
中断源优先级 | 中断源优先级 #0 到 #1023 | 1024 * 4 = 4096(0x1000) bytes | 这是一个包含 PLIC 中断源优先级的连续内存块。该内存块中共有 1024 个中断源优先级。 中断源优先级 #0 被保留,表示它不存在。 |
中断挂起位
PLIC 内核中中断源挂起位的当前状态可以从挂起数组中读取,组织为 32 位寄存器。中断 ID N 的未决位存储在字 (N/32) 的位 (Nmod 32) 中。字 0 的位 0,表示不存在的中断源 0,硬接线为零。
PLIC 内核中的挂起位可以通过设置关联的使能位然后执行声明来清除。
PLIC Memory Map 区域内的 Interrupt Pending Bits 块的基地址固定为 0x001000。
PLIC 寄存器块名称 | 功能 | 以字节为单位的寄存器块大小 | 描述 |
---|---|---|---|
中断挂起位 | 中断源#0 到#N 的中断挂起位 | 1024 / 8 =128(0x80) 字节 | 这是一个连续的内存块,包含 PLIC 中断挂起位。每个中断挂起位占用该寄存器块的 1 位。 |
PLIC 中断挂起位内存映射
1 | 0x001000: Interrupt Source #0 to #31 Pending Bits |
中断使能
每个全局中断都可以通过设置启用寄存器中的相应位来启用。启用寄存器作为 32 位寄存器的连续数组进行访问,其使用方式与中断挂起位相同。使能寄存器 0 的位 0 表示不存在的中断 ID 0,并硬连线为 0。PLIC 有 15872 个上下文中断启用块。
PLIC 如何为上下文(Hart 和特权模式)组织中断超出了 RISC-V PLIC 规范范围,但它必须在供应商的 PLIC 规范中进行规范。
(在某些中断源只能路由到目标子集的情况下,大量潜在的 IE 位可能会硬连线为零。对于具有固定中断路由的嵌入式设备,可能会有更多位连接到 1。中断优先级、阈值和 hart 内部中断屏蔽在忽略外部中断方面提供了相当大的灵活性,即使始终启用全局中断源也是如此。)
PLIC Memory Map 区域内的 Interrupt Enable Bits 块的基地址固定为 0x002000。
PLIC 寄存器块名称 | 功能 | 以字节为单位的寄存器块大小 | 描述 |
---|---|---|---|
中断使能位 | 15872 上下文的中断源 #0 到 #1023 的中断启用位 | 1024 / 8) * 15872 = 2031616(0x1f0000) 字节 | 这是一个连续的内存块,包含 15872 个上下文的 PLIC 中断启用位。每个中断使能位占用该寄存器块的 1 位,总共 15872 个中断使能位块 |
PLIC 中断使能位内存映射
1 | 0x002000: Interrupt Source #0 to #31 Enable Bits on context 0 |
优先级阈值
PLIC 提供了基于上下文的阈值寄存器,用于设置每个上下文的中断优先级阈值。阈值寄存器是一个 WARL 字段。PLIC 将屏蔽优先级小于或等于阈值的所有 PLIC 中断。例如,零阈值允许所有具有非零优先级的中断。
优先级阈值寄存器块的基地址位于 4K 对齐,从偏移量 0x200000 开始。
PLIC 寄存器块名称 | 功能 | 以字节为单位的寄存器块大小 | 描述 |
---|---|---|---|
优先级阈值 | 15872 上下文的优先级阈值 | 4096 * 15872 = 65011712(0x3e00000) 字节 | 这是每个上下文的优先级阈值设置寄存器 |
PLIC 中断优先级阈值内存映射
1 | 0x200000: Priority threshold for context 0 |
中断声明进程
在目标收到中断通知后的某个时间,它可能会决定为中断服务。目标向 PLIC 核心发送中断请求消息,该消息通常作为非幂等内存映射 I/O 控制寄存器读取来实现。收到声明消息后,PLIC 核心将自动确定目标的最高优先级挂起中断的 ID,然后清除相应源的 IP 位。然后 PLIC 内核会将 ID 返回给目标。如果在服务声明时目标没有挂起的中断,则 PLIC 核心将返回一个 ID 零。
在最高优先级的挂起中断被目标声明并且相应的 IP 位被清除后,其他较低优先级的挂起中断可能对目标可见,因此 PLIC EIP 位可能不会在声明后被清除。中断处理程序可以在退出处理程序之前检查本地 meip/seip/ueip 位,以允许更有效地服务其他中断,而无需先恢复中断上下文并采取另一个中断陷阱。
即使未设置 EIP,hart 执行索赔始终是合法的。特别是,hart 可以将阈值设置为最大值以禁用中断通知,而是使用定期声明请求轮询活动中断,尽管实现轮询的更简单方法是清除相应 xie 寄存器中的外部中断启用以实现特权模式 X。
PLIC 可以通过读取请求/完成寄存器来执行中断请求,该寄存器返回最高优先级挂起中断的 ID,如果没有挂起中断,则返回零。成功的声明还将自动清除中断源上相应的挂起位。PLIC可以随时进行claim操作,claim操作不受优先级阈值寄存器设置的影响。
中断声明进程寄存器是基于上下文的,位于 (4K 对齐 + 4) 从偏移量 0x200000 开始。
PLIC 寄存器块名称 | 功能 | 以字节为单位的寄存器块大小 | 描述 |
---|---|---|---|
中断请求寄存器 | 15872 上下文的中断声明过程 | 4096 * 15872 = 65011712(0x3e00000) bytes | 这是用于获取每个上下文的中断 ID 的寄存器 |
PLIC 中断声明进程内存映射
1 | 0x200004: Interrupt Claim Process for context 0 |
中断完成
PLIC 通过将从声明中接收到的中断 ID 写入声明/完成寄存器来表示它已完成执行中断处理程序。PLIC 不检查完成 ID 是否与该目标的最后一个声明 ID 相同。如果完成 ID 与当前为目标启用的中断源不匹配,则完成将被静默忽略。
在处理程序完成中断服务后,必须向相关网关发送中断完成消息,通常作为对非幂等内存映射 I/O 控制寄存器的写入。网关只会在收到完成消息后将额外的中断转发给 PLIC 内核。
中断完成寄存器是基于上下文的,与中断声明处理寄存器位于同一地址,该寄存器位于 (4K 对齐 + 4) 从偏移量 0x200000 开始。
PLIC 寄存器块名称 | 功能 | 以字节为单位的寄存器块大小 | 描述 |
---|---|---|---|
中断完成寄存器 | 15872 上下文的中断完成 | 4096 * 15872 = 65011712(0x3e000 00) bytes | 这是要写入以完成中断过程的寄存器 |
PLIC 中断完成内存映射
1 | 0x200004: Interrupt Completion for context 0 |