From f436f8bb73138bc74eb1c6527723e00988ad8a8a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 1 Oct 2009 16:14:32 +0200 Subject: x86: EDAC: MCE: Fix MCE decoding callback logic Make decoding of MCEs happen only on AMD hardware by registering a non-default callback only on CPU families which support it. While looking at the interaction of decode_mce() with the other MCE code i also noticed a few other things and made the following cleanups/fixes: - Fixed the mce_decode() weak alias - a weak alias is really not good here, it should be a proper callback. A weak alias will be overriden if a piece of code is built into the kernel - not good, obviously. - The patch initializes the callback on AMD family 10h and 11h. - Added the more correct fallback printk of: No support for human readable MCE decoding on this CPU type. Transcribe the message and run it through 'mcelog --ascii' to decode. On CPUs that dont have a decoder. - Made the surrounding code more readable. Note that the callback allows us to have a default fallback - without having to check the CPU versions during the printout itself. When an EDAC module registers itself, it can install the decode-print function. (there's no unregister needed as this is core code.) version -v2 by Borislav Petkov: - add K8 to the set of supported CPUs - always build in edac_mce_amd since we use an early_initcall now - fix checkpatch warnings Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Andi Kleen LKML-Reference: <20091001141432.GA11410@aftab> Signed-off-by: Ingo Molnar --- drivers/edac/Makefile | 2 +- drivers/edac/edac_mce_amd.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers/edac') diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 7a473bbe8ab..8701cd7ce4e 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -18,7 +18,7 @@ edac_core-objs += edac_pci.o edac_pci_sysfs.o endif ifdef CONFIG_CPU_SUP_AMD -edac_core-objs += edac_mce_amd.o +obj-$(CONFIG_X86_MCE) += edac_mce_amd.o endif obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c index 0c21c370c9d..83a01a1187d 100644 --- a/drivers/edac/edac_mce_amd.c +++ b/drivers/edac/edac_mce_amd.c @@ -362,7 +362,7 @@ static inline void amd_decode_err_code(unsigned int ec) pr_warning("Huh? Unknown MCE error 0x%x\n", ec); } -void decode_mce(struct mce *m) +static void amd_decode_mce(struct mce *m) { struct err_regs regs; int node, ecc; @@ -420,3 +420,16 @@ void decode_mce(struct mce *m) amd_decode_err_code(m->status & 0xffff); } + +static int __init mce_amd_init(void) +{ + /* + * We can decode MCEs for Opteron and later CPUs: + */ + if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && + (boot_cpu_data.x86 >= 0xf)) + x86_mce_decode_callback = amd_decode_mce; + + return 0; +} +early_initcall(mce_amd_init); -- cgit v1.2.3 From 0d18b2e34bd1ad8f5bd3f3a17b5e7df132e511a9 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 2 Oct 2009 15:31:48 +0200 Subject: x86: EDAC: carve out AMD MCE decoding logic This converts the MCE decoding logic into a standalone config option which can be built-in or a module, the first one being the default for MCEs happening early on in the boot process. This, beyond being separated in a cleaner way, also saves RAM by making the decoding logic modular. Signed-off-by: Borislav Petkov Cc: Linus Torvalds Cc: Andi Kleen LKML-Reference: <20091002133148.GD28682@aftab> Signed-off-by: Ingo Molnar --- drivers/edac/Kconfig | 14 +++++++++++++- drivers/edac/Makefile | 5 +---- drivers/edac/edac_mce_amd.c | 19 ++++++++++++++++++- 3 files changed, 32 insertions(+), 6 deletions(-) (limited to 'drivers/edac') diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 02127e59fe8..55c9c59b3f7 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -47,6 +47,18 @@ config EDAC_DEBUG_VERBOSE Source file name and line number where debugging message printed will be added to debugging message. + config EDAC_DECODE_MCE + tristate "Decode MCEs in human-readable form (only on AMD for now)" + depends on CPU_SUP_AMD && X86_MCE + default y + ---help--- + Enable this option if you want to decode Machine Check Exceptions + occuring on your machine in human-readable form. + + You should definitely say Y here in case you want to decode MCEs + which occur really early upon boot, before the module infrastructure + has been initialized. + config EDAC_MM_EDAC tristate "Main Memory EDAC (Error Detection And Correction) reporting" help @@ -59,7 +71,7 @@ config EDAC_MM_EDAC config EDAC_AMD64 tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h" - depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && CPU_SUP_AMD + depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE help Support for error detection and correction on the AMD 64 Families of Memory Controllers (K8, F10h and F11h) diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 8701cd7ce4e..bc5dc232a0f 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -6,7 +6,6 @@ # GNU General Public License. # - obj-$(CONFIG_EDAC) := edac_stub.o obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o @@ -17,9 +16,7 @@ ifdef CONFIG_PCI edac_core-objs += edac_pci.o edac_pci_sysfs.o endif -ifdef CONFIG_CPU_SUP_AMD -obj-$(CONFIG_X86_MCE) += edac_mce_amd.o -endif +obj-$(CONFIG_EDAC_DECODE_MCE) += edac_mce_amd.o obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o obj-$(CONFIG_EDAC_CPC925) += cpc925_edac.o diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c index 83a01a1187d..713ed7d3724 100644 --- a/drivers/edac/edac_mce_amd.c +++ b/drivers/edac/edac_mce_amd.c @@ -3,6 +3,7 @@ static bool report_gart_errors; static void (*nb_bus_decoder)(int node_id, struct err_regs *regs); +static void (*orig_mce_callback)(struct mce *m); void amd_report_gart_errors(bool v) { @@ -427,9 +428,25 @@ static int __init mce_amd_init(void) * We can decode MCEs for Opteron and later CPUs: */ if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && - (boot_cpu_data.x86 >= 0xf)) + (boot_cpu_data.x86 >= 0xf)) { + /* safe the default decode mce callback */ + orig_mce_callback = x86_mce_decode_callback; + x86_mce_decode_callback = amd_decode_mce; + } return 0; } early_initcall(mce_amd_init); + +#ifdef MODULE +static void __exit mce_amd_exit(void) +{ + x86_mce_decode_callback = orig_mce_callback; +} + +MODULE_DESCRIPTION("AMD MCE decoder"); +MODULE_ALIAS("edac-mce-amd"); +MODULE_LICENSE("GPL"); +module_exit(mce_amd_exit); +#endif -- cgit v1.2.3