diff options
author | Andi Kleen <andi@firstfloor.org> | 2009-02-12 07:39:32 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2009-02-17 18:32:14 -0500 |
commit | 973a2dd1d50a11d380086601f14e59116f93e8c5 (patch) | |
tree | 8fad8589e95a034b8c33da8f3c17056ae60c2294 /arch/x86/kernel/cpu | |
parent | 07db1c140eb233971341396e492cc73d4280e698 (diff) |
x86, mce: disable machine checks on suspend
Impact: Bug fix
During suspend it is not reliable to process machine check
exceptions, because CPUs disappear but can still get machine check
broadcasts. Also the system is slightly more likely to
machine check them, but the handler is typically not a position
to handle them in a meaningfull way.
So disable them during suspend and enable them during resume.
Also make sure they are always disabled on hot-unplugged CPUs.
This new code assumes that suspend always hotunplugs all
non BP CPUs.
v2: Remove the WARN_ONs Thomas objected to.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_64.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 25cf624eccb7..5ed80991ab9e 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c | |||
@@ -728,6 +728,29 @@ __setup("mce=", mcheck_enable); | |||
728 | * Sysfs support | 728 | * Sysfs support |
729 | */ | 729 | */ |
730 | 730 | ||
731 | /* | ||
732 | * Disable machine checks on suspend and shutdown. We can't really handle | ||
733 | * them later. | ||
734 | */ | ||
735 | static int mce_disable(void) | ||
736 | { | ||
737 | int i; | ||
738 | |||
739 | for (i = 0; i < banks; i++) | ||
740 | wrmsrl(MSR_IA32_MC0_CTL + i*4, 0); | ||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static int mce_suspend(struct sys_device *dev, pm_message_t state) | ||
745 | { | ||
746 | return mce_disable(); | ||
747 | } | ||
748 | |||
749 | static int mce_shutdown(struct sys_device *dev) | ||
750 | { | ||
751 | return mce_disable(); | ||
752 | } | ||
753 | |||
731 | /* On resume clear all MCE state. Don't want to see leftovers from the BIOS. | 754 | /* On resume clear all MCE state. Don't want to see leftovers from the BIOS. |
732 | Only one CPU is active at this time, the others get readded later using | 755 | Only one CPU is active at this time, the others get readded later using |
733 | CPU hotplug. */ | 756 | CPU hotplug. */ |
@@ -752,6 +775,8 @@ static void mce_restart(void) | |||
752 | } | 775 | } |
753 | 776 | ||
754 | static struct sysdev_class mce_sysclass = { | 777 | static struct sysdev_class mce_sysclass = { |
778 | .suspend = mce_suspend, | ||
779 | .shutdown = mce_shutdown, | ||
755 | .resume = mce_resume, | 780 | .resume = mce_resume, |
756 | .name = "machinecheck", | 781 | .name = "machinecheck", |
757 | }; | 782 | }; |