aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/traps.c
diff options
context:
space:
mode:
authoranton@samba.org <anton@samba.org>2007-03-20 21:38:13 -0400
committerPaul Mackerras <paulus@samba.org>2007-03-25 22:34:30 -0400
commit34c2a14fc20e4ab878fbf87e5f7fe1cff6afb3d4 (patch)
tree4af304129787a7873c03d114226dd2af9ef3ded1 /arch/powerpc/kernel/traps.c
parent6031d9d9ad905b514bf45572bd1877fe6b5145ab (diff)
[POWERPC] Handle recursive oopses
Handle recursive oopses, like on x86. We had a few cases recently where we locked up in oops printing and didnt make it into crashdump. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r--arch/powerpc/kernel/traps.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 6297da743db9..55d221ffcf1e 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -108,42 +108,62 @@ static void pmac_backlight_unblank(void)
108static inline void pmac_backlight_unblank(void) { } 108static inline void pmac_backlight_unblank(void) { }
109#endif 109#endif
110 110
111static DEFINE_SPINLOCK(die_lock);
112
113int die(const char *str, struct pt_regs *regs, long err) 111int die(const char *str, struct pt_regs *regs, long err)
114{ 112{
113 static struct {
114 spinlock_t lock;
115 u32 lock_owner;
116 int lock_owner_depth;
117 } die = {
118 .lock = __SPIN_LOCK_UNLOCKED(die.lock),
119 .lock_owner = -1,
120 .lock_owner_depth = 0
121 };
115 static int die_counter; 122 static int die_counter;
123 unsigned long flags;
116 124
117 if (debugger(regs)) 125 if (debugger(regs))
118 return 1; 126 return 1;
119 127
120 oops_enter(); 128 oops_enter();
121 129
122 console_verbose(); 130 if (die.lock_owner != raw_smp_processor_id()) {
123 spin_lock_irq(&die_lock); 131 console_verbose();
124 bust_spinlocks(1); 132 spin_lock_irqsave(&die.lock, flags);
125 if (machine_is(powermac)) 133 die.lock_owner = smp_processor_id();
126 pmac_backlight_unblank(); 134 die.lock_owner_depth = 0;
135 bust_spinlocks(1);
136 if (machine_is(powermac))
137 pmac_backlight_unblank();
138 } else {
139 local_save_flags(flags);
140 }
127 141
128 printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); 142 if (++die.lock_owner_depth < 3) {
143 printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
129#ifdef CONFIG_PREEMPT 144#ifdef CONFIG_PREEMPT
130 printk("PREEMPT "); 145 printk("PREEMPT ");
131#endif 146#endif
132#ifdef CONFIG_SMP 147#ifdef CONFIG_SMP
133 printk("SMP NR_CPUS=%d ", NR_CPUS); 148 printk("SMP NR_CPUS=%d ", NR_CPUS);
134#endif 149#endif
135#ifdef CONFIG_DEBUG_PAGEALLOC 150#ifdef CONFIG_DEBUG_PAGEALLOC
136 printk("DEBUG_PAGEALLOC "); 151 printk("DEBUG_PAGEALLOC ");
137#endif 152#endif
138#ifdef CONFIG_NUMA 153#ifdef CONFIG_NUMA
139 printk("NUMA "); 154 printk("NUMA ");
140#endif 155#endif
141 printk("%s\n", ppc_md.name ? "" : ppc_md.name); 156 printk("%s\n", ppc_md.name ? "" : ppc_md.name);
157
158 print_modules();
159 show_regs(regs);
160 } else {
161 printk("Recursive die() failure, output suppressed\n");
162 }
142 163
143 print_modules();
144 show_regs(regs);
145 bust_spinlocks(0); 164 bust_spinlocks(0);
146 spin_unlock_irq(&die_lock); 165 die.lock_owner = -1;
166 spin_unlock_irqrestore(&die.lock, flags);
147 167
148 if (kexec_should_crash(current) || 168 if (kexec_should_crash(current) ||
149 kexec_sr_activated(smp_processor_id())) 169 kexec_sr_activated(smp_processor_id()))