opensbi 介绍
背景
RISC-V指令集的SBI标准规定了类Unix平台下,操作系统运行环境的规范。这个规范拥有多种实现,OpenSBI是它的一种实现.
这个运行环境不仅将引导启动RISC-V下的操作系统, 还将常驻后台,为操作系统提供一系列二进制接口,以便其获取和操作硬件信息。 RISC-V给出了此类环境和二进制接口的规范,称为“操作系统二进制接口”,即“SBI”。
SBI是在M模式下运行的特定于平台的固件,它将管理S、U等特权上的程序或通用的操作系统。
RISCV 模式
Machine-Level ISA
- 处理器内核被复位后,默认处于 Machine Mode
- machine mode读写的寄存器,如mhartid、mstatus、mtvec、mcause
- machine特权指令,如ecall(所有模式)、mret、sret、wfi(所有模式、U模式可选)
- 复位、NMI发生后hart状态
- PMA物理内存属性,原子、order、一致性
- PMP物理内存保护机制和寄存器
Supervisor-Level ISA
- Supervisor mode读写的寄存器,如sstaus、stvec、scause、satp
- Supervisor特权指令,如ecal、sret、sfence.vma
- Page-Based 32/39/48/57-bit Virtual-Memory Systems
User-Level ISA
Hypervisor Extension (扩展 H-extension)
- hypervisor 虚拟化读写的寄存器,如hstatus、vstvec、vepc
- hypervisor特权指令,load/store、fence
RISV 特权模式演进
- AEE: application execution environment
- ABI: application binary interface
- The ABI includes the supported user-level ISA plus a set of ABI calls to interact with the AEE. The ABI hides details of the AEE from the application to allow greater flexibility in implementing the AEE.
- SEE: supervisor execution environment
- SBI: supervisor binary interface
- HEE: hypervisor execution environment
- isolate the hypervisor from details of the hardware platform.
- HBI: hypervisor binary interface
所有硬件必须提供M-mode,因为它拥有访问整个机器的能力,最简单的RISC-V实现只有M-mode,但是不能抑制恶意APP。
- 未扩展前,不支持hypervisor模式
- hypervisor扩展模式,V标识当前hart是否处于虚拟化模式
- 为操作系统层(S-mode) 提供
SBI
接口的高特权级别的软件被称为SBI
实现或 特权执行环境(SEE
). - SBI 实现或SEE工作在M层, 带H扩展的 Host S层 os 也可以实现相关的sbi 接口用来与Guest os 交互通信.
1) 不带H 扩展的 RISCV 系统
2) 带 H 扩展的 RISCV 系统
MIPS 架构
Each Hart can host an application under the same or different guest OS
Allows efficient utilization of pipeline hardware and local cache
With RISC-V H-extension, each hart is a Virtual Machine (RV64GHC
)
MIPS UDI (User Defined Instructions)
MIPS (MIPS64r6) User Defined Instructions fills the gap
- Performance – Prefetch, Paired load/store
- Coherency – Cache Maintenance
- Multi-core, multi-cluster – Global Invalidates, Cache Maintenance
- Diagnostic capabilities – Diagnostic Read/Write
SBI 的作用
- 可以为多个os提供公共driver
- 可以避免为每个不同os 适配平台相关的功能, 将功能做到sbi层, 其他的各种os 只需要ecall 调用, 访问sbi层来实现平台的功能
- 在S层工作的OS 可以通过ecall sbi 来访问或修改受限在M层的硬件资源 (如只能m层访问的CSR)
- 多个OS之间的通信媒介, 限制不同OS的可以访问的硬件资源 (如PMP限制os可以使用哪些内存地址)
SBI CALL EXTENSION
Base Extension (EID
#0x10
)Machine Implementation ID Register (mimpid) 提供了处理器实现版本的唯一编码 Machine Architecture ID Register (marchid) 处理器核架构编号 Machine Vendor ID Register (mvendorid) 用于指示供应商 ID 的寄存器
Legacy Extensions (EIDs
#0x00 - #0x0F
)
- Timer Extension (EID
#0x54494D45
“TIME”)
- Timer Extension (EID
IPI Extension (EID
#0x735049
“sPI: s-mode IPI”)
RFENCE Extension (EID
#0x52464E43
“RFNC”)
Hart State Management Extension (EID
#0x48534D
“HSM”)The Hart State Management (HSM) Extension introduces a set of hart states and a set of functions which allow the supervisor-mode software to request a hart state change.
System Reset Extension (EID
#0x53525354
“SRST”)The System Reset Extension provides a function that allow the supervisor software to request system-level reboot or shutdown.
The term “system” refers to the world-view of supervisor software and the underlying SBI implementation could be machine mode firmware or hypervisor.
Performance Monitoring Unit Extension (EID
#0x504D55
“PMU”)
- Experimental SBI Extension Space (EIDs
#0x08000000
-#0x08FFFFFF
)
- Experimental SBI Extension Space (EIDs
- Vendor-Specific SBI Extension Space (EIDs
#0x09000000
-#0x09FFFFFF
)
- Vendor-Specific SBI Extension Space (EIDs
- Firmware Specific SBI Extension Space (EIDs
#0x0A000000
-#0x0AFFFFFF
)
- Firmware Specific SBI Extension Space (EIDs
ecall 初始化过程及调用过程
mtvec 寄存器用于配置m-mode 中断和异常处理程序的入口地址
mscratch 寄存器用于 Machine Mode 下的程序临时保存某些数据
OPENSBI 集成模式
OpenSBI提供了几种类型的参考固件, 都是平台相关的
- FW_PAYLOAD: Firmware with the next booting stage as a payload
- FW_JUMP: Firmware with static jump address to the next booting stage
- FW_DYNAMIC: Firmware with dynamic information on the next booting stage
vendor 厂商可以选择下面的策略定制opensbi:
参考上面的三个模型里的一个定制M层 runtime SEE
使用opensbi的静态库 弹性定制M-mode runtime SEE
使用opensbi静态库扩展 M-mode 的spl
FW_PAYLOAD
优点:
- opensbi的前一级只需要加载opensbi
- 允许opensbi 覆盖设备树
缺点:
- 每次下级镜像改动, 都需要重新编译opensbi
- opensbi的前一级无法给opensbi的下一级传递参数
FW_JUMP
优点:
- opensbi不需要加载下一级镜像
- opensbi的体积小, 下一级镜像变动时, 只要固定地址不变, 就不需要重新编译
缺点:
- opensbi的前一级需要同时加载opensbi 和 opensbi的下一级, 加载的地址也必须是固定的, opensbi需要提前知道这个固定地址
- opensbi的前一级无法给opensbi传参
FW_DYNAMIC
优点:
- opensbi不需要加载下一级镜像
- opensbi的前一级可以给opensbi传递参数
- opensbi 的下一级变动后不需要重新编译
缺点:
- opensbi的前一级需要同时加载opensbi 和 opensbi的下一级
使用opensbi 扩展spl
M-mode spl 和 opensbi的静态库链接起来, spl承接SEE runtime
ex: open-source EDK2 (UEFI implementation) OpenSBI integration
引导过程
RISC-V芯片的启动流程演变历程:
ZSBL(第0阶段Bootloader)
处于M-mode的ZSBL保存在bootrom中,它负责从GPT中加载更为复杂的spl(寻找uuid的GPT分区)。通过先加载GPT的头文件,然后一块一顺序地扫描GPT。加载过程结束后,spl被加载进地址为sram中,随后,将执行spl阶段。
SPL(第1阶段Bootloader)
处于M-mode的SPL从SRAM上执行,它负责为在DDR上运行系统做准备,可大概分为如下的这些任务:
- 配置芯片上的PLL 核心频率
- 配置DDR PLL,PHY和DDR控制器
- 外部PHY,重置
- 从编号为uuid的GTP分区下载 SEE(opensbi 实现)
- 扫描OTP获取的芯片序列号
- 将DTB(硬件设备树)复制到DDR,填写SPL版本,内存大小和MAC地址
- 跳转到DDR上, 启动SEE (opensbi 实现)
SEE (opensbi 实现)
OpenSBI的初始化流程如下:
(1)底层初始化:
1. 判断hart(Hardware Thread) id
2. 代码重定位(判断_load_start与_start函数是否一致)
3. 清除除保存设备树地址的寄存器的值
4. 清除bss段
5. 设置栈指针(预留栈空间)
6. 读取设备树中的设备信息
7. 设备树重定位,为U-Boot提供信息
8. 至此,底层初始化结束,执行sbi_init,进行正式的初始化程序
(2)设备初始化:
1. sbi_domain_init 初始化动态加载的镜像的模块
2. sbi_platform_early_init 平台的早期初始化
3. sbi_console_init 控制台初始化,从这里开始,就可以使用串口输出了。
4. sbi_platform_irqchip_init irq中断初始化
5. sbi_ipi_init 核间中断初始化
6. sbi_tlb_init mmu的tlb表的初始化
7. sbi_timer_init timer初始化
8. sbi_hsm_prepare_next_jump 准备下一级的boot
(3)二级boot跳转,跳转Uboot, PAYLOAD 模式中, uboot的代码会装载到 SEE的特定位置 (汇编中使用.incbin 实现), 跳转时, 不再需要从GPT 加载uboot, 只需要跳转到 uboot 起始地址即可
uboot(第2阶段的Bootloader)
uboot 从gpt分区中加载kernel到DDR, 解压, 验证kernel, 跳转到kernel
U-Boot属于一种bootloader,简单来说,其作用就是从flash中读出内核,随后加载在内存中,最终初始化并启动操作系统内核。
具体来说,可以分为下述几个方面:
- U-Boot主要作用是用来启动操作系统内核。体现在uboot最后一句代码就是启动内核。
- U-Boot还要负责部署操作系统内核。体现在uboot最后的传参。
- U-Boot中还有操作Flash等板子上硬件的驱动。例如串口要打印,ping网络,擦除、烧写flash等。提供烧写功能等
- U-Boot还得提供一个命令行界面供人来操作。如果kernel 起不来, uboot命令行可以提供操作界面, 让用户来手动加载kernel
opensbi 软件栈层级
通用平台抽象 libsbi.a
抽象出平台无关的feature 接口, 供外界组件使用, 生成libsbi.a, 外界组件link
平台相关实现 (硬件依赖驱动实现) libplatsbi.a
实现特定平台特定硬件驱动的 sbi_platform 的hook
libplatsbi.a = libsbi.a + struct sbi_platform instance
平台自定集成固件
厂商自定义添加ecall extension
ex: SBI_EXT_EXPERIMENTAL_KEYSTONE_ENCLAVE 0x08424b45
ARM架构中的Hypervisor与OpenSBI的对比
在ARM架构中,Hypervisor层承担了虚拟化的作用,承担了如内存管理、设备模拟、设备分配、异常处理、指令捕获、虚拟异常管理、中断控制器管理、调度、上下文切换、内存转换、多个虚拟地址空间管理等非常多的功能。
相比之下,SBI在RISC-V架构中充当了BIOS和在操作系统运行时为上层提供底层抽象的作用,功能较少。不过SBI也在不断发展中,可能在将来SBI会去承担虚拟化的功能。