aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/edac_mce_amd.c
diff options
context:
space:
mode:
authorBorislav Petkov <borislav.petkov@amd.com>2009-07-24 07:51:42 -0400
committerBorislav Petkov <borislav.petkov@amd.com>2009-09-14 12:59:17 -0400
commit549d042df240dfb4203bab40ad44f9336751b7d6 (patch)
treeaf357ed8eaf06c26f19d458686b6c7ea4e425a05 /drivers/edac/edac_mce_amd.c
parentecaf5606de65cdd04de5f526185fe28fb0df654e (diff)
x86, mce: pass mce info to EDAC for decoding
Move NB decoder along with required defines to EDAC MCE core. Add registration routines for further decoding of the MCE info in the AMD64 EDAC module. CC: Andi Kleen <andi@firstfloor.org> Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'drivers/edac/edac_mce_amd.c')
-rw-r--r--drivers/edac/edac_mce_amd.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c
index 918567e8cfd..444c2cc4472 100644
--- a/drivers/edac/edac_mce_amd.c
+++ b/drivers/edac/edac_mce_amd.c
@@ -1,6 +1,31 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include "edac_mce_amd.h" 2#include "edac_mce_amd.h"
3 3
4static bool report_gart_errors;
5static void (*nb_bus_decoder)(int node_id, struct err_regs *regs, int ecc_type);
6
7void amd_report_gart_errors(bool v)
8{
9 report_gart_errors = v;
10}
11EXPORT_SYMBOL_GPL(amd_report_gart_errors);
12
13void amd_register_ecc_decoder(void (*f)(int, struct err_regs *, int))
14{
15 nb_bus_decoder = f;
16}
17EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
18
19void amd_unregister_ecc_decoder(void (*f)(int, struct err_regs *, int))
20{
21 if (nb_bus_decoder) {
22 WARN_ON(nb_bus_decoder != f);
23
24 nb_bus_decoder = NULL;
25 }
26}
27EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
28
4/* 29/*
5 * string representation for the different MCA reported error types, see F3x48 30 * string representation for the different MCA reported error types, see F3x48
6 * or MSR0000_0411. 31 * or MSR0000_0411.
@@ -102,3 +127,93 @@ const char *ext_msgs[] = {
102 "Probe Filter error" /* 1_1111b */ 127 "Probe Filter error" /* 1_1111b */
103}; 128};
104EXPORT_SYMBOL_GPL(ext_msgs); 129EXPORT_SYMBOL_GPL(ext_msgs);
130
131void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors)
132{
133 int ecc;
134 u32 ec = ERROR_CODE(regs->nbsl);
135 u32 xec = EXT_ERROR_CODE(regs->nbsl);
136
137 if (!handle_errors)
138 return;
139
140 pr_emerg(" Northbridge Error, node %d", node_id);
141
142 /*
143 * F10h, revD can disable ErrCpu[3:0] so check that first and also the
144 * value encoding has changed so interpret those differently
145 */
146 if ((boot_cpu_data.x86 == 0x10) &&
147 (boot_cpu_data.x86_model > 8)) {
148 if (regs->nbsh & K8_NBSH_ERR_CPU_VAL)
149 pr_cont(", core: %u\n", (u8)(regs->nbsh & 0xf));
150 } else {
151 pr_cont(", core: %d\n", ilog2((regs->nbsh & 0xf)));
152 }
153
154 pr_emerg(" Error: %sorrected",
155 ((regs->nbsh & K8_NBSH_UC_ERR) ? "Unc" : "C"));
156 pr_cont(", Report Error: %s",
157 ((regs->nbsh & K8_NBSH_ERR_EN) ? "yes" : "no"));
158 pr_cont(", MiscV: %svalid, CPU context corrupt: %s",
159 ((regs->nbsh & K8_NBSH_MISCV) ? "" : "In"),
160 ((regs->nbsh & K8_NBSH_PCC) ? "yes" : "no"));
161
162 /* do the two bits[14:13] together */
163 ecc = regs->nbsh & (0x3 << 13);
164 if (ecc)
165 pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
166
167 pr_cont("\n");
168
169 if (TLB_ERROR(ec)) {
170 /*
171 * GART errors are intended to help graphics driver developers
172 * to detect bad GART PTEs. It is recommended by AMD to disable
173 * GART table walk error reporting by default[1] (currently
174 * being disabled in mce_cpu_quirks()) and according to the
175 * comment in mce_cpu_quirks(), such GART errors can be
176 * incorrectly triggered. We may see these errors anyway and
177 * unless requested by the user, they won't be reported.
178 *
179 * [1] section 13.10.1 on BIOS and Kernel Developers Guide for
180 * AMD NPT family 0Fh processors
181 */
182 if (!report_gart_errors)
183 return;
184
185 pr_emerg(" GART TLB error, Transaction: %s, Cache Level %s\n",
186 TT_MSG(ec), LL_MSG(ec));
187 } else if (MEM_ERROR(ec)) {
188 pr_emerg(" Memory/Cache error, Transaction: %s, Type: %s,"
189 " Cache Level: %s",
190 RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec));
191 } else if (BUS_ERROR(ec)) {
192 pr_emerg(" Bus (Link/DRAM) error\n");
193 if (nb_bus_decoder)
194 nb_bus_decoder(node_id, regs, ecc);
195 } else {
196 /* shouldn't reach here! */
197 pr_warning("%s: unknown MCE error 0x%x\n", __func__, ec);
198 }
199
200 pr_emerg("%s.\n", EXT_ERR_MSG(xec));
201}
202EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
203
204void decode_mce(struct mce *m)
205{
206 struct err_regs regs;
207 int node;
208
209 if (m->bank != 4)
210 return;
211
212 regs.nbsl = (u32) m->status;
213 regs.nbsh = (u32)(m->status >> 32);
214 regs.nbeal = (u32) m->addr;
215 regs.nbeah = (u32)(m->addr >> 32);
216 node = topology_cpu_node_id(m->extcpu);
217
218 amd_decode_nb_mce(node, &regs, 1);
219}