2. RISC-V架构基础

OpenSBI 是运行在 RISC-V 平台上、位于 M 模式(Machine Mode)的固件层,它向上为 S 模式操作系统提供统一的引导与运行时服务,向下直接管理硬件与特权状态。要做好 OpenSBI 的平台适配,必须先建立对 RISC-V 架构五个关键维度的准确认知:指令集、特权级、CSR、中断异常模型以及 SBI 规范。本节围绕这五个维度展开,并说明它们如何共同决定 OpenSBI 的适配边界。

一、指令集:模块化的 ISA 设计

RISC-V 采用模块化指令集设计,基础整数指令集(RV32I / RV64I)是必选核心,其余以字母后缀表示扩展。OpenSBI 平台适配中最常打交道的扩展包括:M(乘除法)、A(原子操作)、F/D(单双精度浮点)、C(压缩指令)、以及特权架构相关的 CSR 访问指令。平台适配时,设备树中的 riscv,isa 属性会声明该 hart 支持的扩展集合,OpenSBI 据此决定是否启用某些优化路径。

需要特别注意的是,OpenSBI 自身运行在 M 模式,其代码通常只依赖基础整数指令集与 CSR 指令,避免依赖浮点扩展,因为浮点上下文在 M 模式下并不保证可用。平台适配中若发现某 hart 缺少 A 扩展,则涉及原子操作的同步原语需要改用其他实现方式。

二、特权级:M / S / U 三层模型

RISC-V 定义了三个标准特权级:M 模式(机器模式)、S 模式(监管者模式)、U 模式(用户模式)。M 模式拥有最高权限,可访问全部 CSR 与物理内存;S 模式运行操作系统内核;U 模式运行用户进程。OpenSBI 固定运行在 M 模式,操作系统运行在 S 模式,应用程序运行在 U 模式。

特权级之间的切换由 ecall 指令、mret / sret 返回指令以及异常/中断机制共同完成。OpenSBI 的核心职责之一,就是在 M 模式与 S 模式之间建立一条受控的调用通道,即 SBI 调用接口。下图展示了三个特权级与 OpenSBI、操作系统、应用之间的层次关系及调用方向。

RISC-V 特权级层次与 SBI 调用通道 M 模式(Machine Mode) OpenSBI 固件:平台初始化、CSR 管理、SBI 服务分发、中断委托 S 模式(Supervisor Mode) 操作系统内核:通过 ecall 发起 SBI 调用,处理已委托的 S 模式中断 U 模式(User Mode) 用户应用程序:通过系统调用进入 S 模式内核 ecall → SBI 调用 系统调用 mret / sret 返回 返回

三、CSR:控制与状态寄存器

CSR(Control and Status Register)是 RISC-V 特权架构的核心载体,通过 csrrw、csrrs、csrrc 等指令访问。CSR 地址空间按特权级划分:0x000–0x0FF 为 U 模式,0x100–0x1FF 为 S 模式,0x300–0x3FF 为 M 模式。OpenSBI 平台适配中必须重点掌握的 CSR 包括:

CSR 名称 地址 作用 OpenSBI 适配关注点
mstatus 0x300 M 模式状态:MIE、MPIE、MPP 等 保存/恢复 S 模式上下文
misa 0x301 ISA 扩展支持位图 判断 hart 能力,决定优化路径
mie / mip 0x304 / 0x344 M 模式中断使能与挂起 配置定时器、软件、外部中断
mtvec 0x305 M 模式异常向量基址 指向 OpenSBI 异常入口
medeleg / mideleg 0x302 / 0x303 异常/中断委托给 S 模式 决定哪些事件由 OS 直接处理
mhartid 0xF14 当前 hart 的硬件 ID 多核启动时区分 hart

四、中断与异常模型

RISC-V 将异常(同步)与中断(异步)统一建模:当事件发生时,硬件将当前 PC 保存到 mepc(或 sepc),将原因编码写入 mcause(或 scause),并跳转到 mtvec(或 stvec)指向的入口。OpenSBI 在 M 模式设置 mtvec 指向自己的异常处理入口,同时通过 medeleg / mideleg 将大部分 S 模式异常和中断委托给操作系统处理,仅保留必须由 M 模式介入的部分,例如定时器中断和 SBI 调用。

平台适配中一个常见误区是:把所有中断都委托给 S 模式,导致 OpenSBI 无法处理定时器事件,进而使 SBI 定时器服务失效。正确做法是保留 M 模式定时器中断,并在处理完成后通过 mip.STIP 向 S 模式注入软件定时器中断。

适配提示:在设备树中,riscv,ndev 与 interrupt-controller 节点描述了 PLIC 的中断源数量与布局。OpenSBI 初始化 PLIC 时,需要根据这些参数配置 M 模式与 S 模式的中断使能位,确保委托关系与硬件实际一致。

五、SBI 规范概览

SBI(Supervisor Binary Interface)是 OpenSBI 向上暴露的标准化接口,定义了 S 模式软件如何请求 M 模式固件服务。SBI 调用通过 ecall 指令发起,使用 a7 寄存器传递扩展 ID(EID),a6 传递功能 ID(FID),参数放在 a0–a5,返回值放在 a0 与 a1。

// SBI 调用示例:获取 SBI 规范版本
// a7 = 0x10 (BASE Extension), a6 = 0 (get_spec_version)
register unsigned long a7 asm("a7") = 0x10;
register unsigned long a6 asm("a6") = 0;
register unsigned long a0 asm("a0");
asm volatile("ecall" : "=r"(a0) : "r"(a7), "r"(a6) : "memory");
// a0 返回版本号,a1 返回实现 ID

SBI 规范当前主流版本为 v0.3 与 v1.0。v1.0 引入了更清晰的错误码与扩展机制,OpenSBI 同时兼容两者。平台适配时需要关注的核心扩展包括:BASE(基础查询)、TIME(定时器)、IPI(核间中断)、RFENCE(远程栅栏)、HSM(hart 状态管理)、SRST(系统复位)以及 PMU(性能监控)。

常见误区:误以为 SBI 调用可以直接访问硬件寄存器。实际上 SBI 调用必须经过 M 模式固件转发,S 模式无法直接操作 M 模式 CSR。平台适配中若发现 OS 直接读写 mtime 等 M 模式资源,说明委托配置或 SBI 服务实现存在问题。

六、五个维度的协同关系

指令集决定可用指令与扩展能力,特权级决定代码运行位置与权限边界,CSR 是特权级之间传递状态与控制信息的载体,中断异常模型定义了事件如何跨特权级流动,SBI 规范则把这些机制封装成操作系统可调用的稳定接口。OpenSBI 平台适配的本质,就是围绕这五个维度,把具体硬件平台的差异(hart 数量、中断控制器、定时器、内存布局)映射到统一的 SBI 服务语义上。