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