aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c75
1 files changed, 64 insertions, 11 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 9c7419e459d6..54bd1b2fb4c0 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -204,6 +204,9 @@ static void print_mce_tail(void)
204 204
205static atomic_t mce_paniced; 205static atomic_t mce_paniced;
206 206
207static int fake_panic;
208static atomic_t mce_fake_paniced;
209
207/* Panic in progress. Enable interrupts and wait for final IPI */ 210/* Panic in progress. Enable interrupts and wait for final IPI */
208static void wait_for_panic(void) 211static void wait_for_panic(void)
209{ 212{
@@ -221,15 +224,21 @@ static void mce_panic(char *msg, struct mce *final, char *exp)
221{ 224{
222 int i; 225 int i;
223 226
224 /* 227 if (!fake_panic) {
225 * Make sure only one CPU runs in machine check panic 228 /*
226 */ 229 * Make sure only one CPU runs in machine check panic
227 if (atomic_inc_return(&mce_paniced) > 1) 230 */
228 wait_for_panic(); 231 if (atomic_inc_return(&mce_paniced) > 1)
229 barrier(); 232 wait_for_panic();
233 barrier();
230 234
231 bust_spinlocks(1); 235 bust_spinlocks(1);
232 console_verbose(); 236 console_verbose();
237 } else {
238 /* Don't log too much for fake panic */
239 if (atomic_inc_return(&mce_fake_paniced) > 1)
240 return;
241 }
233 print_mce_head(); 242 print_mce_head();
234 /* First print corrected ones that are still unlogged */ 243 /* First print corrected ones that are still unlogged */
235 for (i = 0; i < MCE_LOG_LEN; i++) { 244 for (i = 0; i < MCE_LOG_LEN; i++) {
@@ -256,9 +265,12 @@ static void mce_panic(char *msg, struct mce *final, char *exp)
256 print_mce_tail(); 265 print_mce_tail();
257 if (exp) 266 if (exp)
258 printk(KERN_EMERG "Machine check: %s\n", exp); 267 printk(KERN_EMERG "Machine check: %s\n", exp);
259 if (panic_timeout == 0) 268 if (!fake_panic) {
260 panic_timeout = mce_panic_timeout; 269 if (panic_timeout == 0)
261 panic(msg); 270 panic_timeout = mce_panic_timeout;
271 panic(msg);
272 } else
273 printk(KERN_EMERG "Fake kernel panic: %s\n", msg);
262} 274}
263 275
264/* Support code for software error injection */ 276/* Support code for software error injection */
@@ -2015,4 +2027,45 @@ struct dentry *mce_get_debugfs_dir(void)
2015 2027
2016 return dmce; 2028 return dmce;
2017} 2029}
2030
2031static void mce_reset(void)
2032{
2033 cpu_missing = 0;
2034 atomic_set(&mce_fake_paniced, 0);
2035 atomic_set(&mce_executing, 0);
2036 atomic_set(&mce_callin, 0);
2037 atomic_set(&global_nwo, 0);
2038}
2039
2040static int fake_panic_get(void *data, u64 *val)
2041{
2042 *val = fake_panic;
2043 return 0;
2044}
2045
2046static int fake_panic_set(void *data, u64 val)
2047{
2048 mce_reset();
2049 fake_panic = val;
2050 return 0;
2051}
2052
2053DEFINE_SIMPLE_ATTRIBUTE(fake_panic_fops, fake_panic_get,
2054 fake_panic_set, "%llu\n");
2055
2056static int __init mce_debugfs_init(void)
2057{
2058 struct dentry *dmce, *ffake_panic;
2059
2060 dmce = mce_get_debugfs_dir();
2061 if (!dmce)
2062 return -ENOMEM;
2063 ffake_panic = debugfs_create_file("fake_panic", 0444, dmce, NULL,
2064 &fake_panic_fops);
2065 if (!ffake_panic)
2066 return -ENOMEM;
2067
2068 return 0;
2069}
2070late_initcall(mce_debugfs_init);
2018#endif 2071#endif