This corrects the sparc64 setjmp implementation.

We need to store the return address register, the
stack pointer, and frame pointer into the jump buf.

And on longjmp we need restore those registers, flush the register
window state, and pull in the top-most register window.

2009-03-03  David S. Miller  <da...@davemloft.net>

        * normal/sparc64/setjmp.S: Fix setjmp implementation.
        * include/grub/sparc64/setjmp.h: Update grub_jmp_buf[].
---
 include/grub/sparc64/setjmp.h |    3 +--
 normal/sparc64/setjmp.S       |   18 +++++++++++++-----
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/include/grub/sparc64/setjmp.h b/include/grub/sparc64/setjmp.h
index 12d8e01..183a820 100644
--- a/include/grub/sparc64/setjmp.h
+++ b/include/grub/sparc64/setjmp.h
@@ -19,8 +19,7 @@
 #ifndef GRUB_SETJMP_CPU_HEADER
 #define GRUB_SETJMP_CPU_HEADER 1
 
-/* FIXME (sparc64).  */
-typedef unsigned long grub_jmp_buf[20];
+typedef unsigned long grub_jmp_buf[3];
 
 int grub_setjmp (grub_jmp_buf env);
 void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));
diff --git a/normal/sparc64/setjmp.S b/normal/sparc64/setjmp.S
index b1a9b6e..02e61b1 100644
--- a/normal/sparc64/setjmp.S
+++ b/normal/sparc64/setjmp.S
@@ -26,13 +26,21 @@
  * int grub_setjmp (grub_jmp_buf env)
  */
 FUNCTION(grub_setjmp)
-        ret
-         nop
+       stx     %o7, [%o0 + 0x00]
+       stx     %sp, [%o0 + 0x08]
+       retl
+        stx    %fp, [%o0 + 0x10]
 
 /*
  * int grub_longjmp (grub_jmp_buf env, int val)
  */
 FUNCTION(grub_longjmp)
-        ret
-         nop
-
+       ldx     [%o0 + 0x10], %g1
+       movrz   %o1, 1, %o1
+       ta      0x3
+       ldx     [%o0 + 0x00], %o7
+       ldx     [%o0 + 0x08], %fp
+       sub     %fp, 192, %sp
+       stx     %g1, [%sp + 2047 + (14 * 8)]
+        retl
+        restore %o1, 0, %o0
-- 
1.6.1.2.253.ga34a



_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to