aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-internal.h14
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c109
2 files changed, 67 insertions, 56 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h
index 54dcb8ff12e5..6bd51e7ba87b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
+++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
@@ -1,3 +1,4 @@
1#include <linux/sysdev.h>
1#include <asm/mce.h> 2#include <asm/mce.h>
2 3
3enum severity_level { 4enum severity_level {
@@ -10,6 +11,19 @@ enum severity_level {
10 MCE_PANIC_SEVERITY, 11 MCE_PANIC_SEVERITY,
11}; 12};
12 13
14#define ATTR_LEN 16
15
16/* One object for each MCE bank, shared by all CPUs */
17struct mce_bank {
18 u64 ctl; /* subevents to enable */
19 unsigned char init; /* initialise bank? */
20 struct sysdev_attribute attr; /* sysdev attribute */
21 char attrname[ATTR_LEN]; /* attribute name */
22};
23
13int mce_severity(struct mce *a, int tolerant, char **msg); 24int mce_severity(struct mce *a, int tolerant, char **msg);
14 25
15extern int mce_ser; 26extern int mce_ser;
27
28extern struct mce_bank *mce_banks;
29
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index e16271f01ac4..a04806e01a82 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -64,7 +64,6 @@ DEFINE_PER_CPU(unsigned, mce_exception_count);
64 */ 64 */
65static int tolerant __read_mostly = 1; 65static int tolerant __read_mostly = 1;
66static int banks __read_mostly; 66static int banks __read_mostly;
67static u64 *bank __read_mostly;
68static int rip_msr __read_mostly; 67static int rip_msr __read_mostly;
69static int mce_bootlog __read_mostly = -1; 68static int mce_bootlog __read_mostly = -1;
70static int monarch_timeout __read_mostly = -1; 69static int monarch_timeout __read_mostly = -1;
@@ -74,13 +73,13 @@ int mce_cmci_disabled __read_mostly;
74int mce_ignore_ce __read_mostly; 73int mce_ignore_ce __read_mostly;
75int mce_ser __read_mostly; 74int mce_ser __read_mostly;
76 75
76struct mce_bank *mce_banks __read_mostly;
77
77/* User mode helper program triggered by machine check event */ 78/* User mode helper program triggered by machine check event */
78static unsigned long mce_need_notify; 79static unsigned long mce_need_notify;
79static char mce_helper[128]; 80static char mce_helper[128];
80static char *mce_helper_argv[2] = { mce_helper, NULL }; 81static char *mce_helper_argv[2] = { mce_helper, NULL };
81 82
82static unsigned long dont_init_banks;
83
84static DECLARE_WAIT_QUEUE_HEAD(mce_wait); 83static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
85static DEFINE_PER_CPU(struct mce, mces_seen); 84static DEFINE_PER_CPU(struct mce, mces_seen);
86static int cpu_missing; 85static int cpu_missing;
@@ -91,11 +90,6 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
91 [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL 90 [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL
92}; 91};
93 92
94static inline int skip_bank_init(int i)
95{
96 return i < BITS_PER_LONG && test_bit(i, &dont_init_banks);
97}
98
99static DEFINE_PER_CPU(struct work_struct, mce_work); 93static DEFINE_PER_CPU(struct work_struct, mce_work);
100 94
101/* Do initial initialization of a struct mce */ 95/* Do initial initialization of a struct mce */
@@ -482,7 +476,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
482 476
483 m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS); 477 m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
484 for (i = 0; i < banks; i++) { 478 for (i = 0; i < banks; i++) {
485 if (!bank[i] || !test_bit(i, *b)) 479 if (!mce_banks[i].ctl || !test_bit(i, *b))
486 continue; 480 continue;
487 481
488 m.misc = 0; 482 m.misc = 0;
@@ -903,7 +897,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
903 order = mce_start(&no_way_out); 897 order = mce_start(&no_way_out);
904 for (i = 0; i < banks; i++) { 898 for (i = 0; i < banks; i++) {
905 __clear_bit(i, toclear); 899 __clear_bit(i, toclear);
906 if (!bank[i]) 900 if (!mce_banks[i].ctl)
907 continue; 901 continue;
908 902
909 m.misc = 0; 903 m.misc = 0;
@@ -1146,6 +1140,21 @@ int mce_notify_irq(void)
1146} 1140}
1147EXPORT_SYMBOL_GPL(mce_notify_irq); 1141EXPORT_SYMBOL_GPL(mce_notify_irq);
1148 1142
1143static int mce_banks_init(void)
1144{
1145 int i;
1146
1147 mce_banks = kzalloc(banks * sizeof(struct mce_bank), GFP_KERNEL);
1148 if (!mce_banks)
1149 return -ENOMEM;
1150 for (i = 0; i < banks; i++) {
1151 struct mce_bank *b = &mce_banks[i];
1152 b->ctl = -1ULL;
1153 b->init = 1;
1154 }
1155 return 0;
1156}
1157
1149/* 1158/*
1150 * Initialize Machine Checks for a CPU. 1159 * Initialize Machine Checks for a CPU.
1151 */ 1160 */
@@ -1169,11 +1178,10 @@ static int mce_cap_init(void)
1169 /* Don't support asymmetric configurations today */ 1178 /* Don't support asymmetric configurations today */
1170 WARN_ON(banks != 0 && b != banks); 1179 WARN_ON(banks != 0 && b != banks);
1171 banks = b; 1180 banks = b;
1172 if (!bank) { 1181 if (!mce_banks) {
1173 bank = kmalloc(banks * sizeof(u64), GFP_KERNEL); 1182 int err = mce_banks_init();
1174 if (!bank) 1183 if (err)
1175 return -ENOMEM; 1184 return err;
1176 memset(bank, 0xff, banks * sizeof(u64));
1177 } 1185 }
1178 1186
1179 /* Use accurate RIP reporting if available. */ 1187 /* Use accurate RIP reporting if available. */
@@ -1205,9 +1213,10 @@ static void mce_init(void)
1205 wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); 1213 wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
1206 1214
1207 for (i = 0; i < banks; i++) { 1215 for (i = 0; i < banks; i++) {
1208 if (skip_bank_init(i)) 1216 struct mce_bank *b = &mce_banks[i];
1217 if (!b->init)
1209 continue; 1218 continue;
1210 wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]); 1219 wrmsrl(MSR_IA32_MC0_CTL+4*i, b->ctl);
1211 wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); 1220 wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
1212 } 1221 }
1213} 1222}
@@ -1223,7 +1232,7 @@ static void mce_cpu_quirks(struct cpuinfo_x86 *c)
1223 * trips off incorrectly with the IOMMU & 3ware 1232 * trips off incorrectly with the IOMMU & 3ware
1224 * & Cerberus: 1233 * & Cerberus:
1225 */ 1234 */
1226 clear_bit(10, (unsigned long *)&bank[4]); 1235 clear_bit(10, (unsigned long *)&mce_banks[4].ctl);
1227 } 1236 }
1228 if (c->x86 <= 17 && mce_bootlog < 0) { 1237 if (c->x86 <= 17 && mce_bootlog < 0) {
1229 /* 1238 /*
@@ -1237,7 +1246,7 @@ static void mce_cpu_quirks(struct cpuinfo_x86 *c)
1237 * by default. 1246 * by default.
1238 */ 1247 */
1239 if (c->x86 == 6 && banks > 0) 1248 if (c->x86 == 6 && banks > 0)
1240 bank[0] = 0; 1249 mce_banks[0].ctl = 0;
1241 } 1250 }
1242 1251
1243 if (c->x86_vendor == X86_VENDOR_INTEL) { 1252 if (c->x86_vendor == X86_VENDOR_INTEL) {
@@ -1250,8 +1259,8 @@ static void mce_cpu_quirks(struct cpuinfo_x86 *c)
1250 * valid event later, merely don't write CTL0. 1259 * valid event later, merely don't write CTL0.
1251 */ 1260 */
1252 1261
1253 if (c->x86 == 6 && c->x86_model < 0x1A) 1262 if (c->x86 == 6 && c->x86_model < 0x1A && banks > 0)
1254 __set_bit(0, &dont_init_banks); 1263 mce_banks[0].init = 0;
1255 1264
1256 /* 1265 /*
1257 * All newer Intel systems support MCE broadcasting. Enable 1266 * All newer Intel systems support MCE broadcasting. Enable
@@ -1578,7 +1587,8 @@ static int mce_disable(void)
1578 int i; 1587 int i;
1579 1588
1580 for (i = 0; i < banks; i++) { 1589 for (i = 0; i < banks; i++) {
1581 if (!skip_bank_init(i)) 1590 struct mce_bank *b = &mce_banks[i];
1591 if (b->init)
1582 wrmsrl(MSR_IA32_MC0_CTL + i*4, 0); 1592 wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
1583 } 1593 }
1584 return 0; 1594 return 0;
@@ -1654,14 +1664,15 @@ DEFINE_PER_CPU(struct sys_device, mce_dev);
1654__cpuinitdata 1664__cpuinitdata
1655void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu); 1665void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
1656 1666
1657static struct sysdev_attribute *bank_attrs; 1667static inline struct mce_bank *attr_to_bank(struct sysdev_attribute *attr)
1668{
1669 return container_of(attr, struct mce_bank, attr);
1670}
1658 1671
1659static ssize_t show_bank(struct sys_device *s, struct sysdev_attribute *attr, 1672static ssize_t show_bank(struct sys_device *s, struct sysdev_attribute *attr,
1660 char *buf) 1673 char *buf)
1661{ 1674{
1662 u64 b = bank[attr - bank_attrs]; 1675 return sprintf(buf, "%llx\n", attr_to_bank(attr)->ctl);
1663
1664 return sprintf(buf, "%llx\n", b);
1665} 1676}
1666 1677
1667static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr, 1678static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr,
@@ -1672,7 +1683,7 @@ static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr,
1672 if (strict_strtoull(buf, 0, &new) < 0) 1683 if (strict_strtoull(buf, 0, &new) < 0)
1673 return -EINVAL; 1684 return -EINVAL;
1674 1685
1675 bank[attr - bank_attrs] = new; 1686 attr_to_bank(attr)->ctl = new;
1676 mce_restart(); 1687 mce_restart();
1677 1688
1678 return size; 1689 return size;
@@ -1816,7 +1827,7 @@ static __cpuinit int mce_create_device(unsigned int cpu)
1816 } 1827 }
1817 for (j = 0; j < banks; j++) { 1828 for (j = 0; j < banks; j++) {
1818 err = sysdev_create_file(&per_cpu(mce_dev, cpu), 1829 err = sysdev_create_file(&per_cpu(mce_dev, cpu),
1819 &bank_attrs[j]); 1830 &mce_banks[j].attr);
1820 if (err) 1831 if (err)
1821 goto error2; 1832 goto error2;
1822 } 1833 }
@@ -1825,10 +1836,10 @@ static __cpuinit int mce_create_device(unsigned int cpu)
1825 return 0; 1836 return 0;
1826error2: 1837error2:
1827 while (--j >= 0) 1838 while (--j >= 0)
1828 sysdev_remove_file(&per_cpu(mce_dev, cpu), &bank_attrs[j]); 1839 sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[j].attr);
1829error: 1840error:
1830 while (--i >= 0) 1841 while (--i >= 0)
1831 sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]); 1842 sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[i].attr);
1832 1843
1833 sysdev_unregister(&per_cpu(mce_dev, cpu)); 1844 sysdev_unregister(&per_cpu(mce_dev, cpu));
1834 1845
@@ -1846,7 +1857,7 @@ static __cpuinit void mce_remove_device(unsigned int cpu)
1846 sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]); 1857 sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
1847 1858
1848 for (i = 0; i < banks; i++) 1859 for (i = 0; i < banks; i++)
1849 sysdev_remove_file(&per_cpu(mce_dev, cpu), &bank_attrs[i]); 1860 sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[i].attr);
1850 1861
1851 sysdev_unregister(&per_cpu(mce_dev, cpu)); 1862 sysdev_unregister(&per_cpu(mce_dev, cpu));
1852 cpumask_clear_cpu(cpu, mce_dev_initialized); 1863 cpumask_clear_cpu(cpu, mce_dev_initialized);
@@ -1863,7 +1874,8 @@ static void mce_disable_cpu(void *h)
1863 if (!(action & CPU_TASKS_FROZEN)) 1874 if (!(action & CPU_TASKS_FROZEN))
1864 cmci_clear(); 1875 cmci_clear();
1865 for (i = 0; i < banks; i++) { 1876 for (i = 0; i < banks; i++) {
1866 if (!skip_bank_init(i)) 1877 struct mce_bank *b = &mce_banks[i];
1878 if (b->init)
1867 wrmsrl(MSR_IA32_MC0_CTL + i*4, 0); 1879 wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
1868 } 1880 }
1869} 1881}
@@ -1879,8 +1891,9 @@ static void mce_reenable_cpu(void *h)
1879 if (!(action & CPU_TASKS_FROZEN)) 1891 if (!(action & CPU_TASKS_FROZEN))
1880 cmci_reenable(); 1892 cmci_reenable();
1881 for (i = 0; i < banks; i++) { 1893 for (i = 0; i < banks; i++) {
1882 if (!skip_bank_init(i)) 1894 struct mce_bank *b = &mce_banks[i];
1883 wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]); 1895 if (b->init)
1896 wrmsrl(MSR_IA32_MC0_CTL + i*4, b->ctl);
1884 } 1897 }
1885} 1898}
1886 1899
@@ -1928,35 +1941,21 @@ static struct notifier_block mce_cpu_notifier __cpuinitdata = {
1928 .notifier_call = mce_cpu_callback, 1941 .notifier_call = mce_cpu_callback,
1929}; 1942};
1930 1943
1931static __init int mce_init_banks(void) 1944static __init void mce_init_banks(void)
1932{ 1945{
1933 int i; 1946 int i;
1934 1947
1935 bank_attrs = kzalloc(sizeof(struct sysdev_attribute) * banks,
1936 GFP_KERNEL);
1937 if (!bank_attrs)
1938 return -ENOMEM;
1939
1940 for (i = 0; i < banks; i++) { 1948 for (i = 0; i < banks; i++) {
1941 struct sysdev_attribute *a = &bank_attrs[i]; 1949 struct mce_bank *b = &mce_banks[i];
1950 struct sysdev_attribute *a = &b->attr;
1942 1951
1943 a->attr.name = kasprintf(GFP_KERNEL, "bank%d", i); 1952 a->attr.name = b->attrname;
1944 if (!a->attr.name) 1953 snprintf(b->attrname, ATTR_LEN, "bank%d", i);
1945 goto nomem;
1946 1954
1947 a->attr.mode = 0644; 1955 a->attr.mode = 0644;
1948 a->show = show_bank; 1956 a->show = show_bank;
1949 a->store = set_bank; 1957 a->store = set_bank;
1950 } 1958 }
1951 return 0;
1952
1953nomem:
1954 while (--i >= 0)
1955 kfree(bank_attrs[i].attr.name);
1956 kfree(bank_attrs);
1957 bank_attrs = NULL;
1958
1959 return -ENOMEM;
1960} 1959}
1961 1960
1962static __init int mce_init_device(void) 1961static __init int mce_init_device(void)
@@ -1969,9 +1968,7 @@ static __init int mce_init_device(void)
1969 1968
1970 zalloc_cpumask_var(&mce_dev_initialized, GFP_KERNEL); 1969 zalloc_cpumask_var(&mce_dev_initialized, GFP_KERNEL);
1971 1970
1972 err = mce_init_banks(); 1971 mce_init_banks();
1973 if (err)
1974 return err;
1975 1972
1976 err = sysdev_class_register(&mce_sysclass); 1973 err = sysdev_class_register(&mce_sysclass);
1977 if (err) 1974 if (err)