跳到主要内容

RISC-V:整数寄存器、ABI、CSR 与 trap 处理

RISC-V 基础整数 ISA 定义 x0–x31、程序计数器和整数指令;ABI 规定寄存器在函数调用中的用途;特权架构定义 CSR、特权级、中断、异常和地址转换。三部分解决的问题不同:ISA 约束指令的硬件行为,ABI 约束不同目标文件之间的调用兼容性,特权架构约束操作系统与处理器之间的控制接口。

32 个整数寄存器​

RV32 与 RV64 均有 32 个整数寄存器。每个寄存器宽度等于 XLEN,即 RV32 为 32 位,RV64 为 64 位。x0 的读值恒为零;其余寄存器没有硬件固定用途,表中的名称和保存规则来自标准 psABI。

物理寄存器ABI 名称标准用途跨函数调用保留详细说明
x0zero常数零固定值读值恒为 0,写入结果被丢弃;常用于生成伪指令和不保留 CSR 旧值。
x1ra返回地址否jal/jalr 通常写入返回地址;非叶子函数若继续调用其他函数,必须先保存原值。
x2sp栈指针是栈向低地址增长;标准 ABI 要求函数入口处按 16 字节对齐,并在函数执行期间维持规定对齐。
x3gp全局指针固定用途工具链可用它访问小数据区;标准 ABI 将其列为不可分配寄存器,普通函数不应修改。
x4tp线程指针固定用途指向线程局部存储或运行时线程结构;信号处理与运行库可能直接读取,普通函数不应修改。
x5t0临时寄存器 0否调用者保存;也常用于 trap 入口的临时交换。
x6t1临时寄存器 1否调用者保存。
x7t2临时寄存器 2否调用者保存。
x8s0 / fp保存寄存器 0 / 帧指针是使用帧指针时必须选用 x8;无帧指针时仍按 s0 的保存规则处理。
x9s1保存寄存器 1是被调用者使用后必须恢复入口值。
x10a0参数 0 / 返回值 0否第一个整数参数;也是第一个整数返回值。
x11a1参数 1 / 返回值 1否第二个整数参数;也是第二个整数返回值,可与 a0 共同返回宽值。
x12a2参数 2否第三个整数参数。
x13a3参数 3否第四个整数参数。
x14a4参数 4否第五个整数参数。
x15a5参数 5否第六个整数参数。
x16a6参数 6否第七个整数参数。
x17a7参数 7 / 系统调用号否第八个整数参数;许多执行环境用它传递系统调用号,但具体定义由运行环境规定。
x18s2保存寄存器 2是被调用者保存。
x19s3保存寄存器 3是被调用者保存。
x20s4保存寄存器 4是被调用者保存。
x21s5保存寄存器 5是被调用者保存。
x22s6保存寄存器 6是被调用者保存。
x23s7保存寄存器 7是被调用者保存。
x24s8保存寄存器 8是被调用者保存。
x25s9保存寄存器 9是被调用者保存。
x26s10保存寄存器 10是被调用者保存。
x27s11保存寄存器 11是被调用者保存。
x28t3临时寄存器 3否调用者保存。
x29t4临时寄存器 4否调用者保存。
x30t5临时寄存器 5否调用者保存。
x31t6临时寄存器 6否调用者保存。

“调用者保存”表示调用指令执行前,调用方必须保存调用后仍需使用的值;“被调用者保存”表示被调用函数若修改寄存器,必须在返回前恢复入口值。gp 与 tp 属于固定用途寄存器,不应按普通临时寄存器分配。

参数、返回值与栈帧​

标准整数调用约定提供八个参数寄存器 a0–a7。宽度不超过 XLEN 的标量优先使用一个参数寄存器;寄存器不足时,后续参数按 ABI 规则放入栈中。a0 和 a1 兼作返回值寄存器。栈向低地址增长,函数入口的 sp 必须按 128 位对齐。

帧指针不是强制状态。编译器启用帧指针时,s0/fp 指向当前栈帧的固定位置,使调试器和栈展开器不依赖函数执行期间变化的 sp。叶子函数若不保存寄存器且不分配局部对象,可以不建立栈帧。

下例是一个 RV64 非叶子函数的基本栈帧。实际帧大小由局部对象、保存寄存器和栈上传参共同决定。

sum_then_scale:
addi sp, sp, -32
sd ra, 24(sp)
sd s0, 16(sp)
addi s0, sp, 32

call sum2 # a0/a1 传参,a0 返回结果
slli a0, a0, 1

ld s0, 16(sp)
ld ra, 24(sp)
addi sp, sp, 32
ret

CSR 地址与访问权限​

CSR 使用 12 位地址,因此指令编码可表示 4096 个 CSR 地址。地址高四位同时编码默认读写属性和最低访问特权级:csr[11:10] 为 11 时表示只读,csr[9:8] 表示 U、S、H/VS 或 M 级。更高特权级通常可以访问低特权级 CSR,但实现仍可依据特权扩展截获部分访问。

CSR 地址空间的完整分类​

最低特权级地址范围属性标准或自定义用途
U0x000–0x0FF读写标准 U 级 CSR
U0x400–0x4FF读写标准 U 级 CSR
U0x800–0x8FF读写自定义 U 级 CSR
U0xC00–0xC7F只读标准 U 级 CSR
U0xC80–0xCBF只读标准 U 级 CSR,常用于 RV32 高 32 位计数器
U0xCC0–0xCFF只读自定义 U 级 CSR
S0x100–0x1FF读写标准 S 级 CSR
S0x500–0x5BF读写标准 S 级 CSR
S0x5C0–0x5FF读写自定义 S 级 CSR
S0x900–0x9BF读写标准 S 级 CSR
S0x9C0–0x9FF读写自定义 S 级 CSR
S0xD00–0xDBF只读标准 S 级 CSR
S0xDC0–0xDFF只读自定义 S 级 CSR
H/VS0x200–0x2FF读写标准虚拟化 CSR
H/VS0x600–0x6BF读写标准虚拟化 CSR
H/VS0x6C0–0x6FF读写自定义虚拟化 CSR
H/VS0xA00–0xABF读写标准虚拟化 CSR
H/VS0xAC0–0xAFF读写自定义虚拟化 CSR
H/VS0xE00–0xEBF只读标准虚拟化 CSR
H/VS0xEC0–0xEFF只读自定义虚拟化 CSR
M0x300–0x3FF读写标准 M 级 CSR
M0x700–0x79F读写标准 M 级 CSR
M0x7A0–0x7AF读写M 级可访问的调试触发器 CSR
Debug0x7B0–0x7BF读写仅 Debug Mode 可见
M0x7C0–0x7FF读写自定义 M 级 CSR
M0xB00–0xBBF读写标准 M 级计数器 CSR
M0xBC0–0xBFF读写自定义 M 级 CSR
M0xF00–0xFBF只读标准 M 级信息 CSR
M0xFC0–0xFFF只读自定义 M 级 CSR

访问不存在的 CSR、以不足的特权级访问 CSR,或写入只读 CSR,通常产生非法指令异常。表中的“标准”只表示地址由规范分配,不表示所有处理器都必须实现对应扩展。

六条 CSR 访问指令​

Zicsr 定义三种寄存器形式和三种立即数形式。每条指令对单个 CSR 执行原子读改写,软件不会观察到指令内部的中间值。

指令读操作写操作省略读或写的条件
csrrw rd, csr, rs1旧值写入 rd将 rs1 完整写入 CSRrd=x0 时不读取 CSR;写操作仍执行。
csrrs rd, csr, rs1旧值写入 rd将 CSR 与 rs1 按位 OR 后写回rs1=x0 时只读,不执行写操作。
csrrc rd, csr, rs1旧值写入 rd将 rs1 中为 1 的对应 CSR 位清零rs1=x0 时只读,不执行写操作。
csrrwi rd, csr, uimm旧值写入 rd将 5 位零扩展立即数完整写入 CSRrd=x0 时不读取 CSR。
csrrsi rd, csr, uimm旧值写入 rd按立即数掩码置位uimm=0 时只读。
csrrci rd, csr, uimm旧值写入 rd按立即数掩码清零uimm=0 时只读。

汇编器提供 csrr、csrw、csrs、csrc 等伪指令。例如 csrr a0, mstatus 通常展开为 csrrs a0, mstatus, x0。

CSR 字段的写入类型​

类型含义软件处理方式
WPRI保留写值、读时忽略修改同一 CSR 的其他字段时,应保留这些位的原值。未实现字段通常读为 0。
WLRL只允许写入有限的合法编码软件只写规范列出的合法值;读回值一定属于合法集合。
WARL可写任意值、读回合法值实现可把不支持的写值转换成某个合法值;软件应写入后读回以确认实际设置。

当前规范分配的 U 级 CSR​

下表覆盖当前特权规范列出的 U 级 CSR。带扩展名称的寄存器只在对应扩展存在时实现。

地址名称权限所属功能说明
0x001fflagsURWF/D/Q浮点累积异常标志。
0x002frmURWF/D/Q浮点动态舍入模式。
0x003fcsrURWF/D/Qfrm 与 fflags 的组合视图。
0x008vstartURWV向量指令开始处理的元素序号。
0x009vxsatURWV向量定点饱和累积标志。
0x00AvxrmURWV向量定点舍入模式。
0x00FvcsrURWVvxrm 与 vxsat 的组合视图。
0x011sspURWZicfiss影子栈指针。
0x015seedURW熵源扩展密码随机数发生器的种子接口。
0x017jvtURWZcmt表跳转基址与控制。
0xC00cycleUROZicntr周期计数器的低 XLEN 位。
0xC01timeUROZicntr实时时钟计数值的低 XLEN 位。
0xC02instretUROZicntr已退休指令数的低 XLEN 位。
0xC03–0xC1Fhpmcounter3–hpmcounter31UROZihpm性能监测计数器。
0xC20vlUROV当前向量长度。
0xC21vtypeUROV当前向量元素宽度、寄存器组和非活动元素策略。
0xC22vlenbUROV单个向量寄存器的字节数。
0xC80cyclehUROZicntr,RV32cycle 的高 32 位。
0xC81timehUROZicntr,RV32time 的高 32 位。
0xC82instrethUROZicntr,RV32instret 的高 32 位。
0xC83–0xC9Fhpmcounter3h–hpmcounter31hUROZihpm,RV32性能监测计数器的高 32 位。

当前规范分配的 S 级 CSR​

地址名称权限功能分类说明
0x100sstatusSRWtrap 配置mstatus 中 S 级可见字段的受限视图。
0x104sieSRWtrap 配置S 级中断使能。
0x105stvecSRWtrap 配置S 级 trap 入口基址与模式。
0x106scounterenSRW计数器控制 U 级是否可读取各计数器。
0x10AsenvcfgSRW环境配置S 级执行环境功能控制。
0x10C–0x10Fsstateen0–sstateen3SRW状态使能控制低特权级对扩展状态的访问。
0x120scountinhibitSRW计数器S 级计数器停止控制。
0x140sscratchSRWtrap 处理S 级 trap handler 临时寄存器。
0x141sepcSRWtrap 处理进入 S 级 trap 前的 PC。
0x142scauseSRWtrap 处理S 级 trap 的中断标志与原因码。
0x143stvalSRWtrap 处理与 trap 原因相关的附加值。
0x144sipSRWtrap 处理S 级中断挂起状态。
0x14DstimecmpSRWSstcS 级定时比较值。
0x14EsctrctlSRW控制转移记录S 级控制转移记录控制。
0x14FsctrstatusSRW控制转移记录S 级控制转移记录状态。
0x150siselectSRWSmcsrind/SscsrindS 级间接 CSR 选择。
0x151–0x153sireg–sireg3SRWSmcsrind/SscsrindS 级间接 CSR 别名 1–3。
0x155–0x157sireg4–sireg6SRWSmcsrind/SscsrindS 级间接 CSR 别名 4–6。
0x15DstimecmphSRWSstc,RV32stimecmp 的高 32 位。
0x15FsctrdepthSRW控制转移记录S 级控制转移记录深度。
0x180satpSRW地址转换地址转换模式、地址空间标识符和根页表物理页号。
0x181srmcfgSRW资源管理S 级资源管理配置。
0x5A8scontextSRW调试/跟踪S 级上下文标识。
0xDA0scountovfSRO计数器S 级可见的计数器溢出状态。

当前规范分配的 M 级 CSR​

M-mode 是唯一强制实现的特权级,但表中仍有多个 CSR 依赖可选扩展。实现不支持某个扩展时,对应地址不必存在。

地址名称权限功能分类说明
0x300mstatusMRWtrap 配置全局中断、此前特权级、扩展上下文和内存访问控制。
0x301misaMRW/WARLISA 配置MXL 与已实现扩展位;部分实现可只读。
0x302medelegMRWtrap 委托将指定同步异常交给 S-mode。
0x303midelegMRWtrap 委托将指定中断交给 S-mode。
0x304mieMRWtrap 配置M/S 级各中断源使能位。
0x305mtvecMRWtrap 配置M 级 trap 入口基址与模式。
0x306mcounterenMRW计数器控制 S/U 级能否访问硬件计数器。
0x30AmenvcfgMRW环境配置M 级对低特权级执行环境的控制。
0x30C–0x30Fmstateen0–mstateen3MRW状态使能控制低特权级对扩展状态的访问。
0x310mstatushMRWtrap 配置,RV32mstatus 的附加高位字段。
0x312medeleghMRWtrap 委托,RV32medeleg 的高 32 位。
0x31AmenvcfghMRW环境配置,RV32menvcfg 的高 32 位。
0x31C–0x31Fmstateen0h–mstateen3hMRW状态使能,RV32mstateen* 的高 32 位。
0x320mcountinhibitMRW计数器按位停止 mcycle、minstret 与性能计数器。
0x321mcyclecfgMRWSmcntrpmf周期计数器过滤配置。
0x322minstretcfgMRWSmcntrpmf指令退休计数器过滤配置。
0x323–0x33Fmhpmevent3–mhpmevent31MRWZihpm选择性能计数器统计的事件。
0x340mscratchMRWtrap 处理M 级 trap handler 临时寄存器。
0x341mepcMRWtrap 处理进入 M 级 trap 前的 PC。
0x342mcauseMRWtrap 处理M 级 trap 的中断标志与原因码。
0x343mtvalMRWtrap 处理错误地址、非法指令位或其他原因相关值。
0x344mipMRWtrap 处理M/S 级各中断源挂起状态。
0x34AmtinstMRWH 扩展转换后的 trap 指令信息。
0x34Bmtval2MRWH 扩展第二个 trap 附加值。
0x34EmctrctlMRW控制转移记录M 级控制转移记录控制。
0x350miselectMRWSmcsrindM 级间接 CSR 选择。
0x351–0x353mireg–mireg3MRWSmcsrindM 级间接 CSR 别名 1–3。
0x355–0x357mireg4–mireg6MRWSmcsrindM 级间接 CSR 别名 4–6。
0x3A0–0x3AFpmpcfg0–pmpcfg15MRWPMPPMP 条目的权限和地址匹配方式;部分奇数编号仅用于 RV32。
0x3B0–0x3EFpmpaddr0–pmpaddr63MRWPMPPMP 地址寄存器。实际条目数量由实现决定。
0x721–0x73Fmcyclecfgh、minstretcfgh、mhpmevent3h–mhpmevent31hMRWSmcntrpmf,RV32计数器过滤和事件选择的高 32 位。
0x740mnscratchMRWSmrnmi可恢复 NMI 临时寄存器。
0x741mnepcMRWSmrnmi可恢复 NMI 返回 PC。
0x742mncauseMRWSmrnmi可恢复 NMI 原因。
0x744mnstatusMRWSmrnmi可恢复 NMI 状态。
0x747mseccfgMRWSmepmpM 级安全配置。
0x757mseccfghMRWSmepmp,RV32mseccfg 的高 32 位。
0x7A0tselectMRW调试触发器选择当前触发器。
0x7A1–0x7A3tdata1–tdata3MRW调试触发器触发器配置与比较数据。
0x7A8mcontextMRW调试/跟踪M 级上下文标识。
0x7B0dcsrDRWDebug Mode调试控制和状态。M-mode 普通访问不可见。
0x7B1dpcDRWDebug Mode调试返回 PC。
0x7B2–0x7B3dscratch0–dscratch1DRWDebug Mode调试临时寄存器。
0xB00mcycleMRW计数器机器周期计数。
0xB02minstretMRW计数器已退休指令计数。
0xB03–0xB1Fmhpmcounter3–mhpmcounter31MRWZihpmM 级性能监测计数器。
0xB80mcyclehMRW计数器,RV32mcycle 的高 32 位。
0xB82minstrethMRW计数器,RV32minstret 的高 32 位。
0xB83–0xB9Fmhpmcounter3h–mhpmcounter31hMRWZihpm,RV32M 级性能计数器的高 32 位。
0xF11mvendoridMRO实现信息JEDEC 厂商编号。允许为 0。
0xF12marchidMRO实现信息架构实现编号。
0xF13mimpidMRO实现信息实现版本编号。
0xF14mhartidMRO实现信息当前硬件线程 ID。系统内必须唯一。
0xF15mconfigptrMRO实现信息配置数据结构指针;为 0 表示未提供。

H 扩展还定义 hstatus、hedeleg、hideleg、hie、hgatp、htval、htinst、hgeip、vsstatus、vstvec、vsepc、vscause、vsatp 等虚拟化 CSR。它们只在实现 H 扩展时存在,不属于基础 M/S trap 处理的必需状态。

与 trap 直接相关的字段​

mstatus 的主要控制字段​

字段位位置作用
SIE[1]S-mode 全局中断使能。
MIE[3]M-mode 全局中断使能。
SPIE[5]进入 S 级 trap 前保存的 SIE。
MPIE[7]进入 M 级 trap 前保存的 MIE。
SPP[8]进入 S 级 trap 前的特权级。
VS[10:9]向量状态:Off、Initial、Clean、Dirty。
MPP[12:11]进入 M 级 trap 前的特权级。
FS[14:13]浮点状态:Off、Initial、Clean、Dirty。
XS[16:15]其他扩展状态的摘要。通常只读。
MPRV[17]M-mode 数据访问按 MPP 指定的特权级执行权限检查。
SUM[18]S-mode 是否允许访问 U 级页中的数据。
MXR[19]是否允许从只可执行页读取数据。
TVM[20]在 S-mode 截获 satp 访问和 SFENCE.VMA。
TW[21]限制低特权级执行 WFI。
TSR[22]在 S-mode 截获 SRET。
SD[XLEN-1]FS、VS 或 XS 为 Dirty 时置 1,供上下文保存代码快速判断。

trap 进入 M-mode 时,硬件执行等效状态更新:MPIE ← MIE、MIE ← 0、MPP ← trap 前特权级。执行 mret 时,MIE ← MPIE,当前特权级恢复为 MPP,并按规范重置返回相关字段。

mtvec、mepc、mcause 与 mtval​

CSR关键字段处理含义
mtvecBASE = mtvec[XLEN-1:2],MODE = mtvec[1:0]MODE=0 时所有 trap 跳到 BASE;MODE=1 时同步异常跳到 BASE,中断跳到 BASE + 4 × cause。
mepc可执行地址保存被中断指令或产生异常指令的 PC。最低不可表示位读为 0。
mcauseInterrupt = mcause[XLEN-1],其余位为原因码最高位区分异步中断与同步异常。
mtval原因相关值地址异常时通常保存错误地址;非法指令时可保存指令位;没有附加信息时为 0。

mepc 是否需要增加 2 或 4 取决于异常类型和指令长度。中断返回通常使用原 mepc;ecall、断点或软件已处理的非法指令需要由 handler 按预期处理行为决定后续 PC,不能统一执行固定增量。

mie 与 mip 的标准中断位​

位mie 名称mip 名称中断来源
1SSIESSIPS 级软件中断。
3MSIEMSIPM 级软件中断。
5STIESTIPS 级定时器中断。
7MTIEMTIPM 级定时器中断。
9SEIESEIPS 级外部中断。
11MEIEMEIPM 级外部中断。
13LCOFIELCOFIPSscofpmf 本地计数器溢出中断。
16 及以上平台或扩展定义平台或扩展定义实现和扩展规定的本地中断。

中断进入 M-mode 需要同时满足挂起位、使能位、委托设置、全局中断状态和特权级规则。mip 某些位由硬件只读驱动,某些位允许软件写入;必须按每个位的规范实现,而不能把整个 CSR 视为普通读写寄存器。

M-mode trap 的硬件与软件分工​

发生未委托给低特权级的 trap 时,硬件完成以下操作:

  1. 将当前 PC 写入 mepc。
  2. 将中断标志和原因码写入 mcause。
  3. 按原因向 mtval 写入附加信息或零。
  4. 更新 mstatus.MPIE、MIE 与 MPP。
  5. 按 mtvec.MODE 计算入口地址并开始取指。

硬件不会自动保存 32 个整数寄存器。软件入口必须先取得可用的临时寄存器和栈,再保存后续处理代码会修改的上下文。mscratch 常保存当前 hart 的 trap 栈或控制块指针,入口用 csrrw 与某个整数寄存器交换。

# RV64 示意:只展示入口结构,不是完整操作系统实现
trap_entry:
csrrw t0, mscratch, t0
sd sp, 0(t0) # 保存被中断上下文的 sp
ld sp, 8(t0) # 装载该 hart 的 trap 栈

addi sp, sp, -32
sd ra, 24(sp)
sd t1, 16(sp)
csrr t1, mcause
sd t1, 8(sp)
csrr t1, mepc
sd t1, 0(sp)

call handle_trap

ld t1, 0(sp)
csrw mepc, t1
ld t1, 16(sp)
ld ra, 24(sp)
addi sp, sp, 32
mret

完整入口还要处理所有被修改的 GPR、嵌套 trap、每 hart 栈、RV32/RV64 宽度、浮点与向量上下文、地址转换状态以及返回前的中断恢复顺序。若 handler 调用遵循 C ABI 的函数,入口必须先把调用者保存寄存器中属于被中断程序的值保存到上下文结构,因为 C 函数可以修改这些寄存器。

RTL 实现中的关键规则​

  • CSR 解码同时检查地址是否存在、当前特权级、只读属性和扩展使能状态。
  • CSRRS/CSRRC 的源寄存器为 x0 时不产生写访问,这一点会影响只读 CSR 和写副作用判断。
  • WARL 字段需要确定合法化函数,并保证相同输入在同一实现上得到确定结果。
  • trap 写 CSR、普通 CSR 指令和返回指令可能在同一流水线阶段竞争写口;必须规定优先级并保证精确异常。
  • mepc、mtvec.BASE 与地址对齐受 IALIGN 及实现支持的指令长度影响。
  • mie/mip 中每个位的可写属性不同,外部中断输入与软件写操作不能简单合并成普通寄存器写使能。
  • FS、VS 和 SD 参与延迟上下文保存;浮点或向量状态发生写入时,应按规范更新 Dirty 状态。

参考:RISC-V psABI、CSR 地址与字段规范、Machine-Level ISA、Supervisor-Level ISA。