xref: /linux/drivers/firmware/efi/cper-arm.c (revision bd628c1bed7902ec1f24ba0fe70758949146abbe)
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 static 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 
45 static const char * const arm_err_trans_type_strs[] = {
46 	"Instruction",
47 	"Data Access",
48 	"Generic",
49 };
50 
51 static 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 
61 static 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 
75 static 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 
87 static 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 
94 static 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 
101 static 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 
250 void 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;
256 	char newpfx[64], infopfx[64];
257 
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 
284 	snprintf(newpfx, sizeof(newpfx), "%s ", pfx);
285 
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");
308 		if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) {
309 			printk("%serror_info: 0x%016llx\n", newpfx,
310 			       err_info->error_info);
311 			snprintf(infopfx, sizeof(infopfx), "%s ", newpfx);
312 			cper_print_arm_err_info(infopfx, err_info->type,
313 						err_info->error_info);
314 		}
315 		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 }
355