文章目录
前言
P L I C ( P l a t f o r m − L e v e l I n t e r r u p t C o n t r o l l e r ) PLIC(Platform-Level \ Interrupt \ Controller) PLIC(Platform−Level Interrupt Controller) 平台级中断控制器主要用于 R I S C V RISCV RISCV 架构下外部中断的控制和处理。本文主要翻译自官方 P L I C PLIC PLIC 文档并根据自己的理解做润色修改。
PLIC的中断目标(Interrupt target)
中断目标通常是核心 ( h a r t ) (hart) (hart) 的上下文 ( c o n t e x t ) (context) (context),其中核心 ( h a r t ) (hart) (hart) 上下文是给定核心上的给定特权模式。(中断目标也可以是 D M A DMA DMA 引擎)。例如,在4核8线程的机器中,共8个 h a r t hart hart,每个 h a r t hart hart 可能至少有两种特权模式:机器 ( M a c h i n e ) (Machine) (Machine) 模式和特权级/监管者 ( S u p e r v i s i o r ) (Supervisior) (Supervisior) 模式。
同时,并非所有 h a r t hart hart 上下文都是中断目标。特别的,如果处理器核心不支持将外部中断委派给较低特权级,那么处于低特权的 h a r t hart hart 上下文将不会是中断目标。
由 P L I C PLIC PLIC 产生的中断通知会根据当前 h a r t hart hart 所处的 M / S M/S M/S 特权级分别出现在 M / S M/S M/S 模式的 m i p / s i p mip/sip mip/sip 寄存器的 m e i p / s e i p meip/seip meip/seip 位中。另外,只有当处理器支持中断委派且外部中断被委托给低权限模式时,中断通知才会出现在低权限的 S I P SIP SIP 寄存器中( U I P UIP UIP 寄存器尚未支持,通常情况是把 M M M 模式的外部中断委派到 S S S 模式处理)。
对于单个 h a r t hart hart,高特权上下文的中断可以抢占低特权上下文的中断处理程序的执行。因此如果某一个中断必须在高特权级下执行,例如时钟中断,则必须考虑再中断响应中保存寄存器,并在中断处理完成之后恢复现场。一个多线程处理器内核可以同时在不同的 h a r t hart hart 上下文中运行多个独立的中断处理程序。 P L I C PLIC PLIC 独立地处理每个中断目标,并且不考虑包含多个中断目标的组件所使用的任何中断优先级方案。因此, P L I C PLIC PLIC 没有提供中断抢占或嵌套的概念,因此这必须由中断目标上下文的核心处理,即软件方式实现中断嵌套。
下图为
R
I
S
C
−
V
RISC-V
RISC−V
P
L
I
C
PLIC
PLIC 中断架构图
中断网关(Interrupt Gateway)
中断网关负责将全局中断信号转换为通用的中断请求格式,并控制到PLIC核心的中断请求流。通过设置源的 I P ( I n t e r r u p t P e n d i n g ) IP(Interrupt Pending) IP(InterruptPending) 位来表示,每个中断源在任何时候最多只能在 P L I C PLIC PLIC 核心中挂起一个中断请求。网关只有在接收到来自同一源的先前中断请求服务的中断处理程序已经完成的通知后,才会将新的中断请求转发给 P L I C PLIC PLIC 核心。
如果全局中断源使用水平触发方式,中断网关将把中断电平的首次置位转换为中断请求,但此后除非收到中断完成消息,否则网关将不再转发额外的中断请求。收到中断完成消息后,如果中断是水平触发的并且中断仍然处于置位状态,网关将向 P L I C PLIC PLIC 核心转发一个新的中断请求。一旦将中断请求转发给 P L I C PLIC PLIC 核心,网关就没有撤销该请求的功能。如果在 P L I C PLIC PLIC 核心接受请求并处理中断之前,水平触发的中断源撤销了中断,那么中断请求将保留在 P L I C PLIC PLIC 核心的 I P ( I n t e r r u p t P e n d i n g ) IP(Interrupt Pending) IP(InterruptPending) 位中,并由一个中断处理程序来处理。然后,处理程序必须确定中断设备不再需要服务。
如果全局中断源是边沿触发的,网关会将第一个匹配的信号边沿转换为中断请求。根据设备的设计和中断处理程序,在发送中断请求和接收其处理程序完成的通知之间,网关可能会忽略其他匹配的边沿,或者增加挂起中断的计数器。在任何一种情况下,直到收到上一个完成消息,下一个中断请求才会转发到 P L I C PLIC PLIC 核心。如果网关有一个挂起中断计数器,当中断请求被 P L I C PLIC PLIC 核心接受时,计数器将递减。
中断通知(Interrupt Notifications)
1:每个中断目标在
P
L
I
C
PLIC
PLIC 核心中都有一个外部中断待处理
E
I
P
(
E
x
t
e
r
n
a
l
I
n
t
e
r
r
u
p
t
P
e
n
d
i
n
g
)
EIP(External Interrupt Pending)
EIP(ExternalInterruptPending) 位,该位表明对应的中断目标有一个等待服务的挂起中断。若中断目标为
h
a
r
t
hart
hart 则
E
I
P
EIP
EIP 为
M
E
I
P
MEIP
MEIP 或
S
E
I
P
SEIP
SEIP 位。
P
L
I
C
PLIC
PLIC 对这些位可写。
2:
E
I
P
EIP
EIP 的值可能会因为
P
L
I
C
PLIC
PLIC 核心状态的变化而改变,这些变化可能是由中断源、中断目标或是其他修改
P
L
I
C
PLIC
PLIC 寄存器值的代理所引起的。
E
I
P
EIP
EIP 的值会传达给目标作为中断通知。如果目标是一个RISC-V hart上下文,那么中断通知会根据
h
a
r
t
hart
hart 上下文的权限级别,出现在
m
i
p
mip
mip 寄存器的
m
e
i
p
meip
meip(机器模式下的中断挂起位)或
S
I
P
SIP
SIP 寄存器的
s
e
i
p
seip
seip(
S
S
S模式下的中断挂起位)上。
3: P L I C PLIC PLIC 硬件只支持中断的多播,这样所有启用的目标都将收到给定中断的中断通知。即若有有效中断到来,则所有符合条件的 h a r t hart hart 都将收到通知。同时,这种方案也可能造成资源的浪费,可以通过软件设置 P L I C PLIC PLIC 的 I E ( I n t e r r u p t E n a b l e ) IE(Interrupt \ Enable) IE(Interrupt Enable) 位来实现不同策略。
中断标识符Interrupt Identifiers (IDs)
I
D
ID
ID 从
1
1
1 开始,到
1023
1023
1023 结束。中断标识符
0
0
0 被保留用于表示没有中断。
中断标识符也用于以下场景:当两个中断优先级相同时,小的中断标识符则拥有更高的优先级。
中断处理流程(Interrupt Flow)
1:中断网关处理来自中断源的全局中断信号,转为中断请求。
2:中断网关向
P
L
I
C
PLIC
PLIC 核心发送中断请求,
P
L
I
C
PLIC
PLIC 核心设置该中断源的中断挂起位
I
P
IP
IP。
3:
P
L
I
C
PLIC
PLIC 核心发送中断通知给能够合法接收本次中断源的所有中断目标。即本次中断源的
I
D
ID
ID 高于中断目标的中断阈值且该中断在该目标使能
(
I
E
=
I
n
t
e
r
r
u
p
t
E
n
a
b
l
e
)
(IE=Interrupt \ Enable)
(IE=Interrupt Enable)。
4:当某一个中断目标接受该外部中断时,它发送一个中断声明
(
c
l
a
i
m
)
(claim)
(claim) 请求,从
P
L
I
C
PLIC
PLIC 核心对应位置读取属于该中断目标的最高优先级全局中断源的标识符。即
h
a
r
t
hart
hart 读取
P
L
I
C
PLIC
PLIC 的
m
e
m
o
r
y
m
a
p
memory \ map
memory map 中对应于该
h
a
r
t
hart
hart 的
c
l
a
i
m
/
c
o
m
p
l
e
t
e
claim/complete
claim/complete 寄存器的值作为判断中断源的依据。
5:
P
L
I
C
PLIC
PLIC 核心清除该中断源的中断挂起位。
6:中断目标完成中断处理,发送中断完成信号。具体为
h
a
r
t
hart
hart 向
P
L
I
C
PLIC
PLIC 的
m
e
m
o
r
y
m
a
p
memory \ map
memory map 中对应于该
h
a
r
t
hart
hart 的
c
l
a
i
m
/
c
o
m
p
l
e
t
e
claim/complete
claim/complete 寄存器中写入
I
D
ID
ID号。
7:中断网关可以把来自同一个中断源的请求发送给
P
L
I
C
PLIC
PLIC 核心。
下图为PLIC中断服务流程
PLIC运行参数(Operation Parameters)
我们只需要读写一系列寄存器,通过控制参数寄存器的值即可控制
P
L
I
C
PLIC
PLIC 的运行。
1:
I
n
t
e
r
r
u
p
t
P
r
i
o
r
i
t
i
e
s
r
e
g
i
s
t
e
r
s
Interrupt \ Priorities \ registers
Interrupt Priorities registers 中断优先级寄存器,记录每个中断源的优先级
2:
I
n
t
e
r
r
u
p
t
P
e
n
d
i
n
g
B
i
t
s
r
e
g
i
s
t
e
r
s
Interrupt \ Pending \ Bits \ registers
Interrupt Pending Bits registers 终端挂起位寄存器,记录每个中断源的中断挂起状态
3:
I
n
t
e
r
r
u
p
t
E
n
a
b
l
e
s
r
e
g
i
s
t
e
r
s
Interrupt \ Enables \ registers
Interrupt Enables registers 中断使能寄存器,控制该中断是否使能,即是否接收该中断源产生的中断。
4:
I
n
t
e
r
r
u
p
t
T
h
r
e
s
h
o
l
d
s
r
e
g
i
s
t
e
r
s
Interrupt \ Thresholds \ registers
Interrupt Thresholds registers 中断阈值寄存器,记录每个context的中断阈值。
5:
I
n
t
e
r
r
u
p
t
C
l
a
i
m
r
e
g
i
s
t
e
r
s
Interrupt \ Claim \ registers
Interrupt Claim registers 中断响应寄存器,用于每个context从PLIC读取中断源ID
6:
I
n
t
e
r
r
u
p
t
C
o
m
p
l
e
t
i
o
n
r
e
g
i
s
t
e
r
s
Interrupt \ Completion \ registers
Interrupt Completion registers 中断完成寄存器,用于向中断网关发送中断完成消息。
下图为
P
L
I
C
PLIC
PLIC 操作参数块图
PLIC内存映射
P L I C PLIC PLIC 内存映射的基址是平台实现特定的, k v m t o o l kvmtool kvmtool 中定义的 P L I C PLIC PLIC 基地址为 0 x 08000000 U L L 0x08000000ULL 0x08000000ULL。 P L I C PLIC PLIC 内存映射寄存器的宽度为 32 32 32 位。这些位通过 L W LW LW 和 S W SW SW 指令自动访问。
内存映射中各寄存器的位置如下所示:
base + 0x000000: Reserved (interrupt source 0 does not exist)
base + 0x000004: Interrupt source 1 priority
base + 0x000008: Interrupt source 2 priority
...
base + 0x000FFC: Interrupt source 1023 priority
base + 0x001000: Interrupt Pending bit 0-31
base + 0x00107C: Interrupt Pending bit 992-1023
...
base + 0x002000: Enable bits for sources 0-31 on context 0
base + 0x002004: Enable bits for sources 32-63 on context 0
...
base + 0x00207C: Enable bits for sources 992-1023 on context 0
base + 0x002080: Enable bits for sources 0-31 on context 1
base + 0x002084: Enable bits for sources 32-63 on context 1
...
base + 0x0020FC: Enable bits for sources 992-1023 on context 1
base + 0x002100: Enable bits for sources 0-31 on context 2
base + 0x002104: Enable bits for sources 32-63 on context 2
...
base + 0x00217C: Enable bits for sources 992-1023 on context 2
...
base + 0x1F1F80: Enable bits for sources 0-31 on context 15871
base + 0x1F1F84: Enable bits for sources 32-63 on context 15871
base + 0x1F1FFC: Enable bits for sources 992-1023 on context 15871
...
base + 0x1FFFFC: Reserved
base + 0x200000: Priority threshold for context 0
base + 0x200004: Claim/complete for context 0
base + 0x200008: Reserved
...
base + 0x200FFC: Reserved
base + 0x201000: Priority threshold for context 1
base + 0x201004: Claim/complete for context 1
...
base + 0x3FFF000: Priority threshold for context 15871
base + 0x3FFF004: Claim/complete for context 15871
base + 0x3FFF008: Reserved
...
base + 0x3FFFFFC: Reserved
中断优先级
中断所支持的最大优先级因平台而异。但中断优先级
0
0
0 被保留用于表示从不中断或禁用中断,一般将
0
0
0 号中断优先级设置为
0
0
0 。
每一个全局中断源都有一个与他相关的
32
b
i
t
32bit
32bit 中断优先级寄存器位于
P
L
I
C
PLIC
PLIC 的
M
M
I
O
MMIO
MMIO 中。
中断优先级
1
1
1 是优先级最小的有效中断优先级,最大中断优先级取决于平台的具体实现。同时,当两个中断源中断优先级相同,则
I
D
ID
ID 号小的中断源优先级更高。
以下为 P L I C PLIC PLIC 的中断优先级寄存器内存映射:
0x000000: Reserved (interrupt source 0 does not exist)
0x000004: Interrupt source 1 priority
0x000008: Interrupt source 2 priority
...
0x000FFC: Interrupt source 1023 priority
中断优先级寄存器组起始地址在 P L I C PLIC PLIC 的 M M I O MMIO MMIO 中偏移为 0 0 0,每个中断源的中断优先级占用 4 4 4 字节。中断优先级寄存器共占用空间: 1024 ∗ 4 = 4096 = 0 x 1000 1024*4=4096=0x1000 1024∗4=4096=0x1000 字节。
中断挂起位(Interrupt Pending Bits)
1:当前 RISC-V 平台级中断控制器 ( P L I C ) (PLIC) (PLIC)核心中,中断源的挂起状态(即中断是否正在等待处理)可以通过读取 p e n d i n g pending pending 数组来获取,这个数组是以 32 32 32 位寄存器的形式组织的。
2:即
32
32
32 个中断源为一组,若一个中断源
I
D
ID
ID 号为
N
N
N,则其中断挂起位
(
I
P
)
(IP)
(IP)位于第
N
/
32
N/32
N/32个中断挂起寄存器中,且该寄存器的第
N
m
o
d
32
N \ mod \ 32
N mod 32 位表示该中断源是否挂起。
3:
0
0
0 号中断挂起寄存器的第
0
b
i
t
0bit
0bit 被硬连线为
0
0
0,表示不存在的中断源。
4:当与中断源相关联的
c
l
a
i
m
claim
claim 寄存器被读之后,中断挂起位会被清除。即
h
a
r
t
hart
hart 发送的一个中断响应信号:读中断
I
D
ID
ID 号。
以下为
P
L
I
C
PLIC
PLIC 的中断挂起寄存器组内存映射:
0x001000: Interrupt Source #0 to #31 Pending Bits
...
0x00107C: Interrupt Source #992 to #1023 Pending Bits
中断挂起寄存器组起始地址在 P L I C PLIC PLIC 的 M M I O MMIO MMIO 中偏移为 0 x 1000 0x1000 0x1000,每 32 32 32 个中断位于一个寄存器,共占用空间为 128 = 0 x 80 128=0x80 128=0x80 字节。
中断使能
1:由于每个
h
a
r
t
hart
hart 对于待接收的中断源可自行控制,所以每个
h
a
r
t
hart
hart 都有一组自己的中断使能寄存器,用于控制是否接收某一个中断源的中断。中断使能寄存器以连续的
32
b
i
t
32bit
32bit 寄存器方式组织,对于中断的组织形式和中断挂起位一样,
32
32
32 个中断一组,由一个寄存器控制。
2:
0
0
0 号使能寄存器的第0bit位硬连线为
0
0
0,永不使能该中断。
3:
P
L
I
C
PLIC
PLIC 最大支持
h
a
r
t
hart
hart 上下文数目为
15872
15872
15872。
以下为 P L I C PLIC PLIC 的中断使能寄存器组内存映射:
0x002000: Interrupt Source #0 to #31 Enable Bits on context 0
...
0x00207C: Interrupt Source #992 to #1023 Enable Bits on context 0
0x002080: Interrupt Source #0 to #31 Enable Bits on context 1
...
0x0020FC: Interrupt Source #992 to #1023 Enable Bits on context 1
0x002100: Interrupt Source #0 to #31 Enable Bits on context 2
...
0x00217C: Interrupt Source #992 to #1023 Enable Bits on context 2
0x002180: Interrupt Source #0 to #31 Enable Bits on context 3
...
0x0021FC: Interrupt Source #992 to #1023 Enable Bits on context 3
...
...
...
0x1F1F80: Interrupt Source #0 to #31 on context 15871
...
0x1F1FFC: Interrupt Source #992 to #1023 on context 15871
中断使能寄存器组起始地址在 P L I C PLIC PLIC 的 M M I O MMIO MMIO 中偏移为 0 x 2000 0x2000 0x2000,每个 h a r t hart hart 上下文一组中断使能寄存器,每 32 32 32 个中断位于一个寄存器,单个 h a r t hart hart 共占用空间为 128 = 0 x 80 128=0x80 128=0x80 字节。
中断优先级阈值
中断优先级阈值为每个 h a r t hart hart 上下文设置一个优先级阈值,中断源优先级低于或等于阈值的中断则不会递交给此 h a r t hart hart。等于阈值的中断依旧屏蔽。当中断优先级阈值设置为 0 0 0,则接收所有中断,除了 I D ID ID 号为 0 0 0 的中断。
以下为 P L I C PLIC PLIC 的中断优先级阈值寄存器组内存映射:
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
中断阈值寄存器组起始地址在 P L I C PLIC PLIC 的 M M I O MMIO MMIO 中偏移为 0 x 200000 0x200000 0x200000,每个 h a r t hart hart 上下文一个中断优先级阈值寄存器,另外,每个 h a r t hart hart 上下文有别的寄存器组,以及多余空间待扩展,故每个 h a r t hart hart 占用空间 0 x 1000 0x1000 0x1000。
中断响应寄存器(claim)
1:中断响应和中断完成寄存器属于同一个寄存器。区别在于中断响应寄存器是读操作,中断完成是写操作。
2:当中断目标收到中断通知,即
X
I
P
XIP
XIP 寄存器中
X
E
I
P
XEIP
XEIP 置位,表示有外部中断到来。此时,为响应中断,
h
a
r
t
hart
hart 需发送中断响应信号,即读取该
h
a
r
t
hart
hart 在
P
L
I
C
PLIC
PLIC 中对应的中断响应寄存器,
P
L
I
C
PLIC
PLIC 会返回所有挂起中断中优先级最高的中断
I
D
ID
ID,若此时没有挂起中断,则返回
0
0
0。若中断响应有效,则清除对应中断源的中断挂起位。
3:一个高优先级的中断被响应后,可能仍旧有中断待处理,外部中断
E
I
P
EIP
EIP 位可能仍旧为
1
1
1。中断处理程序可以在退出前检查
E
I
P
EIP
EIP 位,若仍有中断待处理,可不必恢复上下文退出,继续处理剩余中断,节省资源。
4:中断响应不受中断阈值的影响,
h
a
r
t
hart
hart 上下文可以设置中断阈值寄存器为平台所支持的最大值以禁用所有中断通知。但
h
a
r
t
hart
hart 仍旧可主动发起中断响应请求,读取中断响应寄存器,此时
P
L
I
C
PLIC
PLIC 仍会返回挂起中断中优先级最高中断
I
D
ID
ID。(一个更加有效的禁用外部中断的方法是在
X
X
X 模式下的
X
I
E
XIE
XIE 寄存器中清除
X
E
I
P
XEIP
XEIP 位。)
以下为 P L I C PLIC PLIC 的中断优先级阈值寄存器组和中断响应/完成寄存器组内存映射:
* base + 0x200000: Priority threshold for context 0
* base + 0x200004: Claim/complete for context 0
* base + 0x200008: Reserved
* ...
* base + 0x200FFC: Reserved
* base + 0x201000: Priority threshold for context 1
* base + 0x201004: Claim/complete for context 1
* ...
* base + 0xFFE000: Priority threshold for context 15871
* base + 0xFFE004: Claim/complete for context 15871
* base + 0xFFE008: Reserved
* ...
* base + 0xFFFFFC: Reserved
*/
中断响应寄存器组起始地址在 P L I C PLIC PLIC 的 M M I O MMIO MMIO 中偏移为 0 x 200000 0x200000 0x200000,可以看到,中断响应寄存器正位于中断阈值寄存器之后,剩余hart相关寄存器空间保留待扩展使用。
中断完成寄存器(complete)
1:
P
L
I
C
PLIC
PLIC 的中断完成信号即向中断完成寄存器中写入中断
I
D
ID
ID。
P
L
I
C
PLIC
PLIC 不检查写入的内容是否为中断响应时给出的中断
I
D
ID
ID。若该中断对于发送该中断完成信号的
h
a
r
t
hart
hart上下文并未使能,则PLIC会忽略此次中断完成信号。
2:中断完成信号有效,则中断网关才会继续发送该中断源的中断到
P
L
I
C
PLIC
PLIC 核心。
以下为 P L I C PLIC PLIC 的中断优先级阈值寄存器组和中断响应/完成寄存器组内存映射:
* base + 0x200000: Priority threshold for context 0
* base + 0x200004: Claim/complete for context 0
* base + 0x200008: Reserved
* ...
* base + 0x200FFC: Reserved
* base + 0x201000: Priority threshold for context 1
* base + 0x201004: Claim/complete for context 1
* ...
* base + 0xFFE000: Priority threshold for context 15871
* base + 0xFFE004: Claim/complete for context 15871
* base + 0xFFE008: Reserved
* ...
* base + 0xFFFFFC: Reserved
*/
总结
完结撒花!
参考
PLIC官方文档地址:https://github.com/riscv/riscv-plic-spec/blob/master/riscv-plic.adoc