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

sparc32: Fix truncated relocation errors when linking large kernels

Use jumps instead of branches when jumping from one section to another
to avoid branches to addresses further away than 22 bit offsets can
handle that results in errors such as

arch/sparc/kernel/signal_32.o:(.fixup+0x0): relocation truncated to fit: R_SPARC_WDISP22 against `.text'

This is the same approach that was taken for sparc64 in commit
52eb053b7191 ("[SPARC64]: Fix linkage of enormous kernels.")

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202405080936.tWaJdO3P-lkp@intel.com/
Closes: https://lore.kernel.org/oe-kbuild-all/202406240441.5zaoshVX-lkp@intel.com/
Link: https://lore.kernel.org/r/20240710092341.457591-1-andreas@gaisler.com
Signed-off-by: Andreas Larsson <andreas@gaisler.com>

+15 -6
+4 -2
arch/sparc/include/asm/uaccess_32.h
··· 95 95 ".section .fixup,#alloc,#execinstr\n\t" \ 96 96 ".align 4\n" \ 97 97 "3:\n\t" \ 98 - "b 2b\n\t" \ 98 + "sethi %%hi(2b), %0\n\t" \ 99 + "jmpl %0 + %%lo(2b), %%g0\n\t" \ 99 100 " mov %3, %0\n\t" \ 100 101 ".previous\n\n\t" \ 101 102 ".section __ex_table,#alloc\n\t" \ ··· 164 163 ".section .fixup,#alloc,#execinstr\n\t" \ 165 164 ".align 4\n" \ 166 165 "3:\n\t" \ 166 + "sethi %%hi(2b), %0\n\t" \ 167 167 "clr %1\n\t" \ 168 - "b 2b\n\t" \ 168 + "jmpl %0 + %%lo(2b), %%g0\n\t" \ 169 169 " mov %3, %0\n\n\t" \ 170 170 ".previous\n\t" \ 171 171 ".section __ex_table,#alloc\n\t" \
+11 -4
arch/sparc/kernel/head_32.S
··· 118 118 mov %o7, %g3 119 119 120 120 tst %o0 121 - be no_sun4u_here 121 + bne 2f 122 122 mov %g4, %o7 /* Previous %o7. */ 123 - 123 + sethi %hi(no_sun4u_here), %l1 124 + jmpl %l1 + %lo(no_sun4u_here), %g0 125 + nop 126 + 2: 124 127 mov %o0, %l0 ! stash away romvec 125 128 mov %o0, %g7 ! put it here too 126 129 mov %o1, %l1 ! stash away debug_vec too ··· 198 195 sub %o0, %l6, %o0 199 196 call %o1 200 197 nop 201 - ba halt_me 198 + sethi %hi(halt_me), %o0 199 + jmpl %o0 + %lo(halt_me), %g0 202 200 nop 203 201 204 202 not_a_sun4: ··· 435 431 #ifdef CONFIG_SMP 436 432 ldub [%g2 + %lo(boot_cpu_id)], %g1 437 433 cmp %g1, 0xff ! unset means first CPU 438 - bne leon_smp_cpu_startup ! continue only with master 434 + be 1f 435 + sethi %hi(leon_smp_cpu_startup), %g1 436 + jmpl %g1 + %lo(leon_smp_cpu_startup), %g0 439 437 nop 438 + 1: 440 439 #endif 441 440 /* Get CPU-ID from most significant 4-bit of ASR17 */ 442 441 rd %asr17, %g1