预备知识
GNU Binutils参考文档
GNU Binutils是一系列用来生成可执行文件的软件的集合体,它包括我们常常使用的ld,as等软件。即使你没有亲自使用过这些软件,只要你使用了gcc就相当于间接使用了它们,因为gcc会在生成可执行程序时使用这些软件。
我们需要准备好as和ld的参考文档,因为我们不可避免地要了解汇编和链接脚本。我不在博客中详细介绍他们的内容,因为没有比官方文档更好的教材了。
文档可以在GNU Binutils主页获取。
RISC-V参考文档
准备好如下文档,在不理解的时候可以参考
- 《The RISC-V Instruction Set Manual Volume I: Unprivileged ISA》
- 《The RISC-V Instruction Set Manual Volume II: Privileged Architecture》
- OpenSBI主页
- Qemu文档以及源代码
这里我们建议自己编译qemu,因为有的地方想要真正理解需要阅读qemu源代码。
我始终坚持一个观点,官方文档是最好的教材,所以我会尽可能指出每个知识点究竟在官方文档的那一部分。如果查阅官方文档无法给你答案,那么最好的办法就是咨询那些对这方面有了解的人。
RISC-V异常处理
根据RISC-V标准文档《The RISC-V Instruction Set Manual Volume I: Unprivileged ISA》,RISV异常处理的具体过程是由EEI(RISC-V execution environment interface)决定的。
首先我们必须明确一个观点,RISCV的特权等级分为三个层次,分别是M模式,S模式,U模式。SBI运行在M模式,操作系统内核运行在S模式,应用程序运行在U模式,这部分的资料可以在RISC-V特权文档中的第一章看到。
系统调用
这里我们主要说说系统调用。在U模式下运行的用户程序,一旦调用ecall
指令,就会陷入到S模式中,操控权也就转交到内核手里。RISC-V的特权寄存器中有一个寄存器叫做stvec
,这个寄存器储存了陷阱处理程序的基地址,具体内容可以参照RISC-V特权文档的4.1.2节。总之,在调用了ecall后,芯片将会跳转到stvec
所指向的程序代码,因此我们需要在操作系统启动时设置好该寄存器的值。
RISC-V的启动过程
我们使用qemu模拟RISC-V来运行操作系统。我们从qemu命令行开始讲解一个内核被加载的过程:
qemu-system-riscv32 -kernel target -machine virt -m 64M -nographic -no-reboot \
-global virtio-mmio.force-legacy=false \
-drive file=target/fs.img,if=none,format=raw,id=hd \
-device virtio-blk-device,drive=hd,bus=virtio-mmio-bus.0
一些参数的说明
-
-kernel kernel
加载内核 -
-machine virt
指明机器类型 -
-m 64M
设置内存 -
-nographic
关闭图形化显示
在机器启动时,首先会运行SBI加载内核,这里SBI起到了类似于Bootloader的作用,具体SBI的运行过程,我查找了很多资料都没有找到描述,最终还得依靠阅读qemu的源代码。
由于上面的命令行没有指定sbi文件,所以会使用默认的sbi文件,对于riscv32来说,这个文件名被定义在include/hw/riscv/boot.h中,为
#define RISCV32_BIOS_BIN "opensbi-riscv32-generic-fw_dynamic.bin"
加载opensbi的函数为riscv_find_and_load_firmware
,阅读代码会发现这个函数将opensbi加载到0x80000000这个位置上。
接下来opensbi会加载内核,阅读opensbi有关firmware的文档,我们发现opensbi有三种内核加载方式,分别是fw_dynamic
、fw_payload
、fw_jump
,而我们默认的固件使用的是fw_dynamic
加载方式。这种方式会将内核加载到qemu给出的地址上。
qemu负责加载内核的函数是riscv_load_kernel
,在这个函数中我们发现,如果内核是elf文件(这也是我们这次试验选择的方式),那么内核加载地址将根据elf的程序入口决定。但是注意不要与固件加载的地方发生冲突,也不要和virt的内存布局不协调。这里我建议在riscv32上将内存布局加载到0x80400000上,因为这是qemu在没有elf文件配置的情况下自行计算出的程序入口,最符合qemu的习惯。