V-PLIC
PLIC即Platform-Level Interrupt Controller,是riscv架构下的一种中断控制器。它将各种设备中断多路复用到Hart上下文的外部中断线上。
在使用PLIC的场景下,外部设备会连接到PLIC上作为中断源。当外部设备发起中断信号,信号会传递给PLIC,PLIC会根据自身配置,选出一个“最优”中断源,并发出外部中断信号给满足条件的Hart。Hart收到外部中断后,需要查询PLIC当前的“最优”中断源ID,以知晓是哪个设备发出了中断,并做相应处理。Hart需要写入PLIC的特定寄存器,以通知PLIC此趟中断处理完成;PLIC在收到完成信号后,便可处理下一个“最优”中断源。
结构

Gateway
每个中断源都有一个对应的Gateway。中断网关负责将全局中断信号转换为通用中断请求(Interrupt Request)格式,并控制中断请求流向 PLIC Core。在 PLIC Core中,每个中断源在任何时候最多可以有一个中断请求(Interrupt Request)处于待处理状态,通过设置中断源的 IP 位来指示。网关仅在收到完成通知后,才会将同一源的新的中断请求转发到 PLIC Core。
即当一个中断源A发送了中断信号S1到Gateway,Gateway也已经向Core发送S1对应的一个中断请求R1,且Gateway没有收到完成(Complete)通知,那么若中断源A再次发送中断信号S2到Gateway,Gateway不会发送新的中断请求R2。
一般而言,当中断处理程序完成后,会写入Claim/Complete寄存器,此时Gateway可以收到完成(Complete)通知。
Source相关
Source's IP(Interrupt Pending Bits)
每个中断源的Interrupt Pending Bits registers。
寄存器中的每个bit标识了一个中断源的pending状态。
它会被两种行为改变: 1. Gateway向Core发送中断请求(Interrupt Request)后,此请求会被锁存(latch)到Interrupt Pending Bit 2. PLIC收到中断声明(Claim)请求后,会清除对应中断源的Pending Bit
即使所有context的enable关闭,也不影响gateway发送request并被latch到pending bit这一过程。当context的enable打开,pending bit的信号会自然流入
Interrupt Priorities
每个中断源的优先级寄存器。
可以写入此寄存器来为每个中断源设置优先级,优先级按数值大小从低到高排列,其中0表示“从不中断”,等于禁用此中断。
当两个中断源具有相同的优先级时,中断ID更小的中断源优先级更高。
Context相关
Interrupt Enable
每个context的中断使能寄存器。寄存器中的每一个bit,对应一个中断源,表示此context是否接受来自此bit对应中断源的中断。
可以写入此寄存器来为context配置中断使能。
Priority Thresholds
每个context的优先级阈值寄存器。若中断源的优先级小于或等于此寄存器的值,那么此中断源的信号会在此context上会被屏蔽。阈值为0则允许所有优先级为非0的中断。
Interrupt Claim/Complete
每个context的Claim/Complete寄存器,这是一个寄存器,同时承担了Claim/Complete的过程。
目标可以通过mmio读取claim寄存器,此时PLIC会原子的确定,当前最高优先级的待定中断ID,并将此ID作为claim寄存器的值提供给目标;然后清除此ID对应中断源的IP位。
如果在处理claim时目标没有待处理的中断,则PLIC Core返回ID为0。
claim操作不受优先级阈值的影响,它查询当前活动中断中,优先级最高的那个的ID,是context无关的。目标甚至可以将优先级阈值设为MAX,意味关闭外部中断,然后通过主动轮询claim寄存器,来获知活动的中断。
PLIC通过将从claim收到的中断ID写入claim/complete寄存器来表示它已完成执行中断处理程序。PLIC 不会检查写入的complete ID是否与该目标的最后一个claim的ID相同。如果写入的complete ID与当前为目标启用的中断源ID不匹配,PLIC则会忽略这一差异。
在处理程序完成中断服务后,必须向关联的网关发送中断完成消息,通常由写入claim/complete寄存器来完成这一操作。网关只有在收到完成消息后,才会将其他中断转发到PLIC内核。
EIP
每个中断目标在PLIC内核中都有一个外部中断挂起(EIP)位,表示相应的目标有一个等待服务的挂起中断。EIP中的值可能会因PLIC内核中状态的变化而发生变化,这是由中断源、中断目标或操作 PLIC 中寄存器值的其他代理引起的。EIP中的值将作为中断通知传达给目标目标。如果目标是 RISC-V hart 上下文,则中断通知会到达meip/seip 位。
PLIC硬件仅支持中断的多播,因此所有使能的目标都将收到给定活动中断的中断通知(多播提供快速响应,因为最快的响应者声明中断,但在高中断率场景中,如果多个hart为只有一个hart可以成功声明的中断占用trap,则可能会造成浪费。软件可以利用IE位进行调制,以提供替代策略)
中断通知中的值仅保证是在过去某个时间点有效的EIP值。特别是,当向第一个目标发送的通知仍在传输中时,第二个目标可以响应并声明(claim)中断,这样,当第一个目标尝试声明(claim)中断时,它发现它在PLIC内核中没有活动中断。
物理中断过程

- 中断源发送信号至其对应Gateway
- Gateway发送中断请求(Interrupt Request)给PLIC核心,IP位被设置
- PLIC核心给所有满足条件的target发送Notification
- target收到外部中断,并进行Claim来获取中断源ID
- 而后PLIC核心清除对应的IP位
- target处理完中断后,发送Complete通告对应Gateway
- Gateway转发同一中断源的下一个中断请求
模拟
PLIC为设备提供服务,接受来自设备的中断信号。同时使用目标cpu的中断引脚,给目标cpu发送外部中断信号。
相应的,虚拟PLIC需要为模拟设备提供一个接口,让模拟设备调用此接口来向虚拟PLIC发送中断信号。同时虚拟PLIC需要使用vcpu提供的接口,来给vcpu发送外部中断。
1 |
|
模拟过程: 1. 模拟设备调用plic发送中断信号 2. 占据gateway后,设置pending位 3. 更新plic状态,看context是否有可通知的中断,若有则为对应vcpu设置相应中断,并将最优中断id放入claim 4. vcpu收到中断,尝试读取claim来获知是哪个设备 5. plic收到读取claim请求后,清除对应中断源的pending,返回claim 6. vcpu获取中断源,做相应处理,并写complete 7. 写入claim/complete后,解除gateway,可发送下个中断请求
key
- 同一时间内每个中断源最多只能有一个中断请求被pending在plic
- gateway只会在同一中断源的上一个请求完成后,再转发新的中断请求
- 若target为hart context,中断最终会根据context的特权级,到达meip/seip
- plic只支持多播,当有活动的中断时,所有enable的target都会收到notification,但只有一个hart能够claim
- 根据平台架构和用于传输中断通知的方法,目标可能需要一些时间才能接收到这些通知。只要PLIC核心中没有干预活动,PLIC就保证最终将EIP中的所有状态变化传递给所有目标?
- 中断通知中的值仅保证包含过去某个时间点有效的EIP值。特别地,第二目标可以在向第一目标发送通知的过程中响应并声明中断,这样当第一目标试图声明中断时,它会发现PLIC核心中没有活动的中断。
problem
- 假设中断源1的信号通过gateway后让Hart A和Hart B都产生了中断,是只要Hart A/B中任意一个发送interrupt completion,gateway就可以让中断源1的信号再次通过;还是需要Hart A和B都完成interrupt completion才行?
- 要么直通要么全模拟?因为物理设备的中断信号无法传入模拟plic,而模拟设备无法发送物理信号给物理plic,但guest只能要么读取硬件plic(直通plic给guest),要么只能读取物理plic(不设置页表)。可能的解决办法:让模拟plic在一趟notification/complete过程中完全互斥,即保证一趟外部中断处理过程中不会有其他中断源被响应,当读模拟plic找不到有效中断时,可认为此处为物理设备中断,读物理plic;这样效率可能较低。
emmm,虚拟设备只会引发vs中断,在虚拟机内处理,而物理直通设备会产生s中断,会导致vmexit,这种情况好像也只能单纯注入了?能以此做区分吗?
ou,物理设备发送s中断后,将其以现实的irq_source导入到虚拟plic中即可?
next
hart写入plic的时候,是直接写新值还是用mask“增量”写?
使用u32还是bitvec?
todo: 多核、level触发/被gateway block时的处理、raise irq后对此中断源单独的更新和notification、用vec还是array还是box array?host中断号和guest中断号的对应关系?如何共享直通设备?
source
https://siriusdemon.github.io/Rare/v6-Plic-Clint.html
https://gallium70.github.io/osblog-translation/ch5.html
https://www.skyzh.dev/