MIPS: Only use current_stack_pointer on GCC
authorKees Cook <keescook@chromium.org>
Wed, 9 Mar 2022 22:09:39 +0000 (14:09 -0800)
committerThomas Bogendoerfer <tsbogend@alpha.franken.de>
Mon, 14 Mar 2022 14:02:53 +0000 (15:02 +0100)
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>
arch/mips/Kconfig
arch/mips/include/asm/thread_info.h
arch/mips/kernel/irq.c
arch/mips/lib/uncached.c

index 3f58b45fc953e53baeabc4cff9cd89656ce338e4..0dae5f1e61cc15039c159bcd923d8f7134657a68 100644 (file)
@@ -4,7 +4,7 @@ config MIPS
        default y
        select ARCH_32BIT_OFF_T if !64BIT
        select ARCH_BINFMT_ELF_STATE if MIPS_FP_SUPPORT
-       select ARCH_HAS_CURRENT_STACK_POINTER
+       select ARCH_HAS_CURRENT_STACK_POINTER if !CC_IS_CLANG || CLANG_VERSION >= 140000
        select ARCH_HAS_DEBUG_VIRTUAL if !64BIT
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_KCOV
index 4463348d237239e5c07f10cdf0de153de26583a1..ecae7470faa4058403b259c9ea199267684e30db 100644 (file)
@@ -69,7 +69,9 @@ static inline struct thread_info *current_thread_info(void)
        return __current_thread_info;
 }
 
+#ifdef CONFIG_ARCH_HAS_CURRENT_STACK_POINTER
 register unsigned long current_stack_pointer __asm__("sp");
+#endif
 
 #endif /* !__ASSEMBLY__ */
 
index fc313c49a4178f4699f6fa4dcf42e4ae98023457..5e11582fe308fac55fd317d2a85db5fd44bad80c 100644 (file)
@@ -75,8 +75,9 @@ void __init init_IRQ(void)
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 static inline void check_stack_overflow(void)
 {
-       unsigned long sp = current_stack_pointer;
+       unsigned long sp;
 
+       __asm__ __volatile__("move %0, $sp" : "=r" (sp));
        sp &= THREAD_MASK;
 
        /*
index f8d4ca046c3e3a4c10cb8b97576cba6465c7e45e..f80a67c092b63f9413c21bdedd0439df91ccd7f3 100644 (file)
@@ -40,7 +40,9 @@ unsigned long run_uncached(void *func)
        register long ret __asm__("$2");
        long lfunc = (long)func, ufunc;
        long usp;
-       long sp = current_stack_pointer;
+       long sp;
+
+       __asm__("move %0, $sp" : "=r" (sp));
 
        if (sp >= (long)CKSEG0 && sp < (long)CKSEG2)
                usp = CKSEG1ADDR(sp);