1.3 RISC-V寄存器

1.3.1 通用寄存器

64位/32位的RISC-V体系结构提供32个64位/32位的整型通用寄存器,分别是x0~x31寄存器,如图1.5所示。对于浮点数运算,64位的RISC-V体系结构也提供32个浮点数通用寄存器,分别是f0~f31寄存器。

RISC-V的通用寄存器通常具有别名和特殊用途,在书写汇编指令时可以直接使用别名。

x0寄存器的别名为zero。寄存器的内容全是0,可以用作源寄存器,也可以用作目标寄存器。

x1寄存器的别名为ra——链接寄存器,用于保存函数返回地址。

x2寄存器的别名为sp——栈指针寄存器,指向栈的地址。

图1.5 RISC-V整型通用寄存器

x3寄存器的别名为gp——全局寄存器,用于链接器松弛优化。

x4寄存器的别名为tp——线程寄存器,通常在操作系统中用于保存指向进程控制块——task_struct数据结构的指针。

x5~x7以及x28~x31寄存器为临时寄存器,它们的别名分别是t0~t6。

x8~x9以及x18~x27寄存器的别名分别是s0~s11。如果函数调用过程中要使用这些寄存器,需要先保存到栈里。另外,s0寄存器可以用作栈帧指针(Frame Pointer,FP)。

x10~x17寄存器的别名分别为a0~a7,用于在调用函数时传递参数和返回结果。

除用于数据运算和存储之外,通用寄存器还可以在函数调用过程中起到特殊作用。RISC-V体系结构的函数调用规范对此有约定,详见第4章。

1.3.2 系统寄存器

除上面介绍的通用寄存器之外,RISC-V体系结构还定义了很多的系统控制和状态寄存器(Control and Status Register,CSR),通过访问和设置这些系统寄存器可以完成对处理器不同的功能配置。

RISC-V体系结构支持以下3类系统寄存器。

M模式的系统寄存器。

S模式的系统寄存器。

U模式的系统寄存器。

程序可以通过CSR指令(如CSRRW指令)访问系统寄存器,详见3.11节。

CSR指令编码中预留了12位编码空间(csr[11:0])用来索引系统寄存器,如图1.6所示,即指令编码中的Bit[31:20]。

图1.6 CSR指令编码

RISC-V体系结构对12位CSR编码空间做了约定。其中,Bit[11:10]用来表示系统寄存器的读写属性,0b11表示只读,其余表示可读可写。Bit[9:8]表示允许访问该系统寄存器的处理器模式,0b00表示U模式,0b01表示S模式,0b10表示HS/VS模式,0b11表示M模式。剩余的位用作寄存器的索引。使用CSR地址的最高位对默认的访问权限进行编码,简化了硬件中的错误检查流程,并提供了更大的CSR编码空间,但限制了CSR到地址空间的映射。CSR地址空间映射如表1.3所示。

表1.3 CSR地址空间映射

注:① CSR编码中的“X”可以是0或1。

下面的访问行为会触发非法指令异常。

访问不存在或者没有实现的系统寄存器。

尝试写入只具有只读属性的系统寄存器。

在低级别的处理器模式下访问高级别的处理器模式的系统寄存器,例如,在S模式下访问M模式的系统寄存器。

1.3.3 U模式下的系统寄存器

U模式下的系统寄存器如表1.4所示。

表1.4 U模式下的系统寄存器

RDCYCLE伪指令读取cycle系统寄存器的值,返回处理器内核执行的时钟周期数。注意,它返回的是物理处理器内核(而不是处理器硬件线程)的时钟周期数。RDCYCLE伪指令的主要作用是进行性能监控和调优。

RDTIME伪指令读取time系统寄存器的值,获取系统的实际时间。系统每次启动时读取互补金属-氧化物-半导体(Complementary Metal-Oxide-Semiconductor,CMOS)上的RTC(Real Time Clock,实时时钟)计数,时钟中断时更新该计数。

RDINSTRET伪指令读取instret系统寄存器的值,返回处理器执行线程已经执行的指令数量。

hpmcounter3~hpmcounter31为29个用于系统性能监测的寄存器,这些计数器的计数记录平台的事件,并通过额外的特权寄存器进行配置。

RDCYCLE、RDTIME以及RDINSTRET伪指令在某些处理器上是通过SBI固件进行软件模拟实现的。例如,在U模式下使用RDTIME伪指令会触发非法指令异常,处理器将陷入M模式,M模式下的异常处理程序会读取time系统寄存器的值,然后返回U模式。

1.3.4 S模式下的系统寄存器

S模式下的系统寄存器如表1.5所示。

表1.5 S模式下的系统寄存器

接下来,介绍表1.5中的部分寄存器。

1.sstatus寄存器

sstatus寄存器表示S模式下的处理器状态,如图1.7所示。

图1.7 sstatus寄存器

图1.7中的WPRI表示这些字段是保留的,软件应该忽略从这些字段读取的值,并且在向同一寄存器的其他字段写入值时,应该保留这些字段中保存的值。通常,为了向前兼容,硬件会将这些字段设为只读的零值。sstatus寄存器中其他字段的含义如表1.6所示。

表1.6 sstatus寄存器中其他字段的含义

2.sie寄存器

sie寄存器用来使能和关闭S模式下的中断,详见第8章。

3.stvec寄存器

stvec寄存器用来在S模式下配置异常向量表入口地址和异常访问模式,详见第8章。

4.scounteren寄存器

scounteren寄存器是一个32位寄存器,用来使能U模式下的硬件性能监测和计数寄存器,如图1.8所示。

图1.8 scounteren寄存器

各字段的含义如下。

CY字段:使能U模式下的cycle系统寄存器。

TM字段:使能U模式下的time系统寄存器。

IR字段:使能U模式下的instret系统寄存器。

HPM3~HPM31字段:使能U模式下的hpmcounter3~hpmcounter31系统寄存器。

5.sscratch寄存器

sscratch寄存器是一个专门给S模式使用的临时寄存器,当处理器运行在U模式下时,它用来保存S模式下的进程控制块(例如,BenOS中的task_struct数据结构)的指针。

在操作系统中,当一个进程从S模式返回U模式时,通常使用sscratch寄存器来保存该进程的task_struct数据结构的指针。当该进程需要重新返回S模式时,读取sscratch寄存器即可得到task_struct数据结构。有人认为,进程可以在U模式下调度。这是不正确的,一个进程要调度,必须返回S模式下的调度器里(见17.3.8小节)。

6.sepc寄存器

当处理器陷入S模式时,会把中断现场或触发异常时的指令对应的虚拟地址写入sepc寄存器中。

7.scause寄存器

scause寄存器用于保存S模式下的异常原因,详见第8章。

8.stval寄存器

当处理器陷入S模式时,stval寄存器会记录发生异常的虚拟地址。

9.sip寄存器

sip寄存器用来表示哪些中断处于待定(pending)状态,详见第8章。

10.satp寄存器

satp寄存器用于地址转换,详见第10章。

1.3.5 M模式下的系统寄存器

M模式下的系统寄存器如表1.7所示。

表1.7 M模式下的系统寄存器

接下来,介绍表1.7中常用的寄存器。

1.misa寄存器

misa寄存器用来表示处理器支持的指令集体系结构和扩展,如图1.9所示。

图1.9 misa寄存器

字段的含义如下。

Extensions:表示处理器支持的扩展,如表1.8所示。

MXL:表示M模式下寄存器的长度。

1:表示32位。

2:表示64位。

3:表示128位。

表1.8 处理器支持的扩展

2.mvendorid寄存器

mvendorid寄存器是一个32位只读寄存器,遵循JEDEC制造商ID规范。

3.marchid寄存器

marchid寄存器用于返回处理器体系结构ID,该ID由RISC-V基金会统一分配。

4.mimpid寄存器

mimpid寄存器用于返回处理器的实现版本ID。

5.mhartid寄存器

mhartid寄存器用于返回处理器硬件线程ID。多核处理器中硬件线程的ID不一定是连续编号的,但至少有一个硬件线程的ID为0,同时需保证运行环境中硬件线程的ID互不相同。

6.mstatus寄存器

mstatus寄存器表示M模式下的处理器状态,如图1.10所示。

图1.10 mstatus寄存器

mstatus寄存器中部分字段的含义如表1.9所示。

表1.9 mstatus寄存器中部分字段的含义

7.medeleg寄存器

medeleg寄存器用于把异常委托到S模式下处理,详见第8章。

8.mideleg寄存器

mideleg寄存器用于把中断委托到S模式下处理,详见第8章。

9.mie寄存器

mie寄存器用来使能和关闭M模式下的中断,详见第8章。

10.mtval寄存器

当处理器陷入M模式时,mtval寄存器记录发生异常的虚拟地址。

11.mcounteren寄存器

mcounteren寄存器是一个32位寄存器,用来使能S模式或者U模式下的硬件性能监测和计数寄存器,如图1.11所示。

图1.11 mcounteren寄存器

字段的含义如下。

CY字段:使能S模式或者U模式下的cycle系统寄存器。

TM字段:使能S模式或者U模式下的time系统寄存器。

IR字段:使能S模式或者U模式下的instret系统寄存器。

HPM3~HPM31字段:使能S模式或者U模式下的hpmcounter3~hpmcounter31系统寄存器。

12.mscratch寄存器

mscratch寄存器是一个专门给M模式使用的临时寄存器,当处理器运行在S模式或者U模式下时,它用来保存M模式中上下文数据结构的指针。例如,在MySBI固件中用来保存M模式下的栈指针( Stack Pointer,SP),在OpenSBI中用来保存M模式下的sbi_scratch数据结构。

13.mepc寄存器

当处理器陷入M模式时,会将中断或遇到异常的指令的虚拟地址写入mepc寄存器中。

14.mcause寄存器

mcause寄存器是M模式下的异常原因寄存器,详见第8章。

15.mip寄存器

mip寄存器用来表示哪些中断处于待定状态,详见第8章。