* [PATCH 0/8] MCE decoding on F14h
@ 2010-10-05 10:54 Borislav Petkov
2010-10-05 10:54 ` [PATCH 1/8] EDAC, MCE: Rework MCE injection Borislav Petkov
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Borislav Petkov @ 2010-10-05 10:54 UTC (permalink / raw)
To: norsk5; +Cc: linux-edac, x86, linux-kernel, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Hi,
continuing the EDAC series from last week
(http://marc.info/?l=linux-kernel&m=128584454524242&w=2), here's an
add-on set which adds MCE decoding for AMD F14h, models 0x0-0xf CPUs on
top of the previous patchqueue. Another change from last week is that we
decided to turn-off building the MCE injection module by default so that
it can be enabled explicitly by distro kernels only (or other curious
individuals who have a lot of time on their hands).
Whole series at git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git for-next
Thanks,
Boris.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/8] EDAC, MCE: Rework MCE injection
2010-10-05 10:54 [PATCH 0/8] MCE decoding on F14h Borislav Petkov
@ 2010-10-05 10:54 ` Borislav Petkov
2010-10-05 10:54 ` [PATCH 2/8] EDAC, MCE: Rename files Borislav Petkov
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2010-10-05 10:54 UTC (permalink / raw)
To: norsk5; +Cc: linux-edac, x86, linux-kernel, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Add sysfs injection facilities for testing of the MCE decoding code.
Remove large parts of amd64_edac_dbg.c, as a result, which did only
NB MCE injection anyway and the new injection code supports that
functionality already.
Add an injection module so that MCE decoding code in production kernels
like those in RHEL and SLES can be tested.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/Kconfig | 14 +++-
drivers/edac/Makefile | 2 +
drivers/edac/amd64_edac.h | 2 +-
drivers/edac/amd64_edac_dbg.c | 213 +++--------------------------------------
drivers/edac/edac_mce_amd.c | 4 +-
drivers/edac/edac_mce_amd.h | 4 +-
drivers/edac/mce_amd_inj.c | 171 +++++++++++++++++++++++++++++++++
7 files changed, 203 insertions(+), 207 deletions(-)
create mode 100644 drivers/edac/mce_amd_inj.c
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 70bb350..3bb3a67 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -39,7 +39,7 @@ config EDAC_DEBUG
there're four debug levels (x=0,1,2,3 from low to high).
Usually you should select 'N'.
- config EDAC_DECODE_MCE
+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
@@ -51,6 +51,16 @@ config EDAC_DEBUG
which occur really early upon boot, before the module infrastructure
has been initialized.
+config EDAC_MCE_INJ
+ tristate "Simple MCE injection interface over /sysfs"
+ depends on EDAC_DECODE_MCE
+ default n
+ help
+ This is a simple interface to inject MCEs over /sysfs and test
+ the MCE decoding code in EDAC.
+
+ This is currently AMD-only.
+
config EDAC_MM_EDAC
tristate "Main Memory EDAC (Error Detection And Correction) reporting"
help
@@ -72,7 +82,7 @@ config EDAC_AMD64
Families of Memory Controllers (K8, F10h and F11h)
config EDAC_AMD64_ERROR_INJECTION
- bool "Sysfs Error Injection facilities"
+ bool "Sysfs HW Error injection facilities"
depends on EDAC_AMD64
help
Recent Opterons (Family 10h and later) provide for Memory Error
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index ca6b1bb..5c38ad3 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -17,6 +17,8 @@ ifdef CONFIG_PCI
edac_core-objs += edac_pci.o edac_pci_sysfs.o
endif
+obj-$(CONFIG_EDAC_MCE_INJ) += mce_amd_inj.o
+
obj-$(CONFIG_EDAC_DECODE_MCE) += edac_mce_amd.o
obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 613b938..67d9ceb 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -486,7 +486,7 @@ extern const char *ext_msgs[32];
extern const char *htlink_msgs[8];
#ifdef CONFIG_EDAC_DEBUG
-#define NUM_DBG_ATTRS 9
+#define NUM_DBG_ATTRS 5
#else
#define NUM_DBG_ATTRS 0
#endif
diff --git a/drivers/edac/amd64_edac_dbg.c b/drivers/edac/amd64_edac_dbg.c
index f6d5695..e356228 100644
--- a/drivers/edac/amd64_edac_dbg.c
+++ b/drivers/edac/amd64_edac_dbg.c
@@ -1,173 +1,16 @@
#include "amd64_edac.h"
-/*
- * accept a hex value and store it into the virtual error register file, field:
- * nbeal and nbeah. Assume virtual error values have already been set for: NBSL,
- * NBSH and NBCFG. Then proceed to map the error values to a MC, CSROW and
- * CHANNEL
- */
-static ssize_t amd64_nbea_store(struct mem_ctl_info *mci, const char *data,
- size_t count)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- u64 value;
- int ret = 0;
- struct mce m;
-
- ret = strict_strtoull(data, 16, &value);
- if (ret != -EINVAL) {
- struct err_regs *regs = &pvt->ctl_error_info;
-
- debugf0("received NBEA= 0x%llx\n", value);
-
- /* place the value into the virtual error packet */
- pvt->ctl_error_info.nbeal = (u32) value;
- value >>= 32;
- pvt->ctl_error_info.nbeah = (u32) value;
-
- m.addr = value;
- m.status = regs->nbsl | ((u64)regs->nbsh << 32);
-
- /* Process the Mapping request */
- /* TODO: Add race prevention */
- amd_decode_nb_mce(pvt->mc_node_id, &m, regs->nbcfg);
-
- return count;
- }
- return ret;
+#define EDAC_DCT_ATTR_SHOW(reg) \
+static ssize_t amd64_##reg##_show(struct mem_ctl_info *mci, char *data) \
+{ \
+ struct amd64_pvt *pvt = mci->pvt_info; \
+ return sprintf(data, "0x%016llx\n", (u64)pvt->reg); \
}
-/* display back what the last NBEA (MCA NB Address (MC4_ADDR)) was written */
-static ssize_t amd64_nbea_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- u64 value;
-
- value = pvt->ctl_error_info.nbeah;
- value <<= 32;
- value |= pvt->ctl_error_info.nbeal;
-
- return sprintf(data, "%llx\n", value);
-}
-
-/* store the NBSL (MCA NB Status Low (MC4_STATUS)) value user desires */
-static ssize_t amd64_nbsl_store(struct mem_ctl_info *mci, const char *data,
- size_t count)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- unsigned long value;
- int ret = 0;
-
- ret = strict_strtoul(data, 16, &value);
- if (ret != -EINVAL) {
- debugf0("received NBSL= 0x%lx\n", value);
-
- pvt->ctl_error_info.nbsl = (u32) value;
-
- return count;
- }
- return ret;
-}
-
-/* display back what the last NBSL value written */
-static ssize_t amd64_nbsl_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- u32 value;
-
- value = pvt->ctl_error_info.nbsl;
-
- return sprintf(data, "%x\n", value);
-}
-
-/* store the NBSH (MCA NB Status High) value user desires */
-static ssize_t amd64_nbsh_store(struct mem_ctl_info *mci, const char *data,
- size_t count)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- unsigned long value;
- int ret = 0;
-
- ret = strict_strtoul(data, 16, &value);
- if (ret != -EINVAL) {
- debugf0("received NBSH= 0x%lx\n", value);
-
- pvt->ctl_error_info.nbsh = (u32) value;
-
- return count;
- }
- return ret;
-}
-
-/* display back what the last NBSH value written */
-static ssize_t amd64_nbsh_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- u32 value;
-
- value = pvt->ctl_error_info.nbsh;
-
- return sprintf(data, "%x\n", value);
-}
-
-/* accept and store the NBCFG (MCA NB Configuration) value user desires */
-static ssize_t amd64_nbcfg_store(struct mem_ctl_info *mci,
- const char *data, size_t count)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- unsigned long value;
- int ret = 0;
-
- ret = strict_strtoul(data, 16, &value);
- if (ret != -EINVAL) {
- debugf0("received NBCFG= 0x%lx\n", value);
-
- pvt->ctl_error_info.nbcfg = (u32) value;
-
- return count;
- }
- return ret;
-}
-
-/* various show routines for the controls of a MCI */
-static ssize_t amd64_nbcfg_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
-
- return sprintf(data, "%x\n", pvt->ctl_error_info.nbcfg);
-}
-
-
-static ssize_t amd64_dhar_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
-
- return sprintf(data, "%x\n", pvt->dhar);
-}
-
-
-static ssize_t amd64_dbam_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
-
- return sprintf(data, "%x\n", pvt->dbam0);
-}
-
-
-static ssize_t amd64_topmem_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
-
- return sprintf(data, "%llx\n", pvt->top_mem);
-}
-
-
-static ssize_t amd64_topmem2_show(struct mem_ctl_info *mci, char *data)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
-
- return sprintf(data, "%llx\n", pvt->top_mem2);
-}
+EDAC_DCT_ATTR_SHOW(dhar);
+EDAC_DCT_ATTR_SHOW(dbam0);
+EDAC_DCT_ATTR_SHOW(top_mem);
+EDAC_DCT_ATTR_SHOW(top_mem2);
static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data)
{
@@ -188,38 +31,6 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
{
.attr = {
- .name = "nbea_ctl",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = amd64_nbea_show,
- .store = amd64_nbea_store,
- },
- {
- .attr = {
- .name = "nbsl_ctl",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = amd64_nbsl_show,
- .store = amd64_nbsl_store,
- },
- {
- .attr = {
- .name = "nbsh_ctl",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = amd64_nbsh_show,
- .store = amd64_nbsh_store,
- },
- {
- .attr = {
- .name = "nbcfg_ctl",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = amd64_nbcfg_show,
- .store = amd64_nbcfg_store,
- },
- {
- .attr = {
.name = "dhar",
.mode = (S_IRUGO)
},
@@ -231,7 +42,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
.name = "dbam",
.mode = (S_IRUGO)
},
- .show = amd64_dbam_show,
+ .show = amd64_dbam0_show,
.store = NULL,
},
{
@@ -239,7 +50,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
.name = "topmem",
.mode = (S_IRUGO)
},
- .show = amd64_topmem_show,
+ .show = amd64_top_mem_show,
.store = NULL,
},
{
@@ -247,7 +58,7 @@ struct mcidev_sysfs_attribute amd64_dbg_attrs[] = {
.name = "topmem2",
.mode = (S_IRUGO)
},
- .show = amd64_topmem2_show,
+ .show = amd64_top_mem2_show,
.store = NULL,
},
{
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c
index 6cfa881..c75c47b 100644
--- a/drivers/edac/edac_mce_amd.c
+++ b/drivers/edac/edac_mce_amd.c
@@ -324,8 +324,7 @@ static inline void amd_decode_err_code(u16 ec)
pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
}
-static int amd_decode_mce(struct notifier_block *nb, unsigned long val,
- void *data)
+int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
{
struct mce *m = (struct mce *)data;
int node, ecc;
@@ -379,6 +378,7 @@ static int amd_decode_mce(struct notifier_block *nb, unsigned long val,
return NOTIFY_STOP;
}
+EXPORT_SYMBOL_GPL(amd_decode_mce);
static struct notifier_block amd_mce_dec_nb = {
.notifier_call = amd_decode_mce,
diff --git a/drivers/edac/edac_mce_amd.h b/drivers/edac/edac_mce_amd.h
index 0fba0e7..2712a90 100644
--- a/drivers/edac/edac_mce_amd.h
+++ b/drivers/edac/edac_mce_amd.h
@@ -1,6 +1,8 @@
#ifndef _EDAC_MCE_AMD_H
#define _EDAC_MCE_AMD_H
+#include <linux/notifier.h>
+
#include <asm/mce.h>
#define ERROR_CODE(x) ((x) & 0xffff)
@@ -61,10 +63,10 @@ struct err_regs {
u32 nbeal;
};
-
void amd_report_gart_errors(bool);
void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32));
void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32));
void amd_decode_nb_mce(int, struct mce *, u32);
+int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
#endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
new file mode 100644
index 0000000..0e4f2dc
--- /dev/null
+++ b/drivers/edac/mce_amd_inj.c
@@ -0,0 +1,171 @@
+/*
+ * A simple MCE injection facility for testing the MCE decoding code. This
+ * driver should be built as module so that it can be loaded on production
+ * kernels for testing purposes.
+ *
+ * This file may be distributed under the terms of the GNU General Public
+ * License version 2.
+ *
+ * Copyright (c) 2010: Borislav Petkov <borislav.petkov@amd.com>
+ * Advanced Micro Devices Inc.
+ */
+
+#include <linux/kobject.h>
+#include <linux/sysdev.h>
+#include <linux/edac.h>
+#include <asm/mce.h>
+
+#include "edac_mce_amd.h"
+
+struct edac_mce_attr {
+ struct attribute attr;
+ ssize_t (*show) (struct kobject *kobj, struct edac_mce_attr *attr, char *buf);
+ ssize_t (*store)(struct kobject *kobj, struct edac_mce_attr *attr,
+ const char *buf, size_t count);
+};
+
+#define EDAC_MCE_ATTR(_name, _mode, _show, _store) \
+static struct edac_mce_attr mce_attr_##_name = __ATTR(_name, _mode, _show, _store)
+
+static struct kobject *mce_kobj;
+
+/*
+ * Collect all the MCi_XXX settings
+ */
+static struct mce i_mce;
+
+#define MCE_INJECT_STORE(reg) \
+static ssize_t edac_inject_##reg##_store(struct kobject *kobj, \
+ struct edac_mce_attr *attr, \
+ const char *data, size_t count)\
+{ \
+ int ret = 0; \
+ unsigned long value; \
+ \
+ ret = strict_strtoul(data, 16, &value); \
+ if (ret < 0) \
+ printk(KERN_ERR "Error writing MCE " #reg " field.\n"); \
+ \
+ i_mce.reg = value; \
+ \
+ return count; \
+}
+
+MCE_INJECT_STORE(status);
+MCE_INJECT_STORE(misc);
+MCE_INJECT_STORE(addr);
+
+#define MCE_INJECT_SHOW(reg) \
+static ssize_t edac_inject_##reg##_show(struct kobject *kobj, \
+ struct edac_mce_attr *attr, \
+ char *buf) \
+{ \
+ return sprintf(buf, "0x%016llx\n", i_mce.reg); \
+}
+
+MCE_INJECT_SHOW(status);
+MCE_INJECT_SHOW(misc);
+MCE_INJECT_SHOW(addr);
+
+EDAC_MCE_ATTR(status, 0644, edac_inject_status_show, edac_inject_status_store);
+EDAC_MCE_ATTR(misc, 0644, edac_inject_misc_show, edac_inject_misc_store);
+EDAC_MCE_ATTR(addr, 0644, edac_inject_addr_show, edac_inject_addr_store);
+
+/*
+ * This denotes into which bank we're injecting and triggers
+ * the injection, at the same time.
+ */
+static ssize_t edac_inject_bank_store(struct kobject *kobj,
+ struct edac_mce_attr *attr,
+ const char *data, size_t count)
+{
+ int ret = 0;
+ unsigned long value;
+
+ ret = strict_strtoul(data, 10, &value);
+ if (ret < 0) {
+ printk(KERN_ERR "Invalid bank value!\n");
+ return -EINVAL;
+ }
+
+ if (value > 5) {
+ printk(KERN_ERR "Non-existant MCE bank: %lu\n", value);
+ return -EINVAL;
+ }
+
+ i_mce.bank = value;
+
+ amd_decode_mce(NULL, 0, &i_mce);
+
+ return count;
+}
+
+static ssize_t edac_inject_bank_show(struct kobject *kobj,
+ struct edac_mce_attr *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", i_mce.bank);
+}
+
+EDAC_MCE_ATTR(bank, 0644, edac_inject_bank_show, edac_inject_bank_store);
+
+static struct edac_mce_attr *sysfs_attrs[] = { &mce_attr_status, &mce_attr_misc,
+ &mce_attr_addr, &mce_attr_bank
+};
+
+static int __init edac_init_mce_inject(void)
+{
+ struct sysdev_class *edac_class = NULL;
+ int i, err = 0;
+
+ edac_class = edac_get_sysfs_class();
+ if (!edac_class)
+ return -EINVAL;
+
+ mce_kobj = kobject_create_and_add("mce", &edac_class->kset.kobj);
+ if (!mce_kobj) {
+ printk(KERN_ERR "Error creating a mce kset.\n");
+ err = -ENOMEM;
+ goto err_mce_kobj;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++) {
+ err = sysfs_create_file(mce_kobj, &sysfs_attrs[i]->attr);
+ if (err) {
+ printk(KERN_ERR "Error creating %s in sysfs.\n",
+ sysfs_attrs[i]->attr.name);
+ goto err_sysfs_create;
+ }
+ }
+ return 0;
+
+err_sysfs_create:
+ while (i-- >= 0)
+ sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+
+ kobject_del(mce_kobj);
+
+err_mce_kobj:
+ edac_put_sysfs_class();
+
+ return err;
+}
+
+static void __exit edac_exit_mce_inject(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++)
+ sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+
+ kobject_del(mce_kobj);
+
+ edac_put_sysfs_class();
+}
+
+module_init(edac_init_mce_inject);
+module_exit(edac_exit_mce_inject);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>");
+MODULE_AUTHOR("AMD Inc.");
+MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding");
--
1.7.3.1.50.g1e633
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/8] EDAC, MCE: Rename files
2010-10-05 10:54 [PATCH 0/8] MCE decoding on F14h Borislav Petkov
2010-10-05 10:54 ` [PATCH 1/8] EDAC, MCE: Rework MCE injection Borislav Petkov
@ 2010-10-05 10:54 ` Borislav Petkov
2010-10-05 10:54 ` [PATCH 3/8] EDAC, MCE: Adjust DC decoders to F14h Borislav Petkov
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2010-10-05 10:54 UTC (permalink / raw)
To: norsk5; +Cc: linux-edac, x86, linux-kernel, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Drop "edac_" string from the filenames since they're prefixed with edac/
in their pathname anyway.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/Makefile | 1 +
drivers/edac/amd64_edac.h | 2 +-
drivers/edac/edac_mce_amd.c | 414 -------------------------------------------
drivers/edac/edac_mce_amd.h | 72 --------
drivers/edac/mce_amd.c | 414 +++++++++++++++++++++++++++++++++++++++++++
drivers/edac/mce_amd.h | 72 ++++++++
drivers/edac/mce_amd_inj.c | 2 +-
7 files changed, 489 insertions(+), 488 deletions(-)
delete mode 100644 drivers/edac/edac_mce_amd.c
delete mode 100644 drivers/edac/edac_mce_amd.h
create mode 100644 drivers/edac/mce_amd.c
create mode 100644 drivers/edac/mce_amd.h
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 5c38ad3..32c7bc9 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -19,6 +19,7 @@ endif
obj-$(CONFIG_EDAC_MCE_INJ) += mce_amd_inj.o
+edac_mce_amd-objs := mce_amd.o
obj-$(CONFIG_EDAC_DECODE_MCE) += edac_mce_amd.o
obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 67d9ceb..13e1d6f 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -72,7 +72,7 @@
#include <linux/edac.h>
#include <asm/msr.h>
#include "edac_core.h"
-#include "edac_mce_amd.h"
+#include "mce_amd.h"
#define amd64_printk(level, fmt, arg...) \
edac_printk(level, "amd64", fmt, ##arg)
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c
deleted file mode 100644
index c75c47b..0000000
--- a/drivers/edac/edac_mce_amd.c
+++ /dev/null
@@ -1,414 +0,0 @@
-#include <linux/module.h>
-#include "edac_mce_amd.h"
-
-static bool report_gart_errors;
-static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
-
-void amd_report_gart_errors(bool v)
-{
- report_gart_errors = v;
-}
-EXPORT_SYMBOL_GPL(amd_report_gart_errors);
-
-void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
-{
- nb_bus_decoder = f;
-}
-EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
-
-void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
-{
- if (nb_bus_decoder) {
- WARN_ON(nb_bus_decoder != f);
-
- nb_bus_decoder = NULL;
- }
-}
-EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
-
-/*
- * string representation for the different MCA reported error types, see F3x48
- * or MSR0000_0411.
- */
-
-/* transaction type */
-const char *tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
-EXPORT_SYMBOL_GPL(tt_msgs);
-
-/* cache level */
-const char *ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
-EXPORT_SYMBOL_GPL(ll_msgs);
-
-/* memory transaction type */
-const char *rrrr_msgs[] = {
- "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
-};
-EXPORT_SYMBOL_GPL(rrrr_msgs);
-
-/* participating processor */
-const char *pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
-EXPORT_SYMBOL_GPL(pp_msgs);
-
-/* request timeout */
-const char *to_msgs[] = { "no timeout", "timed out" };
-EXPORT_SYMBOL_GPL(to_msgs);
-
-/* memory or i/o */
-const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
-EXPORT_SYMBOL_GPL(ii_msgs);
-
-/*
- * Map the 4 or 5 (family-specific) bits of Extended Error code to the
- * string table.
- */
-const char *ext_msgs[] = {
- "K8 ECC error", /* 0_0000b */
- "CRC error on link", /* 0_0001b */
- "Sync error packets on link", /* 0_0010b */
- "Master Abort during link operation", /* 0_0011b */
- "Target Abort during link operation", /* 0_0100b */
- "Invalid GART PTE entry during table walk", /* 0_0101b */
- "Unsupported atomic RMW command received", /* 0_0110b */
- "WDT error: NB transaction timeout", /* 0_0111b */
- "ECC/ChipKill ECC error", /* 0_1000b */
- "SVM DEV Error", /* 0_1001b */
- "Link Data error", /* 0_1010b */
- "Link/L3/Probe Filter Protocol error", /* 0_1011b */
- "NB Internal Arrays Parity error", /* 0_1100b */
- "DRAM Address/Control Parity error", /* 0_1101b */
- "Link Transmission error", /* 0_1110b */
- "GART/DEV Table Walk Data error" /* 0_1111b */
- "Res 0x100 error", /* 1_0000b */
- "Res 0x101 error", /* 1_0001b */
- "Res 0x102 error", /* 1_0010b */
- "Res 0x103 error", /* 1_0011b */
- "Res 0x104 error", /* 1_0100b */
- "Res 0x105 error", /* 1_0101b */
- "Res 0x106 error", /* 1_0110b */
- "Res 0x107 error", /* 1_0111b */
- "Res 0x108 error", /* 1_1000b */
- "Res 0x109 error", /* 1_1001b */
- "Res 0x10A error", /* 1_1010b */
- "Res 0x10B error", /* 1_1011b */
- "ECC error in L3 Cache Data", /* 1_1100b */
- "L3 Cache Tag error", /* 1_1101b */
- "L3 Cache LRU Parity error", /* 1_1110b */
- "Probe Filter error" /* 1_1111b */
-};
-EXPORT_SYMBOL_GPL(ext_msgs);
-
-static void amd_decode_dc_mce(struct mce *m)
-{
- u32 ec = m->status & 0xffff;
- u32 xec = (m->status >> 16) & 0xf;
-
- pr_emerg(HW_ERR "Data Cache Error: ");
-
- if (xec == 1 && TLB_ERROR(ec))
- pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
- else if (xec == 0) {
- if (m->status & (1ULL << 40))
- pr_cont(" during Data Scrub.\n");
- else if (TLB_ERROR(ec))
- pr_cont(": %s TLB parity error.\n", LL_MSG(ec));
- else if (MEM_ERROR(ec)) {
- u8 ll = ec & 0x3;
- u8 tt = (ec >> 2) & 0x3;
- u8 rrrr = (ec >> 4) & 0xf;
-
- /* see F10h BKDG (31116), Table 92. */
- if (ll == 0x1) {
- if (tt != 0x1)
- goto wrong_dc_mce;
-
- pr_cont(": Data/Tag %s error.\n", RRRR_MSG(ec));
-
- } else if (ll == 0x2 && rrrr == 0x3)
- pr_cont(" during L1 linefill from L2.\n");
- else
- goto wrong_dc_mce;
- } else if (BUS_ERROR(ec) && boot_cpu_data.x86 == 0xf)
- pr_cont(" during system linefill.\n");
- else
- goto wrong_dc_mce;
- } else
- goto wrong_dc_mce;
-
- return;
-
-wrong_dc_mce:
- pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
-}
-
-static void amd_decode_ic_mce(struct mce *m)
-{
- u32 ec = m->status & 0xffff;
- u32 xec = (m->status >> 16) & 0xf;
-
- pr_emerg(HW_ERR "Instruction Cache Error");
-
- if (xec == 1 && TLB_ERROR(ec))
- pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
- else if (xec == 0) {
- if (TLB_ERROR(ec))
- pr_cont(": %s TLB Parity error.\n", LL_MSG(ec));
- else if (BUS_ERROR(ec)) {
- if (boot_cpu_data.x86 == 0xf &&
- (m->status & BIT(58)))
- pr_cont(" during system linefill.\n");
- else
- pr_cont(" during attempted NB data read.\n");
- } else if (MEM_ERROR(ec)) {
- u8 ll = ec & 0x3;
- u8 rrrr = (ec >> 4) & 0xf;
-
- if (ll == 0x2)
- pr_cont(" during a linefill from L2.\n");
- else if (ll == 0x1) {
-
- switch (rrrr) {
- case 0x5:
- pr_cont(": Parity error during "
- "data load.\n");
- break;
-
- case 0x7:
- pr_cont(": Copyback Parity/Victim"
- " error.\n");
- break;
-
- case 0x8:
- pr_cont(": Tag Snoop error.\n");
- break;
-
- default:
- goto wrong_ic_mce;
- break;
- }
- }
- } else
- goto wrong_ic_mce;
- } else
- goto wrong_ic_mce;
-
- return;
-
-wrong_ic_mce:
- pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
-}
-
-static void amd_decode_bu_mce(struct mce *m)
-{
- u32 ec = m->status & 0xffff;
- u32 xec = (m->status >> 16) & 0xf;
-
- pr_emerg(HW_ERR "Bus Unit Error");
-
- if (xec == 0x1)
- pr_cont(" in the write data buffers.\n");
- else if (xec == 0x3)
- pr_cont(" in the victim data buffers.\n");
- else if (xec == 0x2 && MEM_ERROR(ec))
- pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
- else if (xec == 0x0) {
- if (TLB_ERROR(ec))
- pr_cont(": %s error in a Page Descriptor Cache or "
- "Guest TLB.\n", TT_MSG(ec));
- else if (BUS_ERROR(ec))
- pr_cont(": %s/ECC error in data read from NB: %s.\n",
- RRRR_MSG(ec), PP_MSG(ec));
- else if (MEM_ERROR(ec)) {
- u8 rrrr = (ec >> 4) & 0xf;
-
- if (rrrr >= 0x7)
- pr_cont(": %s error during data copyback.\n",
- RRRR_MSG(ec));
- else if (rrrr <= 0x1)
- pr_cont(": %s parity/ECC error during data "
- "access from L2.\n", RRRR_MSG(ec));
- else
- goto wrong_bu_mce;
- } else
- goto wrong_bu_mce;
- } else
- goto wrong_bu_mce;
-
- return;
-
-wrong_bu_mce:
- pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
-}
-
-static void amd_decode_ls_mce(struct mce *m)
-{
- u32 ec = m->status & 0xffff;
- u32 xec = (m->status >> 16) & 0xf;
-
- pr_emerg(HW_ERR "Load Store Error");
-
- if (xec == 0x0) {
- u8 rrrr = (ec >> 4) & 0xf;
-
- if (!BUS_ERROR(ec) || (rrrr != 0x3 && rrrr != 0x4))
- goto wrong_ls_mce;
-
- pr_cont(" during %s.\n", RRRR_MSG(ec));
- }
- return;
-
-wrong_ls_mce:
- pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
-}
-
-void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
-{
- u32 ec = m->status & 0xffff;
- u32 nbsh = (u32)(m->status >> 32);
- u32 nbsl = (u32)m->status;
-
- /*
- * GART TLB error reporting is disabled by default. Bail out early.
- */
- if (TLB_ERROR(ec) && !report_gart_errors)
- return;
-
- pr_emerg(HW_ERR "Northbridge Error, node %d", node_id);
-
- /*
- * F10h, revD can disable ErrCpu[3:0] so check that first and also the
- * value encoding has changed so interpret those differently
- */
- if ((boot_cpu_data.x86 == 0x10) &&
- (boot_cpu_data.x86_model > 7)) {
- if (nbsh & K8_NBSH_ERR_CPU_VAL)
- pr_cont(", core: %u\n", (u8)(nbsh & 0xf));
- } else {
- u8 assoc_cpus = nbsh & 0xf;
-
- if (assoc_cpus > 0)
- pr_cont(", core: %d", fls(assoc_cpus) - 1);
-
- pr_cont("\n");
- }
-
- pr_emerg(HW_ERR "%s.\n", EXT_ERR_MSG(nbsl));
-
- if (BUS_ERROR(ec) && nb_bus_decoder)
- nb_bus_decoder(node_id, m, nbcfg);
-}
-EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
-
-static void amd_decode_fr_mce(struct mce *m)
-{
- /* we have only one error signature so match all fields at once. */
- if ((m->status & 0xffff) == 0x0f0f)
- pr_emerg(HW_ERR " FR Error: CPU Watchdog timer expire.\n");
- else
- pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
-}
-
-static inline void amd_decode_err_code(u16 ec)
-{
- if (TLB_ERROR(ec)) {
- pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
- TT_MSG(ec), LL_MSG(ec));
- } else if (MEM_ERROR(ec)) {
- pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
- RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
- } else if (BUS_ERROR(ec)) {
- pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
- "Participating Processor: %s\n",
- RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
- PP_MSG(ec));
- } else
- pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
-}
-
-int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
-{
- struct mce *m = (struct mce *)data;
- int node, ecc;
-
- pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
-
- pr_cont("%sorrected error, other errors lost: %s, "
- "CPU context corrupt: %s",
- ((m->status & MCI_STATUS_UC) ? "Unc" : "C"),
- ((m->status & MCI_STATUS_OVER) ? "yes" : "no"),
- ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
-
- /* do the two bits[14:13] together */
- ecc = (m->status >> 45) & 0x3;
- if (ecc)
- pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
-
- pr_cont("\n");
-
- switch (m->bank) {
- case 0:
- amd_decode_dc_mce(m);
- break;
-
- case 1:
- amd_decode_ic_mce(m);
- break;
-
- case 2:
- amd_decode_bu_mce(m);
- break;
-
- case 3:
- amd_decode_ls_mce(m);
- break;
-
- case 4:
- node = amd_get_nb_id(m->extcpu);
- amd_decode_nb_mce(node, m, 0);
- break;
-
- case 5:
- amd_decode_fr_mce(m);
- break;
-
- default:
- break;
- }
-
- amd_decode_err_code(m->status & 0xffff);
-
- return NOTIFY_STOP;
-}
-EXPORT_SYMBOL_GPL(amd_decode_mce);
-
-static struct notifier_block amd_mce_dec_nb = {
- .notifier_call = amd_decode_mce,
-};
-
-static int __init mce_amd_init(void)
-{
- /*
- * We can decode MCEs for K8, F10h and F11h CPUs:
- */
- if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
- return 0;
-
- if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
- return 0;
-
- atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
-
- return 0;
-}
-early_initcall(mce_amd_init);
-
-#ifdef MODULE
-static void __exit mce_amd_exit(void)
-{
- atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
-}
-
-MODULE_DESCRIPTION("AMD MCE decoder");
-MODULE_ALIAS("edac-mce-amd");
-MODULE_LICENSE("GPL");
-module_exit(mce_amd_exit);
-#endif
diff --git a/drivers/edac/edac_mce_amd.h b/drivers/edac/edac_mce_amd.h
deleted file mode 100644
index 2712a90..0000000
--- a/drivers/edac/edac_mce_amd.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _EDAC_MCE_AMD_H
-#define _EDAC_MCE_AMD_H
-
-#include <linux/notifier.h>
-
-#include <asm/mce.h>
-
-#define ERROR_CODE(x) ((x) & 0xffff)
-#define EXT_ERROR_CODE(x) (((x) >> 16) & 0x1f)
-#define EXT_ERR_MSG(x) ext_msgs[EXT_ERROR_CODE(x)]
-
-#define LOW_SYNDROME(x) (((x) >> 15) & 0xff)
-#define HIGH_SYNDROME(x) (((x) >> 24) & 0xff)
-
-#define TLB_ERROR(x) (((x) & 0xFFF0) == 0x0010)
-#define MEM_ERROR(x) (((x) & 0xFF00) == 0x0100)
-#define BUS_ERROR(x) (((x) & 0xF800) == 0x0800)
-
-#define TT(x) (((x) >> 2) & 0x3)
-#define TT_MSG(x) tt_msgs[TT(x)]
-#define II(x) (((x) >> 2) & 0x3)
-#define II_MSG(x) ii_msgs[II(x)]
-#define LL(x) (((x) >> 0) & 0x3)
-#define LL_MSG(x) ll_msgs[LL(x)]
-#define TO(x) (((x) >> 8) & 0x1)
-#define TO_MSG(x) to_msgs[TO(x)]
-#define PP(x) (((x) >> 9) & 0x3)
-#define PP_MSG(x) pp_msgs[PP(x)]
-
-#define RRRR(x) (((x) >> 4) & 0xf)
-#define RRRR_MSG(x) ((RRRR(x) < 9) ? rrrr_msgs[RRRR(x)] : "Wrong R4!")
-
-#define K8_NBSH 0x4C
-
-#define K8_NBSH_VALID_BIT BIT(31)
-#define K8_NBSH_OVERFLOW BIT(30)
-#define K8_NBSH_UC_ERR BIT(29)
-#define K8_NBSH_ERR_EN BIT(28)
-#define K8_NBSH_MISCV BIT(27)
-#define K8_NBSH_VALID_ERROR_ADDR BIT(26)
-#define K8_NBSH_PCC BIT(25)
-#define K8_NBSH_ERR_CPU_VAL BIT(24)
-#define K8_NBSH_CECC BIT(14)
-#define K8_NBSH_UECC BIT(13)
-#define K8_NBSH_ERR_SCRUBER BIT(8)
-
-extern const char *tt_msgs[];
-extern const char *ll_msgs[];
-extern const char *rrrr_msgs[];
-extern const char *pp_msgs[];
-extern const char *to_msgs[];
-extern const char *ii_msgs[];
-extern const char *ext_msgs[];
-
-/*
- * relevant NB regs
- */
-struct err_regs {
- u32 nbcfg;
- u32 nbsh;
- u32 nbsl;
- u32 nbeah;
- u32 nbeal;
-};
-
-void amd_report_gart_errors(bool);
-void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32));
-void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32));
-void amd_decode_nb_mce(int, struct mce *, u32);
-int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
-
-#endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
new file mode 100644
index 0000000..5eb8042
--- /dev/null
+++ b/drivers/edac/mce_amd.c
@@ -0,0 +1,414 @@
+#include <linux/module.h>
+#include "mce_amd.h"
+
+static bool report_gart_errors;
+static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
+
+void amd_report_gart_errors(bool v)
+{
+ report_gart_errors = v;
+}
+EXPORT_SYMBOL_GPL(amd_report_gart_errors);
+
+void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32))
+{
+ nb_bus_decoder = f;
+}
+EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
+
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32))
+{
+ if (nb_bus_decoder) {
+ WARN_ON(nb_bus_decoder != f);
+
+ nb_bus_decoder = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
+
+/*
+ * string representation for the different MCA reported error types, see F3x48
+ * or MSR0000_0411.
+ */
+
+/* transaction type */
+const char *tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" };
+EXPORT_SYMBOL_GPL(tt_msgs);
+
+/* cache level */
+const char *ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" };
+EXPORT_SYMBOL_GPL(ll_msgs);
+
+/* memory transaction type */
+const char *rrrr_msgs[] = {
+ "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP"
+};
+EXPORT_SYMBOL_GPL(rrrr_msgs);
+
+/* participating processor */
+const char *pp_msgs[] = { "SRC", "RES", "OBS", "GEN" };
+EXPORT_SYMBOL_GPL(pp_msgs);
+
+/* request timeout */
+const char *to_msgs[] = { "no timeout", "timed out" };
+EXPORT_SYMBOL_GPL(to_msgs);
+
+/* memory or i/o */
+const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
+EXPORT_SYMBOL_GPL(ii_msgs);
+
+/*
+ * Map the 4 or 5 (family-specific) bits of Extended Error code to the
+ * string table.
+ */
+const char *ext_msgs[] = {
+ "K8 ECC error", /* 0_0000b */
+ "CRC error on link", /* 0_0001b */
+ "Sync error packets on link", /* 0_0010b */
+ "Master Abort during link operation", /* 0_0011b */
+ "Target Abort during link operation", /* 0_0100b */
+ "Invalid GART PTE entry during table walk", /* 0_0101b */
+ "Unsupported atomic RMW command received", /* 0_0110b */
+ "WDT error: NB transaction timeout", /* 0_0111b */
+ "ECC/ChipKill ECC error", /* 0_1000b */
+ "SVM DEV Error", /* 0_1001b */
+ "Link Data error", /* 0_1010b */
+ "Link/L3/Probe Filter Protocol error", /* 0_1011b */
+ "NB Internal Arrays Parity error", /* 0_1100b */
+ "DRAM Address/Control Parity error", /* 0_1101b */
+ "Link Transmission error", /* 0_1110b */
+ "GART/DEV Table Walk Data error" /* 0_1111b */
+ "Res 0x100 error", /* 1_0000b */
+ "Res 0x101 error", /* 1_0001b */
+ "Res 0x102 error", /* 1_0010b */
+ "Res 0x103 error", /* 1_0011b */
+ "Res 0x104 error", /* 1_0100b */
+ "Res 0x105 error", /* 1_0101b */
+ "Res 0x106 error", /* 1_0110b */
+ "Res 0x107 error", /* 1_0111b */
+ "Res 0x108 error", /* 1_1000b */
+ "Res 0x109 error", /* 1_1001b */
+ "Res 0x10A error", /* 1_1010b */
+ "Res 0x10B error", /* 1_1011b */
+ "ECC error in L3 Cache Data", /* 1_1100b */
+ "L3 Cache Tag error", /* 1_1101b */
+ "L3 Cache LRU Parity error", /* 1_1110b */
+ "Probe Filter error" /* 1_1111b */
+};
+EXPORT_SYMBOL_GPL(ext_msgs);
+
+static void amd_decode_dc_mce(struct mce *m)
+{
+ u32 ec = m->status & 0xffff;
+ u32 xec = (m->status >> 16) & 0xf;
+
+ pr_emerg(HW_ERR "Data Cache Error: ");
+
+ if (xec == 1 && TLB_ERROR(ec))
+ pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
+ else if (xec == 0) {
+ if (m->status & (1ULL << 40))
+ pr_cont(" during Data Scrub.\n");
+ else if (TLB_ERROR(ec))
+ pr_cont(": %s TLB parity error.\n", LL_MSG(ec));
+ else if (MEM_ERROR(ec)) {
+ u8 ll = ec & 0x3;
+ u8 tt = (ec >> 2) & 0x3;
+ u8 rrrr = (ec >> 4) & 0xf;
+
+ /* see F10h BKDG (31116), Table 92. */
+ if (ll == 0x1) {
+ if (tt != 0x1)
+ goto wrong_dc_mce;
+
+ pr_cont(": Data/Tag %s error.\n", RRRR_MSG(ec));
+
+ } else if (ll == 0x2 && rrrr == 0x3)
+ pr_cont(" during L1 linefill from L2.\n");
+ else
+ goto wrong_dc_mce;
+ } else if (BUS_ERROR(ec) && boot_cpu_data.x86 == 0xf)
+ pr_cont(" during system linefill.\n");
+ else
+ goto wrong_dc_mce;
+ } else
+ goto wrong_dc_mce;
+
+ return;
+
+wrong_dc_mce:
+ pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
+}
+
+static void amd_decode_ic_mce(struct mce *m)
+{
+ u32 ec = m->status & 0xffff;
+ u32 xec = (m->status >> 16) & 0xf;
+
+ pr_emerg(HW_ERR "Instruction Cache Error");
+
+ if (xec == 1 && TLB_ERROR(ec))
+ pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
+ else if (xec == 0) {
+ if (TLB_ERROR(ec))
+ pr_cont(": %s TLB Parity error.\n", LL_MSG(ec));
+ else if (BUS_ERROR(ec)) {
+ if (boot_cpu_data.x86 == 0xf &&
+ (m->status & BIT(58)))
+ pr_cont(" during system linefill.\n");
+ else
+ pr_cont(" during attempted NB data read.\n");
+ } else if (MEM_ERROR(ec)) {
+ u8 ll = ec & 0x3;
+ u8 rrrr = (ec >> 4) & 0xf;
+
+ if (ll == 0x2)
+ pr_cont(" during a linefill from L2.\n");
+ else if (ll == 0x1) {
+
+ switch (rrrr) {
+ case 0x5:
+ pr_cont(": Parity error during "
+ "data load.\n");
+ break;
+
+ case 0x7:
+ pr_cont(": Copyback Parity/Victim"
+ " error.\n");
+ break;
+
+ case 0x8:
+ pr_cont(": Tag Snoop error.\n");
+ break;
+
+ default:
+ goto wrong_ic_mce;
+ break;
+ }
+ }
+ } else
+ goto wrong_ic_mce;
+ } else
+ goto wrong_ic_mce;
+
+ return;
+
+wrong_ic_mce:
+ pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
+}
+
+static void amd_decode_bu_mce(struct mce *m)
+{
+ u32 ec = m->status & 0xffff;
+ u32 xec = (m->status >> 16) & 0xf;
+
+ pr_emerg(HW_ERR "Bus Unit Error");
+
+ if (xec == 0x1)
+ pr_cont(" in the write data buffers.\n");
+ else if (xec == 0x3)
+ pr_cont(" in the victim data buffers.\n");
+ else if (xec == 0x2 && MEM_ERROR(ec))
+ pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec));
+ else if (xec == 0x0) {
+ if (TLB_ERROR(ec))
+ pr_cont(": %s error in a Page Descriptor Cache or "
+ "Guest TLB.\n", TT_MSG(ec));
+ else if (BUS_ERROR(ec))
+ pr_cont(": %s/ECC error in data read from NB: %s.\n",
+ RRRR_MSG(ec), PP_MSG(ec));
+ else if (MEM_ERROR(ec)) {
+ u8 rrrr = (ec >> 4) & 0xf;
+
+ if (rrrr >= 0x7)
+ pr_cont(": %s error during data copyback.\n",
+ RRRR_MSG(ec));
+ else if (rrrr <= 0x1)
+ pr_cont(": %s parity/ECC error during data "
+ "access from L2.\n", RRRR_MSG(ec));
+ else
+ goto wrong_bu_mce;
+ } else
+ goto wrong_bu_mce;
+ } else
+ goto wrong_bu_mce;
+
+ return;
+
+wrong_bu_mce:
+ pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
+}
+
+static void amd_decode_ls_mce(struct mce *m)
+{
+ u32 ec = m->status & 0xffff;
+ u32 xec = (m->status >> 16) & 0xf;
+
+ pr_emerg(HW_ERR "Load Store Error");
+
+ if (xec == 0x0) {
+ u8 rrrr = (ec >> 4) & 0xf;
+
+ if (!BUS_ERROR(ec) || (rrrr != 0x3 && rrrr != 0x4))
+ goto wrong_ls_mce;
+
+ pr_cont(" during %s.\n", RRRR_MSG(ec));
+ }
+ return;
+
+wrong_ls_mce:
+ pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
+}
+
+void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
+{
+ u32 ec = m->status & 0xffff;
+ u32 nbsh = (u32)(m->status >> 32);
+ u32 nbsl = (u32)m->status;
+
+ /*
+ * GART TLB error reporting is disabled by default. Bail out early.
+ */
+ if (TLB_ERROR(ec) && !report_gart_errors)
+ return;
+
+ pr_emerg(HW_ERR "Northbridge Error, node %d", node_id);
+
+ /*
+ * F10h, revD can disable ErrCpu[3:0] so check that first and also the
+ * value encoding has changed so interpret those differently
+ */
+ if ((boot_cpu_data.x86 == 0x10) &&
+ (boot_cpu_data.x86_model > 7)) {
+ if (nbsh & K8_NBSH_ERR_CPU_VAL)
+ pr_cont(", core: %u\n", (u8)(nbsh & 0xf));
+ } else {
+ u8 assoc_cpus = nbsh & 0xf;
+
+ if (assoc_cpus > 0)
+ pr_cont(", core: %d", fls(assoc_cpus) - 1);
+
+ pr_cont("\n");
+ }
+
+ pr_emerg(HW_ERR "%s.\n", EXT_ERR_MSG(nbsl));
+
+ if (BUS_ERROR(ec) && nb_bus_decoder)
+ nb_bus_decoder(node_id, m, nbcfg);
+}
+EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
+
+static void amd_decode_fr_mce(struct mce *m)
+{
+ /* we have only one error signature so match all fields at once. */
+ if ((m->status & 0xffff) == 0x0f0f)
+ pr_emerg(HW_ERR " FR Error: CPU Watchdog timer expire.\n");
+ else
+ pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
+}
+
+static inline void amd_decode_err_code(u16 ec)
+{
+ if (TLB_ERROR(ec)) {
+ pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n",
+ TT_MSG(ec), LL_MSG(ec));
+ } else if (MEM_ERROR(ec)) {
+ pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n",
+ RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
+ } else if (BUS_ERROR(ec)) {
+ pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, "
+ "Participating Processor: %s\n",
+ RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec),
+ PP_MSG(ec));
+ } else
+ pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
+}
+
+int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
+{
+ struct mce *m = (struct mce *)data;
+ int node, ecc;
+
+ pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
+
+ pr_cont("%sorrected error, other errors lost: %s, "
+ "CPU context corrupt: %s",
+ ((m->status & MCI_STATUS_UC) ? "Unc" : "C"),
+ ((m->status & MCI_STATUS_OVER) ? "yes" : "no"),
+ ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
+
+ /* do the two bits[14:13] together */
+ ecc = (m->status >> 45) & 0x3;
+ if (ecc)
+ pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
+
+ pr_cont("\n");
+
+ switch (m->bank) {
+ case 0:
+ amd_decode_dc_mce(m);
+ break;
+
+ case 1:
+ amd_decode_ic_mce(m);
+ break;
+
+ case 2:
+ amd_decode_bu_mce(m);
+ break;
+
+ case 3:
+ amd_decode_ls_mce(m);
+ break;
+
+ case 4:
+ node = amd_get_nb_id(m->extcpu);
+ amd_decode_nb_mce(node, m, 0);
+ break;
+
+ case 5:
+ amd_decode_fr_mce(m);
+ break;
+
+ default:
+ break;
+ }
+
+ amd_decode_err_code(m->status & 0xffff);
+
+ return NOTIFY_STOP;
+}
+EXPORT_SYMBOL_GPL(amd_decode_mce);
+
+static struct notifier_block amd_mce_dec_nb = {
+ .notifier_call = amd_decode_mce,
+};
+
+static int __init mce_amd_init(void)
+{
+ /*
+ * We can decode MCEs for K8, F10h and F11h CPUs:
+ */
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+ return 0;
+
+ if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
+ return 0;
+
+ atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
+
+ return 0;
+}
+early_initcall(mce_amd_init);
+
+#ifdef MODULE
+static void __exit mce_amd_exit(void)
+{
+ atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
+}
+
+MODULE_DESCRIPTION("AMD MCE decoder");
+MODULE_ALIAS("edac-mce-amd");
+MODULE_LICENSE("GPL");
+module_exit(mce_amd_exit);
+#endif
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h
new file mode 100644
index 0000000..2712a90
--- /dev/null
+++ b/drivers/edac/mce_amd.h
@@ -0,0 +1,72 @@
+#ifndef _EDAC_MCE_AMD_H
+#define _EDAC_MCE_AMD_H
+
+#include <linux/notifier.h>
+
+#include <asm/mce.h>
+
+#define ERROR_CODE(x) ((x) & 0xffff)
+#define EXT_ERROR_CODE(x) (((x) >> 16) & 0x1f)
+#define EXT_ERR_MSG(x) ext_msgs[EXT_ERROR_CODE(x)]
+
+#define LOW_SYNDROME(x) (((x) >> 15) & 0xff)
+#define HIGH_SYNDROME(x) (((x) >> 24) & 0xff)
+
+#define TLB_ERROR(x) (((x) & 0xFFF0) == 0x0010)
+#define MEM_ERROR(x) (((x) & 0xFF00) == 0x0100)
+#define BUS_ERROR(x) (((x) & 0xF800) == 0x0800)
+
+#define TT(x) (((x) >> 2) & 0x3)
+#define TT_MSG(x) tt_msgs[TT(x)]
+#define II(x) (((x) >> 2) & 0x3)
+#define II_MSG(x) ii_msgs[II(x)]
+#define LL(x) (((x) >> 0) & 0x3)
+#define LL_MSG(x) ll_msgs[LL(x)]
+#define TO(x) (((x) >> 8) & 0x1)
+#define TO_MSG(x) to_msgs[TO(x)]
+#define PP(x) (((x) >> 9) & 0x3)
+#define PP_MSG(x) pp_msgs[PP(x)]
+
+#define RRRR(x) (((x) >> 4) & 0xf)
+#define RRRR_MSG(x) ((RRRR(x) < 9) ? rrrr_msgs[RRRR(x)] : "Wrong R4!")
+
+#define K8_NBSH 0x4C
+
+#define K8_NBSH_VALID_BIT BIT(31)
+#define K8_NBSH_OVERFLOW BIT(30)
+#define K8_NBSH_UC_ERR BIT(29)
+#define K8_NBSH_ERR_EN BIT(28)
+#define K8_NBSH_MISCV BIT(27)
+#define K8_NBSH_VALID_ERROR_ADDR BIT(26)
+#define K8_NBSH_PCC BIT(25)
+#define K8_NBSH_ERR_CPU_VAL BIT(24)
+#define K8_NBSH_CECC BIT(14)
+#define K8_NBSH_UECC BIT(13)
+#define K8_NBSH_ERR_SCRUBER BIT(8)
+
+extern const char *tt_msgs[];
+extern const char *ll_msgs[];
+extern const char *rrrr_msgs[];
+extern const char *pp_msgs[];
+extern const char *to_msgs[];
+extern const char *ii_msgs[];
+extern const char *ext_msgs[];
+
+/*
+ * relevant NB regs
+ */
+struct err_regs {
+ u32 nbcfg;
+ u32 nbsh;
+ u32 nbsl;
+ u32 nbeah;
+ u32 nbeal;
+};
+
+void amd_report_gart_errors(bool);
+void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32));
+void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32));
+void amd_decode_nb_mce(int, struct mce *, u32);
+int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
+
+#endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
index 0e4f2dc..8d0688f 100644
--- a/drivers/edac/mce_amd_inj.c
+++ b/drivers/edac/mce_amd_inj.c
@@ -15,7 +15,7 @@
#include <linux/edac.h>
#include <asm/mce.h>
-#include "edac_mce_amd.h"
+#include "mce_amd.h"
struct edac_mce_attr {
struct attribute attr;
--
1.7.3.1.50.g1e633
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/8] EDAC, MCE: Adjust DC decoders to F14h
2010-10-05 10:54 [PATCH 0/8] MCE decoding on F14h Borislav Petkov
2010-10-05 10:54 ` [PATCH 1/8] EDAC, MCE: Rework MCE injection Borislav Petkov
2010-10-05 10:54 ` [PATCH 2/8] EDAC, MCE: Rename files Borislav Petkov
@ 2010-10-05 10:54 ` Borislav Petkov
2010-10-05 10:54 ` [PATCH 4/8] EDAC, MCE: Adjust IC " Borislav Petkov
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2010-10-05 10:54 UTC (permalink / raw)
To: norsk5; +Cc: linux-edac, x86, linux-kernel, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Add a per-family data cache decoders. Since there is a certain overlap
between the different DC MCE signatures, reuse functionality between the
families as far as possible.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/mce_amd.c | 162 ++++++++++++++++++++++++++++++++++++++++--------
drivers/edac/mce_amd.h | 40 ++++++++++++
2 files changed, 175 insertions(+), 27 deletions(-)
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 5eb8042..326db40 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -1,6 +1,10 @@
#include <linux/module.h>
+#include <linux/slab.h>
+
#include "mce_amd.h"
+static struct amd_decoder_ops *fam_ops;
+
static bool report_gart_errors;
static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
@@ -97,41 +101,120 @@ const char *ext_msgs[] = {
};
EXPORT_SYMBOL_GPL(ext_msgs);
-static void amd_decode_dc_mce(struct mce *m)
+static bool f10h_dc_mce(u16 ec)
{
- u32 ec = m->status & 0xffff;
- u32 xec = (m->status >> 16) & 0xf;
+ u8 r4 = (ec >> 4) & 0xf;
+ bool ret = false;
- pr_emerg(HW_ERR "Data Cache Error: ");
+ if (r4 == R4_GEN) {
+ pr_cont("during data scrub.\n");
+ return true;
+ }
- if (xec == 1 && TLB_ERROR(ec))
- pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
- else if (xec == 0) {
- if (m->status & (1ULL << 40))
- pr_cont(" during Data Scrub.\n");
- else if (TLB_ERROR(ec))
- pr_cont(": %s TLB parity error.\n", LL_MSG(ec));
- else if (MEM_ERROR(ec)) {
- u8 ll = ec & 0x3;
- u8 tt = (ec >> 2) & 0x3;
- u8 rrrr = (ec >> 4) & 0xf;
+ if (MEM_ERROR(ec)) {
+ u8 ll = ec & 0x3;
+ ret = true;
- /* see F10h BKDG (31116), Table 92. */
- if (ll == 0x1) {
- if (tt != 0x1)
- goto wrong_dc_mce;
+ if (ll == LL_L2)
+ pr_cont("during L1 linefill from L2.\n");
+ else if (ll == LL_L1)
+ pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec));
+ else
+ ret = false;
+ }
+ return ret;
+}
- pr_cont(": Data/Tag %s error.\n", RRRR_MSG(ec));
+static bool k8_dc_mce(u16 ec)
+{
+ if (BUS_ERROR(ec)) {
+ pr_cont("during system linefill.\n");
+ return true;
+ }
- } else if (ll == 0x2 && rrrr == 0x3)
- pr_cont(" during L1 linefill from L2.\n");
- else
- goto wrong_dc_mce;
- } else if (BUS_ERROR(ec) && boot_cpu_data.x86 == 0xf)
- pr_cont(" during system linefill.\n");
+ return f10h_dc_mce(ec);
+}
+
+static bool f14h_dc_mce(u16 ec)
+{
+ u8 r4 = (ec >> 4) & 0xf;
+ u8 ll = ec & 0x3;
+ u8 tt = (ec >> 2) & 0x3;
+ u8 ii = tt;
+ bool ret = true;
+
+ if (MEM_ERROR(ec)) {
+
+ if (tt != TT_DATA || ll != LL_L1)
+ return false;
+
+ switch (r4) {
+ case R4_DRD:
+ case R4_DWR:
+ pr_cont("Data/Tag parity error due to %s.\n",
+ (r4 == R4_DRD ? "load/hw prf" : "store"));
+ break;
+ case R4_EVICT:
+ pr_cont("Copyback parity error on a tag miss.\n");
+ break;
+ case R4_SNOOP:
+ pr_cont("Tag parity error during snoop.\n");
+ break;
+ default:
+ ret = false;
+ }
+ } else if (BUS_ERROR(ec)) {
+
+ if ((ii != II_MEM && ii != II_IO) || ll != LL_LG)
+ return false;
+
+ pr_cont("System read data error on a ");
+
+ switch (r4) {
+ case R4_RD:
+ pr_cont("TLB reload.\n");
+ break;
+ case R4_DWR:
+ pr_cont("store.\n");
+ break;
+ case R4_DRD:
+ pr_cont("load.\n");
+ break;
+ default:
+ ret = false;
+ }
+ } else {
+ ret = false;
+ }
+
+ return ret;
+}
+
+static void amd_decode_dc_mce(struct mce *m)
+{
+ u16 ec = m->status & 0xffff;
+ u8 xec = (m->status >> 16) & 0xf;
+
+ pr_emerg(HW_ERR "Data Cache Error: ");
+
+ /*
+ * check this after F14h BKDG is updated
+ *
+ * TLB error signatures are the same across families
+ */
+ if (TLB_ERROR(ec)) {
+ u8 tt = (ec >> 2) & 0x3;
+
+ if (tt == TT_DATA) {
+ pr_cont("%s TLB %s.\n", LL_MSG(ec),
+ (xec ? "multimatch" : "parity error"));
+ return;
+ }
else
goto wrong_dc_mce;
- } else
+ }
+
+ if (!fam_ops->dc_mce(ec))
goto wrong_dc_mce;
return;
@@ -395,6 +478,30 @@ static int __init mce_amd_init(void)
if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
return 0;
+ fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
+ if (!fam_ops)
+ return -ENOMEM;
+
+ switch (boot_cpu_data.x86) {
+ case 0xf:
+ fam_ops->dc_mce = k8_dc_mce;
+ break;
+
+ case 0x10:
+ fam_ops->dc_mce = f10h_dc_mce;
+ break;
+
+ case 0x14:
+ fam_ops->dc_mce = f14h_dc_mce;
+ break;
+
+ default:
+ printk(KERN_WARNING "Huh? What family is that: %d?!\n",
+ boot_cpu_data.x86);
+ kfree(fam_ops);
+ return -EINVAL;
+ }
+
atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
return 0;
@@ -405,6 +512,7 @@ early_initcall(mce_amd_init);
static void __exit mce_amd_exit(void)
{
atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &amd_mce_dec_nb);
+ kfree(fam_ops);
}
MODULE_DESCRIPTION("AMD MCE decoder");
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h
index 2712a90..85985c2 100644
--- a/drivers/edac/mce_amd.h
+++ b/drivers/edac/mce_amd.h
@@ -44,6 +44,39 @@
#define K8_NBSH_UECC BIT(13)
#define K8_NBSH_ERR_SCRUBER BIT(8)
+enum tt_ids {
+ TT_INSTR = 0,
+ TT_DATA,
+ TT_GEN,
+ TT_RESV,
+};
+
+enum ll_ids {
+ LL_RESV = 0,
+ LL_L1,
+ LL_L2,
+ LL_LG,
+};
+
+enum ii_ids {
+ II_MEM = 0,
+ II_RESV,
+ II_IO,
+ II_GEN,
+};
+
+enum rrrr_ids {
+ R4_GEN = 0,
+ R4_RD,
+ R4_WR,
+ R4_DRD,
+ R4_DWR,
+ R4_IRD,
+ R4_PREF,
+ R4_EVICT,
+ R4_SNOOP,
+};
+
extern const char *tt_msgs[];
extern const char *ll_msgs[];
extern const char *rrrr_msgs[];
@@ -63,6 +96,13 @@ struct err_regs {
u32 nbeal;
};
+/*
+ * per-family decoder ops
+ */
+struct amd_decoder_ops {
+ bool (*dc_mce)(u16);
+};
+
void amd_report_gart_errors(bool);
void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32));
void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32));
--
1.7.3.1.50.g1e633
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/8] EDAC, MCE: Adjust IC decoders to F14h
2010-10-05 10:54 [PATCH 0/8] MCE decoding on F14h Borislav Petkov
` (2 preceding siblings ...)
2010-10-05 10:54 ` [PATCH 3/8] EDAC, MCE: Adjust DC decoders to F14h Borislav Petkov
@ 2010-10-05 10:54 ` Borislav Petkov
2010-10-05 10:54 ` [PATCH 5/8] EDAC, MCE: Warn about LS MCEs on F14h Borislav Petkov
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2010-10-05 10:54 UTC (permalink / raw)
To: norsk5; +Cc: linux-edac, x86, linux-kernel, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Add support for IC MCEs for F14h CPUs. K8 and F10h are almost identical
so use one function for both.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/mce_amd.c | 118 ++++++++++++++++++++++++++++-------------------
drivers/edac/mce_amd.h | 1 +
2 files changed, 71 insertions(+), 48 deletions(-)
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 326db40..6e49f1e 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -223,61 +223,80 @@ wrong_dc_mce:
pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
}
-static void amd_decode_ic_mce(struct mce *m)
+static bool k8_ic_mce(u16 ec)
{
- u32 ec = m->status & 0xffff;
- u32 xec = (m->status >> 16) & 0xf;
+ u8 ll = ec & 0x3;
+ u8 r4 = (ec >> 4) & 0xf;
+ bool ret = true;
- pr_emerg(HW_ERR "Instruction Cache Error");
+ if (!MEM_ERROR(ec))
+ return false;
- if (xec == 1 && TLB_ERROR(ec))
- pr_cont(": %s TLB multimatch.\n", LL_MSG(ec));
- else if (xec == 0) {
- if (TLB_ERROR(ec))
- pr_cont(": %s TLB Parity error.\n", LL_MSG(ec));
- else if (BUS_ERROR(ec)) {
- if (boot_cpu_data.x86 == 0xf &&
- (m->status & BIT(58)))
- pr_cont(" during system linefill.\n");
- else
- pr_cont(" during attempted NB data read.\n");
- } else if (MEM_ERROR(ec)) {
- u8 ll = ec & 0x3;
- u8 rrrr = (ec >> 4) & 0xf;
+ if (ll == 0x2)
+ pr_cont("during a linefill from L2.\n");
+ else if (ll == 0x1) {
+ switch (r4) {
+ case R4_IRD:
+ pr_cont("Parity error during data load.\n");
+ break;
- if (ll == 0x2)
- pr_cont(" during a linefill from L2.\n");
- else if (ll == 0x1) {
-
- switch (rrrr) {
- case 0x5:
- pr_cont(": Parity error during "
- "data load.\n");
- break;
-
- case 0x7:
- pr_cont(": Copyback Parity/Victim"
- " error.\n");
- break;
-
- case 0x8:
- pr_cont(": Tag Snoop error.\n");
- break;
-
- default:
- goto wrong_ic_mce;
- break;
- }
- }
- } else
- goto wrong_ic_mce;
+ case R4_EVICT:
+ pr_cont("Copyback Parity/Victim error.\n");
+ break;
+
+ case R4_SNOOP:
+ pr_cont("Tag Snoop error.\n");
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
} else
- goto wrong_ic_mce;
+ ret = false;
- return;
+ return ret;
+}
+
+static bool f14h_ic_mce(u16 ec)
+{
+ u8 ll = ec & 0x3;
+ u8 tt = (ec >> 2) & 0x3;
+ u8 r4 = (ec >> 4) & 0xf;
+ bool ret = true;
-wrong_ic_mce:
- pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
+ if (MEM_ERROR(ec)) {
+ if (tt != 0 || ll != 1)
+ ret = false;
+
+ if (r4 == R4_IRD)
+ pr_cont("Data/tag array parity error for a tag hit.\n");
+ else if (r4 == R4_SNOOP)
+ pr_cont("Tag error during snoop/victimization.\n");
+ else
+ ret = false;
+ }
+ return ret;
+}
+
+static void amd_decode_ic_mce(struct mce *m)
+{
+ u16 ec = m->status & 0xffff;
+ u8 xec = (m->status >> 16) & 0xf;
+
+ pr_emerg(HW_ERR "Instruction Cache Error: ");
+
+ if (TLB_ERROR(ec))
+ pr_cont("%s TLB %s.\n", LL_MSG(ec),
+ (xec ? "multimatch" : "parity error"));
+ else if (BUS_ERROR(ec)) {
+ bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT(58)));
+
+ pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
+ } else if (fam_ops->ic_mce(ec))
+ ;
+ else
+ pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
}
static void amd_decode_bu_mce(struct mce *m)
@@ -485,14 +504,17 @@ static int __init mce_amd_init(void)
switch (boot_cpu_data.x86) {
case 0xf:
fam_ops->dc_mce = k8_dc_mce;
+ fam_ops->ic_mce = k8_ic_mce;
break;
case 0x10:
fam_ops->dc_mce = f10h_dc_mce;
+ fam_ops->ic_mce = k8_ic_mce;
break;
case 0x14:
fam_ops->dc_mce = f14h_dc_mce;
+ fam_ops->ic_mce = f14h_ic_mce;
break;
default:
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h
index 85985c2..dc81dba 100644
--- a/drivers/edac/mce_amd.h
+++ b/drivers/edac/mce_amd.h
@@ -101,6 +101,7 @@ struct err_regs {
*/
struct amd_decoder_ops {
bool (*dc_mce)(u16);
+ bool (*ic_mce)(u16);
};
void amd_report_gart_errors(bool);
--
1.7.3.1.50.g1e633
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/8] EDAC, MCE: Warn about LS MCEs on F14h
2010-10-05 10:54 [PATCH 0/8] MCE decoding on F14h Borislav Petkov
` (3 preceding siblings ...)
2010-10-05 10:54 ` [PATCH 4/8] EDAC, MCE: Adjust IC " Borislav Petkov
@ 2010-10-05 10:54 ` Borislav Petkov
2010-10-05 10:54 ` [PATCH 6/8] EDAC, MCE: Complete NB MCE decoders Borislav Petkov
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2010-10-05 10:54 UTC (permalink / raw)
To: norsk5; +Cc: linux-edac, x86, linux-kernel, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
F14h CPUs do not generate LS MCEs so exit early and warn the user in
case this path is ever hit that something else might be going haywire.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/mce_amd.c | 18 +++++++++++++-----
1 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 6e49f1e..adb5d25 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -343,19 +343,27 @@ wrong_bu_mce:
static void amd_decode_ls_mce(struct mce *m)
{
- u32 ec = m->status & 0xffff;
- u32 xec = (m->status >> 16) & 0xf;
+ u16 ec = m->status & 0xffff;
+ u8 xec = (m->status >> 16) & 0xf;
+
+ if (boot_cpu_data.x86 == 0x14) {
+ pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
+ " please report on LKML.\n");
+ return;
+ }
pr_emerg(HW_ERR "Load Store Error");
if (xec == 0x0) {
- u8 rrrr = (ec >> 4) & 0xf;
+ u8 r4 = (ec >> 4) & 0xf;
- if (!BUS_ERROR(ec) || (rrrr != 0x3 && rrrr != 0x4))
+ if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
goto wrong_ls_mce;
pr_cont(" during %s.\n", RRRR_MSG(ec));
- }
+ } else
+ goto wrong_ls_mce;
+
return;
wrong_ls_mce:
--
1.7.3.1.50.g1e633
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 6/8] EDAC, MCE: Complete NB MCE decoders
2010-10-05 10:54 [PATCH 0/8] MCE decoding on F14h Borislav Petkov
` (4 preceding siblings ...)
2010-10-05 10:54 ` [PATCH 5/8] EDAC, MCE: Warn about LS MCEs on F14h Borislav Petkov
@ 2010-10-05 10:54 ` Borislav Petkov
2010-10-05 10:54 ` [PATCH 7/8] EDAC, MCE: Fix FR MCEs decoding Borislav Petkov
2010-10-05 10:54 ` [PATCH 8/8] EDAC, MCE: Enable MCE decoding on F14h Borislav Petkov
7 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2010-10-05 10:54 UTC (permalink / raw)
To: norsk5; +Cc: linux-edac, x86, linux-kernel, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Add support for decoding F14h BU MCEs and improve decoding of the
remaining families.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/amd64_edac.h | 1 -
drivers/edac/mce_amd.c | 210 +++++++++++++++++++++++++++++++++-----------
drivers/edac/mce_amd.h | 3 +-
3 files changed, 158 insertions(+), 56 deletions(-)
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 13e1d6f..044aee4 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -482,7 +482,6 @@ extern const char *rrrr_msgs[16];
extern const char *to_msgs[2];
extern const char *pp_msgs[4];
extern const char *ii_msgs[4];
-extern const char *ext_msgs[32];
extern const char *htlink_msgs[8];
#ifdef CONFIG_EDAC_DEBUG
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index adb5d25..cf6d44a 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -5,6 +5,8 @@
static struct amd_decoder_ops *fam_ops;
+static u8 nb_err_cpumask = 0xf;
+
static bool report_gart_errors;
static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg);
@@ -61,45 +63,16 @@ EXPORT_SYMBOL_GPL(to_msgs);
const char *ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
EXPORT_SYMBOL_GPL(ii_msgs);
-/*
- * Map the 4 or 5 (family-specific) bits of Extended Error code to the
- * string table.
- */
-const char *ext_msgs[] = {
- "K8 ECC error", /* 0_0000b */
- "CRC error on link", /* 0_0001b */
- "Sync error packets on link", /* 0_0010b */
- "Master Abort during link operation", /* 0_0011b */
- "Target Abort during link operation", /* 0_0100b */
- "Invalid GART PTE entry during table walk", /* 0_0101b */
- "Unsupported atomic RMW command received", /* 0_0110b */
- "WDT error: NB transaction timeout", /* 0_0111b */
- "ECC/ChipKill ECC error", /* 0_1000b */
- "SVM DEV Error", /* 0_1001b */
- "Link Data error", /* 0_1010b */
- "Link/L3/Probe Filter Protocol error", /* 0_1011b */
- "NB Internal Arrays Parity error", /* 0_1100b */
- "DRAM Address/Control Parity error", /* 0_1101b */
- "Link Transmission error", /* 0_1110b */
- "GART/DEV Table Walk Data error" /* 0_1111b */
- "Res 0x100 error", /* 1_0000b */
- "Res 0x101 error", /* 1_0001b */
- "Res 0x102 error", /* 1_0010b */
- "Res 0x103 error", /* 1_0011b */
- "Res 0x104 error", /* 1_0100b */
- "Res 0x105 error", /* 1_0101b */
- "Res 0x106 error", /* 1_0110b */
- "Res 0x107 error", /* 1_0111b */
- "Res 0x108 error", /* 1_1000b */
- "Res 0x109 error", /* 1_1001b */
- "Res 0x10A error", /* 1_1010b */
- "Res 0x10B error", /* 1_1011b */
- "ECC error in L3 Cache Data", /* 1_1100b */
- "L3 Cache Tag error", /* 1_1101b */
- "L3 Cache LRU Parity error", /* 1_1110b */
- "Probe Filter error" /* 1_1111b */
+static const char *f10h_nb_mce_desc[] = {
+ "HT link data error",
+ "Protocol error (link, L3, probe filter, etc.)",
+ "Parity error in NB-internal arrays",
+ "Link Retry due to IO link transmission error",
+ "L3 ECC data cache error",
+ "ECC error in L3 cache tag",
+ "L3 LRU parity bits error",
+ "ECC Error in the Probe Filter directory"
};
-EXPORT_SYMBOL_GPL(ext_msgs);
static bool f10h_dc_mce(u16 ec)
{
@@ -370,19 +343,97 @@ wrong_ls_mce:
pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
}
+static bool k8_nb_mce(u16 ec, u8 xec)
+{
+ bool ret = true;
+
+ switch (xec) {
+ case 0x1:
+ pr_cont("CRC error detected on HT link.\n");
+ break;
+
+ case 0x5:
+ pr_cont("Invalid GART PTE entry during GART table walk.\n");
+ break;
+
+ case 0x6:
+ pr_cont("Unsupported atomic RMW received from an IO link.\n");
+ break;
+
+ case 0x0:
+ case 0x8:
+ pr_cont("DRAM ECC error detected on the NB.\n");
+ break;
+
+ case 0xd:
+ pr_cont("Parity error on the DRAM addr/ctl signals.\n");
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+static bool f10h_nb_mce(u16 ec, u8 xec)
+{
+ bool ret = true;
+ u8 offset = 0;
+
+ if (k8_nb_mce(ec, xec))
+ return true;
+
+ switch(xec) {
+ case 0xa ... 0xc:
+ offset = 10;
+ break;
+
+ case 0xe:
+ offset = 11;
+ break;
+
+ case 0xf:
+ if (TLB_ERROR(ec))
+ pr_cont("GART Table Walk data error.\n");
+ else if (BUS_ERROR(ec))
+ pr_cont("DMA Exclusion Vector Table Walk error.\n");
+ else
+ ret = false;
+
+ goto out;
+ break;
+
+ case 0x1c ... 0x1f:
+ offset = 24;
+ break;
+
+ default:
+ ret = false;
+
+ goto out;
+ break;
+ }
+
+ pr_cont("%s.\n", f10h_nb_mce_desc[xec - offset]);
+
+out:
+ return ret;
+}
+
+static bool f14h_nb_mce(u16 ec, u8 xec)
+{
+ return false;
+}
+
void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
{
- u32 ec = m->status & 0xffff;
+ u8 xec = (m->status >> 16) & 0x1f;
+ u16 ec = m->status & 0xffff;
u32 nbsh = (u32)(m->status >> 32);
- u32 nbsl = (u32)m->status;
-
- /*
- * GART TLB error reporting is disabled by default. Bail out early.
- */
- if (TLB_ERROR(ec) && !report_gart_errors)
- return;
- pr_emerg(HW_ERR "Northbridge Error, node %d", node_id);
+ pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id);
/*
* F10h, revD can disable ErrCpu[3:0] so check that first and also the
@@ -391,20 +442,50 @@ void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
if ((boot_cpu_data.x86 == 0x10) &&
(boot_cpu_data.x86_model > 7)) {
if (nbsh & K8_NBSH_ERR_CPU_VAL)
- pr_cont(", core: %u\n", (u8)(nbsh & 0xf));
+ pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask));
} else {
- u8 assoc_cpus = nbsh & 0xf;
+ u8 assoc_cpus = nbsh & nb_err_cpumask;
if (assoc_cpus > 0)
pr_cont(", core: %d", fls(assoc_cpus) - 1);
+ }
- pr_cont("\n");
+ switch (xec) {
+ case 0x2:
+ pr_cont("Sync error (sync packets on HT link detected).\n");
+ return;
+
+ case 0x3:
+ pr_cont("HT Master abort.\n");
+ return;
+
+ case 0x4:
+ pr_cont("HT Target abort.\n");
+ return;
+
+ case 0x7:
+ pr_cont("NB Watchdog timeout.\n");
+ return;
+
+ case 0x9:
+ pr_cont("SVM DMA Exclusion Vector error.\n");
+ return;
+
+ default:
+ break;
}
- pr_emerg(HW_ERR "%s.\n", EXT_ERR_MSG(nbsl));
+ if (!fam_ops->nb_mce(ec, xec))
+ goto wrong_nb_mce;
+
+ if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
+ if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
+ nb_bus_decoder(node_id, m, nbcfg);
- if (BUS_ERROR(ec) && nb_bus_decoder)
- nb_bus_decoder(node_id, m, nbcfg);
+ return;
+
+wrong_nb_mce:
+ pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
}
EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
@@ -434,11 +515,30 @@ static inline void amd_decode_err_code(u16 ec)
pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec);
}
+/*
+ * Filter out unwanted MCE signatures here.
+ */
+static bool amd_filter_mce(struct mce *m)
+{
+ u8 xec = (m->status >> 16) & 0x1f;
+
+ /*
+ * NB GART TLB error reporting is disabled by default.
+ */
+ if (m->bank == 4 && xec == 0x5 && !report_gart_errors)
+ return true;
+
+ return false;
+}
+
int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
{
struct mce *m = (struct mce *)data;
int node, ecc;
+ if (amd_filter_mce(m))
+ return NOTIFY_STOP;
+
pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank);
pr_cont("%sorrected error, other errors lost: %s, "
@@ -513,16 +613,20 @@ static int __init mce_amd_init(void)
case 0xf:
fam_ops->dc_mce = k8_dc_mce;
fam_ops->ic_mce = k8_ic_mce;
+ fam_ops->nb_mce = k8_nb_mce;
break;
case 0x10:
fam_ops->dc_mce = f10h_dc_mce;
fam_ops->ic_mce = k8_ic_mce;
+ fam_ops->nb_mce = f10h_nb_mce;
break;
case 0x14:
+ nb_err_cpumask = 0x3;
fam_ops->dc_mce = f14h_dc_mce;
fam_ops->ic_mce = f14h_ic_mce;
+ fam_ops->nb_mce = f14h_nb_mce;
break;
default:
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h
index dc81dba..0d0637d 100644
--- a/drivers/edac/mce_amd.h
+++ b/drivers/edac/mce_amd.h
@@ -7,7 +7,6 @@
#define ERROR_CODE(x) ((x) & 0xffff)
#define EXT_ERROR_CODE(x) (((x) >> 16) & 0x1f)
-#define EXT_ERR_MSG(x) ext_msgs[EXT_ERROR_CODE(x)]
#define LOW_SYNDROME(x) (((x) >> 15) & 0xff)
#define HIGH_SYNDROME(x) (((x) >> 24) & 0xff)
@@ -83,7 +82,6 @@ extern const char *rrrr_msgs[];
extern const char *pp_msgs[];
extern const char *to_msgs[];
extern const char *ii_msgs[];
-extern const char *ext_msgs[];
/*
* relevant NB regs
@@ -102,6 +100,7 @@ struct err_regs {
struct amd_decoder_ops {
bool (*dc_mce)(u16);
bool (*ic_mce)(u16);
+ bool (*nb_mce)(u16, u8);
};
void amd_report_gart_errors(bool);
--
1.7.3.1.50.g1e633
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 7/8] EDAC, MCE: Fix FR MCEs decoding
2010-10-05 10:54 [PATCH 0/8] MCE decoding on F14h Borislav Petkov
` (5 preceding siblings ...)
2010-10-05 10:54 ` [PATCH 6/8] EDAC, MCE: Complete NB MCE decoders Borislav Petkov
@ 2010-10-05 10:54 ` Borislav Petkov
2010-10-05 10:54 ` [PATCH 8/8] EDAC, MCE: Enable MCE decoding on F14h Borislav Petkov
7 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2010-10-05 10:54 UTC (permalink / raw)
To: norsk5; +Cc: linux-edac, x86, linux-kernel, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Those are N/A on K8, so don't decode them there.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/mce_amd.c | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index cf6d44a..82dc0de 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -491,11 +491,17 @@ EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
static void amd_decode_fr_mce(struct mce *m)
{
+ if (boot_cpu_data.x86 == 0xf)
+ goto wrong_fr_mce;
+
/* we have only one error signature so match all fields at once. */
- if ((m->status & 0xffff) == 0x0f0f)
- pr_emerg(HW_ERR " FR Error: CPU Watchdog timer expire.\n");
- else
- pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
+ if ((m->status & 0xffff) == 0x0f0f) {
+ pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n");
+ return;
+ }
+
+wrong_fr_mce:
+ pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
}
static inline void amd_decode_err_code(u16 ec)
--
1.7.3.1.50.g1e633
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 8/8] EDAC, MCE: Enable MCE decoding on F14h
2010-10-05 10:54 [PATCH 0/8] MCE decoding on F14h Borislav Petkov
` (6 preceding siblings ...)
2010-10-05 10:54 ` [PATCH 7/8] EDAC, MCE: Fix FR MCEs decoding Borislav Petkov
@ 2010-10-05 10:54 ` Borislav Petkov
7 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2010-10-05 10:54 UTC (permalink / raw)
To: norsk5; +Cc: linux-edac, x86, linux-kernel, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Now that all decoders have been taught about F14h, models < 0x10
MCEs, enable decoding on this family of CPUs. Also, issue a short
informational message upon boot that MCE decoding gets enabled.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/mce_amd.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 82dc0de..f8dcd241 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -602,13 +602,12 @@ static struct notifier_block amd_mce_dec_nb = {
static int __init mce_amd_init(void)
{
- /*
- * We can decode MCEs for K8, F10h and F11h CPUs:
- */
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
return 0;
- if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
+ if (boot_cpu_data.x86 != 0xf &&
+ boot_cpu_data.x86 != 0x10 &&
+ (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf))
return 0;
fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
@@ -642,6 +641,8 @@ static int __init mce_amd_init(void)
return -EINVAL;
}
+ pr_info("MCE: In-kernel MCE decoding enabled.\n");
+
atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb);
return 0;
--
1.7.3.1.50.g1e633
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-10-05 10:53 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-05 10:54 [PATCH 0/8] MCE decoding on F14h Borislav Petkov
2010-10-05 10:54 ` [PATCH 1/8] EDAC, MCE: Rework MCE injection Borislav Petkov
2010-10-05 10:54 ` [PATCH 2/8] EDAC, MCE: Rename files Borislav Petkov
2010-10-05 10:54 ` [PATCH 3/8] EDAC, MCE: Adjust DC decoders to F14h Borislav Petkov
2010-10-05 10:54 ` [PATCH 4/8] EDAC, MCE: Adjust IC " Borislav Petkov
2010-10-05 10:54 ` [PATCH 5/8] EDAC, MCE: Warn about LS MCEs on F14h Borislav Petkov
2010-10-05 10:54 ` [PATCH 6/8] EDAC, MCE: Complete NB MCE decoders Borislav Petkov
2010-10-05 10:54 ` [PATCH 7/8] EDAC, MCE: Fix FR MCEs decoding Borislav Petkov
2010-10-05 10:54 ` [PATCH 8/8] EDAC, MCE: Enable MCE decoding on F14h Borislav Petkov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®