From d9202429e60d16d39c427cd4e4408cf1827ab9e9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Jun 2007 13:38:27 +0100 Subject: [ARM] Add support for pause_on_oops and display preempt/smp options Add calls to oops_enter() and oops_exit() to __die(), so that things like lockdep know when an oops occurs. Add suffixes to the oops report to indicate whether the running kernel has been built with preempt or smp support. Signed-off-by: Russell King --- arch/arm/kernel/traps.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'arch/arm/kernel/traps.c') diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 10ff36e4e41..1b68d365d0e 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -204,12 +204,24 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) barrier(); } +#ifdef CONFIG_PREEMPT +#define S_PREEMPT " PREEMPT" +#else +#define S_PREEMPT "" +#endif +#ifdef CONFIG_SMP +#define S_SMP " SMP" +#else +#define S_SMP "" +#endif + static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) { struct task_struct *tsk = thread->task; static int die_counter; - printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter); + printk("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n", + str, err, ++die_counter); print_modules(); __show_regs(regs); printk("Process %s (pid: %d, stack limit = 0x%p)\n", @@ -232,6 +244,8 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) { struct thread_info *thread = current_thread_info(); + oops_enter(); + console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); @@ -239,9 +253,13 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) bust_spinlocks(0); spin_unlock_irq(&die_lock); + if (in_interrupt()) + panic("Fatal exception in interrupt"); + if (panic_on_oops) panic("Fatal exception"); + oops_exit(); do_exit(SIGSEGV); } -- cgit v1.2.3-70-g09d2 From 082f47a79bfc8a526b9a3e14a0ae9504fc09cc12 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 5 Jul 2007 19:59:51 +0100 Subject: [ARM] always allow dump_stack() to produce a backtrace Don't make this dependent on CONFIG_DEBUG_KERNEL - if we hit a WARN_ON we need the stack trace to work out how we got to that point. Signed-off-by: Russell King --- arch/arm/kernel/traps.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/arm/kernel/traps.c') diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 1b68d365d0e..237f4999b9a 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -181,9 +181,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) void dump_stack(void) { -#ifdef CONFIG_DEBUG_ERRORS __backtrace(); -#endif } EXPORT_SYMBOL(dump_stack); -- cgit v1.2.3-70-g09d2 From bcdcd8e725b923ad7c0de809680d5d5658a7bf8c Mon Sep 17 00:00:00 2001 From: Pavel Emelianov Date: Tue, 17 Jul 2007 04:03:42 -0700 Subject: Report that kernel is tainted if there was an OOPS If the kernel OOPSed or BUGed then it probably should be considered as tainted. Thus, all subsequent OOPSes and SysRq dumps will report the tainted kernel. This saves a lot of time explaining oddities in the calltraces. Signed-off-by: Pavel Emelianov Acked-by: Randy Dunlap Cc: Signed-off-by: Andrew Morton [ Added parisc patch from Matthew Wilson -Linus ] Signed-off-by: Linus Torvalds --- Documentation/oops-tracing.txt | 2 ++ arch/alpha/kernel/traps.c | 1 + arch/arm/kernel/traps.c | 1 + arch/arm26/kernel/traps.c | 1 + arch/avr32/kernel/traps.c | 1 + arch/i386/kernel/traps.c | 1 + arch/ia64/kernel/traps.c | 1 + arch/m68k/kernel/traps.c | 1 + arch/m68knommu/kernel/traps.c | 1 + arch/mips/kernel/traps.c | 1 + arch/parisc/kernel/traps.c | 1 + arch/powerpc/kernel/traps.c | 1 + arch/ppc/kernel/traps.c | 1 + arch/s390/kernel/traps.c | 1 + arch/sh/kernel/traps.c | 1 + arch/sparc/kernel/traps.c | 1 + arch/sparc64/kernel/traps.c | 1 + arch/x86_64/kernel/traps.c | 1 + arch/xtensa/kernel/traps.c | 1 + include/linux/kernel.h | 1 + kernel/panic.c | 5 +++-- 21 files changed, 24 insertions(+), 2 deletions(-) (limited to 'arch/arm/kernel/traps.c') diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt index 23e6dde7eea..7f60dfe642c 100644 --- a/Documentation/oops-tracing.txt +++ b/Documentation/oops-tracing.txt @@ -251,6 +251,8 @@ characters, each representing a particular tainted value. 7: 'U' if a user or user application specifically requested that the Tainted flag be set, ' ' otherwise. + 8: 'D' if the kernel has died recently, i.e. there was an OOPS or BUG. + The primary reason for the 'Tainted: ' string is to tell kernel debuggers if this is a clean kernel or if anything unusual has occurred. Tainting is permanent: even if an offending module is diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index d6e665d567b..ec0f05e0d8f 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -184,6 +184,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15) #endif printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); dik_show_regs(regs, r9_15); + add_taint(TAINT_DIE); dik_show_trace((unsigned long *)(regs+1)); dik_show_code((unsigned int *)regs->pc); diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 237f4999b9a..f2114bcf09d 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -249,6 +249,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) bust_spinlocks(1); __die(str, err, thread, regs); bust_spinlocks(0); + add_taint(TAINT_DIE); spin_unlock_irq(&die_lock); if (in_interrupt()) diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c index d594fb59e94..2911e2eae80 100644 --- a/arch/arm26/kernel/traps.c +++ b/arch/arm26/kernel/traps.c @@ -185,6 +185,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) printk("Internal error: %s: %x\n", str, err); printk("CPU: %d\n", smp_processor_id()); show_regs(regs); + add_taint(TAINT_DIE); printk("Process %s (pid: %d, stack limit = 0x%p)\n", current->comm, current->pid, end_of_stack(tsk)); diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index aaa792815cd..9a73ce7eb50 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c @@ -56,6 +56,7 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) show_regs_log_lvl(regs, KERN_EMERG); show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG); bust_spinlocks(0); + add_taint(TAINT_DIE); spin_unlock_irq(&die_lock); if (in_interrupt()) diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 28bd1c5163e..18c1c285836 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -433,6 +433,7 @@ void die(const char * str, struct pt_regs * regs, long err) bust_spinlocks(0); die.lock_owner = -1; + add_taint(TAINT_DIE); spin_unlock_irqrestore(&die.lock, flags); if (!regs) diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index 15ad85da15a..3aeaf15e468 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -69,6 +69,7 @@ die (const char *str, struct pt_regs *regs, long err) bust_spinlocks(0); die.lock_owner = -1; + add_taint(TAINT_DIE); spin_unlock_irq(&die.lock); if (panic_on_oops) diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index a27a4fa3329..4e2752a0e89 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -1170,6 +1170,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr) console_verbose(); printk("%s: %08x\n",str,nr); show_registers(fp); + add_taint(TAINT_DIE); do_exit(SIGSEGV); } diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c index bed5f47bf56..fde04e1757f 100644 --- a/arch/m68knommu/kernel/traps.c +++ b/arch/m68knommu/kernel/traps.c @@ -83,6 +83,7 @@ void die_if_kernel(char *str, struct pt_regs *fp, int nr) printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n", current->comm, current->pid, PAGE_SIZE+(unsigned long)current); show_stack(NULL, (unsigned long *)fp); + add_taint(TAINT_DIE); do_exit(SIGSEGV); } diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 37c562c4c81..ce277cb34dd 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -326,6 +326,7 @@ void __noreturn die(const char * str, struct pt_regs * regs) #endif /* CONFIG_MIPS_MT_SMTC */ printk("%s[#%d]:\n", str, ++die_counter); show_registers(regs); + add_taint(TAINT_DIE); spin_unlock_irq(&die_lock); if (in_interrupt()) diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index f9bca2d74b3..bbf029a184a 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -264,6 +264,7 @@ KERN_CRIT " || ||\n"); show_regs(regs); dump_stack(); + add_taint(TAINT_DIE); if (in_interrupt()) panic("Fatal exception in interrupt"); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 3b8427e6283..2bb1cb91178 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -149,6 +149,7 @@ int die(const char *str, struct pt_regs *regs, long err) bust_spinlocks(0); die.lock_owner = -1; + add_taint(TAINT_DIE); spin_unlock_irqrestore(&die.lock, flags); if (kexec_should_crash(current) || diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 0eaef7c8378..3f3b292eb77 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -92,6 +92,7 @@ int die(const char * str, struct pt_regs * fp, long err) if (nl) printk("\n"); show_regs(fp); + add_taint(TAINT_DIE); spin_unlock_irq(&die_lock); /* do_exit() should take care of panic'ing from an interrupt * context so we don't handle it here diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 81e03b9c384..8ec9def83cc 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -262,6 +262,7 @@ void die(const char * str, struct pt_regs * regs, long err) print_modules(); show_regs(regs); bust_spinlocks(0); + add_taint(TAINT_DIE); spin_unlock_irq(&die_lock); if (in_interrupt()) panic("Fatal exception in interrupt"); diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 05a40f3c30b..502d43e4785 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -103,6 +103,7 @@ void die(const char * str, struct pt_regs * regs, long err) (unsigned long)task_stack_page(current)); bust_spinlocks(0); + add_taint(TAINT_DIE); spin_unlock_irq(&die_lock); if (kexec_should_crash(current)) diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c index dc9ffea2a4f..3bc3bff51e0 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps.c @@ -101,6 +101,7 @@ void die_if_kernel(char *str, struct pt_regs *regs) printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter); show_regs(regs); + add_taint(TAINT_DIE); __SAVE; __SAVE; __SAVE; __SAVE; __SAVE; __SAVE; __SAVE; __SAVE; diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 00a9e3286c8..6ef2d299fb1 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -2225,6 +2225,7 @@ void die_if_kernel(char *str, struct pt_regs *regs) notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV); __asm__ __volatile__("flushw"); __show_regs(regs); + add_taint(TAINT_DIE); if (regs->tstate & TSTATE_PRIV) { struct reg_window *rw = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS); diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 7fa155c394d..6963b64a76c 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -518,6 +518,7 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err) printk("\n"); notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); show_registers(regs); + add_taint(TAINT_DIE); /* Executive summary in case the oops scrolled away */ printk(KERN_ALERT "RIP "); printk_address(regs->rip); diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 693ab268485..c5e62f9d9f5 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -482,6 +482,7 @@ void die(const char * str, struct pt_regs * regs, long err) if (!user_mode(regs)) show_stack(NULL, (unsigned long*)regs->areg[1]); + add_taint(TAINT_DIE); spin_unlock_irq(&die_lock); if (in_interrupt()) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 7a485250591..1eb9cde550c 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -210,6 +210,7 @@ extern enum system_states { #define TAINT_MACHINE_CHECK (1<<4) #define TAINT_BAD_PAGE (1<<5) #define TAINT_USER (1<<6) +#define TAINT_DIE (1<<7) extern void dump_stack(void); diff --git a/kernel/panic.c b/kernel/panic.c index 623d1828259..f64f4c1ac11 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -159,14 +159,15 @@ const char *print_tainted(void) { static char buf[20]; if (tainted) { - snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c", + snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c", tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G', tainted & TAINT_FORCED_MODULE ? 'F' : ' ', tainted & TAINT_UNSAFE_SMP ? 'S' : ' ', tainted & TAINT_FORCED_RMMOD ? 'R' : ' ', tainted & TAINT_MACHINE_CHECK ? 'M' : ' ', tainted & TAINT_BAD_PAGE ? 'B' : ' ', - tainted & TAINT_USER ? 'U' : ' '); + tainted & TAINT_USER ? 'U' : ' ', + tainted & TAINT_DIE ? 'D' : ' '); } else snprintf(buf, sizeof(buf), "Not tainted"); -- cgit v1.2.3-70-g09d2