了解并熟悉如何在NEMU和QEMU模拟器上运行最简单的BenOS程序。
在Linux主机中安装相关工具。
$ sudo apt-get install qemu-system-misc libncurses5-dev gcc-riscv64-linux-gnu build-essential git bison flex libssl-dev
(1)在QEMU上运行BenOS
在Linux主机上使用make命令编译BenOS 。
$ cd riscv_programming_practice/chapter_2/benos
$ export board=qemu
$ make clean
$ make
CC build_src/uart_c.o
CC build_src/kernel_c.o
AS build_src/boot_s.o
LD build_src/benos.elf
OBJCOPY benos.bin
CC build_sbi/sbi_main_c.o
AS build_sbi/sbi_boot_s.o
AS build_sbi/sbi_payload_s.o
LD build_sbi/mysbi.elf
OBJCOPY mysbi.bin
LD build_sbi/benos_payload.elf
OBJCOPY benos_payload.bin
要想编译能在QEMU模拟器 上运行的可执行二进制文件,需要先设置board=qemu。
直接输入make run命令并运行。
rlk@master:benos$ make run
qemu-system-riscv64 -nographic -machine virt -m 128M -bios mysbi.bin -kernel benos.elf
Welcome RISC-V!
QEMU输出“Welcome RISC-V!”。要关闭QEMU,可以先按“Ctrl +A”键,松开,再快速按“X”键。
(2)在NEMU上运行BenOS
在Linux主机上使用make命令编译BenOS。
$ cd riscv_programming_practice/chapter_2/benos
$ export board=nemu
$ make clean
$ make
CC build_src/uart_c.o
CC build_src/kernel_c.o
AS build_src/boot_s.o
LD build_src/benos.elf
OBJCOPY benos.bin
CC build_sbi/sbi_main_c.o
AS build_sbi/sbi_boot_s.o
AS build_sbi/sbi_payload_s.o
LD build_sbi/mysbi.elf
OBJCOPY mysbi.bin
LD build_sbi/benos_payload.elf
OBJCOPY benos_payload.bin
要想编译能在NEMU模拟器上运行的可执行二进制文件,需要先设置board=nemu。如果想查看更多编译日志,可以使用make V=1命令。编译完成之后会生成以下5个文件。
● benos.bin:BenOS可执行文件。
● benos.elf:BenOS带调试信息的可执行与可链接格式(Executable and Linkable Format,ELF)文件。
● mysbi.bin:MySBI固件的可执行文件。
● mysbi.elf:MySBI带调试信息的ELF文件。
● benos_payload.bin:把benos.bin和mysbi.bin整合到一个可执行二进制文件中。
直接输入make run命令并运行。
rlk@master:benos$ make run
riscv64-nemu-interpreter -b benos_payload.bin
Welcome to riscv64-NEMU!
For help, type "help"
Welcome RISC-V!
NEMU输出“Welcome RISC-V!”,如图2.1所示。
图2.1 NEMU的输出结果
本小节提供两种单步调试BenOS和MySBI的方法。一种是使用QEMU与GDB工具,另一种是使用NEMU内置的单步调试功能。
以实验2-1为例,使用make debug命令在终端启动QEMU虚拟机的gdbserver。
$ cd riscv_programming_practice/chapter_2/benos
$ make debug
或者直接使用如下命令启动gdbserver。
$ qemu-system-riscv64 -nographic -machine virt -m 128M -bios mysbi.bin -kernel benos.elf -S -s
在另一个终端使用如下命令启动GDB工具。
$ gdb-multiarch --tui benos.elf
在GDB命令行中执行如下命令。
(gdb) target remote localhost:1234
(gdb) b _start
Breakpoint 1 at 0x80200000: file src/boot.S, line 6.
(gdb) c
此时,使用GDB工具单步调试BenOS,如图2.2所示。
图2.2 使用GDB工具单步调试BenOS
另外,也可以通过GDB工具调试MySBI固件。为了在终端启动QEMU虚拟机的gdbserver,使用make debug命令。
$ cd riscv_programming_practice/chapter_2/benos
$ make debug
在另一个终端使用如下命令启动GDB工具,这时候需要加载MySBI固件的ELF文件。
$ gdb-multiarch --tui mysbi.elf
在GDB命令行中执行如下命令。
(gdb) target remote localhost:1234
(gdb) b _start
Breakpoint 1 at 0x80000000: file sbi/sbi_boot.S, line 6.
(gdb) c
此时,使用GDB工具进行单步调试,如图2.3所示。
图2.3 单步调试
NEMU内置了简易调试器(Simple Debugger,SDB)。SDB是NEMU中一个非常重要的基础设施,可以获取程序的执行信息,以协助调试。SDB支持的命令如表2.4所示。
表2.4 SDB支持的命令
在Linux主机终端,使用make debug命令启动SDB。
$ cd riscv_programming_practice/chapter_2/benos
$ make debug
riscv64-nemu-interpreter benos_payload.bin
Welcome to riscv64-NEMU!
For help, type "help"
(nemu)
在SDB命令行中输入“help”,查看帮助信息,如图2.4所示。
图2.4 查看帮助信息
输入“si”,进行单步调试,如图2.5所示。
图2.5 进行单步调试
另外,还可以通过监视点命令设置断点,不过目前只支持为地址设置断点。例如,在0x8020 0000地址处设置断点。
$ make debug
(nemu) w $pc==0x80200000 //设置断点
Set watchpoint #0
(nemu) c //继续执行,此时NEMU停在断点处
Hint watchpoint 0 at address 0x00000000800000a8, expr = $pc==0x80200000
old value = 0x0000000000000000
new value = 0x0000000000000001
(nemu) si //单步执行
0x0000000080200000: 73 10 40 10 csrrw $0,0x104,$0
Hint watchpoint 0 at address 0x0000000080200000, expr = $pc==0x80200000
old value = 0x0000000000000001
new value = 0x0000000000000000