[PATCH 0/2] sparc: Two problems in lazy floating point switching

Maksim E. Kozlov maksim.e.kozlov at gmail.com
Wed Jun 5 19:22:35 UTC 2019


Hi,

I think there are two problems in lazy floating point switching:
 1. Missed restoring of PSR after invoked CMP commands in
    syscall_lazy_fp_switch procedure.
 2. Mistaken clearing of PSR[EF] bit in _ISR_Handler

The following is a piece of real code, generated by gcc-9.1.0
from ordinary C++ code containing cycle for(;;) with floating
point operations inside

...
4f102d84:    b1 a6 09 58     fmuld  %f24, %f24, %f24
4f102d88:    95 a5 88 5c     faddd  %f22, %f28, %f10
4f102d8c:    92 02 61 08     add  %o1, 0x108, %o1
4f102d90:    91 a2 08 da     fsubd  %f8, %f26, %f8
4f102d94:    80 a0 80 09     cmp  %g2, %o1             <---- (1)
4f102d98:    95 a2 88 58     faddd  %f10, %f24, %f10
4f102d9c:    91 a2 09 54     fmuld  %f8, %f20, %f8
4f102da0:    95 a0 05 4a     fsqrtd  %f10, %f10
4f102da4:    d5 3b bf f8     std  %f10, [ %sp + -8 ]
4f102da8:    01 00 00 00     nop
4f102dac:    91 a2 08 4a     faddd  %f8, %f10, %f8
4f102db0:    ad a4 89 c8     fdivd  %f18, %f8, %f22
4f102db4:    ed 3b bf f8     std  %f22, [ %sp + -8 ]
4f102db8:    01 00 00 00     nop
4f102dbc:    d1 3a 7f e0     std  %f8, [ %o1 + -32 ]
4f102dc0:    d1 18 40 00     ldd  [ %g1 ], %f8
4f102dc4:    91 a2 08 ce     fsubd  %f8, %f14, %f8
4f102dc8:    91 a2 09 56     fmuld  %f8, %f22, %f8     <---- (2)
4f102dcc:    d1 3a 7f c8     std  %f8, [ %o1 + -56 ]   <---- (3)
4f102dd0:    d5 18 60 08     ldd  [ %g1 + 8 ], %f10
4f102dd4:    99 a2 88 cc     fsubd  %f10, %f12, %f12
4f102dd8:    99 a3 09 56     fmuld  %f12, %f22, %f12
4f102ddc:    d9 3a 7f d0     std  %f12, [ %o1 + -48 ]
4f102de0:    d1 18 60 10     ldd  [ %g1 + 0x10 ], %f8
4f102de4:    a1 a2 08 d0     fsubd  %f8, %f16, %f16
4f102de8:    a1 a4 09 56     fmuld  %f16, %f22, %f16
4f102dec:    e1 3a 7f d8     std  %f16, [ %o1 + -40 ]
4f102df0:    12 bf ff d8     bne  4f102d50             <---- (4)
4f102df4:    01 00 00 00     nop
...

  (1) CMP instruction is invoked and sets icc field properly.
  (2) Asynchronous interrupt occurs, _ISR_Handler clear PSR[EF] bit
  (3) First floating point instruction after interrupt causes the
      lazy fp switch procedure which uses CMP instructions inside
      and does not restores PSR on return.
  (4) "dirty" PSR[icc] is checked and our program makes wrong branch,
      so we get undefined program behavior.

The above is applied at least to gcc versions 7.4.0 and 9.1.0. With
gcc 4.4.7 this situation does not appear because it generates a bit
different code where there are no fp operations between cmp and branch
instructions (even more - nearly all cmp are followed by branches
immediately).

The second problem is - why PSR[EF] bit gets cleared after return from
interrupt although interrupted task was a floating point task? The
second patch about this - EF bit is leared in delayed slot regardless of
branch is done or not.

These two patches resolve described problems and I hope they both are
correct. Any comments are welcome.

Maksim E. Kozlov (2):
  sparc: Fix missed restoring of PSR in syscall_lazy_fp_switch
  sparc: Fix mistakenly cleared PSR[EF] bit.

 cpukit/score/cpu/sparc/cpu_asm.S | 3 ++-
 cpukit/score/cpu/sparc/syscall.S | 4 ++++
 2 files changed, 6 insertions(+), 1 deletion(-)

-- 
2.17.1



More information about the devel mailing list