什么可能导致 RISC-V 上的 SIGILL(非法指令除外)
What might cause a SIGILL (other than an illegal instruction) on RISC-V
我正在尝试将一些 Forth 加载到我的 Forth 编译器 运行ning 在 RISC-V SBC 上(尽管我不认为这是一个与 Forth 相关的问题):
>load /root/repos/riscyforth/test2.4th
: cuboid * * [ The cuboid has a volume of ] . ;
OK
cuboid
Program received signal SIGILL, Illegal instruction.
0x0000003ff7dbd038 in ?? ()
上面显示的是我用 Forth 加载文件,第一行回显到终端,是单词 cuboid 的定义。后面的OK说明Forth编译器编译成功了。
然后第二行是调用这个词,cuboid,然后是程序(在本例中是 运行 在 GDB 下)用 SIGILL 兑现的消息。
但是,反汇编显示如下:
(gdb) disassemble 0x3ff7dbd038, 0x3ff7dbd078
Dump of assembler code from 0x3ff7dbd038 to 0x3ff7dbd078:
=> 0x0000003ff7dbd038: addi s9,s9,-8
0x0000003ff7dbd03c: sd s7,0(s9)
0x0000003ff7dbd040: li s8,63
0x0000003ff7dbd044: slli s8,s8,0x20
0x0000003ff7dbd048: lui t0,0xf7dbd
0x0000003ff7dbd04c: ori t0,t0,0
0x0000003ff7dbd050: slli t0,t0,0x20
0x0000003ff7dbd054: srli t0,t0,0x20
0x0000003ff7dbd058: or s8,s8,t0
0x0000003ff7dbd05c: addi s8,s8,112
0x0000003ff7dbd060: mv s7,s8
0x0000003ff7dbd062: nop
0x0000003ff7dbd064: lui t0,0x10
0x0000003ff7dbd068: addi t0,t0,1976 # 0x107b8 <COLON_NEXT>
0x0000003ff7dbd06c: jr t0
0x0000003ff7dbd070: addi a2,sp,868
0x0000003ff7dbd072: nop
0x0000003ff7dbd074: unimp
0x0000003ff7dbd076: unimp
这完全符合我的预期,并且可以看出在 0x0000003ff7dbd038 处有一条非常好的指令。
此内存作为可执行文件映射到系统中,此机制适用于我在命令行上定义的词(与从文件中读入相反)。此外,如果我只是在我加载的文件中定义单词,然后从命令行 运行 它也很好(我知道这些可能表明加载有问题,但我看不到它或者为什么它会生成这个信号。
更令人困惑的是,如果我使用 GDB 单步执行代码,那么我不会遇到此 SIGILL 问题,并且从 0x0000003ff7dbd038 开始的代码会按我的预期执行。
这是 RVBoards Nezha 上的 RV64 - 在此之前执行标准的 Forth 解释器命令:
NEXT:
ld s8, 0(s7) #word address register takes content of next secondary
addi s7, s7, ADDRWIDTH #next secondary along
RUN:
ld t0, 0(s8) #extract first instruction address of primative
与 x86 不同,RISC-V 不允许编写机器代码并在没有同步的情况下执行它,即使在同一个线程中也是如此。在执行新编写的机器代码之前,发出一条fence.i
指令使指令缓存与当前内存状态同步。
我正在尝试将一些 Forth 加载到我的 Forth 编译器 运行ning 在 RISC-V SBC 上(尽管我不认为这是一个与 Forth 相关的问题):
>load /root/repos/riscyforth/test2.4th
: cuboid * * [ The cuboid has a volume of ] . ;
OK
cuboid
Program received signal SIGILL, Illegal instruction.
0x0000003ff7dbd038 in ?? ()
上面显示的是我用 Forth 加载文件,第一行回显到终端,是单词 cuboid 的定义。后面的OK说明Forth编译器编译成功了。
然后第二行是调用这个词,cuboid,然后是程序(在本例中是 运行 在 GDB 下)用 SIGILL 兑现的消息。
但是,反汇编显示如下:
(gdb) disassemble 0x3ff7dbd038, 0x3ff7dbd078
Dump of assembler code from 0x3ff7dbd038 to 0x3ff7dbd078:
=> 0x0000003ff7dbd038: addi s9,s9,-8
0x0000003ff7dbd03c: sd s7,0(s9)
0x0000003ff7dbd040: li s8,63
0x0000003ff7dbd044: slli s8,s8,0x20
0x0000003ff7dbd048: lui t0,0xf7dbd
0x0000003ff7dbd04c: ori t0,t0,0
0x0000003ff7dbd050: slli t0,t0,0x20
0x0000003ff7dbd054: srli t0,t0,0x20
0x0000003ff7dbd058: or s8,s8,t0
0x0000003ff7dbd05c: addi s8,s8,112
0x0000003ff7dbd060: mv s7,s8
0x0000003ff7dbd062: nop
0x0000003ff7dbd064: lui t0,0x10
0x0000003ff7dbd068: addi t0,t0,1976 # 0x107b8 <COLON_NEXT>
0x0000003ff7dbd06c: jr t0
0x0000003ff7dbd070: addi a2,sp,868
0x0000003ff7dbd072: nop
0x0000003ff7dbd074: unimp
0x0000003ff7dbd076: unimp
这完全符合我的预期,并且可以看出在 0x0000003ff7dbd038 处有一条非常好的指令。
此内存作为可执行文件映射到系统中,此机制适用于我在命令行上定义的词(与从文件中读入相反)。此外,如果我只是在我加载的文件中定义单词,然后从命令行 运行 它也很好(我知道这些可能表明加载有问题,但我看不到它或者为什么它会生成这个信号。
更令人困惑的是,如果我使用 GDB 单步执行代码,那么我不会遇到此 SIGILL 问题,并且从 0x0000003ff7dbd038 开始的代码会按我的预期执行。
这是 RVBoards Nezha 上的 RV64 - 在此之前执行标准的 Forth 解释器命令:
NEXT:
ld s8, 0(s7) #word address register takes content of next secondary
addi s7, s7, ADDRWIDTH #next secondary along
RUN:
ld t0, 0(s8) #extract first instruction address of primative
与 x86 不同,RISC-V 不允许编写机器代码并在没有同步的情况下执行它,即使在同一个线程中也是如此。在执行新编写的机器代码之前,发出一条fence.i
指令使指令缓存与当前内存状态同步。