retitle 943425 klibc: [s390x] setjmp/longjmp do not save/restore all registers 
in use
# because this affects a release architecture
severity 943425 serious
thanks

Recapping for the benefit of d-s390@l.d.o:

> The code in question (where it crashes) is thus:

>    1607                  */
>    1608                 valsub(t, NULL);
>    1609                 subst_exstat = exstat & 0xFF;
>    1610                 /* rewind the tempfile and restore regular stdout */
>    1611                 lseek(shf_fileno(shf), (off_t)0, SEEK_SET);

> The crash occurs in line 1611 because shf (a local variable) is nil.
>
> The really interesting part, though, is in line 1608, a call to valsub():

[…]
>    2104         if (!kshsetjmp(e->jbuf))
>    2105                 execute(t, XXCOM | XERROK, NULL);
[…]

kshsetjmp(x) is sigsetjmp(x,0) (though klibc ignores the 0).

execute() calls siglongjmp().

> - it appears as if the combination of sigsetjmp/siglongjmp does not restore
>   all callee-saved variables correctly on s390x; comparing with glibc shows
>   that the wrong FPU registers seem to be saved but mksh does not use the
>   FPU anyway
>
> Setting breakpoints to lines 1608 (valsub call) and 1609:

[…]
> 1608                    valsub(t, NULL);
> (gdb) print shf
> $5 = (struct shf *) 0x3fffdfe5de8
> (gdb) print &shf
> Address requested for identifier "shf" which is in register $v10
> (gdb) print $v10
> $6 = {v4_float = {1.43352833e-42, -4.22639375e+37, 0, 0}, v2_double = 
> {2.1729070589754877e-311, 0}, v16_int8 = {
>     0, 0, 3, -1, -3, -2, 93, -24, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {0, 
> 1023, -514, 24040, 0, 0, 0, 0},
>   v4_int32 = {1023, -33661464, 0, 0}, v2_int64 = {4398012849640, 0}, uint128 
> = 81129017470195127308370827018240}
>
> 0x3FFFDFE5DE8 is 4398012849640 which is in v2_int64, found.
[…]
> Breakpoint 2, comsub (fn=14, cp=0x0, xp=<synthetic pointer>) at 
> ../../eval.c:1609
> 1609                    subst_exstat = exstat & 0xFF;
[…]
> (gdb) print $v10
> $7 = {v4_float = {0, 0, 0, 0}, v2_double = {0, 0}, v16_int8 = {0 <repeats 16 
> times>}, v8_int16 = {0, 0, 0, 0,
>     0, 0, 0, 0}, v4_int32 = {0, 0, 0, 0}, v2_int64 = {0, 0}, uint128 = 0}

------------------------------------------------------------------

So, setjmp/longjmp in klibc save f1/f3/f5/f7 (as shown on Wikipedia
https://en.wikipedia.org/wiki/Calling_convention#IBM_System/360_and_successors
“the z/Architecture ABI,[11] used in Linux” a page down), while
glibc’s save f8–f15 instead.

https://share.confex.com/share/124/webprogram/Handout/Session16897/SHARE_Seattle_2015_SIMD.pdf
shows that the vector registers overlap and extend the FPU registers.

(gdb) info float
[…]
f10            2.172907066248134e-311 (raw 0x000003fffdfe9768)
(gdb) print shf
$2 = (struct shf *) 0x3fffdfe9768

The real questions here are:

• is register v10 (vector extension) even supposed to be used?
• klibc does not really support the FPU anyway
• the half of v10 that equals f10 just HAPPENS to be saved by
  glibc, but what if the upper half, that is outside of the FPU,
  is used?
• where *is* the s390x̲ ABI documented anyway? syscall(2) has the
  kernel side only

Building with -mno-vx does not seem to help, %f* are still in
the .s files generated by gcc.

So I assume klibc should save registers f8–15 on s390x but what
happened to f1/f3/f5/f7?

Thanks,
//mirabilos
-- 
[17:15:07] Lukas Degener: Kleines Asterix-Latinum für Softwaretechniker:
           veni, vidi, fixi(t) ;-)

Reply via email to