[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