m68k: make the __jmp_buf layout match what setjmp.S actually saves
uClibc-ng's m68k setjmp.S (David McCullough, 2002) saves "d2-d7/a2-a7" as one
moveml block at JB_REGS plus the return PC at JB_PC -- it keeps only the
call-saved registers (d0/d1/a0/a1 and fp0/fp1 are caller-saved). But
bits/setjmp.h still carried glibc's struct, which is laid out for glibc's C
setjmp.c (it saves d1-d7/a1-a5 and fills __fp/__sp explicitly). So the member
names did not line up with the saved data:
- the stack pointer (a7) actually lands in __aregs[4], while __fp/__sp were
never written (they even sat past JB_SIZE);
- JB_SIZE (52) disagreed with sizeof(struct) (60), so the sigjmp_buf
__mask_was_saved flag -- written at JB_SIZE by bsd-_setjmp.S -- and the C
struct's view of it ended up at different offsets.
This broke two things on m68k:
- jmpbuf-unwind.h read the SP from __sp (uninitialised) and __aregs[5] (the
saved PC), so NPTL forced-unwind cancellation longjmped on the first frame
and never ran the -fexceptions cleanup handlers (tst-cancelx16/18/20/21,
tst-cleanupx1/3, tst-oncex3/4);
- the JB_SIZE vs sizeof mismatch corrupted the saved-signal-mask handling
(tst-vfork-longjmp).
Fix the root cause instead of reading the SP from a magic register slot:
redefine the struct to mirror setjmp.S (__dregs[6]=d2-d7, __aregs[5]=a2-a6,
__sp=a7, __pc=return address, __fpregs=fp2-fp7), so every member is meaningful
and sizeof(__jmp_buf) == JB_SIZE. jmpbuf-unwind.h then reads __sp like every
other target, and __mask_was_saved lands where bsd-_setjmp.S writes it. Also
correct JB_SIZE for the FPU build: only fp2-fp7 are saved, so 52 + 6*12 = 124
(76 previously under-counted the fmovem area).
Verified on m68k/kernel-5.4 under qemu-system-m68k: the full test suite drops
from 11 failures to 1 (only tst-cancelx4, an unrelated blocked-in-syscall
case, remains); all setjmp/sigsetjmp/cleanup/once/vfork tests pass.
Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>