Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sparc: fix accurate exception reporting in copy_{from_to}_user for Niagara

The referenced commit introduced exception handlers on user-space memory
references in copy_from_user and copy_to_user. These handlers return from
the respective function and calculate the remaining bytes left to copy
using the current register contents. This commit fixes a couple of bad
calculations and a broken epilogue in the exception handlers. This will
prevent crashes and ensure correct return values of copy_from_user and
copy_to_user in the faulting case. The behaviour of memcpy stays unchanged.

Fixes: 7ae3aaf53f16 ("sparc64: Convert NGcopy_{from,to}_user to accurate exception reporting.")
Tested-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> # on SPARC T4 with modified kernel to use Niagara 1 code
Tested-by: Magnus Lindholm <linmag7@gmail.com> # on Sun Fire T2000
Signed-off-by: Michael Karcher <kernel@mkarcher.dialup.fu-berlin.de>
Tested-by: Ethan Hawke <ehawk@ember.systems> # on Sun Fire T2000
Tested-by: Ken Link <iissmart@numberzero.org> # on Sun Fire T1000
Reviewed-by: Andreas Larsson <andreas@gaisler.com>
Link: https://lore.kernel.org/r/20250905-memcpy_series-v4-3-1ca72dda195b@mkarcher.dialup.fu-berlin.de
Signed-off-by: Andreas Larsson <andreas@gaisler.com>

authored by

Michael Karcher and committed by
Andreas Larsson
0b67c8fc 47b49c06

+18 -11
+18 -11
arch/sparc/lib/NGmemcpy.S
··· 79 79 #ifndef EX_RETVAL 80 80 #define EX_RETVAL(x) x 81 81 __restore_asi: 82 - ret 83 82 wr %g0, ASI_AIUS, %asi 83 + ret 84 84 restore 85 85 ENTRY(NG_ret_i2_plus_i4_plus_1) 86 86 ba,pt %xcc, __restore_asi ··· 125 125 ba,pt %xcc, __restore_asi 126 126 add %i2, %g1, %i0 127 127 ENDPROC(NG_ret_i2_plus_g1_minus_56) 128 - ENTRY(NG_ret_i2_plus_i4) 128 + ENTRY(NG_ret_i2_plus_i4_plus_16) 129 + add %i4, 16, %i4 129 130 ba,pt %xcc, __restore_asi 130 131 add %i2, %i4, %i0 131 - ENDPROC(NG_ret_i2_plus_i4) 132 - ENTRY(NG_ret_i2_plus_i4_minus_8) 133 - sub %i4, 8, %i4 132 + ENDPROC(NG_ret_i2_plus_i4_plus_16) 133 + ENTRY(NG_ret_i2_plus_i4_plus_8) 134 + add %i4, 8, %i4 134 135 ba,pt %xcc, __restore_asi 135 136 add %i2, %i4, %i0 136 - ENDPROC(NG_ret_i2_plus_i4_minus_8) 137 + ENDPROC(NG_ret_i2_plus_i4_plus_8) 137 138 ENTRY(NG_ret_i2_plus_8) 138 139 ba,pt %xcc, __restore_asi 139 140 add %i2, 8, %i0 ··· 158 157 ENDPROC(NG_ret_i2) 159 158 ENTRY(NG_ret_i2_and_7_plus_i4) 160 159 and %i2, 7, %i2 160 + ba,pt %xcc, __restore_asi 161 + add %i2, %i4, %i0 162 + ENDPROC(NG_ret_i2_and_7_plus_i4) 163 + ENTRY(NG_ret_i2_and_7_plus_i4_plus_8) 164 + and %i2, 7, %i2 165 + add %i4, 8, %i4 161 166 ba,pt %xcc, __restore_asi 162 167 add %i2, %i4, %i0 163 168 ENDPROC(NG_ret_i2_and_7_plus_i4) ··· 412 405 andn %i2, 0xf, %i4 413 406 and %i2, 0xf, %i2 414 407 1: subcc %i4, 0x10, %i4 415 - EX_LD(LOAD(ldx, %i1, %o4), NG_ret_i2_plus_i4) 408 + EX_LD(LOAD(ldx, %i1, %o4), NG_ret_i2_plus_i4_plus_16) 416 409 add %i1, 0x08, %i1 417 - EX_LD(LOAD(ldx, %i1, %g1), NG_ret_i2_plus_i4) 410 + EX_LD(LOAD(ldx, %i1, %g1), NG_ret_i2_plus_i4_plus_16) 418 411 sub %i1, 0x08, %i1 419 - EX_ST(STORE(stx, %o4, %i1 + %i3), NG_ret_i2_plus_i4) 412 + EX_ST(STORE(stx, %o4, %i1 + %i3), NG_ret_i2_plus_i4_plus_16) 420 413 add %i1, 0x8, %i1 421 - EX_ST(STORE(stx, %g1, %i1 + %i3), NG_ret_i2_plus_i4_minus_8) 414 + EX_ST(STORE(stx, %g1, %i1 + %i3), NG_ret_i2_plus_i4_plus_8) 422 415 bgu,pt %XCC, 1b 423 416 add %i1, 0x8, %i1 424 417 73: andcc %i2, 0x8, %g0 ··· 475 468 subcc %i4, 0x8, %i4 476 469 srlx %g3, %i3, %i5 477 470 or %i5, %g2, %i5 478 - EX_ST(STORE(stx, %i5, %o0), NG_ret_i2_and_7_plus_i4) 471 + EX_ST(STORE(stx, %i5, %o0), NG_ret_i2_and_7_plus_i4_plus_8) 479 472 add %o0, 0x8, %o0 480 473 bgu,pt %icc, 1b 481 474 sllx %g3, %g1, %g2