diff options
author | anton@samba.org <anton@samba.org> | 2007-03-20 21:38:13 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-03-25 22:34:30 -0400 |
commit | 34c2a14fc20e4ab878fbf87e5f7fe1cff6afb3d4 (patch) | |
tree | 4af304129787a7873c03d114226dd2af9ef3ded1 /arch/powerpc/kernel/traps.c | |
parent | 6031d9d9ad905b514bf45572bd1877fe6b5145ab (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.c | 52 |
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) | |||
108 | static inline void pmac_backlight_unblank(void) { } | 108 | static inline void pmac_backlight_unblank(void) { } |
109 | #endif | 109 | #endif |
110 | 110 | ||
111 | static DEFINE_SPINLOCK(die_lock); | ||
112 | |||
113 | int die(const char *str, struct pt_regs *regs, long err) | 111 | int 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())) |