From: Andi Kleen <ak@muc.de>

do_test_wp_bit cannot be inlined, otherwise the kernel doesn't boot because
the exception tables get reordered.  

Add a new noinline attribute to compiler.h and use it.

This patch is needed for the next unit-at-a-time patch. 


Linus:

 This patch seems to just hide the _real_ bug, which is that the exception
 table gets confused.

 If the exception table is confused, you'll get oopses on bad user system
 call pointers, but since that is uncommon, you'll never see it under normal
 circumstances.  This is the only exception that you'll always see.

 So it sounds like you have a compiler combination that breaks the exception
 table totally for _any_ function called from any non-regular segment, and
 this just happens to be the only one you actually saw.

 How about just fixing the exception table instead?  A bogo-sort at boot
 time?



---

 25-akpm/arch/i386/mm/init.c           |    2 +-
 25-akpm/include/linux/compiler-gcc3.h |    4 ++++
 25-akpm/include/linux/compiler.h      |    4 ++++
 3 files changed, 9 insertions(+), 1 deletion(-)

diff -puN arch/i386/mm/init.c~add-noinline-attribute arch/i386/mm/init.c
--- 25/arch/i386/mm/init.c~add-noinline-attribute	Wed Jan 14 16:07:11 2004
+++ 25-akpm/arch/i386/mm/init.c	Wed Jan 14 16:07:11 2004
@@ -555,7 +555,7 @@ void __init pgtable_cache_init(void)
  * This function cannot be __init, since exceptions don't work in that
  * section.  Put this after the callers, so that it cannot be inlined.
  */
-static int do_test_wp_bit(void)
+static int noinline do_test_wp_bit(void)
 {
 	char tmp_reg;
 	int flag;
diff -puN include/linux/compiler-gcc3.h~add-noinline-attribute include/linux/compiler-gcc3.h
--- 25/include/linux/compiler-gcc3.h~add-noinline-attribute	Wed Jan 14 16:07:11 2004
+++ 25-akpm/include/linux/compiler-gcc3.h	Wed Jan 14 16:07:11 2004
@@ -21,3 +21,7 @@
 
 #define __attribute_pure__	__attribute__((pure))
 #define __attribute_const__	__attribute__((__const__))
+
+#if __GNUC_MINOR__ >= 1
+#define  noinline __attribute__((noinline))
+#endif
diff -puN include/linux/compiler.h~add-noinline-attribute include/linux/compiler.h
--- 25/include/linux/compiler.h~add-noinline-attribute	Wed Jan 14 16:07:11 2004
+++ 25-akpm/include/linux/compiler.h	Wed Jan 14 16:07:11 2004
@@ -94,6 +94,10 @@
 # define __attribute_const__	/* unimplemented */
 #endif
 
+#ifndef noinline
+#define noinline
+#endif
+
 /* Optimization barrier */
 #ifndef barrier
 # define barrier() __memory_barrier()

_