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

MIPS: Only use current_stack_pointer on GCC

Unfortunately, Clang did not have support for "sp" as a global register
definition, and was crashing after the addition of current_stack_pointer.
This has been fixed in Clang 14, but earlier Clang versions need to
avoid this code, so add a versioned test and revert back to the
open-coded asm instances. Fixes Clang build error:

fatal error: error in backend: Invalid register name global variable

Fixes: 200ed341b864 ("mips: Implement "current_stack_pointer"")
Reported-by: Nathan Chancellor <nathan@kernel.org>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Link: https://lore.kernel.org/lkml/YikTQRql+il3HbrK@dev-arch.thelio-3990X
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Yanteng Si <siyanteng01@gmail.com>
Cc: linux-mips@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

authored by

Kees Cook and committed by
Thomas Bogendoerfer
b847bd64 4d409ca3

+8 -3
+1 -1
arch/mips/Kconfig
··· 4 4 default y 5 5 select ARCH_32BIT_OFF_T if !64BIT 6 6 select ARCH_BINFMT_ELF_STATE if MIPS_FP_SUPPORT 7 - select ARCH_HAS_CURRENT_STACK_POINTER 7 + select ARCH_HAS_CURRENT_STACK_POINTER if !CC_IS_CLANG || CLANG_VERSION >= 140000 8 8 select ARCH_HAS_DEBUG_VIRTUAL if !64BIT 9 9 select ARCH_HAS_FORTIFY_SOURCE 10 10 select ARCH_HAS_KCOV
+2
arch/mips/include/asm/thread_info.h
··· 69 69 return __current_thread_info; 70 70 } 71 71 72 + #ifdef CONFIG_ARCH_HAS_CURRENT_STACK_POINTER 72 73 register unsigned long current_stack_pointer __asm__("sp"); 74 + #endif 73 75 74 76 #endif /* !__ASSEMBLY__ */ 75 77
+2 -1
arch/mips/kernel/irq.c
··· 75 75 #ifdef CONFIG_DEBUG_STACKOVERFLOW 76 76 static inline void check_stack_overflow(void) 77 77 { 78 - unsigned long sp = current_stack_pointer; 78 + unsigned long sp; 79 79 80 + __asm__ __volatile__("move %0, $sp" : "=r" (sp)); 80 81 sp &= THREAD_MASK; 81 82 82 83 /*
+3 -1
arch/mips/lib/uncached.c
··· 40 40 register long ret __asm__("$2"); 41 41 long lfunc = (long)func, ufunc; 42 42 long usp; 43 - long sp = current_stack_pointer; 43 + long sp; 44 + 45 + __asm__("move %0, $sp" : "=r" (sp)); 44 46 45 47 if (sp >= (long)CKSEG0 && sp < (long)CKSEG2) 46 48 usp = CKSEG1ADDR(sp);