aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-04 20:21:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-04 20:21:59 -0400
commitd782cebd6b39b4caab8a913180c0acfd6c33e9c2 (patch)
treee8ed959e9475f57bf7f2a0753e5a0f7cf04c8f75 /drivers/firmware
parent8556d44fee6ded9f4287d7ff7b5cc9d8635b0be0 (diff)
parentc3107e3c504d3187ed8eac8179494946faff1481 (diff)
Merge branch 'x86-ras-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull RAS updates from Ingo Molnar: "The main changes in this cycle are: - RAS tracing/events infrastructure, by Gong Chen. - Various generalizations of the APEI code to make it available to non-x86 architectures, by Tomasz Nowicki" * 'x86-ras-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/ras: Fix build warnings in <linux/aer.h> acpi, apei, ghes: Factor out ioremap virtual memory for IRQ and NMI context. acpi, apei, ghes: Make NMI error notification to be GHES architecture extension. apei, mce: Factor out APEI architecture specific MCE calls. RAS, extlog: Adjust init flow trace, eMCA: Add a knob to adjust where to save event log trace, RAS: Add eMCA trace event interface RAS, debugfs: Add debugfs interface for RAS subsystem CPER: Adjust code flow of some functions x86, MCE: Robustify mcheck_init_device trace, AER: Move trace into unified interface trace, RAS: Add basic RAS trace event x86, MCE: Kill CPU_POST_DEAD
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/efi/cper.c192
1 files changed, 137 insertions, 55 deletions
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 1491dd4f08f9..437e6fd47311 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -34,6 +34,9 @@
34#include <linux/aer.h> 34#include <linux/aer.h>
35 35
36#define INDENT_SP " " 36#define INDENT_SP " "
37
38static char rcd_decode_str[CPER_REC_LEN];
39
37/* 40/*
38 * CPER record ID need to be unique even after reboot, because record 41 * CPER record ID need to be unique even after reboot, because record
39 * ID is used as index for ERST storage, while CPER records from 42 * ID is used as index for ERST storage, while CPER records from
@@ -50,18 +53,19 @@ u64 cper_next_record_id(void)
50} 53}
51EXPORT_SYMBOL_GPL(cper_next_record_id); 54EXPORT_SYMBOL_GPL(cper_next_record_id);
52 55
53static const char *cper_severity_strs[] = { 56static const char * const severity_strs[] = {
54 "recoverable", 57 "recoverable",
55 "fatal", 58 "fatal",
56 "corrected", 59 "corrected",
57 "info", 60 "info",
58}; 61};
59 62
60static const char *cper_severity_str(unsigned int severity) 63const char *cper_severity_str(unsigned int severity)
61{ 64{
62 return severity < ARRAY_SIZE(cper_severity_strs) ? 65 return severity < ARRAY_SIZE(severity_strs) ?
63 cper_severity_strs[severity] : "unknown"; 66 severity_strs[severity] : "unknown";
64} 67}
68EXPORT_SYMBOL_GPL(cper_severity_str);
65 69
66/* 70/*
67 * cper_print_bits - print strings for set bits 71 * cper_print_bits - print strings for set bits
@@ -100,32 +104,32 @@ void cper_print_bits(const char *pfx, unsigned int bits,
100 printk("%s\n", buf); 104 printk("%s\n", buf);
101} 105}
102 106
103static const char * const cper_proc_type_strs[] = { 107static const char * const proc_type_strs[] = {
104 "IA32/X64", 108 "IA32/X64",
105 "IA64", 109 "IA64",
106}; 110};
107 111
108static const char * const cper_proc_isa_strs[] = { 112static const char * const proc_isa_strs[] = {
109 "IA32", 113 "IA32",
110 "IA64", 114 "IA64",
111 "X64", 115 "X64",
112}; 116};
113 117
114static const char * const cper_proc_error_type_strs[] = { 118static const char * const proc_error_type_strs[] = {
115 "cache error", 119 "cache error",
116 "TLB error", 120 "TLB error",
117 "bus error", 121 "bus error",
118 "micro-architectural error", 122 "micro-architectural error",
119}; 123};
120 124
121static const char * const cper_proc_op_strs[] = { 125static const char * const proc_op_strs[] = {
122 "unknown or generic", 126 "unknown or generic",
123 "data read", 127 "data read",
124 "data write", 128 "data write",
125 "instruction execution", 129 "instruction execution",
126}; 130};
127 131
128static const char * const cper_proc_flag_strs[] = { 132static const char * const proc_flag_strs[] = {
129 "restartable", 133 "restartable",
130 "precise IP", 134 "precise IP",
131 "overflow", 135 "overflow",
@@ -137,26 +141,26 @@ static void cper_print_proc_generic(const char *pfx,
137{ 141{
138 if (proc->validation_bits & CPER_PROC_VALID_TYPE) 142 if (proc->validation_bits & CPER_PROC_VALID_TYPE)
139 printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type, 143 printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type,
140 proc->proc_type < ARRAY_SIZE(cper_proc_type_strs) ? 144 proc->proc_type < ARRAY_SIZE(proc_type_strs) ?
141 cper_proc_type_strs[proc->proc_type] : "unknown"); 145 proc_type_strs[proc->proc_type] : "unknown");
142 if (proc->validation_bits & CPER_PROC_VALID_ISA) 146 if (proc->validation_bits & CPER_PROC_VALID_ISA)
143 printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa, 147 printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa,
144 proc->proc_isa < ARRAY_SIZE(cper_proc_isa_strs) ? 148 proc->proc_isa < ARRAY_SIZE(proc_isa_strs) ?
145 cper_proc_isa_strs[proc->proc_isa] : "unknown"); 149 proc_isa_strs[proc->proc_isa] : "unknown");
146 if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) { 150 if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) {
147 printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type); 151 printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type);
148 cper_print_bits(pfx, proc->proc_error_type, 152 cper_print_bits(pfx, proc->proc_error_type,
149 cper_proc_error_type_strs, 153 proc_error_type_strs,
150 ARRAY_SIZE(cper_proc_error_type_strs)); 154 ARRAY_SIZE(proc_error_type_strs));
151 } 155 }
152 if (proc->validation_bits & CPER_PROC_VALID_OPERATION) 156 if (proc->validation_bits & CPER_PROC_VALID_OPERATION)
153 printk("%s""operation: %d, %s\n", pfx, proc->operation, 157 printk("%s""operation: %d, %s\n", pfx, proc->operation,
154 proc->operation < ARRAY_SIZE(cper_proc_op_strs) ? 158 proc->operation < ARRAY_SIZE(proc_op_strs) ?
155 cper_proc_op_strs[proc->operation] : "unknown"); 159 proc_op_strs[proc->operation] : "unknown");
156 if (proc->validation_bits & CPER_PROC_VALID_FLAGS) { 160 if (proc->validation_bits & CPER_PROC_VALID_FLAGS) {
157 printk("%s""flags: 0x%02x\n", pfx, proc->flags); 161 printk("%s""flags: 0x%02x\n", pfx, proc->flags);
158 cper_print_bits(pfx, proc->flags, cper_proc_flag_strs, 162 cper_print_bits(pfx, proc->flags, proc_flag_strs,
159 ARRAY_SIZE(cper_proc_flag_strs)); 163 ARRAY_SIZE(proc_flag_strs));
160 } 164 }
161 if (proc->validation_bits & CPER_PROC_VALID_LEVEL) 165 if (proc->validation_bits & CPER_PROC_VALID_LEVEL)
162 printk("%s""level: %d\n", pfx, proc->level); 166 printk("%s""level: %d\n", pfx, proc->level);
@@ -177,7 +181,7 @@ static void cper_print_proc_generic(const char *pfx,
177 printk("%s""IP: 0x%016llx\n", pfx, proc->ip); 181 printk("%s""IP: 0x%016llx\n", pfx, proc->ip);
178} 182}
179 183
180static const char *cper_mem_err_type_strs[] = { 184static const char * const mem_err_type_strs[] = {
181 "unknown", 185 "unknown",
182 "no error", 186 "no error",
183 "single-bit ECC", 187 "single-bit ECC",
@@ -196,58 +200,136 @@ static const char *cper_mem_err_type_strs[] = {
196 "physical memory map-out event", 200 "physical memory map-out event",
197}; 201};
198 202
199static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) 203const char *cper_mem_err_type_str(unsigned int etype)
200{ 204{
201 if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS) 205 return etype < ARRAY_SIZE(mem_err_type_strs) ?
202 printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status); 206 mem_err_type_strs[etype] : "unknown";
203 if (mem->validation_bits & CPER_MEM_VALID_PA) 207}
204 printk("%s""physical_address: 0x%016llx\n", 208EXPORT_SYMBOL_GPL(cper_mem_err_type_str);
205 pfx, mem->physical_addr); 209
206 if (mem->validation_bits & CPER_MEM_VALID_PA_MASK) 210static int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
207 printk("%s""physical_address_mask: 0x%016llx\n", 211{
208 pfx, mem->physical_addr_mask); 212 u32 len, n;
213
214 if (!msg)
215 return 0;
216
217 n = 0;
218 len = CPER_REC_LEN - 1;
209 if (mem->validation_bits & CPER_MEM_VALID_NODE) 219 if (mem->validation_bits & CPER_MEM_VALID_NODE)
210 pr_debug("node: %d\n", mem->node); 220 n += scnprintf(msg + n, len - n, "node: %d ", mem->node);
211 if (mem->validation_bits & CPER_MEM_VALID_CARD) 221 if (mem->validation_bits & CPER_MEM_VALID_CARD)
212 pr_debug("card: %d\n", mem->card); 222 n += scnprintf(msg + n, len - n, "card: %d ", mem->card);
213 if (mem->validation_bits & CPER_MEM_VALID_MODULE) 223 if (mem->validation_bits & CPER_MEM_VALID_MODULE)
214 pr_debug("module: %d\n", mem->module); 224 n += scnprintf(msg + n, len - n, "module: %d ", mem->module);
215 if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER) 225 if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER)
216 pr_debug("rank: %d\n", mem->rank); 226 n += scnprintf(msg + n, len - n, "rank: %d ", mem->rank);
217 if (mem->validation_bits & CPER_MEM_VALID_BANK) 227 if (mem->validation_bits & CPER_MEM_VALID_BANK)
218 pr_debug("bank: %d\n", mem->bank); 228 n += scnprintf(msg + n, len - n, "bank: %d ", mem->bank);
219 if (mem->validation_bits & CPER_MEM_VALID_DEVICE) 229 if (mem->validation_bits & CPER_MEM_VALID_DEVICE)
220 pr_debug("device: %d\n", mem->device); 230 n += scnprintf(msg + n, len - n, "device: %d ", mem->device);
221 if (mem->validation_bits & CPER_MEM_VALID_ROW) 231 if (mem->validation_bits & CPER_MEM_VALID_ROW)
222 pr_debug("row: %d\n", mem->row); 232 n += scnprintf(msg + n, len - n, "row: %d ", mem->row);
223 if (mem->validation_bits & CPER_MEM_VALID_COLUMN) 233 if (mem->validation_bits & CPER_MEM_VALID_COLUMN)
224 pr_debug("column: %d\n", mem->column); 234 n += scnprintf(msg + n, len - n, "column: %d ", mem->column);
225 if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION) 235 if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION)
226 pr_debug("bit_position: %d\n", mem->bit_pos); 236 n += scnprintf(msg + n, len - n, "bit_position: %d ",
237 mem->bit_pos);
227 if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID) 238 if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID)
228 pr_debug("requestor_id: 0x%016llx\n", mem->requestor_id); 239 n += scnprintf(msg + n, len - n, "requestor_id: 0x%016llx ",
240 mem->requestor_id);
229 if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID) 241 if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID)
230 pr_debug("responder_id: 0x%016llx\n", mem->responder_id); 242 n += scnprintf(msg + n, len - n, "responder_id: 0x%016llx ",
243 mem->responder_id);
231 if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID) 244 if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID)
232 pr_debug("target_id: 0x%016llx\n", mem->target_id); 245 scnprintf(msg + n, len - n, "target_id: 0x%016llx ",
246 mem->target_id);
247
248 msg[n] = '\0';
249 return n;
250}
251
252static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
253{
254 u32 len, n;
255 const char *bank = NULL, *device = NULL;
256
257 if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE))
258 return 0;
259
260 n = 0;
261 len = CPER_REC_LEN - 1;
262 dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
263 if (bank && device)
264 n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
265 else
266 n = snprintf(msg, len,
267 "DIMM location: not present. DMI handle: 0x%.4x ",
268 mem->mem_dev_handle);
269
270 msg[n] = '\0';
271 return n;
272}
273
274void cper_mem_err_pack(const struct cper_sec_mem_err *mem,
275 struct cper_mem_err_compact *cmem)
276{
277 cmem->validation_bits = mem->validation_bits;
278 cmem->node = mem->node;
279 cmem->card = mem->card;
280 cmem->module = mem->module;
281 cmem->bank = mem->bank;
282 cmem->device = mem->device;
283 cmem->row = mem->row;
284 cmem->column = mem->column;
285 cmem->bit_pos = mem->bit_pos;
286 cmem->requestor_id = mem->requestor_id;
287 cmem->responder_id = mem->responder_id;
288 cmem->target_id = mem->target_id;
289 cmem->rank = mem->rank;
290 cmem->mem_array_handle = mem->mem_array_handle;
291 cmem->mem_dev_handle = mem->mem_dev_handle;
292}
293
294const char *cper_mem_err_unpack(struct trace_seq *p,
295 struct cper_mem_err_compact *cmem)
296{
297 const char *ret = p->buffer + p->len;
298
299 if (cper_mem_err_location(cmem, rcd_decode_str))
300 trace_seq_printf(p, "%s", rcd_decode_str);
301 if (cper_dimm_err_location(cmem, rcd_decode_str))
302 trace_seq_printf(p, "%s", rcd_decode_str);
303 trace_seq_putc(p, '\0');
304
305 return ret;
306}
307
308static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem)
309{
310 struct cper_mem_err_compact cmem;
311
312 if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS)
313 printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status);
314 if (mem->validation_bits & CPER_MEM_VALID_PA)
315 printk("%s""physical_address: 0x%016llx\n",
316 pfx, mem->physical_addr);
317 if (mem->validation_bits & CPER_MEM_VALID_PA_MASK)
318 printk("%s""physical_address_mask: 0x%016llx\n",
319 pfx, mem->physical_addr_mask);
320 cper_mem_err_pack(mem, &cmem);
321 if (cper_mem_err_location(&cmem, rcd_decode_str))
322 printk("%s%s\n", pfx, rcd_decode_str);
233 if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) { 323 if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
234 u8 etype = mem->error_type; 324 u8 etype = mem->error_type;
235 printk("%s""error_type: %d, %s\n", pfx, etype, 325 printk("%s""error_type: %d, %s\n", pfx, etype,
236 etype < ARRAY_SIZE(cper_mem_err_type_strs) ? 326 cper_mem_err_type_str(etype));
237 cper_mem_err_type_strs[etype] : "unknown");
238 }
239 if (mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
240 const char *bank = NULL, *device = NULL;
241 dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
242 if (bank != NULL && device != NULL)
243 printk("%s""DIMM location: %s %s", pfx, bank, device);
244 else
245 printk("%s""DIMM DMI handle: 0x%.4x",
246 pfx, mem->mem_dev_handle);
247 } 327 }
328 if (cper_dimm_err_location(&cmem, rcd_decode_str))
329 printk("%s%s\n", pfx, rcd_decode_str);
248} 330}
249 331
250static const char *cper_pcie_port_type_strs[] = { 332static const char * const pcie_port_type_strs[] = {
251 "PCIe end point", 333 "PCIe end point",
252 "legacy PCI end point", 334 "legacy PCI end point",
253 "unknown", 335 "unknown",
@@ -266,8 +348,8 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
266{ 348{
267 if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) 349 if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
268 printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, 350 printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
269 pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ? 351 pcie->port_type < ARRAY_SIZE(pcie_port_type_strs) ?
270 cper_pcie_port_type_strs[pcie->port_type] : "unknown"); 352 pcie_port_type_strs[pcie->port_type] : "unknown");
271 if (pcie->validation_bits & CPER_PCIE_VALID_VERSION) 353 if (pcie->validation_bits & CPER_PCIE_VALID_VERSION)
272 printk("%s""version: %d.%d\n", pfx, 354 printk("%s""version: %d.%d\n", pfx,
273 pcie->version.major, pcie->version.minor); 355 pcie->version.major, pcie->version.minor);