3. OpenSBI概述
OpenSBI 是 RISC-V 平台上最主流的开源 SBI(Supervisor Binary Interface)实现,运行在 M 模式(Machine Mode),为 S 模式操作系统提供统一的运行时服务。理解 OpenSBI 的项目结构、启动流程、固件类型和核心组件,是进行平台适配工程的第一步。本节从工程视角梳理 OpenSBI 的整体骨架,帮助读者建立“代码在哪里、启动怎么走、固件怎么选、组件怎么协作”的完整认知。
一、项目结构:从目录看职责划分
OpenSBI 源码仓库的目录组织高度模块化,每个目录对应一类明确职责。掌握目录结构,能快速定位平台适配时需要修改的文件。
| 目录/文件 | 职责说明 | 平台适配关注点 |
|---|---|---|
| firmware/ | 三种固件类型的入口实现:FW_DYNAMIC、FW_JUMP、FW_PAYLOAD | 选择并配置固件类型 |
| lib/sbi/ | SBI 核心服务实现,如 ecall 分发、IPI、定时器、RFENCE | 一般无需修改 |
| lib/utils/ | 通用工具:设备树解析、串口、IRQ、复位、系统挂起 | 按需扩展驱动 |
| platform/ | 具体平台支持,如 generic、kendryte、sifive、thead | 新增平台目录与 platform.c |
| include/ | 公共头文件,含 sbi 接口、平台配置宏 | 定义平台常量 |
| docs/ | 文档,含 firmware、platform、library 说明 | 查阅接口约定 |
| Makefile / Kconfig | 构建系统与配置项 | 添加平台编译目标 |
其中 platform/ 是平台适配的核心战场。每个平台通常包含 platform.c、config.mk、objects.mk 以及可选的 Kconfig,用于描述内存布局、时钟频率、串口地址、中断控制器等硬件参数。
二、启动流程:从复位向量到 S 模式交接
OpenSBI 的启动流程可以概括为“冷启动初始化 → 平台初始化 → 核心服务注册 → 跳转下一阶段”。下图展示了从复位到交接给 S 模式的关键路径与组件关系。
启动流程中的关键函数调用链如下:
_start
└─ sbi_init
├─ sbi_platform_early_init // 平台早期初始化
├─ sbi_hart_init // HART 级初始化
├─ sbi_console_init // 串口控制台
├─ sbi_irqchip_init // 中断控制器
├─ sbi_ipi_init // 核间中断
├─ sbi_timer_init // 定时器
└─ sbi_hsm_init // HSM 状态管理
└─ sbi_hart_switch_mode // 切换到 S 模式
冷启动时,OpenSBI 完成全部初始化并跳转下一阶段;热启动(secondary hart)则通过 HSM 机制等待主核唤醒,避免重复初始化全局资源。
三、固件类型:三种形态的适用场景
OpenSBI 提供三种固件类型,本质区别在于“下一阶段镜像从哪里来、跳转地址如何确定”。
- FW_DYNAMIC:最灵活。OpenSBI 不关心下一阶段是谁,由上一级固件(如 U-Boot SPL)在跳转前填充
fw_dynamic_info结构体,传入next_addr、next_mode和options。适合多级启动链。 - FW_JUMP:最简单。编译期通过
FW_JUMP_ADDR指定固定跳转地址,OpenSBI 初始化完成后直接跳转。适合地址固定的场景,如某些 SoC 的 BootROM 直接加载。 - FW_PAYLOAD:最自包含。将下一阶段镜像(如 Linux 内核、U-Boot)作为 payload 内嵌到 OpenSBI 二进制中,通过
FW_PAYLOAD_PATH指定。适合单镜像直接引导。
四、核心组件:SBI 服务与平台抽象
OpenSBI 的核心组件可分为“SBI 服务层”和“平台抽象层”两大部分。
SBI 服务层实现标准 SBI 接口,通过 ecall 指令从 S 模式陷入 M 模式后分发处理。主要服务包括:
- TIME:定时器设置与读取,对应
sbi_set_timer。 - IPI:核间中断发送,对应
sbi_send_ipi。 - RFENCE:远程栅栏,对应
sbi_remote_fence_i等。 - HSM:HART 状态管理,对应
sbi_hart_start、sbi_hart_stop。 - SRST:系统复位,对应
sbi_system_reset。 - PMU:性能监控单元访问。
平台抽象层通过 struct sbi_platform 描述硬件差异,关键字段包括:
struct sbi_platform {
const char *name;
unsigned long features;
u32 hart_count;
u32 hart_index2id[];
const struct sbi_platform_operations *platform_ops;
const struct sbi_hart_operations *hart_ops;
const struct sbi_ipi_operations *ipi_ops;
const struct sbi_timer_operations *timer_ops;
const struct sbi_console_operations *console_ops;
const struct sbi_system_reset_operations *reset_ops;
};
平台适配的本质,就是实现这些 operations 结构体中的回调函数,把具体硬件的串口、定时器、中断控制器、复位控制器接入 OpenSBI 的通用框架。
五、常见误区与复盘
platform/ 下新增目录并实现 operations 回调,核心库无需改动。
复盘平台适配流程时,建议按“确认固件类型 → 核对内存布局 → 实现平台 operations → 验证串口输出 → 验证定时器与 IPI → 验证多核启动”的顺序逐项排查。每一步都应有明确的日志或现象作为验证依据,避免一次性修改过多变量导致问题难以定位。