linux/arch
Yao Zi 1fe3b402b1 MIPS: Work around LLVM bug when gp is used as global register variable
commit 30bfc2d6a1 upstream.

On MIPS, __current_thread_info is defined as global register variable
locating in $gp, and is simply assigned with new address during kernel
relocation.

This however is broken with LLVM, which always restores $gp if it finds
$gp is clobbered in any form, including when intentionally through a
global register variable. This is against GCC's documentation[1], which
requires a callee-saved register used as global register variable not to
be restored if it's clobbered.

As a result, $gp will continue to point to the unrelocated kernel after
the epilog of relocate_kernel(), leading to an early crash in init_idle,

[    0.000000] CPU 0 Unable to handle kernel paging request at virtual address 0000000000000000, epc == ffffffff81afada8, ra == ffffffff81afad90
[    0.000000] Oops[#1]:
[    0.000000] CPU: 0 UID: 0 PID: 0 Comm: swapper Tainted: G        W           6.19.0-rc5-00262-gd3eeb99bbc99-dirty #188 VOLUNTARY
[    0.000000] Tainted: [W]=WARN
[    0.000000] Hardware name: loongson,loongson64v-4core-virtio
[    0.000000] $ 0   : 0000000000000000 0000000000000000 0000000000000001 0000000000000000
[    0.000000] $ 4   : ffffffff80b80ec0 ffffffff80b53d48 0000000000000000 00000000000f4240
[    0.000000] $ 8   : 0000000000000100 ffffffff81d82f80 ffffffff81d82f80 0000000000000001
[    0.000000] $12   : 0000000000000000 ffffffff81776f58 00000000000005da 0000000000000002
[    0.000000] $16   : ffffffff80b80e40 0000000000000000 ffffffff80b81614 9800000005dfbe80
[    0.000000] $20   : 00000000540000e0 ffffffff81980000 0000000000000000 ffffffff80f81c80
[    0.000000] $24   : 0000000000000a26 ffffffff8114fb90
[    0.000000] $28   : ffffffff80b50000 ffffffff80b53d40 0000000000000000 ffffffff81afad90
[    0.000000] Hi    : 0000000000000000
[    0.000000] Lo    : 0000000000000000
[    0.000000] epc   : ffffffff81afada8 init_idle+0x130/0x270
[    0.000000] ra    : ffffffff81afad90 init_idle+0x118/0x270
[    0.000000] Status: 540000e2	KX SX UX KERNEL EXL
[    0.000000] Cause : 00000008 (ExcCode 02)
[    0.000000] BadVA : 0000000000000000
[    0.000000] PrId  : 00006305 (ICT Loongson-3)
[    0.000000] Process swapper (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000)
[    0.000000] Stack : 9800000005dfbf00 ffffffff8178e950 0000000000000000 0000000000000000
[    0.000000]         0000000000000000 ffffffff81970000 000000000000003f ffffffff810a6528
[    0.000000]         0000000000000001 9800000005dfbe80 9800000005dfbf00 ffffffff81980000
[    0.000000]         ffffffff810a6450 ffffffff81afb6c0 0000000000000000 ffffffff810a2258
[    0.000000]         ffffffff81d82ec8 ffffffff8198d010 ffffffff81b67e80 ffffffff8197dd98
[    0.000000]         ffffffff81d81c80 ffffffff81930000 0000000000000040 0000000000000000
[    0.000000]         0000000000000000 0000000000000000 0000000000000000 0000000000000000
[    0.000000]         0000000000000000 000000000000009e ffffffff9fc01000 0000000000000000
[    0.000000]         0000000000000000 0000000000000000 0000000000000000 0000000000000000
[    0.000000]         0000000000000000 ffffffff81ae86dc ffffffff81b3c741 0000000000000002
[    0.000000]         ...
[    0.000000] Call Trace:
[    0.000000] [<ffffffff81afada8>] init_idle+0x130/0x270
[    0.000000] [<ffffffff81afb6c0>] sched_init+0x5c8/0x6c0
[    0.000000] [<ffffffff81ae86dc>] start_kernel+0x27c/0x7a8

This bug has been reported to LLVM[2] and affects version from (at
least) 18 to 21. Let's work around this by using inline assembly to
assign $gp before a fix is widely available.

Cc: stable@vger.kernel.org
Link: https://gcc.gnu.org/onlinedocs/gcc-15.2.0/gcc/Global-Register-Variables.html # [1]
Link: https://github.com/llvm/llvm-project/issues/176546 # [2]
Signed-off-by: Yao Zi <me@ziyao.cc>
Acked-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2026-03-04 07:19:54 -05:00
..
alpha alpha: don't reference obsolete termio struct for TC* constants 2026-01-19 13:10:15 +01:00
arc arc: Fix __fls() const-foldability via __builtin_clzl() 2025-12-07 06:09:16 +09:00
arm arm: dts: lpc32xx: add clocks property to Motor Control PWM device tree node 2026-03-04 07:19:29 -05:00
arm64 arm64: dts: qcom: sdm845-db845c: specify power for WiFi CH1 2026-03-04 07:19:30 -05:00
csky csky: fix csky_cmpxchg_fixup not working 2026-01-19 13:10:15 +01:00
h8300 sched: Add wrapper for get_wchan() to keep task blocked 2025-08-28 16:24:03 +02:00
hexagon sched: Add wrapper for get_wchan() to keep task blocked 2025-08-28 16:24:03 +02:00
ia64 sched: Add wrapper for get_wchan() to keep task blocked 2025-08-28 16:24:03 +02:00
m68k m68k: bitops: Fix find_*_bit() signatures 2025-10-29 14:03:10 +01:00
microblaze sched: Add wrapper for get_wchan() to keep task blocked 2025-08-28 16:24:03 +02:00
mips MIPS: Work around LLVM bug when gp is used as global register variable 2026-03-04 07:19:54 -05:00
nds32 sched: Add wrapper for get_wchan() to keep task blocked 2025-08-28 16:24:03 +02:00
nios2 nios2: ensure that memblock.current_limit is set when setting pfn limits 2025-10-29 14:03:10 +01:00
openrisc sched: Add wrapper for get_wchan() to keep task blocked 2025-08-28 16:24:03 +02:00
parisc parisc: entry: set W bit for !compat tasks in syscall_restore_rfi() 2026-01-19 13:10:01 +01:00
powerpc powerpc/eeh: fix recursive pci_lock_rescan_remove locking in EEH event handling 2026-03-04 07:19:29 -05:00
riscv riscv: Replace function-like macro by static inline function 2026-02-11 13:35:34 +01:00
s390 s390/smp: Fix fallback CPU detection 2026-01-19 13:09:24 +01:00
sh sh: Do not use hyphen in exported variable name 2025-08-28 16:24:11 +02:00
sparc sparc/module: Add R_SPARC_UA64 relocation handling 2025-12-07 06:09:23 +09:00
um um: Fix help message for ssl-non-raw 2025-12-07 06:09:24 +09:00
x86 x86/kfence: fix booting on 32bit non-PAE systems 2026-02-11 13:35:26 +01:00
xtensa sched: Add wrapper for get_wchan() to keep task blocked 2025-08-28 16:24:03 +02:00
.gitignore .gitignore: prefix local generated files with a slash 2021-05-02 00:43:35 +09:00
Kconfig cpu: Re-enable CPU mitigations by default for !X86 architectures 2024-05-02 16:24:48 +02:00