From: Andrew Morton Prevent infinite looping when handling a WARN() (I think) Cc: Jeremy Fitzhardinge Cc: Andi Kleen Cc: Hugh Dickens Cc: Michael Ellerman Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: Rusty Russell Signed-off-by: Andrew Morton --- arch/powerpc/kernel/traps.c | 2 +- include/linux/bug.h | 11 ++++++++--- lib/bug.c | 18 +++++++++--------- 3 files changed, 18 insertions(+), 13 deletions(-) diff -puN arch/powerpc/kernel/traps.c~use-generic-bug-for-powerpc-fix-2 arch/powerpc/kernel/traps.c --- a/arch/powerpc/kernel/traps.c~use-generic-bug-for-powerpc-fix-2 +++ a/arch/powerpc/kernel/traps.c @@ -779,7 +779,7 @@ void __kprobes program_check_exception(s return; if (!(regs->msr & MSR_PR) && /* not user-mode */ - report_bug(regs->nip)) { + report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) { regs->nip += 4; return; } diff -puN include/linux/bug.h~use-generic-bug-for-powerpc-fix-2 include/linux/bug.h --- a/include/linux/bug.h~use-generic-bug-for-powerpc-fix-2 +++ a/include/linux/bug.h @@ -6,12 +6,17 @@ #ifdef CONFIG_GENERIC_BUG #include +enum bug_trap_type { + BUG_TRAP_TYPE_NONE = 0, + BUG_TRAP_TYPE_WARN = 1, + BUG_TRAP_TYPE_BUG = 2, +}; + const struct bug_entry *find_bug(unsigned long bugaddr); -int report_bug(unsigned long bug_addr); +enum bug_trap_type report_bug(unsigned long bug_addr); -int module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *, - struct module *); +int module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *, struct module *); void module_bug_cleanup(struct module *); /* These are defined by the architecture */ diff -puN lib/bug.c~use-generic-bug-for-powerpc-fix-2 lib/bug.c --- a/lib/bug.c~use-generic-bug-for-powerpc-fix-2 +++ a/lib/bug.c @@ -75,18 +75,18 @@ const struct bug_entry *find_bug(unsigne return module_find_bug(bugaddr); } -int report_bug(unsigned long bugaddr) +enum bug_trap_type report_bug(unsigned long bugaddr) { const struct bug_entry *bug; const char *file, *function; unsigned line; if (!is_valid_bugaddr(bugaddr)) - return 0; + return BUG_TRAP_TYPE_NONE; bug = find_bug(bugaddr); if (!bug) - return 0; + return BUG_TRAP_TYPE_NONE; printk(KERN_EMERG "------------[ cut here ]------------\n"); @@ -100,19 +100,19 @@ int report_bug(unsigned long bugaddr) printk(KERN_ERR "Badness in %s at %s:%u\n", function, file, line); else - printk(KERN_ERR "Badness at %p [verbose debug info unavailable]\n", - (void *)bugaddr); + printk(KERN_ERR "Badness at %p [verbose debug info " + "unavailable]\n", (void *)bugaddr); dump_stack(); - return 1; + return BUG_TRAP_TYPE_WARN; } if (file) printk(KERN_CRIT "kernel BUG in %s at %s:%u!\n", function, file, line); else - printk(KERN_EMERG "Kernel BUG at %p [verbose debug info unavailable]\n", - (void *)bugaddr); + printk(KERN_EMERG "Kernel BUG at %p [verbose debug info " + "unavailable]\n", (void *)bugaddr); - return 0; + return BUG_TRAP_TYPE_BUG; } _