diff options
Diffstat (limited to 'arch/x86_64/kernel/mce.c')
-rw-r--r-- | arch/x86_64/kernel/mce.c | 27 |
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 }; | |||
37 | static unsigned long console_logged; | 37 | static unsigned long console_logged; |
38 | static int notify_user; | 38 | static int notify_user; |
39 | static int rip_msr; | 39 | static int rip_msr; |
40 | static int mce_bootlog; | 40 | static 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 | ||
349 | static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) | 357 | static 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. */ |
496 | static int __init mcheck_enable(char *str) | 507 | static 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 |