RISC-V总共有四种工作模式,分别是U、S、H和M模式:
Level |
Encoding |
Name |
Abbreviation |
0 |
00 |
User/Application |
U |
1 |
01 |
Suppervisor |
S |
2 |
10 |
Reserved |
|
3 |
11 |
Machine |
M |
U模式被编码为00,S模式编码为01,H模式编码为10,M模式编码为11。Level越高,等级越高。等级越高,拥有的访问权限也更高。按照特权等级,由高到低依次为M、H、S、U。
上表中编码为10的模式是保留的,这个模式实际上就是H模式,H模式是用作虚拟化,但是目前RISC-V对虚拟化还不太完善,基本不支持。因此上表并没有将H模式标出来,而是作为保留。也正是因此,有人经常将RISC-V的模式说成三种U、S和M。
- U模式:User,用户模式
- S模式:Supervisor,监管者模式
- M模式:Machine,机器模式
以RISC-V Linux为例,Linux应用程序处于U模式,Linux内核/uboot处于S模式,M模式则是OpenSBI。M模式拥有最高访问权限,Linux内核如果要访问CSR寄存器,则必须由S模式切换到M模式,由OpenSBI读取CSR寄存器,然后将数据返回给内核。
M模式是必须要选择的,RISC-V的裸机代码都运行在M模式下。
RISC-V通用寄存器
寄存器 |
ABI名称 |
说明 |
x0 |
zero |
0值寄存器,硬编码为0,写入数据忽略,读取数据为0 |
x1 |
ra |
用于返回地址(return address) |
x2 |
sp |
用于栈指针(stack pointer) |
x3 |
gp |
用于通用指针(global pointer) |
x4 |
tp |
用于线程指针 |
x5 |
t0 |
用于存放临时数据或者备用链接寄存器 |
x6~x7 |
t1~t2 |
用于存放临时数据寄存器 |
x8 |
s0/fp |
需要保存的寄存器或者帧指针寄存器 |
x9 |
s1 |
需要保存寄存器 |
x10~x11 |
a0~a1 |
函数参数或者返回值寄存器 |
x12~x17 |
a2-a7 |
函数传递参数寄存器 |
x18~x27 |
s2-s11 |
需要保存的寄存器 |
x28~x31 |
t3~t6 |
用于存放临时数据寄存器 |
RISC-V有x0~x31共32个通用寄存器,每个通用寄存器都有各自的用途,例如x2是作为sp栈指针、a0 ~ a1用来保存函数参数或返回值。x0寄存器被硬编码为了0,就是个0值寄存器。
ABI名称相当于这些通用寄存器的别名,在RISC-V汇编当中,都使用ABI名称来代表这些寄存器。
RISC-V CSR寄存器
CSR是控制状态寄存器,RISC-V中CSR寄存器,需要使用csrr、csrw、csrrw等特定指令进行访问。
M模式和S模式都有自己的CSR寄存器,但是大体上相同。下面列举一些常用的CSR。
M模式CSR寄存器
mstatus
状态寄存器,保存了全局中断使能状态和其他状态,例如切换模式前,保存当前模式。
mtvec
异常入口基地址寄存器。保存发生异常时需要跳转的地址。
medeleg 和 mideleg
medeleg是异常委托,mideleg是中断委托。例如,在M模式下发生异常或中断时,可以通过这两个寄存器,将中断/异常交给S模式或者其他模式处理。
mip 和 mie
mie是中断使能寄存器,对需要使能的中断,在对应位使能。
mip是中断等待寄存器,表示目前正准备处理的中断。
hpm
全称Hardware Performance Monitor,硬件性能单元,用于性能计数。包括了两类寄存器:mhpmcounter和mhpmevent
- mhpmcounter:性能计数器
- mhpmevent:用于配置性能事件
mcounteren 和 mcountinhibit
这两个也是hpm相关的寄存器,主要用于控制hpm的使能、计数禁止。
- mcounteren:计数器使能
- mcountinhibit:禁止计数
mscratch
用于保存M模式指向hart上下文的指针,并在进入M模式的处理程序时,和用户寄存器交换。
mepc
发生中断时,当前程序的PC值,保存在mepc中,中断返回时,会从mepc读取PC值。
mcause
用于保存发生中断或异常的情况,中断和异常描述如下:
Interrupt |
Exception |
Description |
1 |
0 |
Reserved |
1 |
1 |
Supervisor software interrupt |
1 |
2 |
Reserved |
1 |
3 |
Machine software interrupt |
1 |
4 |
Reserved |
1 |
5 |
Supervisor timer interrupt |
1 |
6 |
Reserved |
1 |
7 |
Machine timer interrupt |
1 |
8 |
Reserved |
1 |
9 |
Supervisor external interrupt |
1 |
10 |
Reserved |
1 |
11 |
Machine external interrupt |
1 |
12-15 |
Reserved |
1 |
>=16 |
Designated for platform use |
0 |
0 |
Instruction address misaligned |
0 |
1 |
Instruction access fault |
0 |
2 |
Illegal Instruction |
0 |
3 |
Breakpoint |
0 |
4 |
Load address misaligned |
0 |
5 |
Load access fault |
0 |
6 |
Store/AMO address misaligned |
0 |
7 |
Store/AMO access fault |
0 |
8 |
Environment call from U-mode |
0 |
9 |
Environment call from S-mode |
0 |
10 |
Reserved |
0 |
11 |
Environment call from M-mode |
0 |
12 |
Instruction page fault |
0 |
13 |
Load page fault |
0 |
14 |
Reserved |
0 |
15 |
Store/AMO page fault |
0 |
16-23 |
Reserved |
0 |
24-31 |
Designated for custom use |
0 |
32-47 |
Reserved |
0 |
48-63 |
Designated for custom use |
0 |
>=64 |
Reserved |
上表中1代表中断,0代表异常,每个异常/中断都有对应的编码值,通过mcause的值,可以很清楚的知道发生了什么中断或异常,特别在调试过程, mcause 发挥了很大作用。
mvtal
异常值寄存器,例如发生异常时,保存出错的地址。
S模式CSR寄存器
S模式的CSR和M模式基本上是一样的,只不过将第一个字母m改为了s,例如 mcause 改为了 scause , mvtal 改为了 svtal 。它们的功能基本相同,不再赘述。
要注意的是,S模式除了拥有M模式相同功能的CSR外,另外还增加了一个 stap 寄存器。
stap
stap 寄存器主要是给MMU使用, stap 寄存器保存了页表的基地址,MMU通过 stap 可以找到第一级页表,进而找到物理地址。