linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Proposed patch to kernel.h
@ 2003-05-27 22:51 Paul Mackerras
  2003-05-29  2:00 ` Paul Mackerras
  0 siblings, 1 reply; 5+ messages in thread
From: Paul Mackerras @ 2003-05-27 22:51 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel

Linus,

PowerPC has a conditional trap instruction that I would like to use
for BUG_ON.  I would like to make BUG_ON for ppc look like this:

#define BUG_ON(x) do {						\
	__asm__ __volatile__(					\
		"1:	twnei %0,0\n"				\
		".section __bug_table,\"a\"\n"			\
		"	.long 1b,%1,%2\n"			\
		".previous"					\
		: : "r" (x), "i" (__LINE__), "i" (__FILE__));	\
} while (0)

This avoids a conditional branch and is nice and compact.  (The twnei
instruction takes an exception if the register operand is not equal
to the immediate operand - trap word not equal immediate.)

However, at the moment BUG_ON is unconditionally defined in kernel.h.
The patch below is the simplest way I can see to make it possible for
architectures to supply their own BUG_ON.  Please apply.

Thanks,
Paul.

diff -urN linux-2.5/include/linux/kernel.h pmac-2.5/include/linux/kernel.h
--- linux-2.5/include/linux/kernel.h	2003-05-21 08:27:25.000000000 +1000
+++ pmac-2.5/include/linux/kernel.h	2003-05-26 22:01:54.000000000 +1000
@@ -228,7 +228,9 @@
 	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
 };
 
+#ifndef BUG_ON
 #define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#endif
 #define WARN_ON(condition) do { \
 	if (unlikely((condition)!=0)) { \
 		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Proposed patch to kernel.h
  2003-05-27 22:51 Proposed patch to kernel.h Paul Mackerras
@ 2003-05-29  2:00 ` Paul Mackerras
  2003-05-29  2:23   ` Linus Torvalds
  0 siblings, 1 reply; 5+ messages in thread
From: Paul Mackerras @ 2003-05-29  2:00 UTC (permalink / raw)
  To: torvalds
  Cc: davem, rth, rmk, bjorn, jes, ralf, matthew, gniibe, jdike,
	uclinux-v850, davidm, anton, ak, linux-kernel

On second thoughts, it would be cleaner to move BUG_ON() into each
architecture's bug.h alongside BUG() and PAGE_BUG(), rather than using
an ifdef in kernel.h as my previous patch did.

This patch moves the definition of BUG_ON from include/linux/kernel.h
into include/asm-*/bug.h so that I can use a conditional-trap
instruction to implement BUG_ON on PowerPC.

Architecture maintainers, this should be completely benign.  An ack
would still be appreciated, though.  If this will let you improve your
BUG_ON too, please let me know.

Thanks,
Paul.

diff -urN linux-2.5/include/asm-alpha/bug.h pmac-2.5/include/asm-alpha/bug.h
--- linux-2.5/include/asm-alpha/bug.h	2002-02-25 03:51:44.000000000 +1100
+++ pmac-2.5/include/asm-alpha/bug.h	2003-05-28 18:33:23.000000000 +1000
@@ -9,6 +9,8 @@
   __asm__ __volatile__("call_pal %0  # bugchk\n\t"".long %1\n\t.8byte %2" \
 		       : : "i" (PAL_bugchk), "i"(__LINE__), "i"(__FILE__))
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #define PAGE_BUG(page)	BUG()
 
 #endif
diff -urN linux-2.5/include/asm-arm/bug.h pmac-2.5/include/asm-arm/bug.h
--- linux-2.5/include/asm-arm/bug.h	2003-02-02 04:15:11.000000000 +1100
+++ pmac-2.5/include/asm-arm/bug.h	2003-05-28 18:33:35.000000000 +1000
@@ -18,4 +18,6 @@
 
 #endif
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #endif
diff -urN linux-2.5/include/asm-cris/bug.h pmac-2.5/include/asm-cris/bug.h
--- linux-2.5/include/asm-cris/bug.h	2002-01-06 22:46:09.000000000 +1100
+++ pmac-2.5/include/asm-cris/bug.h	2003-05-28 18:33:44.000000000 +1000
@@ -9,4 +9,6 @@
          BUG(); \
 } while (0)
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #endif
diff -urN linux-2.5/include/asm-h8300/bug.h pmac-2.5/include/asm-h8300/bug.h
--- linux-2.5/include/asm-h8300/bug.h	2003-04-18 05:31:21.000000000 +1000
+++ pmac-2.5/include/asm-h8300/bug.h	2003-05-28 18:34:07.000000000 +1000
@@ -9,4 +9,6 @@
          BUG(); \
 } while (0)
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #endif
diff -urN linux-2.5/include/asm-i386/bug.h pmac-2.5/include/asm-i386/bug.h
--- linux-2.5/include/asm-i386/bug.h	2003-02-17 10:52:20.000000000 +1100
+++ pmac-2.5/include/asm-i386/bug.h	2003-05-28 18:34:35.000000000 +1000
@@ -19,6 +19,8 @@
 #define BUG() __asm__ __volatile__("ud2\n")
 #endif
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
diff -urN linux-2.5/include/asm-ia64/bug.h pmac-2.5/include/asm-ia64/bug.h
--- linux-2.5/include/asm-ia64/bug.h	2002-01-06 22:57:28.000000000 +1100
+++ pmac-2.5/include/asm-ia64/bug.h	2003-05-28 18:34:51.000000000 +1000
@@ -7,6 +7,7 @@
 # define ia64_abort()	(*(volatile int *) 0 = 0)
 #endif
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0)
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #define PAGE_BUG(page) do { BUG(); } while (0)
 
 #endif
diff -urN linux-2.5/include/asm-m68k/bug.h pmac-2.5/include/asm-m68k/bug.h
--- linux-2.5/include/asm-m68k/bug.h	2002-07-26 06:17:16.000000000 +1000
+++ pmac-2.5/include/asm-m68k/bug.h	2003-05-28 18:35:34.000000000 +1000
@@ -21,6 +21,11 @@
 } while (0)
 #endif
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
diff -urN linux-2.5/include/asm-m68knommu/bug.h pmac-2.5/include/asm-m68knommu/bug.h
--- linux-2.5/include/asm-m68knommu/bug.h	2003-01-15 22:04:34.000000000 +1100
+++ pmac-2.5/include/asm-m68knommu/bug.h	2003-05-28 18:35:54.000000000 +1000
@@ -5,6 +5,11 @@
   printk("%s(%d): kernel BUG!\n", __FILE__, __LINE__); \
 } while (0)
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
          BUG(); \
 } while (0)
diff -urN linux-2.5/include/asm-mips/bug.h pmac-2.5/include/asm-mips/bug.h
--- linux-2.5/include/asm-mips/bug.h	2002-01-06 22:57:49.000000000 +1100
+++ pmac-2.5/include/asm-mips/bug.h	2003-05-28 18:36:16.000000000 +1000
@@ -3,6 +3,7 @@
 #define __ASM_BUG_H
 
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #define PAGE_BUG(page) do {  BUG(); } while (0)
 
 #endif
diff -urN linux-2.5/include/asm-mips64/bug.h pmac-2.5/include/asm-mips64/bug.h
--- linux-2.5/include/asm-mips64/bug.h	2002-01-06 22:51:12.000000000 +1100
+++ pmac-2.5/include/asm-mips64/bug.h	2003-05-28 18:36:23.000000000 +1000
@@ -2,6 +2,7 @@
 #define _ASM_BUG_H
 
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #define PAGE_BUG(page) do {  BUG(); } while (0)
 
 #endif
diff -urN linux-2.5/include/asm-parisc/bug.h pmac-2.5/include/asm-parisc/bug.h
--- linux-2.5/include/asm-parisc/bug.h	2003-03-18 04:58:50.000000000 +1100
+++ pmac-2.5/include/asm-parisc/bug.h	2003-05-28 18:36:42.000000000 +1000
@@ -10,6 +10,11 @@
 	dump_stack(); \
 } while (0)
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
diff -urN linux-2.5/include/asm-ppc/bug.h pmac-2.5/include/asm-ppc/bug.h
--- linux-2.5/include/asm-ppc/bug.h	2003-05-26 22:18:59.000000000 +1000
+++ pmac-2.5/include/asm-ppc/bug.h	2003-05-27 11:24:03.000000000 +1000
@@ -1,9 +1,28 @@
 #ifndef _PPC_BUG_H
 #define _PPC_BUG_H
 
-#define BUG() do { \
-	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-	__asm__ __volatile__(".long 0x0"); \
+struct bug_entry {
+	unsigned long	bug_addr;
+	int		line;
+	const char	*file;
+};
+
+#define BUG() do {					\
+	__asm__ __volatile__(				\
+		"1:	twi 31,0,0\n"			\
+		".section __bug_table,\"a\"\n\t"	\
+		"	.long 1b,%0,%1\n"		\
+		".previous"				\
+		: : "i" (__LINE__), "i" (__FILE__));	\
+} while (0)
+
+#define BUG_ON(x) do {						\
+	__asm__ __volatile__(					\
+		"1:	twnei %0,0\n"				\
+		".section __bug_table,\"a\"\n\t"		\
+		"	.long 1b,%1,%2\n"			\
+		".previous"					\
+		: : "r" (x), "i" (__LINE__), "i" (__FILE__));	\
 } while (0)
 
 #define PAGE_BUG(page) do { BUG(); } while (0)
diff -urN linux-2.5/include/asm-ppc64/bug.h pmac-2.5/include/asm-ppc64/bug.h
--- linux-2.5/include/asm-ppc64/bug.h	2003-01-15 20:38:42.000000000 +1100
+++ pmac-2.5/include/asm-ppc64/bug.h	2003-05-28 18:36:55.000000000 +1000
@@ -27,6 +27,8 @@
 } while (0)
 #endif
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #define PAGE_BUG(page) do { BUG(); } while (0)
 
 #endif
diff -urN linux-2.5/include/asm-s390/bug.h pmac-2.5/include/asm-s390/bug.h
--- linux-2.5/include/asm-s390/bug.h	2002-01-06 22:53:36.000000000 +1100
+++ pmac-2.5/include/asm-s390/bug.h	2003-05-28 18:37:12.000000000 +1000
@@ -6,6 +6,11 @@
         __asm__ __volatile__(".long 0"); \
 } while (0)                                       
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
         BUG(); \
 } while (0)                      
diff -urN linux-2.5/include/asm-sh/bug.h pmac-2.5/include/asm-sh/bug.h
--- linux-2.5/include/asm-sh/bug.h	2002-01-06 22:54:51.000000000 +1100
+++ pmac-2.5/include/asm-sh/bug.h	2003-05-28 18:37:24.000000000 +1000
@@ -9,6 +9,11 @@
 	asm volatile("nop"); \
 } while (0)
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
diff -urN linux-2.5/include/asm-sparc/bug.h pmac-2.5/include/asm-sparc/bug.h
--- linux-2.5/include/asm-sparc/bug.h	2003-05-21 08:27:25.000000000 +1000
+++ pmac-2.5/include/asm-sparc/bug.h	2003-05-28 18:37:37.000000000 +1000
@@ -12,6 +12,11 @@
 #define BUG()		__builtin_trap()
 #endif
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
diff -urN linux-2.5/include/asm-sparc64/bug.h pmac-2.5/include/asm-sparc64/bug.h
--- linux-2.5/include/asm-sparc64/bug.h	2003-01-15 00:51:44.000000000 +1100
+++ pmac-2.5/include/asm-sparc64/bug.h	2003-05-28 18:37:44.000000000 +1000
@@ -13,6 +13,11 @@
 #define BUG()		__builtin_trap()
 #endif
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
diff -urN linux-2.5/include/asm-um/bug.h pmac-2.5/include/asm-um/bug.h
--- linux-2.5/include/asm-um/bug.h	2003-01-17 02:42:26.000000000 +1100
+++ pmac-2.5/include/asm-um/bug.h	2003-05-28 18:37:56.000000000 +1000
@@ -7,6 +7,11 @@
 	panic("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
 } while (0)
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
diff -urN linux-2.5/include/asm-v850/bug.h pmac-2.5/include/asm-v850/bug.h
--- linux-2.5/include/asm-v850/bug.h	2003-02-18 13:41:09.000000000 +1100
+++ pmac-2.5/include/asm-v850/bug.h	2003-05-28 18:38:18.000000000 +1000
@@ -18,4 +18,6 @@
 #define BUG()		__bug()
 #define PAGE_BUG(page)	__bug()
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #endif /* __V850_BUG_H__ */
diff -urN linux-2.5/include/asm-x86_64/bug.h pmac-2.5/include/asm-x86_64/bug.h
--- linux-2.5/include/asm-x86_64/bug.h	2003-01-17 06:36:26.000000000 +1100
+++ pmac-2.5/include/asm-x86_64/bug.h	2003-05-28 18:38:32.000000000 +1000
@@ -18,6 +18,7 @@
 #define BUG() \
 	asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \
 		     "i"(__LINE__), "i" (__stringify(KBUILD_BASENAME)))
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #define PAGE_BUG(page) BUG()
 void out_of_line_bug(void);
 
diff -urN linux-2.5/include/linux/kernel.h pmac-2.5/include/linux/kernel.h
--- linux-2.5/include/linux/kernel.h	2003-05-21 08:27:25.000000000 +1000
+++ pmac-2.5/include/linux/kernel.h	2003-05-28 18:32:37.000000000 +1000
@@ -228,7 +228,6 @@
 	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
 };
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #define WARN_ON(condition) do { \
 	if (unlikely((condition)!=0)) { \
 		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Proposed patch to kernel.h
  2003-05-29  2:00 ` Paul Mackerras
@ 2003-05-29  2:23   ` Linus Torvalds
  2003-05-29 12:32     ` Paul Mackerras
  0 siblings, 1 reply; 5+ messages in thread
From: Linus Torvalds @ 2003-05-29  2:23 UTC (permalink / raw)
  To: Paul Mackerras
  Cc: davem, rth, rmk, bjorn, jes, ralf, matthew, gniibe, jdike,
	uclinux-v850, davidm, anton, ak, linux-kernel


On Thu, 29 May 2003, Paul Mackerras wrote:
>
> On second thoughts, it would be cleaner to move BUG_ON() into each
> architecture's bug.h alongside BUG() and PAGE_BUG(), rather than using
> an ifdef in kernel.h as my previous patch did.

Wouldn't it make sense to do the same thing to "WARN_ON()" then? It sounds 
entirely appropriate to use the same kind of conditional trap instructions 
for that too.. (The only difference being a bit somewhere that says that 
the "WARN_ON()" kind of trap handler should resume after the fault).

		Linus


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Proposed patch to kernel.h
  2003-05-29  2:23   ` Linus Torvalds
@ 2003-05-29 12:32     ` Paul Mackerras
  2003-05-30  8:03       ` Rusty Russell
  0 siblings, 1 reply; 5+ messages in thread
From: Paul Mackerras @ 2003-05-29 12:32 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: davem, rth, rmk, jes, ralf, matthew, jdike, uclinux-v850, davidm,
	anton, ak, rusty, linux-kernel

Linus Torvalds writes:

> Wouldn't it make sense to do the same thing to "WARN_ON()" then? It sounds 
> entirely appropriate to use the same kind of conditional trap instructions 
> for that too.. (The only difference being a bit somewhere that says that 
> the "WARN_ON()" kind of trap handler should resume after the fault).

Excellent idea.  Here is a patch that does that.

I have included all the bits that handle the __bug_table section on
ppc so you all can see the complete implementation.  The __bug_table
section has 4 words for each BUG/BUG_ON/WARN_ON, which are the address
of the trap instruction, the line number (with a high bit used to
indicate a WARN_ON as distinct from a BUG/BUG_ON), and pointers to the
filename and function name.  I did it this way rather than putting the
information in line because putting it in line would mean an extra
branch and would pollute the icache unnecessarily.

At Rusty's suggestion, I added some fields to the mod_arch_specific
structure for ppc to hold a pointer to the __bug_table section for
each module, so I can use BUG et al. in modules.  That gets set up in
module_finalize and added to a global list.

That meant that I needed to use find_sec(), which was static in
kernel/module.c (to find the __bug_table section), so I renamed it to
elf_find_sec() and made it externally accessible (once again at
Rusty's suggestion).

Tested OK on ppc, and compile-tested on x86 successfully.

How does this look?

Paul.

diff -urN linux-2.5/include/asm-alpha/bug.h pmac-2.5/include/asm-alpha/bug.h
--- linux-2.5/include/asm-alpha/bug.h	2002-02-25 03:51:44.000000000 +1100
+++ pmac-2.5/include/asm-alpha/bug.h	2003-05-29 19:51:06.000000000 +1000
@@ -9,6 +9,15 @@
   __asm__ __volatile__("call_pal %0  # bugchk\n\t"".long %1\n\t.8byte %2" \
 		       : : "i" (PAL_bugchk), "i"(__LINE__), "i"(__FILE__))
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #define PAGE_BUG(page)	BUG()
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-arm/bug.h pmac-2.5/include/asm-arm/bug.h
--- linux-2.5/include/asm-arm/bug.h	2003-02-04 19:36:43.000000000 +1100
+++ pmac-2.5/include/asm-arm/bug.h	2003-05-29 19:49:38.000000000 +1000
@@ -18,4 +18,13 @@
 
 #endif
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-cris/bug.h pmac-2.5/include/asm-cris/bug.h
--- linux-2.5/include/asm-cris/bug.h	2002-01-06 22:46:09.000000000 +1100
+++ pmac-2.5/include/asm-cris/bug.h	2003-05-29 19:49:48.000000000 +1000
@@ -9,4 +9,13 @@
          BUG(); \
 } while (0)
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-h8300/bug.h pmac-2.5/include/asm-h8300/bug.h
--- linux-2.5/include/asm-h8300/bug.h	2003-04-18 05:31:21.000000000 +1000
+++ pmac-2.5/include/asm-h8300/bug.h	2003-05-29 19:50:01.000000000 +1000
@@ -9,4 +9,13 @@
          BUG(); \
 } while (0)
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-i386/bug.h pmac-2.5/include/asm-i386/bug.h
--- linux-2.5/include/asm-i386/bug.h	2003-03-08 14:12:53.000000000 +1100
+++ pmac-2.5/include/asm-i386/bug.h	2003-05-29 19:51:35.000000000 +1000
@@ -19,8 +19,17 @@
 #define BUG() __asm__ __volatile__("ud2\n")
 #endif
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-ia64/bug.h pmac-2.5/include/asm-ia64/bug.h
--- linux-2.5/include/asm-ia64/bug.h	2002-01-06 22:57:28.000000000 +1100
+++ pmac-2.5/include/asm-ia64/bug.h	2003-05-29 19:51:50.000000000 +1000
@@ -7,6 +7,16 @@
 # define ia64_abort()	(*(volatile int *) 0 = 0)
 #endif
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0)
+
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #define PAGE_BUG(page) do { BUG(); } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-m68k/bug.h pmac-2.5/include/asm-m68k/bug.h
--- linux-2.5/include/asm-m68k/bug.h	2002-07-26 06:17:16.000000000 +1000
+++ pmac-2.5/include/asm-m68k/bug.h	2003-05-29 19:50:57.000000000 +1000
@@ -21,8 +21,20 @@
 } while (0)
 #endif
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-m68knommu/bug.h pmac-2.5/include/asm-m68knommu/bug.h
--- linux-2.5/include/asm-m68knommu/bug.h	2003-01-15 22:04:34.000000000 +1100
+++ pmac-2.5/include/asm-m68knommu/bug.h	2003-05-29 19:52:13.000000000 +1000
@@ -5,8 +5,20 @@
   printk("%s(%d): kernel BUG!\n", __FILE__, __LINE__); \
 } while (0)
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
          BUG(); \
 } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-mips/bug.h pmac-2.5/include/asm-mips/bug.h
--- linux-2.5/include/asm-mips/bug.h	2002-01-06 22:57:49.000000000 +1100
+++ pmac-2.5/include/asm-mips/bug.h	2003-05-29 19:52:26.000000000 +1000
@@ -3,6 +3,14 @@
 #define __ASM_BUG_H
 
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #define PAGE_BUG(page) do {  BUG(); } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-mips64/bug.h pmac-2.5/include/asm-mips64/bug.h
--- linux-2.5/include/asm-mips64/bug.h	2002-01-06 22:51:12.000000000 +1100
+++ pmac-2.5/include/asm-mips64/bug.h	2003-05-29 19:52:32.000000000 +1000
@@ -2,6 +2,14 @@
 #define _ASM_BUG_H
 
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #define PAGE_BUG(page) do {  BUG(); } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-parisc/bug.h pmac-2.5/include/asm-parisc/bug.h
--- linux-2.5/include/asm-parisc/bug.h	2003-03-20 09:07:22.000000000 +1100
+++ pmac-2.5/include/asm-parisc/bug.h	2003-05-29 19:52:43.000000000 +1000
@@ -10,8 +10,20 @@
 	dump_stack(); \
 } while (0)
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-ppc/bug.h pmac-2.5/include/asm-ppc/bug.h
--- linux-2.5/include/asm-ppc/bug.h	2003-05-29 13:45:33.000000000 +1000
+++ pmac-2.5/include/asm-ppc/bug.h	2003-05-29 21:23:54.000000000 +1000
@@ -1,11 +1,48 @@
 #ifndef _PPC_BUG_H
 #define _PPC_BUG_H
 
-#define BUG() do { \
-	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-	__asm__ __volatile__(".long 0x0"); \
+struct bug_entry {
+	unsigned long	bug_addr;
+	int		line;
+	const char	*file;
+	const char	*function;
+};
+
+/*
+ * If this bit is set in the line number it means that the trap
+ * is for WARN_ON rather than BUG or BUG_ON.
+ */
+#define BUG_WARNING_TRAP	0x1000000
+
+#define BUG() do {							 \
+	__asm__ __volatile__(						 \
+		"1:	twi 31,0,0\n"					 \
+		".section __bug_table,\"a\"\n\t"			 \
+		"	.long 1b,%0,%1,%2\n"				 \
+		".previous"						 \
+		: : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \
+} while (0)
+
+#define BUG_ON(x) do {						\
+	__asm__ __volatile__(					\
+		"1:	twnei %0,0\n"				\
+		".section __bug_table,\"a\"\n\t"		\
+		"	.long 1b,%1,%2,%3\n"			\
+		".previous"					\
+		: : "r" (x), "i" (__LINE__), "i" (__FILE__),	\
+		    "i" (__FUNCTION__));			\
 } while (0)
 
 #define PAGE_BUG(page) do { BUG(); } while (0)
 
+#define WARN_ON(x) do {						\
+	__asm__ __volatile__(					\
+		"1:	twnei %0,0\n"				\
+		".section __bug_table,\"a\"\n\t"		\
+		"	.long 1b,%1,%2,%3\n"			\
+		".previous"					\
+		: : "r" (x), "i" (__LINE__ + BUG_WARNING_TRAP),	\
+		    "i" (__FILE__), "i" (__FUNCTION__));	\
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-ppc/module.h pmac-2.5/include/asm-ppc/module.h
--- linux-2.5/include/asm-ppc/module.h	2003-01-03 07:26:42.000000000 +1100
+++ pmac-2.5/include/asm-ppc/module.h	2003-05-27 12:15:39.000000000 +1000
@@ -2,6 +2,9 @@
 #define _ASM_PPC_MODULE_H
 /* Module stuff for PPC.  (C) 2001 Rusty Russell */
 
+#include <linux/list.h>
+#include <asm/bug.h>
+
 /* Thanks to Paul M for explaining this.
 
    PPC can only do rel jumps += 32MB, and often the kernel and other
@@ -20,8 +23,15 @@
 {
 	/* Indices of PLT sections within module. */
 	unsigned int core_plt_section, init_plt_section;
+
+	/* List of BUG addresses, source line numbers and filenames */
+	struct list_head bug_list;
+	struct bug_entry *bug_table;
+	unsigned int num_bugs;
 };
 
+extern struct bug_entry *module_find_bug(unsigned long bugaddr);
+
 #define Elf_Shdr Elf32_Shdr
 #define Elf_Sym Elf32_Sym
 #define Elf_Ehdr Elf32_Ehdr
diff -urN linux-2.5/include/asm-ppc64/bug.h pmac-2.5/include/asm-ppc64/bug.h
--- linux-2.5/include/asm-ppc64/bug.h	2003-01-15 20:38:42.000000000 +1100
+++ pmac-2.5/include/asm-ppc64/bug.h	2003-05-29 19:55:29.000000000 +1000
@@ -27,7 +27,16 @@
 } while (0)
 #endif
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
 #define PAGE_BUG(page) do { BUG(); } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
 #endif
diff -urN linux-2.5/include/asm-s390/bug.h pmac-2.5/include/asm-s390/bug.h
--- linux-2.5/include/asm-s390/bug.h	2002-01-06 22:53:36.000000000 +1100
+++ pmac-2.5/include/asm-s390/bug.h	2003-05-29 19:55:38.000000000 +1000
@@ -6,8 +6,20 @@
         __asm__ __volatile__(".long 0"); \
 } while (0)                                       
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
         BUG(); \
 } while (0)                      
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-sh/bug.h pmac-2.5/include/asm-sh/bug.h
--- linux-2.5/include/asm-sh/bug.h	2002-01-06 22:54:51.000000000 +1100
+++ pmac-2.5/include/asm-sh/bug.h	2003-05-29 21:25:48.000000000 +1000
@@ -9,8 +9,20 @@
 	asm volatile("nop"); \
 } while (0)
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-sparc/bug.h pmac-2.5/include/asm-sparc/bug.h
--- linux-2.5/include/asm-sparc/bug.h	2003-05-23 07:41:16.000000000 +1000
+++ pmac-2.5/include/asm-sparc/bug.h	2003-05-29 19:55:49.000000000 +1000
@@ -12,8 +12,20 @@
 #define BUG()		__builtin_trap()
 #endif
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-sparc64/bug.h pmac-2.5/include/asm-sparc64/bug.h
--- linux-2.5/include/asm-sparc64/bug.h	2003-01-16 07:58:55.000000000 +1100
+++ pmac-2.5/include/asm-sparc64/bug.h	2003-05-29 19:55:55.000000000 +1000
@@ -13,8 +13,20 @@
 #define BUG()		__builtin_trap()
 #endif
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/asm-um/bug.h pmac-2.5/include/asm-um/bug.h
--- linux-2.5/include/asm-um/bug.h	2003-01-17 02:42:26.000000000 +1100
+++ pmac-2.5/include/asm-um/bug.h	2003-05-29 19:56:08.000000000 +1000
@@ -7,10 +7,22 @@
 	panic("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
 } while (0)
 
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
 #define PAGE_BUG(page) do { \
 	BUG(); \
 } while (0)
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 extern int foo;
 
 #endif
diff -urN linux-2.5/include/asm-v850/bug.h pmac-2.5/include/asm-v850/bug.h
--- linux-2.5/include/asm-v850/bug.h	2003-02-18 13:41:09.000000000 +1100
+++ pmac-2.5/include/asm-v850/bug.h	2003-05-29 19:56:18.000000000 +1000
@@ -18,4 +18,13 @@
 #define BUG()		__bug()
 #define PAGE_BUG(page)	__bug()
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif /* __V850_BUG_H__ */
diff -urN linux-2.5/include/asm-x86_64/bug.h pmac-2.5/include/asm-x86_64/bug.h
--- linux-2.5/include/asm-x86_64/bug.h	2003-01-17 06:36:26.000000000 +1100
+++ pmac-2.5/include/asm-x86_64/bug.h	2003-05-29 19:56:32.000000000 +1000
@@ -18,7 +18,15 @@
 #define BUG() \
 	asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \
 		     "i"(__LINE__), "i" (__stringify(KBUILD_BASENAME)))
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #define PAGE_BUG(page) BUG()
 void out_of_line_bug(void);
 
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
 #endif
diff -urN linux-2.5/include/linux/kernel.h pmac-2.5/include/linux/kernel.h
--- linux-2.5/include/linux/kernel.h	2003-05-23 07:41:16.000000000 +1000
+++ pmac-2.5/include/linux/kernel.h	2003-05-29 19:48:39.000000000 +1000
@@ -228,14 +228,6 @@
 	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
 };
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
 extern void BUILD_BUG(void);
 #define BUILD_BUG_ON(condition) do { if (condition) BUILD_BUG(); } while(0)
 
diff -urN linux-2.5/include/linux/moduleloader.h pmac-2.5/include/linux/moduleloader.h
--- linux-2.5/include/linux/moduleloader.h	2003-05-14 08:22:46.000000000 +1000
+++ pmac-2.5/include/linux/moduleloader.h	2003-05-27 14:32:42.000000000 +1000
@@ -44,4 +44,10 @@
 /* Any cleanup needed when module leaves. */
 void module_arch_cleanup(struct module *mod);
 
+/* Find a module section: 0 means not found. */
+unsigned int elf_find_sec(const Elf_Ehdr *hdr,
+			  const Elf_Shdr *sechdrs,
+			  const char *secstrings,
+			  const char *name);
+
 #endif
diff -urN linux-2.5/kernel/module.c pmac-2.5/kernel/module.c
--- linux-2.5/kernel/module.c	2003-05-14 08:22:46.000000000 +1000
+++ pmac-2.5/kernel/module.c	2003-05-27 14:32:37.000000000 +1000
@@ -99,10 +99,10 @@
 EXPORT_SYMBOL(init_module);
 
 /* Find a module section: 0 means not found. */
-static unsigned int find_sec(Elf_Ehdr *hdr,
-			     Elf_Shdr *sechdrs,
-			     const char *secstrings,
-			     const char *name)
+unsigned int elf_find_sec(const Elf_Ehdr *hdr,
+			  const Elf_Shdr *sechdrs,
+			  const char *secstrings,
+			  const char *name)
 {
 	unsigned int i;
 
@@ -1175,7 +1175,7 @@
 #endif
 	}
 
-	modindex = find_sec(hdr, sechdrs, secstrings,
+	modindex = elf_find_sec(hdr, sechdrs, secstrings,
 			    ".gnu.linkonce.this_module");
 	if (!modindex) {
 		printk(KERN_WARNING "No module found in object\n");
@@ -1185,15 +1185,15 @@
 	mod = (void *)sechdrs[modindex].sh_addr;
 
 	/* Optional sections */
-	exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
-	gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
-	crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");
-	gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
-	setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
-	exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
-	obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
-	versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
-	infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
+	exportindex = elf_find_sec(hdr, sechdrs, secstrings, "__ksymtab");
+	gplindex = elf_find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
+	crcindex = elf_find_sec(hdr, sechdrs, secstrings, "__kcrctab");
+	gplcrcindex = elf_find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
+	setupindex = elf_find_sec(hdr, sechdrs, secstrings, "__param");
+	exindex = elf_find_sec(hdr, sechdrs, secstrings, "__ex_table");
+	obsparmindex = elf_find_sec(hdr, sechdrs, secstrings, "__obsparm");
+	versindex = elf_find_sec(hdr, sechdrs, secstrings, "__versions");
+	infoindex = elf_find_sec(hdr, sechdrs, secstrings, ".modinfo");
 
 	/* Don't keep modinfo section */
 	sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
diff -urN linux-2.5/arch/ppc/boot/ld.script pmac-2.5/arch/ppc/boot/ld.script
--- linux-2.5/arch/ppc/boot/ld.script	2003-05-29 13:45:33.000000000 +1000
+++ pmac-2.5/arch/ppc/boot/ld.script	2003-05-29 21:06:53.000000000 +1000
@@ -81,6 +81,7 @@
   /DISCARD/ : {
     *(__ksymtab)
     *(__ksymtab_strings)
+    *(__bug_table)
   }
 
 }
diff -urN linux-2.5/arch/ppc/kernel/module.c pmac-2.5/arch/ppc/kernel/module.c
--- linux-2.5/arch/ppc/kernel/module.c	2003-05-14 08:22:45.000000000 +1000
+++ pmac-2.5/arch/ppc/kernel/module.c	2003-05-27 14:33:42.000000000 +1000
@@ -16,6 +16,7 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 #include <linux/module.h>
+#include <linux/moduleloader.h>
 #include <linux/elf.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
@@ -29,6 +30,8 @@
 #define DEBUGP(fmt , ...)
 #endif
 
+LIST_HEAD(module_bug_list);
+
 void *module_alloc(unsigned long size)
 {
 	if (size == 0)
@@ -267,9 +270,47 @@
 		    const Elf_Shdr *sechdrs,
 		    struct module *me)
 {
+	char *secstrings;
+	unsigned int bugindex;
+
+	/* Find the __bug_table section, if present */
+	secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+	bugindex = elf_find_sec(hdr, sechdrs, secstrings, "__bug_table");
+
+	/*
+	 * If there is no __bug_table, find_sec returns 0, and
+	 * section 0 is conveniently always a 0-length section,
+	 * according to Rusty.
+	 */
+	me->arch.bug_table = (void *) sechdrs[bugindex].sh_addr;
+	me->arch.num_bugs = sechdrs[bugindex].sh_size / sizeof(struct bug_entry);
+
+	/*
+	 * Strictly speaking this should have a spinlock to protect against
+	 * traversals, but since we only traverse on BUG()s, a spinlock
+	 * could potentially lead to deadlock and thus be counter-productive.
+	 */
+	list_add(&me->arch.bug_list, &module_bug_list);
+
 	return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
+	list_del(&mod->arch.bug_list);
+}
+
+struct bug_entry *module_find_bug(unsigned long bugaddr)
+{
+	struct mod_arch_specific *mod;
+	unsigned int i;
+	struct bug_entry *bug;
+
+	list_for_each_entry(mod, &module_bug_list, bug_list) {
+		bug = mod->bug_table;
+		for (i = 0; i < mod->num_bugs; ++i, ++bug)
+			if (bugaddr == bug->bug_addr)
+				return bug;
+	}
+	return NULL;
 }
diff -urN linux-2.5/arch/ppc/kernel/traps.c pmac-2.5/arch/ppc/kernel/traps.c
--- linux-2.5/arch/ppc/kernel/traps.c	2003-05-29 13:45:33.000000000 +1000
+++ pmac-2.5/arch/ppc/kernel/traps.c	2003-05-29 21:21:35.000000000 +1000
@@ -296,6 +296,57 @@
 	return(retval);
 }
 
+/*
+ * Look through the list of trap instructions that are used for BUG(),
+ * BUG_ON() and WARN_ON() and see if we hit one.  At this point we know
+ * that the exception was caused by a trap instruction of some kind.
+ * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
+ * otherwise.
+ */
+extern struct bug_entry __start___bug_table[], __stop___bug_table[];
+
+#ifndef CONFIG_MODULES
+#define module_find_bug(x)	NULL
+#endif
+
+static struct bug_entry *find_bug(unsigned long bugaddr)
+{
+	struct bug_entry *bug;
+
+	for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
+		if (bugaddr == bug->bug_addr)
+			return bug;
+	return module_find_bug(bugaddr);
+}
+
+int
+check_bug_trap(struct pt_regs *regs)
+{
+	struct bug_entry *bug;
+	unsigned long addr;
+	int line;
+
+	if (regs->msr & MSR_PR)
+		return 0;	/* not in kernel */
+	addr = regs->nip;	/* address of trap instruction */
+	if (addr < PAGE_OFFSET)
+		return 0;
+	bug = find_bug(regs->nip);
+	if (bug == NULL)
+		return 0;
+	if (bug->line & BUG_WARNING_TRAP) {
+		/* this is a WARN_ON rather than BUG/BUG_ON */
+		printk(KERN_ERR "Badness in %s at %s:%d\n",
+		       bug->function, bug->file,
+		       bug->line & ~BUG_WARNING_TRAP);
+		dump_stack();
+		return 1;
+	}
+	printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n",
+	       bug->function, bug->file, bug->line);
+	return 0;
+}
+
 void
 ProgramCheckException(struct pt_regs *regs)
 {
@@ -325,6 +376,10 @@
 		/* trap exception */
 		if (debugger_bpt(regs))
 			return;
+		if (check_bug_trap(regs)) {
+			regs->nip += 4;
+			return;
+		}
 		_exception(SIGTRAP, regs);
 		return;
 	}
diff -urN linux-2.5/arch/ppc/vmlinux.lds.S pmac-2.5/arch/ppc/vmlinux.lds.S
--- linux-2.5/arch/ppc/vmlinux.lds.S	2003-04-14 09:28:41.000000000 +1000
+++ pmac-2.5/arch/ppc/vmlinux.lds.S	2003-05-26 21:58:49.000000000 +1000
@@ -54,6 +54,10 @@
   __ex_table : { *(__ex_table) }
   __stop___ex_table = .;
 
+  __start___bug_table = .;
+  __bug_table : { *(__bug_table) }
+  __stop___bug_table = .;
+
   /* Read-write section, merged into data segment: */
   . = ALIGN(4096);
   .data    :

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Proposed patch to kernel.h
  2003-05-29 12:32     ` Paul Mackerras
@ 2003-05-30  8:03       ` Rusty Russell
  0 siblings, 0 replies; 5+ messages in thread
From: Rusty Russell @ 2003-05-30  8:03 UTC (permalink / raw)
  To: Paul Mackerras
  Cc: davem, rth, rmk, jes, ralf, matthew, jdike, uclinux-v850, davidm,
	anton, ak, rusty, linux-kernel

In message <16085.64995.7031.949757@argo.ozlabs.ibm.com> you write:
> That meant that I needed to use find_sec(), which was static in
> kernel/module.c (to find the __bug_table section), so I renamed it to
> elf_find_sec() and made it externally accessible (once again at
> Rusty's suggestion).
> 
> Tested OK on ppc, and compile-tested on x86 successfully.
> 
> How does this look?

Looks fine to me.  If every arch goes this way in 2.7 (say) we can
fold it back into kernel/module.c like we do for exception tables.

Cheers,
Rusty.
--
  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-05-30  7:52 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-27 22:51 Proposed patch to kernel.h Paul Mackerras
2003-05-29  2:00 ` Paul Mackerras
2003-05-29  2:23   ` Linus Torvalds
2003-05-29 12:32     ` Paul Mackerras
2003-05-30  8:03       ` Rusty Russell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).