aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <andi@firstfloor.org>2009-05-27 15:56:55 -0400
committerH. Peter Anvin <hpa@zytor.com>2009-06-03 17:45:12 -0400
commitf94b61c2c9fdcc90773c49df9ccf9ede3ad0d7db (patch)
treee928c8a6b254b288076cd7f552cb7fb361b18d41
parentccc3c3192ae78dd56dcdf5353fd1a9ef5f9a3e2b (diff)
x86, mce: implement panic synchronization
In some circumstances multiple CPUs can enter mce_panic() in parallel. This gives quite confused output because they will all dump the same machine check buffer. The other problem is that they would all panic in parallel, but not process each other's shutdown IPIs because interrupts are disabled. Detect this situation early on in mce_panic(). On the first CPU entering will do the panic, the others will just wait to be killed. For paranoia reasons in case the other CPU dies during the MCE I added a 5 seconds timeout. If it expires each CPU will panic on its own again. Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 121781627858..421020f1d7db 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -196,10 +196,32 @@ static void print_mce(struct mce *m)
196 "and contact your hardware vendor\n"); 196 "and contact your hardware vendor\n");
197} 197}
198 198
199#define PANIC_TIMEOUT 5 /* 5 seconds */
200
201static atomic_t mce_paniced;
202
203/* Panic in progress. Enable interrupts and wait for final IPI */
204static void wait_for_panic(void)
205{
206 long timeout = PANIC_TIMEOUT*USEC_PER_SEC;
207 preempt_disable();
208 local_irq_enable();
209 while (timeout-- > 0)
210 udelay(1);
211 panic("Panicing machine check CPU died");
212}
213
199static void mce_panic(char *msg, struct mce *final, char *exp) 214static void mce_panic(char *msg, struct mce *final, char *exp)
200{ 215{
201 int i; 216 int i;
202 217
218 /*
219 * Make sure only one CPU runs in machine check panic
220 */
221 if (atomic_add_return(1, &mce_paniced) > 1)
222 wait_for_panic();
223 barrier();
224
203 bust_spinlocks(1); 225 bust_spinlocks(1);
204 console_verbose(); 226 console_verbose();
205 /* First print corrected ones that are still unlogged */ 227 /* First print corrected ones that are still unlogged */