moxie: Save $r11 in setjmp() and longjmp()

Message ID 20260821081158.323243-1-sebastian.huber@embedded-brains.de
State New
Headers
Series moxie: Save $r11 in setjmp() and longjmp() |

Commit Message

Sebastian Huber Aug. 21, 2026, 8:11 a.m. UTC
  The ABI of the architecture makes $r6 to $r11 call-saved.  The routines
saved and restored $r6 to $r10 only, and _JBLEN left no room for
another register.  A value which the compiler holds in $r11 across a
setjmp() and longjmp() pair was lost.  A caller which returns through
longjmp() and then makes an indirect call through $r11 jumps to
whatever the intervening code left there.

Add $r11 to the jump buffer and raise _JBLEN to 11.  Correct the layout
comment, which swapped $sp and $fp and gave the last stack frame slot
as 0x25.

The size of jmp_buf changes, so the C library and every application
must be built together.

Found with the RTEMS test suite on the moxie GDB simulator.  The test
spmutex01 calls longjmp() from a fatal error extension and returns into
an indirect call through $r11.

Assisted-by: Claude:claude-opus-5 claude-code
Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
---
 newlib/libc/include/machine/setjmp.h | 2 +-
 newlib/libc/machine/moxie/setjmp.S   | 9 ++++++---
 2 files changed, 7 insertions(+), 4 deletions(-)
  

Comments

Jeff Johnston Aug. 25, 2026, 12:38 a.m. UTC | #1
Patch applied.

Regards,

-- Jeff J.

On Fri, Aug 21, 2026 at 4:13 AM Sebastian Huber <
sebastian.huber@embedded-brains.de> wrote:

> The ABI of the architecture makes $r6 to $r11 call-saved.  The routines
> saved and restored $r6 to $r10 only, and _JBLEN left no room for
> another register.  A value which the compiler holds in $r11 across a
> setjmp() and longjmp() pair was lost.  A caller which returns through
> longjmp() and then makes an indirect call through $r11 jumps to
> whatever the intervening code left there.
>
> Add $r11 to the jump buffer and raise _JBLEN to 11.  Correct the layout
> comment, which swapped $sp and $fp and gave the last stack frame slot
> as 0x25.
>
> The size of jmp_buf changes, so the C library and every application
> must be built together.
>
> Found with the RTEMS test suite on the moxie GDB simulator.  The test
> spmutex01 calls longjmp() from a fatal error extension and returns into
> an indirect call through $r11.
>
> Assisted-by: Claude:claude-opus-5 claude-code
> Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
> ---
>  newlib/libc/include/machine/setjmp.h | 2 +-
>  newlib/libc/machine/moxie/setjmp.S   | 9 ++++++---
>  2 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/newlib/libc/include/machine/setjmp.h
> b/newlib/libc/include/machine/setjmp.h
> index 4e74bdb0f..568adef91 100644
> --- a/newlib/libc/include/machine/setjmp.h
> +++ b/newlib/libc/include/machine/setjmp.h
> @@ -259,7 +259,7 @@ _BEGIN_STD_C
>  #endif
>
>  #ifdef __moxie__
> -#define _JBLEN 10
> +#define _JBLEN 11
>  #endif
>
>  #ifdef __CRX__
> diff --git a/newlib/libc/machine/moxie/setjmp.S
> b/newlib/libc/machine/moxie/setjmp.S
> index 014368d64..0bf36afc2 100644
> --- a/newlib/libc/machine/moxie/setjmp.S
> +++ b/newlib/libc/machine/moxie/setjmp.S
> @@ -19,11 +19,12 @@
>  #   $r8             0x08
>  #   $r9             0x0c
>  #   $r10            0x10
> -#   $fp             0x14
> -#   $sp             0x18
> +#   $sp             0x14
> +#   $fp             0x18
>  #   stack frame fp  0x1c
>  #   stack frame ra  0x20
> -#   stack frame sc  0x25
> +#   stack frame sc  0x24
> +#   $r11            0x28
>
>          .text
>          .global setjmp
> @@ -36,6 +37,7 @@ setjmp:
>         sto.l   0x10($r0), $r10
>         sto.l   0x14($r0), $sp
>         sto.l   0x18($r0), $fp
> +       sto.l   0x28($r0), $r11
>         ldo.l   $r1,       0x00($fp)
>         sto.l   0x1c($r0), $r1
>         ldo.l   $r1,       0x04($fp)
> @@ -57,6 +59,7 @@ longjmp:
>         ldo.l   $r10, 0x10($r0)
>         ldo.l   $sp, 0x14($r0)
>         ldo.l   $fp, 0x18($r0)
> +       ldo.l   $r11, 0x28($r0)
>         ldo.l   $r2, 0x1c($r0)
>         sto.l   0x0($fp), $r2
>         ldo.l   $r2, 0x20($r0)
> --
> 2.51.0
>
>
  

Patch

diff --git a/newlib/libc/include/machine/setjmp.h b/newlib/libc/include/machine/setjmp.h
index 4e74bdb0f..568adef91 100644
--- a/newlib/libc/include/machine/setjmp.h
+++ b/newlib/libc/include/machine/setjmp.h
@@ -259,7 +259,7 @@  _BEGIN_STD_C
 #endif
 
 #ifdef __moxie__
-#define _JBLEN 10
+#define _JBLEN 11
 #endif
 
 #ifdef __CRX__
diff --git a/newlib/libc/machine/moxie/setjmp.S b/newlib/libc/machine/moxie/setjmp.S
index 014368d64..0bf36afc2 100644
--- a/newlib/libc/machine/moxie/setjmp.S
+++ b/newlib/libc/machine/moxie/setjmp.S
@@ -19,11 +19,12 @@ 
 #   $r8             0x08
 #   $r9             0x0c
 #   $r10            0x10
-#   $fp             0x14
-#   $sp             0x18
+#   $sp             0x14
+#   $fp             0x18
 #   stack frame fp  0x1c
 #   stack frame ra  0x20
-#   stack frame sc  0x25
+#   stack frame sc  0x24
+#   $r11            0x28
        
         .text
         .global setjmp
@@ -36,6 +37,7 @@  setjmp:
 	sto.l	0x10($r0), $r10
 	sto.l	0x14($r0), $sp
 	sto.l	0x18($r0), $fp
+	sto.l	0x28($r0), $r11
 	ldo.l   $r1,       0x00($fp)
 	sto.l   0x1c($r0), $r1
 	ldo.l   $r1,       0x04($fp)
@@ -57,6 +59,7 @@  longjmp:
 	ldo.l	$r10, 0x10($r0)
 	ldo.l	$sp, 0x14($r0)
 	ldo.l	$fp, 0x18($r0)
+	ldo.l	$r11, 0x28($r0)
 	ldo.l   $r2, 0x1c($r0)
 	sto.l   0x0($fp), $r2
 	ldo.l   $r2, 0x20($r0)