blob: 502811344e81043a7be89f3d6195e85c20f59966 [file] [log] [blame]
Tyler Baicarc6d8c8e2018-01-02 18:10:41 +00001/*
2 * UEFI Common Platform Error Record (CPER) support
3 *
4 * Copyright (C) 2017, The Linux Foundation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/time.h>
23#include <linux/cper.h>
24#include <linux/dmi.h>
25#include <linux/acpi.h>
26#include <linux/pci.h>
27#include <linux/aer.h>
28#include <linux/printk.h>
29#include <linux/bcd.h>
30#include <acpi/ghes.h>
31#include <ras/ras_event.h>
32
Tyler Baicarc6d8c8e2018-01-02 18:10:41 +000033static const char * const arm_reg_ctx_strs[] = {
34 "AArch32 general purpose registers",
35 "AArch32 EL1 context registers",
36 "AArch32 EL2 context registers",
37 "AArch32 secure context registers",
38 "AArch64 general purpose registers",
39 "AArch64 EL1 context registers",
40 "AArch64 EL2 context registers",
41 "AArch64 EL3 context registers",
42 "Misc. system register structure",
43};
44
Tyler Baicar301f55b2018-01-02 18:10:42 +000045static const char * const arm_err_trans_type_strs[] = {
46 "Instruction",
47 "Data Access",
48 "Generic",
49};
50
51static const char * const arm_bus_err_op_strs[] = {
52 "Generic error (type cannot be determined)",
53 "Generic read (type of instruction or data request cannot be determined)",
54 "Generic write (type of instruction of data request cannot be determined)",
55 "Data read",
56 "Data write",
57 "Instruction fetch",
58 "Prefetch",
59};
60
61static const char * const arm_cache_err_op_strs[] = {
62 "Generic error (type cannot be determined)",
63 "Generic read (type of instruction or data request cannot be determined)",
64 "Generic write (type of instruction of data request cannot be determined)",
65 "Data read",
66 "Data write",
67 "Instruction fetch",
68 "Prefetch",
69 "Eviction",
70 "Snooping (processor initiated a cache snoop that resulted in an error)",
71 "Snooped (processor raised a cache error caused by another processor or device snooping its cache)",
72 "Management",
73};
74
75static const char * const arm_tlb_err_op_strs[] = {
76 "Generic error (type cannot be determined)",
77 "Generic read (type of instruction or data request cannot be determined)",
78 "Generic write (type of instruction of data request cannot be determined)",
79 "Data read",
80 "Data write",
81 "Instruction fetch",
82 "Prefetch",
83 "Local management operation (processor initiated a TLB management operation that resulted in an error)",
84 "External management operation (processor raised a TLB error caused by another processor or device broadcasting TLB operations)",
85};
86
87static const char * const arm_bus_err_part_type_strs[] = {
88 "Local processor originated request",
89 "Local processor responded to request",
90 "Local processor observed",
91 "Generic",
92};
93
94static const char * const arm_bus_err_addr_space_strs[] = {
95 "External Memory Access",
96 "Internal Memory Access",
97 "Unknown",
98 "Device Memory Access",
99};
100
101static void cper_print_arm_err_info(const char *pfx, u32 type,
102 u64 error_info)
103{
104 u8 trans_type, op_type, level, participation_type, address_space;
105 u16 mem_attributes;
106 bool proc_context_corrupt, corrected, precise_pc, restartable_pc;
107 bool time_out, access_mode;
108
109 /* If the type is unknown, bail. */
110 if (type > CPER_ARM_MAX_TYPE)
111 return;
112
113 /*
114 * Vendor type errors have error information values that are vendor
115 * specific.
116 */
117 if (type == CPER_ARM_VENDOR_ERROR)
118 return;
119
120 if (error_info & CPER_ARM_ERR_VALID_TRANSACTION_TYPE) {
121 trans_type = ((error_info >> CPER_ARM_ERR_TRANSACTION_SHIFT)
122 & CPER_ARM_ERR_TRANSACTION_MASK);
123 if (trans_type < ARRAY_SIZE(arm_err_trans_type_strs)) {
124 printk("%stransaction type: %s\n", pfx,
125 arm_err_trans_type_strs[trans_type]);
126 }
127 }
128
129 if (error_info & CPER_ARM_ERR_VALID_OPERATION_TYPE) {
130 op_type = ((error_info >> CPER_ARM_ERR_OPERATION_SHIFT)
131 & CPER_ARM_ERR_OPERATION_MASK);
132 switch (type) {
133 case CPER_ARM_CACHE_ERROR:
134 if (op_type < ARRAY_SIZE(arm_cache_err_op_strs)) {
135 printk("%soperation type: %s\n", pfx,
136 arm_cache_err_op_strs[op_type]);
137 }
138 break;
139 case CPER_ARM_TLB_ERROR:
140 if (op_type < ARRAY_SIZE(arm_tlb_err_op_strs)) {
141 printk("%soperation type: %s\n", pfx,
142 arm_tlb_err_op_strs[op_type]);
143 }
144 break;
145 case CPER_ARM_BUS_ERROR:
146 if (op_type < ARRAY_SIZE(arm_bus_err_op_strs)) {
147 printk("%soperation type: %s\n", pfx,
148 arm_bus_err_op_strs[op_type]);
149 }
150 break;
151 }
152 }
153
154 if (error_info & CPER_ARM_ERR_VALID_LEVEL) {
155 level = ((error_info >> CPER_ARM_ERR_LEVEL_SHIFT)
156 & CPER_ARM_ERR_LEVEL_MASK);
157 switch (type) {
158 case CPER_ARM_CACHE_ERROR:
159 printk("%scache level: %d\n", pfx, level);
160 break;
161 case CPER_ARM_TLB_ERROR:
162 printk("%sTLB level: %d\n", pfx, level);
163 break;
164 case CPER_ARM_BUS_ERROR:
165 printk("%saffinity level at which the bus error occurred: %d\n",
166 pfx, level);
167 break;
168 }
169 }
170
171 if (error_info & CPER_ARM_ERR_VALID_PROC_CONTEXT_CORRUPT) {
172 proc_context_corrupt = ((error_info >> CPER_ARM_ERR_PC_CORRUPT_SHIFT)
173 & CPER_ARM_ERR_PC_CORRUPT_MASK);
174 if (proc_context_corrupt)
175 printk("%sprocessor context corrupted\n", pfx);
176 else
177 printk("%sprocessor context not corrupted\n", pfx);
178 }
179
180 if (error_info & CPER_ARM_ERR_VALID_CORRECTED) {
181 corrected = ((error_info >> CPER_ARM_ERR_CORRECTED_SHIFT)
182 & CPER_ARM_ERR_CORRECTED_MASK);
183 if (corrected)
184 printk("%sthe error has been corrected\n", pfx);
185 else
186 printk("%sthe error has not been corrected\n", pfx);
187 }
188
189 if (error_info & CPER_ARM_ERR_VALID_PRECISE_PC) {
190 precise_pc = ((error_info >> CPER_ARM_ERR_PRECISE_PC_SHIFT)
191 & CPER_ARM_ERR_PRECISE_PC_MASK);
192 if (precise_pc)
193 printk("%sPC is precise\n", pfx);
194 else
195 printk("%sPC is imprecise\n", pfx);
196 }
197
198 if (error_info & CPER_ARM_ERR_VALID_RESTARTABLE_PC) {
199 restartable_pc = ((error_info >> CPER_ARM_ERR_RESTARTABLE_PC_SHIFT)
200 & CPER_ARM_ERR_RESTARTABLE_PC_MASK);
201 if (restartable_pc)
202 printk("%sProgram execution can be restarted reliably at the PC associated with the error.\n", pfx);
203 }
204
205 /* The rest of the fields are specific to bus errors */
206 if (type != CPER_ARM_BUS_ERROR)
207 return;
208
209 if (error_info & CPER_ARM_ERR_VALID_PARTICIPATION_TYPE) {
210 participation_type = ((error_info >> CPER_ARM_ERR_PARTICIPATION_TYPE_SHIFT)
211 & CPER_ARM_ERR_PARTICIPATION_TYPE_MASK);
212 if (participation_type < ARRAY_SIZE(arm_bus_err_part_type_strs)) {
213 printk("%sparticipation type: %s\n", pfx,
214 arm_bus_err_part_type_strs[participation_type]);
215 }
216 }
217
218 if (error_info & CPER_ARM_ERR_VALID_TIME_OUT) {
219 time_out = ((error_info >> CPER_ARM_ERR_TIME_OUT_SHIFT)
220 & CPER_ARM_ERR_TIME_OUT_MASK);
221 if (time_out)
222 printk("%srequest timed out\n", pfx);
223 }
224
225 if (error_info & CPER_ARM_ERR_VALID_ADDRESS_SPACE) {
226 address_space = ((error_info >> CPER_ARM_ERR_ADDRESS_SPACE_SHIFT)
227 & CPER_ARM_ERR_ADDRESS_SPACE_MASK);
228 if (address_space < ARRAY_SIZE(arm_bus_err_addr_space_strs)) {
229 printk("%saddress space: %s\n", pfx,
230 arm_bus_err_addr_space_strs[address_space]);
231 }
232 }
233
234 if (error_info & CPER_ARM_ERR_VALID_MEM_ATTRIBUTES) {
235 mem_attributes = ((error_info >> CPER_ARM_ERR_MEM_ATTRIBUTES_SHIFT)
236 & CPER_ARM_ERR_MEM_ATTRIBUTES_MASK);
237 printk("%smemory access attributes:0x%x\n", pfx, mem_attributes);
238 }
239
240 if (error_info & CPER_ARM_ERR_VALID_ACCESS_MODE) {
241 access_mode = ((error_info >> CPER_ARM_ERR_ACCESS_MODE_SHIFT)
242 & CPER_ARM_ERR_ACCESS_MODE_MASK);
243 if (access_mode)
244 printk("%saccess mode: normal\n", pfx);
245 else
246 printk("%saccess mode: secure\n", pfx);
247 }
248}
249
Tyler Baicarc6d8c8e2018-01-02 18:10:41 +0000250void cper_print_proc_arm(const char *pfx,
251 const struct cper_sec_proc_arm *proc)
252{
253 int i, len, max_ctx_type;
254 struct cper_arm_err_info *err_info;
255 struct cper_arm_ctx_info *ctx_info;
Tyler Baicar301f55b2018-01-02 18:10:42 +0000256 char newpfx[64], infopfx[64];
Tyler Baicarc6d8c8e2018-01-02 18:10:41 +0000257
258 printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
259
260 len = proc->section_length - (sizeof(*proc) +
261 proc->err_info_num * (sizeof(*err_info)));
262 if (len < 0) {
263 printk("%ssection length: %d\n", pfx, proc->section_length);
264 printk("%ssection length is too small\n", pfx);
265 printk("%sfirmware-generated error record is incorrect\n", pfx);
266 printk("%sERR_INFO_NUM is %d\n", pfx, proc->err_info_num);
267 return;
268 }
269
270 if (proc->validation_bits & CPER_ARM_VALID_MPIDR)
271 printk("%sMultiprocessor Affinity Register (MPIDR): 0x%016llx\n",
272 pfx, proc->mpidr);
273
274 if (proc->validation_bits & CPER_ARM_VALID_AFFINITY_LEVEL)
275 printk("%serror affinity level: %d\n", pfx,
276 proc->affinity_level);
277
278 if (proc->validation_bits & CPER_ARM_VALID_RUNNING_STATE) {
279 printk("%srunning state: 0x%x\n", pfx, proc->running_state);
280 printk("%sPower State Coordination Interface state: %d\n",
281 pfx, proc->psci_state);
282 }
283
Borislav Petkov75e4fd32018-05-04 07:59:48 +0200284 snprintf(newpfx, sizeof(newpfx), "%s ", pfx);
Tyler Baicarc6d8c8e2018-01-02 18:10:41 +0000285
286 err_info = (struct cper_arm_err_info *)(proc + 1);
287 for (i = 0; i < proc->err_info_num; i++) {
288 printk("%sError info structure %d:\n", pfx, i);
289
290 printk("%snum errors: %d\n", pfx, err_info->multiple_error + 1);
291
292 if (err_info->validation_bits & CPER_ARM_INFO_VALID_FLAGS) {
293 if (err_info->flags & CPER_ARM_INFO_FLAGS_FIRST)
294 printk("%sfirst error captured\n", newpfx);
295 if (err_info->flags & CPER_ARM_INFO_FLAGS_LAST)
296 printk("%slast error captured\n", newpfx);
297 if (err_info->flags & CPER_ARM_INFO_FLAGS_PROPAGATED)
298 printk("%spropagated error captured\n",
299 newpfx);
300 if (err_info->flags & CPER_ARM_INFO_FLAGS_OVERFLOW)
301 printk("%soverflow occurred, error info is incomplete\n",
302 newpfx);
303 }
304
305 printk("%serror_type: %d, %s\n", newpfx, err_info->type,
306 err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ?
307 cper_proc_error_type_strs[err_info->type] : "unknown");
Tyler Baicar301f55b2018-01-02 18:10:42 +0000308 if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) {
Tyler Baicarc6d8c8e2018-01-02 18:10:41 +0000309 printk("%serror_info: 0x%016llx\n", newpfx,
310 err_info->error_info);
Borislav Petkov75e4fd32018-05-04 07:59:48 +0200311 snprintf(infopfx, sizeof(infopfx), "%s ", newpfx);
Tyler Baicar301f55b2018-01-02 18:10:42 +0000312 cper_print_arm_err_info(infopfx, err_info->type,
313 err_info->error_info);
314 }
Tyler Baicarc6d8c8e2018-01-02 18:10:41 +0000315 if (err_info->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
316 printk("%svirtual fault address: 0x%016llx\n",
317 newpfx, err_info->virt_fault_addr);
318 if (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR)
319 printk("%sphysical fault address: 0x%016llx\n",
320 newpfx, err_info->physical_fault_addr);
321 err_info += 1;
322 }
323
324 ctx_info = (struct cper_arm_ctx_info *)err_info;
325 max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
326 for (i = 0; i < proc->context_info_num; i++) {
327 int size = sizeof(*ctx_info) + ctx_info->size;
328
329 printk("%sContext info structure %d:\n", pfx, i);
330 if (len < size) {
331 printk("%ssection length is too small\n", newpfx);
332 printk("%sfirmware-generated error record is incorrect\n", pfx);
333 return;
334 }
335 if (ctx_info->type > max_ctx_type) {
336 printk("%sInvalid context type: %d (max: %d)\n",
337 newpfx, ctx_info->type, max_ctx_type);
338 return;
339 }
340 printk("%sregister context type: %s\n", newpfx,
341 arm_reg_ctx_strs[ctx_info->type]);
342 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
343 (ctx_info + 1), ctx_info->size, 0);
344 len -= size;
345 ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + size);
346 }
347
348 if (len > 0) {
349 printk("%sVendor specific error info has %u bytes:\n", pfx,
350 len);
351 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, ctx_info,
352 len, true);
353 }
354}