Skip to contentSkip to conversation

Generic BUG for parisc

PATCH Grant Grundler 3 participants 3 messages Dec 10, 2006 2 messages not in the archive PA-RISC architecture

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw
Quoted 2 lines · Helge Deller

I found the following patch, which recently went into Linus' 2.6.20-pre kernel very interesting:
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7664c5a1da4711bb6383117f51b94c8dc8f3f1cd

Indeed. that's cool.

...

Quoted 11 lines

The attached patch implements this for parisc, and my vmlinux (32bit) shows me after using it:

Quoted 1 line

hppa-linux-objdump -x vmlinux :

Idx Name          Size      VMA       LMA       File off  Algn
 16 __bug_table   000040a4  104a3000  104a3000  003a4000  2**0

So, there were 1379 BUG()'s covered by that change (0x40a4 = 16548, each entry 12 bytes => 1379 BUG calls).

Since I would like to submit this patch to our tree, I would like to get your feedback first:
- Is the "break" instruction the best one for this task ?
- will it affect runtime of the kernel (maybe break statements, although normally not executed, reduce throughput ?)
- should I submit it as soon as our parisc-tree has the necessary bits from mainline ?

This looks good to me.
It's up to kyle/willy on how they want it pushed back upstream.

I'm sure it will affect the runtime of the kernel becuase it moves a fair chunk of code "out of line". Ie we should get slightly better i-cache utilization with this change.

Quoted 1 line

- any other ideas ?

With this, we could use BUG() to _measure_ exactly how many times we hit a particular BUG() test. It would be usefule to determine how performance critical particular BUG() tests are.
Add a 32-bit counter to the generic struct bug_entry and then increment that in the trap handler. Hrm...need a /proc or /sys interface to dump all of them.

Quoted 5 lines

One idea I had was to encode the file line number into the instruction itself (in im5 & im13), since the break instruction is implemented as "break im5, im13" and 16bit fit easily in there.
This would save some space, but I would need to add some ifdefs in the generic implementation which I didn't wanted to touch yet.

I'd not worry about optimizations until after it's seen broader use. Keep in mind 12 bytes (for 32-bit kernel) is only 3 instructions. So each BUG() only uses 16 bytes + file name string. That's already a major improvement over our existing BUG() which has to setup printk()/dump_stack()/panic calls - at least 56 bytes (14 ops) each.

Keep in mind this change saves us around 55kB (1379*40). Saving another 2 bytes isn't that critical. IMHO, it's not worth making things too complicated just to save another 3kB.

Kudos!

thanks,
grant

#2 lore raw
In reply to a message not in the archive
Quoted 2 lines

Since I would like to submit this patch to our tree, I would like to get your feedback first:
- Is the "break" instruction the best one for this task ?

Yes, i think so.

Quoted 1 line

- will it affect runtime of the kernel (maybe break statements, although normally not executed, reduce throughput ?)

I think the way you have it is fine, the break traps only when executed, so it should not affect normal execution.

Quoted 2 lines

- should I submit it as soon as our parisc-tree has the necessary bits from mainline ?
- any other ideas ?

The only thing I noticed is that your patch has various "cleanups" or maybe just whitespace changes that is mixed it. It's not a big deal, but maybe it'll be cleaner if those are separated out.

Quoted 2 lines

One idea I had was to encode the file line number into the instruction itself (in im5 & im13), since the break instruction is implemented as "break im5, im13" and 16bit fit easily in there. This would save some space, but I would need to add some ifdefs in the generic implementation which I didn't wanted to touch yet.

Please don't do this. It will make things confusing.

Note that there are some other tools that use the break infrastructure, and some of them will be in kernel space. For example, kdb uses "break" to implement breakpoints. If we implement tools like kprobes, they will probably need to use "break" too. We need to have unique break numbers if these tools were to coexist. For reference, the parisc kdb implementation uses the following:

+#define KDB_BREAK_BREAK 0x111 /* kdb breakpoint in kernel */
+#define KDB_BREAK_ENTER 0x112 /* KDB_ENTER() */
+

+#define PA_BREAK_INSN(n)       ((n)<<13)
+#define KDB_BREAK_BREAK_INSN   PA_BREAK_INSN(KDB_BREAK_BREAK)
+#define KDB_BREAK_ENTER_INSN   PA_BREAK_INSN(KDB_BREAK_ENTER)
+
+#define KDB_ENTER2(b)  asm("\tbreak 0,"#b"\n")
+#define KDB_ENTER1(b)  KDB_ENTER2(b)
+#define KDB_ENTER()    KDB_ENTER1(KDB_BREAK_ENTER)

my 2 cents :)
randolph

A message that is not in the archive (sent off-list or not yet received): [email protected]

maintainer
#4 lore raw

On Sunday 10 December 2006 06:37, Grant Grundler wrote:
On Sunday 10 December 2006 14:38, Randolph Chung wrote:
...
Thanks a lot for your both's feedback!

In summary I read, that it's better to keep the patch like it is now without major changes.

Further possible enhancements would be:
- add performance couters to measure how often the tests ran
- implement WARN() the same way

A slightly modified patch (in asm-parisc/bug.h) is attached. It still has 1-2 minimal other cleanups.

Kyle/Willy: Do you think you can integrate this patch into what goes to Linus for 2.6.20 ?

Thanks!
Helge

diff-tree 571c18bb8c00794f38bc522a9d62d699ec17f9b8 (from 12166cbf2a4b90bc9d82262f52a8568362166f91)

Author: Helge Deller <[email protected]>
Date:   Sat Dec 9 16:41:00 2006 +0100

[PATCH] Generic BUG for parisc

arch/parisc/Kconfig | 5 ++
arch/parisc/kernel/module.c | 4 +
arch/parisc/kernel/traps.c | 79 ++++++++++++++++-----------------------
arch/parisc/kernel/vmlinux.lds.S | 2
include/asm-parisc/bug.h | 38 ++++++++++++++++--
5 files changed, 76 insertions(+), 52 deletions(-)

arch/parisc/Kconfig +5 -0
index d210123..a946776 100644
@@ -29,6 +29,11 @@ config GENERIC_FIND_NEXT_BIT
 	bool
 	default y
 
+config GENERIC_BUG
+	bool
+	default y
+	depends on BUG
+
 config GENERIC_HWEIGHT
 	bool
 	default y
arch/parisc/kernel/module.c +3 -1
index 47ea4e4..1808f85 100644
@@ -46,6 +46,7 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/bug.h>
 
 #include <asm/unwind.h>
 
@@ -851,10 +852,11 @@ int module_finalize(const Elf_Ehdr *hdr,
 	nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
 	DEBUGP("NEW num_symtab %lu\n", nsyms);
 	symhdr->sh_size = nsyms * sizeof(Elf_Sym);
-	return 0;
+	return module_bug_finalize(hdr, sechdrs, me);
 }
 
 void module_arch_cleanup(struct module *mod)
 {
 	deregister_unwind_table(mod);
+	module_bug_cleanup(mod);
 }
arch/parisc/kernel/traps.c +33 -46

144 lines not on this page · raw message

arch/parisc/kernel/vmlinux.lds.S +2 -0
index 7b943b4..7b149df 100644
@@ -68,6 +68,8 @@ SECTIONS
 
   RODATA
 
+  BUG_TABLE
+
   /* writeable */
   . = ALIGN(ASM_PAGE_SIZE);	/* Make sure this is page aligned so
   				   that we can properly leave these
include/asm-parisc/bug.h +33 -5
index 695588d..367e458 100644
@@ -1,14 +1,42 @@
 #ifndef _PARISC_BUG_H
 #define _PARISC_BUG_H
 
+/*
+ * Tell the user there is some problem.
+ * The offending file and line are encoded in the __bug_table section.
+ */
+
 #ifdef CONFIG_BUG
 #define HAVE_ARCH_BUG
-#define BUG() do { \
-	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-	dump_stack(); \
-	panic("BUG!"); \
-} while (0)
+
+/* the break instruction is used as BUG() marker.  */
+#define	PARISC_BUG_BREAK_ASM	"break 0x1f, 0x1fff"
+#define	PARISC_BUG_BREAK_INSN	0x03ffe01f  /* PARISC_BUG_BREAK_ASM */
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+#define BUG()								\
+	do {								\
+		asm volatile("\n"					\
+			     "1:\t" PARISC_BUG_BREAK_ASM "\n"		\
+			     "\t.pushsection __bug_table,\"a\"\n"	\
+			     "2:\t.long 1b, %c0\n"			\
+			     "\t.short %c1, 0\n"			\
+			     "\t.org 2b+%c2\n"				\
+			     "\t.popsection"				\
+			     : : "i" (__FILE__), "i" (__LINE__),	\
+			     "i" (sizeof(struct bug_entry)) );		\
+		for(;;) ;						\
+	} while(0)
+
+#else
+#define BUG()								\
+	do {								\
+		asm volatile(PARISC_BUG_BREAK_ASM : : );		\
+		for(;;) ;						\
+	} while(0)
+#endif
 #endif
 
 #include <asm-generic/bug.h>
 #endif
+

_______________________________________________
parisc-linux mailing list
[email protected]
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux