aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/mce.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/mce.c')
-rw-r--r--arch/x86_64/kernel/mce.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 08203b07f4bd..183dc6105429 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -37,7 +37,7 @@ static unsigned long bank[NR_BANKS] = { [0 ... NR_BANKS-1] = ~0UL };
37static unsigned long console_logged; 37static unsigned long console_logged;
38static int notify_user; 38static int notify_user;
39static int rip_msr; 39static int rip_msr;
40static int mce_bootlog; 40static int mce_bootlog = 1;
41 41
42/* 42/*
43 * Lockless MCE logging infrastructure. 43 * Lockless MCE logging infrastructure.
@@ -54,9 +54,12 @@ void mce_log(struct mce *mce)
54{ 54{
55 unsigned next, entry; 55 unsigned next, entry;
56 mce->finished = 0; 56 mce->finished = 0;
57 smp_wmb(); 57 wmb();
58 for (;;) { 58 for (;;) {
59 entry = rcu_dereference(mcelog.next); 59 entry = rcu_dereference(mcelog.next);
60 /* The rmb forces the compiler to reload next in each
61 iteration */
62 rmb();
60 for (;;) { 63 for (;;) {
61 /* When the buffer fills up discard new entries. Assume 64 /* When the buffer fills up discard new entries. Assume
62 that the earlier errors are the more interesting. */ 65 that the earlier errors are the more interesting. */
@@ -69,6 +72,7 @@ void mce_log(struct mce *mce)
69 entry++; 72 entry++;
70 continue; 73 continue;
71 } 74 }
75 break;
72 } 76 }
73 smp_rmb(); 77 smp_rmb();
74 next = entry + 1; 78 next = entry + 1;
@@ -76,9 +80,9 @@ void mce_log(struct mce *mce)
76 break; 80 break;
77 } 81 }
78 memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); 82 memcpy(mcelog.entry + entry, mce, sizeof(struct mce));
79 smp_wmb(); 83 wmb();
80 mcelog.entry[entry].finished = 1; 84 mcelog.entry[entry].finished = 1;
81 smp_wmb(); 85 wmb();
82 86
83 if (!test_and_set_bit(0, &console_logged)) 87 if (!test_and_set_bit(0, &console_logged))
84 notify_user = 1; 88 notify_user = 1;
@@ -343,7 +347,11 @@ static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
343 /* disable GART TBL walk error reporting, which trips off 347 /* disable GART TBL walk error reporting, which trips off
344 incorrectly with the IOMMU & 3ware & Cerberus. */ 348 incorrectly with the IOMMU & 3ware & Cerberus. */
345 clear_bit(10, &bank[4]); 349 clear_bit(10, &bank[4]);
350 /* Lots of broken BIOS around that don't clear them
351 by default and leave crap in there. Don't log. */
352 mce_bootlog = 0;
346 } 353 }
354
347} 355}
348 356
349static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) 357static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c)
@@ -352,6 +360,9 @@ static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c)
352 case X86_VENDOR_INTEL: 360 case X86_VENDOR_INTEL:
353 mce_intel_feature_init(c); 361 mce_intel_feature_init(c);
354 break; 362 break;
363 case X86_VENDOR_AMD:
364 mce_amd_feature_init(c);
365 break;
355 default: 366 default:
356 break; 367 break;
357 } 368 }
@@ -491,16 +502,16 @@ static int __init mcheck_disable(char *str)
491/* mce=off disables machine check. Note you can reenable it later 502/* mce=off disables machine check. Note you can reenable it later
492 using sysfs. 503 using sysfs.
493 mce=TOLERANCELEVEL (number, see above) 504 mce=TOLERANCELEVEL (number, see above)
494 mce=bootlog Log MCEs from before booting. Disabled by default to work 505 mce=bootlog Log MCEs from before booting. Disabled by default on AMD.
495 around buggy BIOS that leave bogus MCEs. */ 506 mce=nobootlog Don't log MCEs from before booting. */
496static int __init mcheck_enable(char *str) 507static int __init mcheck_enable(char *str)
497{ 508{
498 if (*str == '=') 509 if (*str == '=')
499 str++; 510 str++;
500 if (!strcmp(str, "off")) 511 if (!strcmp(str, "off"))
501 mce_dont_init = 1; 512 mce_dont_init = 1;
502 else if (!strcmp(str, "bootlog")) 513 else if (!strcmp(str, "bootlog") || !strcmp(str,"nobootlog"))
503 mce_bootlog = 1; 514 mce_bootlog = str[0] == 'b';
504 else if (isdigit(str[0])) 515 else if (isdigit(str[0]))
505 get_option(&str, &tolerant); 516 get_option(&str, &tolerant);
506 else 517 else