第一章:应用程序与基本执行环境
内存布局
下面图“数据存储器”应该是 Data Memory.
Qemu 启动流程
- Step 1:
- Qemu CPU pc set to 0x1000,执行神秘指令,使得待会儿能跳转到 0x80000000
0x0000000000001000 in ?? ()
(gdb) x/10i $pc
=> 0x1000: auipc t0,0x0
0x1004: addi a2,t0,40
0x1008: csrr a0,mhartid
0x100c: ld a1,32(t0)
0x1010: ld t0,24(t0)
0x1014: jr t0 # 这里 t0 值已经变成 0x80000000
0x1018: unimp
0x101a: 0x8000
0x101c: unimp
0x101e: unimp
- Step 2: 0x80000000
- 这里是 RUSTSBI,会执行很多指令。所以实操时在 0x80200000 打了个断点快速过去.
0x0000000080000000 in ?? ()
(gdb) x/10i $pc
=> 0x80000000: auipc ra,0x2
0x80000004: jalr 834(ra)
0x80000008: auipc ra,0x0
0x8000000c: jalr 116(ra)
0x80000010: j 0x80001690
0x80000014: unimp
0x80000016: addi sp,sp,-80
0x80000018: sd ra,72(sp)
0x8000001a: ld a1,40(a0)
0x8000001c: ld a2,32(a0)
- Step 3: 0x80200000 自己的 Rust 程序
(gdb) x/5i $pc
=> 0x80200000: li ra,100
0x80200004: unimp
0x80200006: unimp
0x80200008: unimp
0x8020000a: unimp
RustSBI is what?
SBI 是 RISC-V Supervisor Binary Interface 规范的缩写,OpenSBI 是RISC-V官方用C语言开发的SBI参考实现;RustSBI 是用Rust语言实现的SBI。
BIOS 是 Basic Input/Output System,作用是引导计算机系统的启动以及硬件测试,并向OS提供硬件抽象层。
机器上电之后,会从ROM中读取引导代码,引导整个计算机软硬件系统的启动。而整个启动过程是分为多个阶段的,现行通用的多阶段引导模型为:
ROM -> LOADER -> RUNTIME -> BOOTLOADER -> OS
Loader 要干的事情,就是内存初始化,以及加载 Runtime 和 BootLoader 程序。而Loader自己也是一段程序,常见的Loader就包括 BIOS 和 UEFI,后者是前者的继任者。
Runtime 固件程序是为了提供运行时服务(runtime services),它是对硬件最基础的抽象,对OS提供服务,当我们要在同一套硬件系统中运行不同的操作系统,或者做硬件级别的虚拟化时,就离不开Runtime服务的支持。SBI就是RISC-V架构的Runtime规范。
BootLoader 要干的事情包括文件系统引导、网卡引导、操作系统启动配置项设置、操作系统加载等等。常见的 BootLoader 包括GRUB,U-Boot,LinuxBoot等。
而 BIOS/UEFI 的大多数实现,都是 Loader、Runtime、BootLoader 三合一的,所以不能粗暴的认为 SBI 跟 BIOS/UEFI 有直接的可比性。
如果把BIOS当做一个泛化的术语使用,而不是指某个具体实现的话,那么可以认为 SBI 是 BIOS 的组成部分之一。