【问题标题】:What might cause a SIGILL (other than an illegal instruction) on RISC-V什么可能导致 RISC-V 上的 SIGILL(非法指令除外)
【发布时间】:2021-07-15 17:20:00
【问题描述】:

我正在尝试将一些 Forth 加载到我在 RISC-V SBC 上运行的 Forth 编译器中(尽管我不认为这是一个与 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

【问题讨论】:

  • 什么是事先说明?显示前面的说明可能更有帮助。 addi 没有错:甚至没有任何潜在的特权。
  • 这是在模拟器上吗?还是这是真正的硬件?
  • 您给出的上下文很少,这可能是因为您在编译一个新单词后忘记刷新 icache。但是,由于您没有提供 minimal reproducible example 或回答我关于仿真的问题,我无法确定这是否是导致此问题的原因。
  • 很抱歉,您已经离开了家:它是真正的硬件,而不是仿真 - RVBoards Nezha SBC。其他信号——当然是错误的访问——在引发并且指令没有错位时会被看到(如果加载但不是从文件中运行,它将按预期在此地址执行)。前面的指令是 Forth 解释器的一部分(见上面的编辑)
  • @adrianmcmenamin 尝试在写完新单词后立即添加fence.i 指令。最好将此添加到,的机器代码中

标签: assembly gdb riscv forth


【解决方案1】:

与 x86 不同,RISC-V 不允许编写机器代码并在没有同步的情况下执行它,即使在同一个线程中也是如此。在执行新编写的机器代码之前,发出fence.i指令,将指令缓存与内存的当前状态同步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-10
    • 2018-11-22
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2011-12-15
    • 2012-09-06
    相关资源
    最近更新 更多