Commit 9c695203a7ddbe49dba5f22f4c941d24f47475df

Authored by Mikael Pettersson
Committed by Linus Torvalds
1 parent 2952095c6b

compiler-gcc.h: gcc-4.5 needs noclone and noinline on __naked functions

A __naked function is defined in C but with a body completely implemented
by asm(), including any prologue and epilogue.  These asm() bodies expect
standard calling conventions for parameter passing.  Older GCCs implement
that correctly, but 4.[56] currently do not, see GCC PR44290.  In the
Linux kernel this breaks ARM, causing most arch/arm/mm/copypage-*.c
modules to get miscompiled, resulting in kernel crashes during bootup.

Part of the kernel fix is to augment the __naked function attribute to
also imply noinline and noclone.  This patch implements that, and has been
verified to fix boot failures with gcc-4.5 compiled 2.6.34 and 2.6.35-rc1
kernels.  The patch is a no-op with older GCCs.

Signed-off-by: Mikael Pettersson <mikpe@it.uu.se>
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 13 additions and 1 deletions Side-by-side Diff

include/linux/compiler-gcc.h
... ... @@ -58,8 +58,12 @@
58 58 * naked functions because then mcount is called without stack and frame pointer
59 59 * being set up and there is no chance to restore the lr register to the value
60 60 * before mcount was called.
  61 + *
  62 + * The asm() bodies of naked functions often depend on standard calling conventions,
  63 + * therefore they must be noinline and noclone. GCC 4.[56] currently fail to enforce
  64 + * this, so we must do so ourselves. See GCC PR44290.
61 65 */
62   -#define __naked __attribute__((naked)) notrace
  66 +#define __naked __attribute__((naked)) noinline __noclone notrace
63 67  
64 68 #define __noreturn __attribute__((noreturn))
65 69  
... ... @@ -85,4 +89,8 @@
85 89 #define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
86 90 #define gcc_header(x) _gcc_header(x)
87 91 #include gcc_header(__GNUC__)
  92 +
  93 +#if !defined(__noclone)
  94 +#define __noclone /* not needed */
  95 +#endif
include/linux/compiler-gcc4.h
... ... @@ -48,6 +48,10 @@
48 48 * unreleased. Really, we need to have autoconf for the kernel.
49 49 */
50 50 #define unreachable() __builtin_unreachable()
  51 +
  52 +/* Mark a function definition as prohibited from being cloned. */
  53 +#define __noclone __attribute__((__noclone__))
  54 +
51 55 #endif
52 56  
53 57 #endif