aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/mcheck/mce.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2009-04-27 12:37:43 -0400
committerH. Peter Anvin <hpa@zytor.com>2009-05-28 12:24:12 -0400
commit06b7a7a5ec917761969444fee967c43868a76468 (patch)
treefc59ae3ccbb90d61bd7be9240a61c4bd31794cec /arch/x86/kernel/cpu/mcheck/mce.c
parent3cde5c8c839bf46a7be799ed0e1d0b4780aaf794 (diff)
x86, mce: implement the PPro bank 0 quirk in the 64bit machine check code
Quoting the comment: * SDM documents that on family 6 bank 0 should not be written * because it aliases to another special BIOS controlled * register. * But it's not aliased anymore on model 0x1a+ * Don't ignore bank 0 completely because there could be a valid * event later, merely don't write CTL0. This is mostly a port on the 32bit code, except that 32bit always didn't write it and didn't have the 0x1a heuristic. I checked with the CPU designers that the quirk is not required starting with this model. Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/cpu/mcheck/mce.c')
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index cd1313b4750..1dcd3be0332 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -65,6 +65,8 @@ static atomic_t mce_events;
65static char trigger[128]; 65static char trigger[128];
66static char *trigger_argv[2] = { trigger, NULL }; 66static char *trigger_argv[2] = { trigger, NULL };
67 67
68static unsigned long dont_init_banks;
69
68static DECLARE_WAIT_QUEUE_HEAD(mce_wait); 70static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
69 71
70/* MCA banks polled by the period polling timer for corrected events */ 72/* MCA banks polled by the period polling timer for corrected events */
@@ -72,6 +74,11 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
72 [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL 74 [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL
73}; 75};
74 76
77static inline int skip_bank_init(int i)
78{
79 return i < BITS_PER_LONG && test_bit(i, &dont_init_banks);
80}
81
75/* Do initial initialization of a struct mce */ 82/* Do initial initialization of a struct mce */
76void mce_setup(struct mce *m) 83void mce_setup(struct mce *m)
77{ 84{
@@ -616,6 +623,8 @@ static void mce_init(void *dummy)
616 wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); 623 wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
617 624
618 for (i = 0; i < banks; i++) { 625 for (i = 0; i < banks; i++) {
626 if (skip_bank_init(i))
627 continue;
619 wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]); 628 wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]);
620 wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); 629 wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
621 } 630 }
@@ -643,6 +652,19 @@ static void mce_cpu_quirks(struct cpuinfo_x86 *c)
643 } 652 }
644 } 653 }
645 654
655 if (c->x86_vendor == X86_VENDOR_INTEL) {
656 /*
657 * SDM documents that on family 6 bank 0 should not be written
658 * because it aliases to another special BIOS controlled
659 * register.
660 * But it's not aliased anymore on model 0x1a+
661 * Don't ignore bank 0 completely because there could be a
662 * valid event later, merely don't write CTL0.
663 */
664
665 if (c->x86 == 6 && c->x86_model < 0x1A)
666 __set_bit(0, &dont_init_banks);
667 }
646} 668}
647 669
648static void mce_cpu_features(struct cpuinfo_x86 *c) 670static void mce_cpu_features(struct cpuinfo_x86 *c)
@@ -911,8 +933,10 @@ static int mce_disable(void)
911{ 933{
912 int i; 934 int i;
913 935
914 for (i = 0; i < banks; i++) 936 for (i = 0; i < banks; i++) {
915 wrmsrl(MSR_IA32_MC0_CTL + i*4, 0); 937 if (!skip_bank_init(i))
938 wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
939 }
916 return 0; 940 return 0;
917} 941}
918 942
@@ -1119,8 +1143,10 @@ static void mce_disable_cpu(void *h)
1119 return; 1143 return;
1120 if (!(action & CPU_TASKS_FROZEN)) 1144 if (!(action & CPU_TASKS_FROZEN))
1121 cmci_clear(); 1145 cmci_clear();
1122 for (i = 0; i < banks; i++) 1146 for (i = 0; i < banks; i++) {
1123 wrmsrl(MSR_IA32_MC0_CTL + i*4, 0); 1147 if (!skip_bank_init(i))
1148 wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
1149 }
1124} 1150}
1125 1151
1126static void mce_reenable_cpu(void *h) 1152static void mce_reenable_cpu(void *h)
@@ -1133,8 +1159,10 @@ static void mce_reenable_cpu(void *h)
1133 1159
1134 if (!(action & CPU_TASKS_FROZEN)) 1160 if (!(action & CPU_TASKS_FROZEN))
1135 cmci_reenable(); 1161 cmci_reenable();
1136 for (i = 0; i < banks; i++) 1162 for (i = 0; i < banks; i++) {
1137 wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]); 1163 if (!skip_bank_init(i))
1164 wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]);
1165 }
1138} 1166}
1139 1167
1140/* Get notified when a cpu comes on/off. Be hotplug friendly. */ 1168/* Get notified when a cpu comes on/off. Be hotplug friendly. */