diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mcheck/mce.c')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 71 |
1 files changed, 32 insertions, 39 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index ed41562909fe..ff1ae9b6464d 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/percpu.h> | 21 | #include <linux/percpu.h> |
22 | #include <linux/string.h> | 22 | #include <linux/string.h> |
23 | #include <linux/sysdev.h> | 23 | #include <linux/sysdev.h> |
24 | #include <linux/syscore_ops.h> | ||
24 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
25 | #include <linux/ctype.h> | 26 | #include <linux/ctype.h> |
26 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
@@ -104,20 +105,6 @@ static int cpu_missing; | |||
104 | ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); | 105 | ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); |
105 | EXPORT_SYMBOL_GPL(x86_mce_decoder_chain); | 106 | EXPORT_SYMBOL_GPL(x86_mce_decoder_chain); |
106 | 107 | ||
107 | static int default_decode_mce(struct notifier_block *nb, unsigned long val, | ||
108 | void *data) | ||
109 | { | ||
110 | pr_emerg(HW_ERR "No human readable MCE decoding support on this CPU type.\n"); | ||
111 | pr_emerg(HW_ERR "Run the message through 'mcelog --ascii' to decode.\n"); | ||
112 | |||
113 | return NOTIFY_STOP; | ||
114 | } | ||
115 | |||
116 | static struct notifier_block mce_dec_nb = { | ||
117 | .notifier_call = default_decode_mce, | ||
118 | .priority = -1, | ||
119 | }; | ||
120 | |||
121 | /* MCA banks polled by the period polling timer for corrected events */ | 108 | /* MCA banks polled by the period polling timer for corrected events */ |
122 | DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { | 109 | DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { |
123 | [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL | 110 | [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL |
@@ -211,6 +198,8 @@ void mce_log(struct mce *mce) | |||
211 | 198 | ||
212 | static void print_mce(struct mce *m) | 199 | static void print_mce(struct mce *m) |
213 | { | 200 | { |
201 | int ret = 0; | ||
202 | |||
214 | pr_emerg(HW_ERR "CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n", | 203 | pr_emerg(HW_ERR "CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n", |
215 | m->extcpu, m->mcgstatus, m->bank, m->status); | 204 | m->extcpu, m->mcgstatus, m->bank, m->status); |
216 | 205 | ||
@@ -238,7 +227,11 @@ static void print_mce(struct mce *m) | |||
238 | * Print out human-readable details about the MCE error, | 227 | * Print out human-readable details about the MCE error, |
239 | * (if the CPU has an implementation for that) | 228 | * (if the CPU has an implementation for that) |
240 | */ | 229 | */ |
241 | atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m); | 230 | ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m); |
231 | if (ret == NOTIFY_STOP) | ||
232 | return; | ||
233 | |||
234 | pr_emerg_ratelimited(HW_ERR "Run the above through 'mcelog --ascii'\n"); | ||
242 | } | 235 | } |
243 | 236 | ||
244 | #define PANIC_TIMEOUT 5 /* 5 seconds */ | 237 | #define PANIC_TIMEOUT 5 /* 5 seconds */ |
@@ -326,7 +319,7 @@ static void mce_panic(char *msg, struct mce *final, char *exp) | |||
326 | 319 | ||
327 | static int msr_to_offset(u32 msr) | 320 | static int msr_to_offset(u32 msr) |
328 | { | 321 | { |
329 | unsigned bank = __get_cpu_var(injectm.bank); | 322 | unsigned bank = __this_cpu_read(injectm.bank); |
330 | 323 | ||
331 | if (msr == rip_msr) | 324 | if (msr == rip_msr) |
332 | return offsetof(struct mce, ip); | 325 | return offsetof(struct mce, ip); |
@@ -346,7 +339,7 @@ static u64 mce_rdmsrl(u32 msr) | |||
346 | { | 339 | { |
347 | u64 v; | 340 | u64 v; |
348 | 341 | ||
349 | if (__get_cpu_var(injectm).finished) { | 342 | if (__this_cpu_read(injectm.finished)) { |
350 | int offset = msr_to_offset(msr); | 343 | int offset = msr_to_offset(msr); |
351 | 344 | ||
352 | if (offset < 0) | 345 | if (offset < 0) |
@@ -369,7 +362,7 @@ static u64 mce_rdmsrl(u32 msr) | |||
369 | 362 | ||
370 | static void mce_wrmsrl(u32 msr, u64 v) | 363 | static void mce_wrmsrl(u32 msr, u64 v) |
371 | { | 364 | { |
372 | if (__get_cpu_var(injectm).finished) { | 365 | if (__this_cpu_read(injectm.finished)) { |
373 | int offset = msr_to_offset(msr); | 366 | int offset = msr_to_offset(msr); |
374 | 367 | ||
375 | if (offset >= 0) | 368 | if (offset >= 0) |
@@ -589,7 +582,6 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) | |||
589 | if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) { | 582 | if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) { |
590 | mce_log(&m); | 583 | mce_log(&m); |
591 | atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, &m); | 584 | atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, &m); |
592 | add_taint(TAINT_MACHINE_CHECK); | ||
593 | } | 585 | } |
594 | 586 | ||
595 | /* | 587 | /* |
@@ -881,7 +873,7 @@ reset: | |||
881 | * Check if the address reported by the CPU is in a format we can parse. | 873 | * Check if the address reported by the CPU is in a format we can parse. |
882 | * It would be possible to add code for most other cases, but all would | 874 | * It would be possible to add code for most other cases, but all would |
883 | * be somewhat complicated (e.g. segment offset would require an instruction | 875 | * be somewhat complicated (e.g. segment offset would require an instruction |
884 | * parser). So only support physical addresses upto page granuality for now. | 876 | * parser). So only support physical addresses up to page granuality for now. |
885 | */ | 877 | */ |
886 | static int mce_usable_address(struct mce *m) | 878 | static int mce_usable_address(struct mce *m) |
887 | { | 879 | { |
@@ -1159,7 +1151,7 @@ static void mce_start_timer(unsigned long data) | |||
1159 | 1151 | ||
1160 | WARN_ON(smp_processor_id() != data); | 1152 | WARN_ON(smp_processor_id() != data); |
1161 | 1153 | ||
1162 | if (mce_available(¤t_cpu_data)) { | 1154 | if (mce_available(__this_cpu_ptr(&cpu_info))) { |
1163 | machine_check_poll(MCP_TIMESTAMP, | 1155 | machine_check_poll(MCP_TIMESTAMP, |
1164 | &__get_cpu_var(mce_poll_banks)); | 1156 | &__get_cpu_var(mce_poll_banks)); |
1165 | } | 1157 | } |
@@ -1625,7 +1617,7 @@ out: | |||
1625 | static unsigned int mce_poll(struct file *file, poll_table *wait) | 1617 | static unsigned int mce_poll(struct file *file, poll_table *wait) |
1626 | { | 1618 | { |
1627 | poll_wait(file, &mce_wait, wait); | 1619 | poll_wait(file, &mce_wait, wait); |
1628 | if (rcu_dereference_check_mce(mcelog.next)) | 1620 | if (rcu_access_index(mcelog.next)) |
1629 | return POLLIN | POLLRDNORM; | 1621 | return POLLIN | POLLRDNORM; |
1630 | if (!mce_apei_read_done && apei_check_mce()) | 1622 | if (!mce_apei_read_done && apei_check_mce()) |
1631 | return POLLIN | POLLRDNORM; | 1623 | return POLLIN | POLLRDNORM; |
@@ -1665,6 +1657,7 @@ struct file_operations mce_chrdev_ops = { | |||
1665 | .read = mce_read, | 1657 | .read = mce_read, |
1666 | .poll = mce_poll, | 1658 | .poll = mce_poll, |
1667 | .unlocked_ioctl = mce_ioctl, | 1659 | .unlocked_ioctl = mce_ioctl, |
1660 | .llseek = no_llseek, | ||
1668 | }; | 1661 | }; |
1669 | EXPORT_SYMBOL_GPL(mce_chrdev_ops); | 1662 | EXPORT_SYMBOL_GPL(mce_chrdev_ops); |
1670 | 1663 | ||
@@ -1720,8 +1713,6 @@ __setup("mce", mcheck_enable); | |||
1720 | 1713 | ||
1721 | int __init mcheck_init(void) | 1714 | int __init mcheck_init(void) |
1722 | { | 1715 | { |
1723 | atomic_notifier_chain_register(&x86_mce_decoder_chain, &mce_dec_nb); | ||
1724 | |||
1725 | mcheck_intel_therm_init(); | 1716 | mcheck_intel_therm_init(); |
1726 | 1717 | ||
1727 | return 0; | 1718 | return 0; |
@@ -1748,14 +1739,14 @@ static int mce_disable_error_reporting(void) | |||
1748 | return 0; | 1739 | return 0; |
1749 | } | 1740 | } |
1750 | 1741 | ||
1751 | static int mce_suspend(struct sys_device *dev, pm_message_t state) | 1742 | static int mce_suspend(void) |
1752 | { | 1743 | { |
1753 | return mce_disable_error_reporting(); | 1744 | return mce_disable_error_reporting(); |
1754 | } | 1745 | } |
1755 | 1746 | ||
1756 | static int mce_shutdown(struct sys_device *dev) | 1747 | static void mce_shutdown(void) |
1757 | { | 1748 | { |
1758 | return mce_disable_error_reporting(); | 1749 | mce_disable_error_reporting(); |
1759 | } | 1750 | } |
1760 | 1751 | ||
1761 | /* | 1752 | /* |
@@ -1763,18 +1754,22 @@ static int mce_shutdown(struct sys_device *dev) | |||
1763 | * Only one CPU is active at this time, the others get re-added later using | 1754 | * Only one CPU is active at this time, the others get re-added later using |
1764 | * CPU hotplug: | 1755 | * CPU hotplug: |
1765 | */ | 1756 | */ |
1766 | static int mce_resume(struct sys_device *dev) | 1757 | static void mce_resume(void) |
1767 | { | 1758 | { |
1768 | __mcheck_cpu_init_generic(); | 1759 | __mcheck_cpu_init_generic(); |
1769 | __mcheck_cpu_init_vendor(¤t_cpu_data); | 1760 | __mcheck_cpu_init_vendor(__this_cpu_ptr(&cpu_info)); |
1770 | |||
1771 | return 0; | ||
1772 | } | 1761 | } |
1773 | 1762 | ||
1763 | static struct syscore_ops mce_syscore_ops = { | ||
1764 | .suspend = mce_suspend, | ||
1765 | .shutdown = mce_shutdown, | ||
1766 | .resume = mce_resume, | ||
1767 | }; | ||
1768 | |||
1774 | static void mce_cpu_restart(void *data) | 1769 | static void mce_cpu_restart(void *data) |
1775 | { | 1770 | { |
1776 | del_timer_sync(&__get_cpu_var(mce_timer)); | 1771 | del_timer_sync(&__get_cpu_var(mce_timer)); |
1777 | if (!mce_available(¤t_cpu_data)) | 1772 | if (!mce_available(__this_cpu_ptr(&cpu_info))) |
1778 | return; | 1773 | return; |
1779 | __mcheck_cpu_init_generic(); | 1774 | __mcheck_cpu_init_generic(); |
1780 | __mcheck_cpu_init_timer(); | 1775 | __mcheck_cpu_init_timer(); |
@@ -1789,7 +1784,7 @@ static void mce_restart(void) | |||
1789 | /* Toggle features for corrected errors */ | 1784 | /* Toggle features for corrected errors */ |
1790 | static void mce_disable_ce(void *all) | 1785 | static void mce_disable_ce(void *all) |
1791 | { | 1786 | { |
1792 | if (!mce_available(¤t_cpu_data)) | 1787 | if (!mce_available(__this_cpu_ptr(&cpu_info))) |
1793 | return; | 1788 | return; |
1794 | if (all) | 1789 | if (all) |
1795 | del_timer_sync(&__get_cpu_var(mce_timer)); | 1790 | del_timer_sync(&__get_cpu_var(mce_timer)); |
@@ -1798,7 +1793,7 @@ static void mce_disable_ce(void *all) | |||
1798 | 1793 | ||
1799 | static void mce_enable_ce(void *all) | 1794 | static void mce_enable_ce(void *all) |
1800 | { | 1795 | { |
1801 | if (!mce_available(¤t_cpu_data)) | 1796 | if (!mce_available(__this_cpu_ptr(&cpu_info))) |
1802 | return; | 1797 | return; |
1803 | cmci_reenable(); | 1798 | cmci_reenable(); |
1804 | cmci_recheck(); | 1799 | cmci_recheck(); |
@@ -1807,9 +1802,6 @@ static void mce_enable_ce(void *all) | |||
1807 | } | 1802 | } |
1808 | 1803 | ||
1809 | static struct sysdev_class mce_sysclass = { | 1804 | static struct sysdev_class mce_sysclass = { |
1810 | .suspend = mce_suspend, | ||
1811 | .shutdown = mce_shutdown, | ||
1812 | .resume = mce_resume, | ||
1813 | .name = "machinecheck", | 1805 | .name = "machinecheck", |
1814 | }; | 1806 | }; |
1815 | 1807 | ||
@@ -2021,7 +2013,7 @@ static void __cpuinit mce_disable_cpu(void *h) | |||
2021 | unsigned long action = *(unsigned long *)h; | 2013 | unsigned long action = *(unsigned long *)h; |
2022 | int i; | 2014 | int i; |
2023 | 2015 | ||
2024 | if (!mce_available(¤t_cpu_data)) | 2016 | if (!mce_available(__this_cpu_ptr(&cpu_info))) |
2025 | return; | 2017 | return; |
2026 | 2018 | ||
2027 | if (!(action & CPU_TASKS_FROZEN)) | 2019 | if (!(action & CPU_TASKS_FROZEN)) |
@@ -2039,7 +2031,7 @@ static void __cpuinit mce_reenable_cpu(void *h) | |||
2039 | unsigned long action = *(unsigned long *)h; | 2031 | unsigned long action = *(unsigned long *)h; |
2040 | int i; | 2032 | int i; |
2041 | 2033 | ||
2042 | if (!mce_available(¤t_cpu_data)) | 2034 | if (!mce_available(__this_cpu_ptr(&cpu_info))) |
2043 | return; | 2035 | return; |
2044 | 2036 | ||
2045 | if (!(action & CPU_TASKS_FROZEN)) | 2037 | if (!(action & CPU_TASKS_FROZEN)) |
@@ -2138,6 +2130,7 @@ static __init int mcheck_init_device(void) | |||
2138 | return err; | 2130 | return err; |
2139 | } | 2131 | } |
2140 | 2132 | ||
2133 | register_syscore_ops(&mce_syscore_ops); | ||
2141 | register_hotcpu_notifier(&mce_cpu_notifier); | 2134 | register_hotcpu_notifier(&mce_cpu_notifier); |
2142 | misc_register(&mce_log_device); | 2135 | misc_register(&mce_log_device); |
2143 | 2136 | ||