diff options
Diffstat (limited to 'arch/x86_64/kernel/mce.c')
| -rw-r--r-- | arch/x86_64/kernel/mce.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 3b267c91bb0c..8aa56736cde3 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c | |||
| @@ -36,6 +36,7 @@ static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL }; | |||
| 36 | static unsigned long console_logged; | 36 | static unsigned long console_logged; |
| 37 | static int notify_user; | 37 | static int notify_user; |
| 38 | static int rip_msr; | 38 | static int rip_msr; |
| 39 | static int mce_bootlog; | ||
| 39 | 40 | ||
| 40 | /* | 41 | /* |
| 41 | * Lockless MCE logging infrastructure. | 42 | * Lockless MCE logging infrastructure. |
| @@ -197,10 +198,11 @@ void do_machine_check(struct pt_regs * regs, long error_code) | |||
| 197 | rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr); | 198 | rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr); |
| 198 | 199 | ||
| 199 | mce_get_rip(&m, regs); | 200 | mce_get_rip(&m, regs); |
| 200 | if (error_code != -1) | 201 | if (error_code >= 0) |
| 201 | rdtscll(m.tsc); | 202 | rdtscll(m.tsc); |
| 202 | wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0); | 203 | wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0); |
| 203 | mce_log(&m); | 204 | if (error_code != -2) |
| 205 | mce_log(&m); | ||
| 204 | 206 | ||
| 205 | /* Did this bank cause the exception? */ | 207 | /* Did this bank cause the exception? */ |
| 206 | /* Assume that the bank with uncorrectable errors did it, | 208 | /* Assume that the bank with uncorrectable errors did it, |
| @@ -315,7 +317,7 @@ static void mce_init(void *dummy) | |||
| 315 | 317 | ||
| 316 | /* Log the machine checks left over from the previous reset. | 318 | /* Log the machine checks left over from the previous reset. |
| 317 | This also clears all registers */ | 319 | This also clears all registers */ |
| 318 | do_machine_check(NULL, -1); | 320 | do_machine_check(NULL, mce_bootlog ? -1 : -2); |
| 319 | 321 | ||
| 320 | set_in_cr4(X86_CR4_MCE); | 322 | set_in_cr4(X86_CR4_MCE); |
| 321 | 323 | ||
| @@ -476,11 +478,17 @@ static int __init mcheck_disable(char *str) | |||
| 476 | } | 478 | } |
| 477 | 479 | ||
| 478 | /* mce=off disables machine check. Note you can reenable it later | 480 | /* mce=off disables machine check. Note you can reenable it later |
| 479 | using sysfs */ | 481 | using sysfs. |
| 482 | mce=bootlog Log MCEs from before booting. Disabled by default to work | ||
| 483 | around buggy BIOS that leave bogus MCEs. */ | ||
| 480 | static int __init mcheck_enable(char *str) | 484 | static int __init mcheck_enable(char *str) |
| 481 | { | 485 | { |
| 486 | if (*str == '=') | ||
| 487 | str++; | ||
| 482 | if (!strcmp(str, "off")) | 488 | if (!strcmp(str, "off")) |
| 483 | mce_dont_init = 1; | 489 | mce_dont_init = 1; |
| 490 | else if (!strcmp(str, "bootlog")) | ||
| 491 | mce_bootlog = 1; | ||
| 484 | else | 492 | else |
| 485 | printk("mce= argument %s ignored. Please use /sys", str); | 493 | printk("mce= argument %s ignored. Please use /sys", str); |
| 486 | return 0; | 494 | return 0; |
