diff options
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 75 |
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 | ||
| 205 | static atomic_t mce_paniced; | 205 | static atomic_t mce_paniced; |
| 206 | 206 | ||
| 207 | static int fake_panic; | ||
| 208 | static 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 */ |
| 208 | static void wait_for_panic(void) | 211 | static 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 | |||
| 2031 | static 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 | |||
| 2040 | static int fake_panic_get(void *data, u64 *val) | ||
| 2041 | { | ||
| 2042 | *val = fake_panic; | ||
| 2043 | return 0; | ||
| 2044 | } | ||
| 2045 | |||
| 2046 | static int fake_panic_set(void *data, u64 val) | ||
| 2047 | { | ||
| 2048 | mce_reset(); | ||
| 2049 | fake_panic = val; | ||
| 2050 | return 0; | ||
| 2051 | } | ||
| 2052 | |||
| 2053 | DEFINE_SIMPLE_ATTRIBUTE(fake_panic_fops, fake_panic_get, | ||
| 2054 | fake_panic_set, "%llu\n"); | ||
| 2055 | |||
| 2056 | static 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 | } | ||
| 2070 | late_initcall(mce_debugfs_init); | ||
| 2018 | #endif | 2071 | #endif |
