Please sign in to comment.
Introduce SMP-support for panic()!
Now once any of the machine cores panics, it broadcasts an IPI to all other cores instructing them to disable interrupts and halt. Measures are taken to avoid races in the concurrent panic() case, and to avoid deadlocking the system if other cores were inside a lock-protected critical region.
- Loading branch information...
Showing with 131 additions and 61 deletions.
Oops, something went wrong.
|@@ -0,0 +1,86 @@|
|* Panic("msg"): to be called on unresolvable fatal errors!|
|* Copyright (C) 2009, 2012 Ahmed S. Darwish <email@example.com>|
|* This program is free software; you can redistribute it and/or modify|
|* it under the terms of the GNU General Public License as published by|
|* the Free Software Foundation, version 2.|
|static char buf;|
|static spinlock_t panic_lock = SPIN_UNLOCKED();|
|* Quickly disable system interrupts upon entrance! Now the|
|* kernel is in an inconsistent state, just gracefully stop|
|* the machine and halt :-(|
|* An interesting case faced from not disabling interrupts|
|* early on (disabling them at the function end instead) was|
|* having other threads getting scheduled between printk()|
|* and disabling interrupts, scrolling-away the caller panic|
|* message and losing information FOREVER.|
|void __no_return panic(const char *fmt, ...)|
|/* NOTE! Do not put anything above this */|
|* NOTE! Manually assure that all the functions called|
|* below are void of any asserts or panics.|
|/* Avoid concurrent panic()s: first call holds the most|
|* important facts; the rest are usually side-effects. */|
|/* If other cores are alive, send them a fixed IPI, which|
|* intentionally avoids interrupting cores with IF=0 till|
|* they re-accept interrupts. Why?|
|* An interrupted critical region may deadlock our panic|
|* code if we tried to acquire the same lock. The other|
|* cores may not also be in long-mode before they enable|
|* interrupts (e.g. in the 16-bit SMP trampoline step.)|
|* IPIs are sent only if more than one core is alive: we|
|* might be on so early a stage that our APIC registers|
|* are not yet memory mapped, leading to memory faults if|
|* locally accessed!|
|* If destination CPUs were alive but have not yet inited|
|* their local APICs, they will not be able to catch this|
|* IPI and will normally continue execution. Beware.|
|if (smpboot_get_nr_alive_cpus() > 1)|
|n = vsnprintf(buf, sizeof(buf) - 1, fmt, args);|
|buf[n] = 0;|
|printk("\nCPU#%d-PANIC: %s", percpu_get(apic_id), buf);|
|/* Since the other cores are stopped only after they re-|
|* accept interrupts, they may print on-screen and scroll|
|* away our message. Acquire all screen locks, forever. */|