xref: /linux/drivers/firmware/efi/cper-arm.c (revision 9a379e77033f02c4a071891afdf0f0a01eff8ccb)
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 }
357