特权架构
RISC-V 特权架构定义了处理器的特权级别和相应的控制机制,用于支持操作系统和系统软件的实现。
特权级别
RISC-V 定义了四个特权级别:
| 级别 | 编码 | 名称 | 缩写 | 典型用途 |
|---|---|---|---|---|
| 0 | 00 | 用户模式 | U-mode | 应用程序 |
| 1 | 01 | 监督模式 | S-mode | 操作系统内核 |
| 2 | 10 | 虚拟监督模式 | HS-mode | 虚拟机监视器 |
| 3 | 11 | 机器模式 | M-mode | 固件/BIOS |
特权级别的作用
特权级别用于:
- 保护系统资源
- 隔离不同软件层
- 控制硬件访问权限
- 实现安全机制
特权指令
不同特权级别可以执行的指令不同:
机器模式专用指令
mret # 从机器模式异常返回
ecall # 环境调用(系统调用)
ebreak # 断点
监督模式专用指令
sret # 从监督模式异常返回
sfence.vma # 刷新 TLB
控制状态寄存器(CSR)
CSR 用于配置处理器行为和查询处理器状态。
CSR 地址编码
CSR 地址为 12 位,按照特权级别分组:
| 地址范围 | 权限 | 用途 |
|---|---|---|
| 0x000-0x3FF | 只读 | 用户级信息 |
| 0x400-0x7FF | 读写 | 用户级 |
| 0x800-0xBFF | 只读 | 监督级信息 |
| 0xC00-0xFFF | 读写 | 监督级 |
| 0xF00-0xFFF | 只读 | 机器级信息 |
| 0x300-0x3FF | 读写 | 机器级 |
机器模式 CSR
mstatus - 机器状态寄存器
位域:
[63] MBE - 机器模式大端
[34:33] UXL - 用户模式位宽(RV64)
[12:11] MPP - 之前的特权模式
[11] SPP - 之前的监督模式
[7] MPIE - 之前的中断使能
[5] SPIE - 之前的监督中断使能
[3] MIE - 机器模式中断使能
[1] SIE - 监督模式中断使能
[0] UIE - 用户模式中断使能
mtvec - 机器陷阱向量
[31:2] BASE - 处理程序基地址
[1:0] MODE - 向量模式
00 = 直接模式
01 = 向量模式
mepc - 机器异常程序计数器
保存发生异常时的 pc 值。
mcause - 机器异常原因
[31] Interrupt - 1 表示中断,0 表示异常
[30:0] Exception Code - 异常/中断编码
mtval - 机器陷阱值
保存异常的附加信息。
mie - 机器中断使能
[11] MEIE - 机器外部中断使能
[7] MTIE - 机器定时器中断使能
[3] MSIE - 机器软件中断使能
mip - 机器中断挂起
[11] MEIP - 机器外部中断挂起
[7] MTIP - 机器定时器中断挂起
[3] MSIP - 机器软件中断挂起
监督模式 CSR
sstatus - 监督状态寄存器
位域:
[34:33] UXL - 用户模式位宽(RV64)
[8] SPP - 之前的特权模式
[5] SPIE - 之前的中断使能
[1] SIE - 监督模式中断使能
stvec - 监督陷阱向量
[31:2] BASE - 处理程序基地址
[1:0] MODE - 向量模式
sepc - 监督异常程序计数器
scause - 监督异常原因
stval - 监督陷阱值
satp - 监督地址翻译和保护
[63:60] MODE - 地址翻译模式
0000 = 裸机模式(无翻译)
1000 = Sv39(39 位虚拟地址)
1001 = Sv48(48 位虚拟地址)
[59:44] ASID - 地址空间标识符
[43:0] PPN - 根页表物理页号
用户模式 CSR
cycle - 周期计数器
只读,记录处理器周期数。
time - 时间计数器
只读,记录实时时间。
instret - 指令计数器
只读,记录已完成的指令数。
CSR 访问指令
CSR 读写指令
csrrw rd, csr, rs1 # 读 CSR 到 rd,写 rs1 到 CSR
csrrs rd, csr, rs1 # 读 CSR 到 rd,设置 CSR 中 rs1 对应的位
csrrc rd, csr, rs1 # 读 CSR 到 rd,清除 CSR 中 rs1 对应的位
立即数版本
csrrwi rd, csr, imm # 读 CSR 到 rd,写立即数到 CSR
csrrsi rd, csr, imm # 读 CSR 到 rd,设置 CSR 中立即数对应的位
csrrci rd, csr, imm # 读 CSR 到 rd,清除 CSR 中立即数对应的位
常用伪指令
csrr rd, csr # 读 CSR
csrw csr, rs1 # 写 CSR
csrc csr, rs1 # 清除 CSR 位
csrs csr, rs1 # 设置 CSR 位
csrwi csr, imm # 写立即数到 CSR
特权模式切换
从用户模式进入更高特权模式
用户模式通过以下方式进入更高特权模式:
- 系统调用(ecall)
ecall # 触发环境调用异常
- 异常
- 非法指令
- 断点
- 加载/存储访问错误
- 中断
- 定时器中断
- 外部中断
- 软件中断
从高特权模式返回低特权模式
使用 mret 或 sret 指令返回:
mret # 从机器模式返回
sret # 从监督模式返回
模式切换示例
用户模式调用系统调用
# 用户模式代码
li a7, 64 # 系统调用号(write)
li a0, 1 # 文件描述符
la a1, buffer # 缓冲区地址
li a2, 100 # 长度
ecall # 进入机器模式
机器模式处理系统调用
# 异常处理程序
trap_handler:
csrr t0, mcause
li t1, 8 # 环境调用异常码
bne t0, t1, other_trap
# 处理系统调用
# a7 包含系统调用号
# a0-a5 包含参数
# ... 处理系统调用 ...
# 返回用户模式
csrr t0, mepc
addi t0, t0, 4 # 跳过 ecall 指令
csrw mepc, t0
mret
异常和中断
异常原因编码
| 编码 | 名称 | 描述 |
|---|---|---|
| 0 | Instruction address misaligned | 指令地址未对齐 |
| 1 | Instruction access fault | 指令访问错误 |
| 2 | Illegal instruction | 非法指令 |
| 3 | Breakpoint | 断点 |
| 4 | Load address misaligned | 加载地址未对齐 |
| 5 | Load access fault | 加载访问错误 |
| 6 | Store/AMO address misaligned | 存储地址未对齐 |
| 7 | Store/AMO access fault | 存储访问错误 |
| 8 | Environment call from U-mode | 用户模式环境调用 |
| 9 | Environment call from S-mode | 监督模式环境调用 |
| 11 | Environment call from M-mode | 机器模式环境调用 |
| 12 | Instruction page fault | 指令页错误 |
| 13 | Load page fault | 加载页错误 |
| 15 | Store/AMO page fault | 存储页错误 |
中断原因编码
| 编码 | 名称 | 描述 |
|---|---|---|
| 1 | Supervisor software interrupt | 监督软件中断 |
| 3 | Machine software interrupt | 机器软件中断 |
| 5 | Supervisor timer interrupt | 监督定时器中断 |
| 7 | Machine timer interrupt | 机器定时器中断 |
| 9 | Supervisor external interrupt | 监督外部中断 |
| 11 | Machine external interrupt | 机器外部中断 |
中断使能
# 使能机器模式中断
li t0, (1 << 3) | (1 << 7) | (1 << 11) # MSIE | MTIE | MEIE
csrs mie, t0
# 使能全局中断
csrs mstatus, (1 << 3) # MIE
异常处理流程
异常进入
- 保存当前 pc 到 mepc(或 sepc)
- 设置 mcause(或 scause)记录异常原因
- 设置 mtval(或 stval)记录附加信息
- 设置 mstatus(或 sstatus)的 MPP(或 SPP)字段记录之前特权模式
- 清除 MIE(或 SIE)禁用中断
- 跳转到 mtvec(或 stvec)指定的处理程序
异常返回
- 从 mepc(或 sepc)恢复 pc
- 从 mstatus(或 sstatus)恢复之前的特权模式和中断使能状态
- 执行 mret(或 sret)指令
异常处理程序示例
.section .text
.globl trap_handler
trap_handler:
# 保存上下文
addi sp, sp, -128
sw ra, 124(sp)
sw gp, 120(sp)
sw tp, 116(sp)
# ... 保存其他寄存器 ...
# 读取异常原因
csrr t0, mcause
# 判断是中断还是异常
blt t0, zero, handle_interrupt
# 处理异常
li t1, 2
beq t0, t1, handle_illegal_instruction
li t1, 8
beq t0, t1, handle_ecall_user
# ... 其他异常处理 ...
handle_interrupt:
# 处理中断
andi t1, t0, 0x7
li t2, 7
beq t1, t2, handle_timer_interrupt
# ... 其他中断处理 ...
trap_return:
# 恢复上下文
lw ra, 124(sp)
lw gp, 120(sp)
lw tp, 116(sp)
# ... 恢复其他寄存器 ...
addi sp, sp, 128
mret
委托机制
机器模式可以将异常和中断委托给监督模式处理。
medeleg / mideleg
medeleg - 机器异常委托
位 n = 1 表示异常 n 委托给监督模式处理
mideleg - 机器中断委托
位 n = 1 表示中断 n 委托给监督模式处理
委托示例
# 委托用户模式系统调用给监督模式
li t0, (1 << 8) # 异常 8:用户模式环境调用
csrw medeleg, t0
# 委托监督模式中断给监督模式
li t0, (1 << 1) | (1 << 5) | (1 << 9) # SSI | STI | SEI
csrw mideleg, t0
小结
本章介绍了 RISC-V 特权架构:
- 特权级别:用户模式、监督模式、机器模式
- CSR 寄存器:mstatus、mtvec、mepc、mcause 等
- CSR 访问指令:csrrw、csrrs、csrrc 等
- 模式切换:ecall、mret、sret
- 异常和中断:原因编码、处理流程
- 委托机制:medeleg、mideleg
特权架构是操作系统和系统软件开发的基础。下一章将详细介绍中断和异常处理。