MIPS:合法的连续两次;“加载单词”;将指令放入同一寄存器?

MIPS:合法的连续两次;“加载单词”;将指令放入同一寄存器?,mips,Mips,Background:我们看到函数foo(int*p)中出现了非常间歇性的崩溃。在取消引用p时发生崩溃,在这些情况下,其值为0xffffffff。对核心转储的分析表明,foo()是从以下程序集片段调用的: bne ... somewhere else lw $a0,44(sp) lw $a0,40(sp) jal foo() lui s1, 0x1000 检查内核转储中的内存表明44(sp)是0xffffff,而40(sp)是我们要取消引用的正确值。但是,碰撞时a0在foo()内的值为0xff

Background:我们看到函数
foo(int*p)
中出现了非常间歇性的崩溃。在取消引用
p
时发生崩溃,在这些情况下,其值为
0xffffffff
。对核心转储的分析表明,
foo()
是从以下程序集片段调用的:

bne ... somewhere else
lw $a0,44(sp)
lw $a0,40(sp)
jal foo()
lui s1, 0x1000
检查内核转储中的内存表明
44(sp)
0xffffff
,而
40(sp)
是我们要取消引用的正确值。但是,碰撞时
a0
foo()
内的值为
0xffffffff
。(需要注意的是,
foo()
在本例中只是访问一个成员;因此它实际上是
foo()中的第一条指令。)
已经尝试通过
a0
访问并崩溃。此外,
ra
指向上述代码段后面的指令,
s1
当前包含
0x10000000
,因此我们非常确信
foo()
确实是从上述代码段调用的。)

目前我们唯一的理论是,两个连续的
lw
s进入
a0
是一种危险——要么是有记录的,在这种情况下,这看起来像是一个编译器错误;或者一个没有文件的

因此:上述集会合法吗?如果是的话,关于这里可能发生的事情还有其他想法吗

谢谢

更新:事实证明,这完全是白费力气:一位同事对coredump的重复分析在代码中找到了一条我错过的路径,在将
a0
设置为
44(sp)
后,立即跳转到
jal foo()
指令。换句话说,代码中有一条路径与我们看到的结果一致,它不涉及危险、或“跳过的指令”或任何东西。。。我想我检查过了,但我想我要么没有,要么错过了…:(


无论如何,我已经接受了markgz的回答,因为它回答了我最初关于这些指令合法性的问题(显然是这样)。

快速搜索MIPS32R2 ISA的MIPS文档不会显示对
LW
指令之后的
LW
的任何限制

您的CPU中的MIPS实现可能存在错误。要查看的内容包括:

  • 44(sp)、40(sp)是什么地址?它们是在页面边界上还是在256MB的边界上,还是在其他有趣的地址上
  • 两个加载是否都会触发页面错误
  • 对二进制文件进行修补以在加载之间插入
    NOP
    SSNOP
    、或
    SYNC
    指令是否可以解决问题

谢谢!地址不在任何特殊边界上(0x17409e8和0x17409ec),也不应触发页面错误(它们都在堆栈上)。我们还没有尝试修补二进制文件,我们的下一步将是/尝试用最小的测试用例进行复制…很有趣。这些信息让我觉得硬件错误的可能性更小。重新分析表明,问题的整个前提都是错误的…有关详细信息,请参阅原始问题中的更新。再次感谢您的帮助!我很高兴您的帮助你发现了什么地方出了问题,这不是CPU错误。谢谢你的更新!