This code seems to have been working on 32-bit builds by accident.
However it totally broke on 64 bits, resulting in "restoring" some
garbage into registers.

The reason the code worked on 32 bits is this. When we are entering the
barebox_exc_handler() function, we are passing in a register the current
stack pointer as an argument (which corresponds to the regs parameter).
On o32 ABI the space for arguments passed in registers is reserved on
the stack by the caller. So, when we are taking the address of regs in
the body of the function, we have to put this argument on the stack,
into the first reserved slot. However, this slot is located exactly at
the current 'sp' and thus the address of regs happens to be the same as
its value!

On n64 ABI, however, the arguments passed in registers are saved onto
the stack on the callee side, so we end up with the wrong value being
used as the stack pointer.

Signed-off-by: Denis Orlov <denorl2...@gmail.com>
---
 arch/mips/lib/traps.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/lib/traps.c b/arch/mips/lib/traps.c
index ff0a54af8e..45694fe7ef 100644
--- a/arch/mips/lib/traps.c
+++ b/arch/mips/lib/traps.c
@@ -173,7 +173,7 @@ void barebox_exc_handler(struct pt_regs *regs)
                        "move\t$29, %0\n\t"
                        "j\tret_from_exception"
                        :/* no outputs */
-                       :"r" (&regs));
+                       :"r" (regs));
 
                /* Unreached */
 
-- 
2.41.0


Reply via email to