]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/firmware/efi/cper-arm.c
efi: Parse ARM error information value
[mirror_ubuntu-bionic-kernel.git] / drivers / firmware / efi / cper-arm.c
1 /*
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
33 #define INDENT_SP " "
34
35 static const char * const arm_reg_ctx_strs[] = {
36 "AArch32 general purpose registers",
37 "AArch32 EL1 context registers",
38 "AArch32 EL2 context registers",
39 "AArch32 secure context registers",
40 "AArch64 general purpose registers",
41 "AArch64 EL1 context registers",
42 "AArch64 EL2 context registers",
43 "AArch64 EL3 context registers",
44 "Misc. system register structure",
45 };
46
47 static const char * const arm_err_trans_type_strs[] = {
48 "Instruction",
49 "Data Access",
50 "Generic",
51 };
52
53 static const char * const arm_bus_err_op_strs[] = {
54 "Generic error (type cannot be determined)",
55 "Generic read (type of instruction or data request cannot be determined)",
56 "Generic write (type of instruction of data request cannot be determined)",
57 "Data read",
58 "Data write",
59 "Instruction fetch",
60 "Prefetch",
61 };
62
63 static const char * const arm_cache_err_op_strs[] = {
64 "Generic error (type cannot be determined)",
65 "Generic read (type of instruction or data request cannot be determined)",
66 "Generic write (type of instruction of data request cannot be determined)",
67 "Data read",
68 "Data write",
69 "Instruction fetch",
70 "Prefetch",
71 "Eviction",
72 "Snooping (processor initiated a cache snoop that resulted in an error)",
73 "Snooped (processor raised a cache error caused by another processor or device snooping its cache)",
74 "Management",
75 };
76
77 static const char * const arm_tlb_err_op_strs[] = {
78 "Generic error (type cannot be determined)",
79 "Generic read (type of instruction or data request cannot be determined)",
80 "Generic write (type of instruction of data request cannot be determined)",
81 "Data read",
82 "Data write",
83 "Instruction fetch",
84 "Prefetch",
85 "Local management operation (processor initiated a TLB management operation that resulted in an error)",
86 "External management operation (processor raised a TLB error caused by another processor or device broadcasting TLB operations)",
87 };
88
89 static const char * const arm_bus_err_part_type_strs[] = {
90 "Local processor originated request",
91 "Local processor responded to request",
92 "Local processor observed",
93 "Generic",
94 };
95
96 static const char * const arm_bus_err_addr_space_strs[] = {
97 "External Memory Access",
98 "Internal Memory Access",
99 "Unknown",
100 "Device Memory Access",
101 };
102
103 static void cper_print_arm_err_info(const char *pfx, u32 type,
104 u64 error_info)
105 {
106 u8 trans_type, op_type, level, participation_type, address_space;
107 u16 mem_attributes;
108 bool proc_context_corrupt, corrected, precise_pc, restartable_pc;
109 bool time_out, access_mode;
110
111 /* If the type is unknown, bail. */
112 if (type > CPER_ARM_MAX_TYPE)
113 return;
114
115 /*
116 * Vendor type errors have error information values that are vendor
117 * specific.
118 */
119 if (type == CPER_ARM_VENDOR_ERROR)
120 return;
121
122 if (error_info & CPER_ARM_ERR_VALID_TRANSACTION_TYPE) {
123 trans_type = ((error_info >> CPER_ARM_ERR_TRANSACTION_SHIFT)
124 & CPER_ARM_ERR_TRANSACTION_MASK);
125 if (trans_type < ARRAY_SIZE(arm_err_trans_type_strs)) {
126 printk("%stransaction type: %s\n", pfx,
127 arm_err_trans_type_strs[trans_type]);
128 }
129 }
130
131 if (error_info & CPER_ARM_ERR_VALID_OPERATION_TYPE) {
132 op_type = ((error_info >> CPER_ARM_ERR_OPERATION_SHIFT)
133 & CPER_ARM_ERR_OPERATION_MASK);
134 switch (type) {
135 case CPER_ARM_CACHE_ERROR:
136 if (op_type < ARRAY_SIZE(arm_cache_err_op_strs)) {
137 printk("%soperation type: %s\n", pfx,
138 arm_cache_err_op_strs[op_type]);
139 }
140 break;
141 case CPER_ARM_TLB_ERROR:
142 if (op_type < ARRAY_SIZE(arm_tlb_err_op_strs)) {
143 printk("%soperation type: %s\n", pfx,
144 arm_tlb_err_op_strs[op_type]);
145 }
146 break;
147 case CPER_ARM_BUS_ERROR:
148 if (op_type < ARRAY_SIZE(arm_bus_err_op_strs)) {
149 printk("%soperation type: %s\n", pfx,
150 arm_bus_err_op_strs[op_type]);
151 }
152 break;
153 }
154 }
155
156 if (error_info & CPER_ARM_ERR_VALID_LEVEL) {
157 level = ((error_info >> CPER_ARM_ERR_LEVEL_SHIFT)
158 & CPER_ARM_ERR_LEVEL_MASK);
159 switch (type) {
160 case CPER_ARM_CACHE_ERROR:
161 printk("%scache level: %d\n", pfx, level);
162 break;
163 case CPER_ARM_TLB_ERROR:
164 printk("%sTLB level: %d\n", pfx, level);
165 break;
166 case CPER_ARM_BUS_ERROR:
167 printk("%saffinity level at which the bus error occurred: %d\n",
168 pfx, level);
169 break;
170 }
171 }
172
173 if (error_info & CPER_ARM_ERR_VALID_PROC_CONTEXT_CORRUPT) {
174 proc_context_corrupt = ((error_info >> CPER_ARM_ERR_PC_CORRUPT_SHIFT)
175 & CPER_ARM_ERR_PC_CORRUPT_MASK);
176 if (proc_context_corrupt)
177 printk("%sprocessor context corrupted\n", pfx);
178 else
179 printk("%sprocessor context not corrupted\n", pfx);
180 }
181
182 if (error_info & CPER_ARM_ERR_VALID_CORRECTED) {
183 corrected = ((error_info >> CPER_ARM_ERR_CORRECTED_SHIFT)
184 & CPER_ARM_ERR_CORRECTED_MASK);
185 if (corrected)
186 printk("%sthe error has been corrected\n", pfx);
187 else
188 printk("%sthe error has not been corrected\n", pfx);
189 }
190
191 if (error_info & CPER_ARM_ERR_VALID_PRECISE_PC) {
192 precise_pc = ((error_info >> CPER_ARM_ERR_PRECISE_PC_SHIFT)
193 & CPER_ARM_ERR_PRECISE_PC_MASK);
194 if (precise_pc)
195 printk("%sPC is precise\n", pfx);
196 else
197 printk("%sPC is imprecise\n", pfx);
198 }
199
200 if (error_info & CPER_ARM_ERR_VALID_RESTARTABLE_PC) {
201 restartable_pc = ((error_info >> CPER_ARM_ERR_RESTARTABLE_PC_SHIFT)
202 & CPER_ARM_ERR_RESTARTABLE_PC_MASK);
203 if (restartable_pc)
204 printk("%sProgram execution can be restarted reliably at the PC associated with the error.\n", pfx);
205 }
206
207 /* The rest of the fields are specific to bus errors */
208 if (type != CPER_ARM_BUS_ERROR)
209 return;
210
211 if (error_info & CPER_ARM_ERR_VALID_PARTICIPATION_TYPE) {
212 participation_type = ((error_info >> CPER_ARM_ERR_PARTICIPATION_TYPE_SHIFT)
213 & CPER_ARM_ERR_PARTICIPATION_TYPE_MASK);
214 if (participation_type < ARRAY_SIZE(arm_bus_err_part_type_strs)) {
215 printk("%sparticipation type: %s\n", pfx,
216 arm_bus_err_part_type_strs[participation_type]);
217 }
218 }
219
220 if (error_info & CPER_ARM_ERR_VALID_TIME_OUT) {
221 time_out = ((error_info >> CPER_ARM_ERR_TIME_OUT_SHIFT)
222 & CPER_ARM_ERR_TIME_OUT_MASK);
223 if (time_out)
224 printk("%srequest timed out\n", pfx);
225 }
226
227 if (error_info & CPER_ARM_ERR_VALID_ADDRESS_SPACE) {
228 address_space = ((error_info >> CPER_ARM_ERR_ADDRESS_SPACE_SHIFT)
229 & CPER_ARM_ERR_ADDRESS_SPACE_MASK);
230 if (address_space < ARRAY_SIZE(arm_bus_err_addr_space_strs)) {
231 printk("%saddress space: %s\n", pfx,
232 arm_bus_err_addr_space_strs[address_space]);
233 }
234 }
235
236 if (error_info & CPER_ARM_ERR_VALID_MEM_ATTRIBUTES) {
237 mem_attributes = ((error_info >> CPER_ARM_ERR_MEM_ATTRIBUTES_SHIFT)
238 & CPER_ARM_ERR_MEM_ATTRIBUTES_MASK);
239 printk("%smemory access attributes:0x%x\n", pfx, mem_attributes);
240 }
241
242 if (error_info & CPER_ARM_ERR_VALID_ACCESS_MODE) {
243 access_mode = ((error_info >> CPER_ARM_ERR_ACCESS_MODE_SHIFT)
244 & CPER_ARM_ERR_ACCESS_MODE_MASK);
245 if (access_mode)
246 printk("%saccess mode: normal\n", pfx);
247 else
248 printk("%saccess mode: secure\n", pfx);
249 }
250 }
251
252 void cper_print_proc_arm(const char *pfx,
253 const struct cper_sec_proc_arm *proc)
254 {
255 int i, len, max_ctx_type;
256 struct cper_arm_err_info *err_info;
257 struct cper_arm_ctx_info *ctx_info;
258 char newpfx[64], infopfx[64];
259
260 printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
261
262 len = proc->section_length - (sizeof(*proc) +
263 proc->err_info_num * (sizeof(*err_info)));
264 if (len < 0) {
265 printk("%ssection length: %d\n", pfx, proc->section_length);
266 printk("%ssection length is too small\n", pfx);
267 printk("%sfirmware-generated error record is incorrect\n", pfx);
268 printk("%sERR_INFO_NUM is %d\n", pfx, proc->err_info_num);
269 return;
270 }
271
272 if (proc->validation_bits & CPER_ARM_VALID_MPIDR)
273 printk("%sMultiprocessor Affinity Register (MPIDR): 0x%016llx\n",
274 pfx, proc->mpidr);
275
276 if (proc->validation_bits & CPER_ARM_VALID_AFFINITY_LEVEL)
277 printk("%serror affinity level: %d\n", pfx,
278 proc->affinity_level);
279
280 if (proc->validation_bits & CPER_ARM_VALID_RUNNING_STATE) {
281 printk("%srunning state: 0x%x\n", pfx, proc->running_state);
282 printk("%sPower State Coordination Interface state: %d\n",
283 pfx, proc->psci_state);
284 }
285
286 snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
287
288 err_info = (struct cper_arm_err_info *)(proc + 1);
289 for (i = 0; i < proc->err_info_num; i++) {
290 printk("%sError info structure %d:\n", pfx, i);
291
292 printk("%snum errors: %d\n", pfx, err_info->multiple_error + 1);
293
294 if (err_info->validation_bits & CPER_ARM_INFO_VALID_FLAGS) {
295 if (err_info->flags & CPER_ARM_INFO_FLAGS_FIRST)
296 printk("%sfirst error captured\n", newpfx);
297 if (err_info->flags & CPER_ARM_INFO_FLAGS_LAST)
298 printk("%slast error captured\n", newpfx);
299 if (err_info->flags & CPER_ARM_INFO_FLAGS_PROPAGATED)
300 printk("%spropagated error captured\n",
301 newpfx);
302 if (err_info->flags & CPER_ARM_INFO_FLAGS_OVERFLOW)
303 printk("%soverflow occurred, error info is incomplete\n",
304 newpfx);
305 }
306
307 printk("%serror_type: %d, %s\n", newpfx, err_info->type,
308 err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ?
309 cper_proc_error_type_strs[err_info->type] : "unknown");
310 if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) {
311 printk("%serror_info: 0x%016llx\n", newpfx,
312 err_info->error_info);
313 snprintf(infopfx, sizeof(infopfx), "%s%s", newpfx, INDENT_SP);
314 cper_print_arm_err_info(infopfx, err_info->type,
315 err_info->error_info);
316 }
317 if (err_info->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
318 printk("%svirtual fault address: 0x%016llx\n",
319 newpfx, err_info->virt_fault_addr);
320 if (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR)
321 printk("%sphysical fault address: 0x%016llx\n",
322 newpfx, err_info->physical_fault_addr);
323 err_info += 1;
324 }
325
326 ctx_info = (struct cper_arm_ctx_info *)err_info;
327 max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
328 for (i = 0; i < proc->context_info_num; i++) {
329 int size = sizeof(*ctx_info) + ctx_info->size;
330
331 printk("%sContext info structure %d:\n", pfx, i);
332 if (len < size) {
333 printk("%ssection length is too small\n", newpfx);
334 printk("%sfirmware-generated error record is incorrect\n", pfx);
335 return;
336 }
337 if (ctx_info->type > max_ctx_type) {
338 printk("%sInvalid context type: %d (max: %d)\n",
339 newpfx, ctx_info->type, max_ctx_type);
340 return;
341 }
342 printk("%sregister context type: %s\n", newpfx,
343 arm_reg_ctx_strs[ctx_info->type]);
344 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
345 (ctx_info + 1), ctx_info->size, 0);
346 len -= size;
347 ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + size);
348 }
349
350 if (len > 0) {
351 printk("%sVendor specific error info has %u bytes:\n", pfx,
352 len);
353 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, ctx_info,
354 len, true);
355 }
356 }