发布于 

为 RT-thread 提交的第一个 PR

为 RT-thread 提交的第一个 PR

具体问题

[libcpu/riscv/virt64] fix (#5979) 修复 qemu-riscv-virt64 smode 下无法启动 by leesum1 · Pull Request #7040 · RT-Thread/rt-thread · GitHub

在当前 master 分支中,qemu-riscv-virt64 smode 启动有问题,只有在使用 Sifive 工具链 的情况下才能进入系统,使用其他工具链则会报 Illegal Instruction 异常。

经过排查,最终确定是在 startup_gcc.S 没有为 boot_hartid 分配空间,在后续的指令中,发生了错误的修改。

1
2
3
4
5
boot_hartid: .int
.global boot_hartid
.global _start
.section ".start", "ax"
_start:
1
2
3
4
5
/* save hartid */
la t0, boot_hartid /* global varible rt_boot_hartid */
mv t1, a0 /* get hartid in S-mode frome a0 register */
// 由于没有为 boot_hartid 分配空间,修改 boot_hartid 导致了其他指令的改动
sw t1, (t0) /* store t1 register low 4 bits in memory address which is stored in t0 */

对应的汇编语句如下,boot_hartidmemset 地址相同

1
2
3
8020001c:   44828293                addi    t0,t0,1096 # 80200460 <memset>
80200020: 00050313 mv t1,a0
80200024: 0062a023 sw t1,0(t0)

map 文件如下,可以明显看到 boot_hartid 的空间为 0x0,地址信息与 memset 相同。

1
2
3
4
.text          0x0000000080200460        0x0 build/kernel/libcpu/risc-v/virt64/startup_gcc.o
0x0000000080200460 boot_hartid
.text 0x0000000080200460 0xdc /opt/riscv/lib/gcc/riscv64-unknown-elf/12.2.0/../../../../riscv64-unknown-elf/lib/libc.a(lib_a-memset.o)
0x0000000080200460 memset

80200024: 0062a023 sw t1,0(t0) 中修改了 memset 的第一条指令,导致后续调用 memset 时,指令发生错误。

使用不同工具链的情况下, 与 boot_hartid 地址相同的函数会有变化,在使用Sifive 工具链 时,地址信息如下

1
2
3
4
.text          0x00000000802002ce        0x0 build/kernel/libcpu/risc-v/virt64/startup_gcc.o
0x00000000802002ce boot_hartid
.text 0x00000000802002ce 0x28 /home/leesum/Downloads/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin/../lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/lib/rv64imac/lp64/libc.a(lib_a-atoi.o)
0x00000000802002ce atoi
1
2
3
80200018:   00000297                auipc   t0,0x0
8020001c: 2b628293 addi t0,t0,694 # 802002ce <atoi>
80200020: 832a mv t1,a0

atoi 函数地址相同,而 atoi 不是很常用的函数,所以没有在一开始启动的时候就报错。
本次提交能够修复上述 bug。

解决方案

原来的 boot_hartid 位于 .start 段,作为全局变量。修改后放在了 .data 段,并分配了 4byte 空间,不会与其他符号冲突

1
2
3
4
.data
.global boot_hartid /* global varible rt_boot_hartid in .data section */
boot_hartid:
.word 0xdeadbeef

测试环境

❯ qemu-system-riscv64 –help
QEMU emulator version 7.2.0