xref: /linux/drivers/firmware/efi/cper-arm.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1*4febfb8dSArd Biesheuvel // SPDX-License-Identifier: GPL-2.0
2c6d8c8efSTyler Baicar /*
3c6d8c8efSTyler Baicar  * UEFI Common Platform Error Record (CPER) support
4c6d8c8efSTyler Baicar  *
5c6d8c8efSTyler Baicar  * Copyright (C) 2017, The Linux Foundation. All rights reserved.
6c6d8c8efSTyler Baicar  */
7c6d8c8efSTyler Baicar 
8c6d8c8efSTyler Baicar #include <linux/kernel.h>
9c6d8c8efSTyler Baicar #include <linux/module.h>
10c6d8c8efSTyler Baicar #include <linux/time.h>
11c6d8c8efSTyler Baicar #include <linux/cper.h>
12c6d8c8efSTyler Baicar #include <linux/dmi.h>
13c6d8c8efSTyler Baicar #include <linux/acpi.h>
14c6d8c8efSTyler Baicar #include <linux/pci.h>
15c6d8c8efSTyler Baicar #include <linux/printk.h>
16c6d8c8efSTyler Baicar #include <linux/bcd.h>
17c6d8c8efSTyler Baicar #include <acpi/ghes.h>
18c6d8c8efSTyler Baicar #include <ras/ras_event.h>
19c6d8c8efSTyler Baicar 
20c6d8c8efSTyler Baicar static const char * const arm_reg_ctx_strs[] = {
21c6d8c8efSTyler Baicar 	"AArch32 general purpose registers",
22c6d8c8efSTyler Baicar 	"AArch32 EL1 context registers",
23c6d8c8efSTyler Baicar 	"AArch32 EL2 context registers",
24c6d8c8efSTyler Baicar 	"AArch32 secure context registers",
25c6d8c8efSTyler Baicar 	"AArch64 general purpose registers",
26c6d8c8efSTyler Baicar 	"AArch64 EL1 context registers",
27c6d8c8efSTyler Baicar 	"AArch64 EL2 context registers",
28c6d8c8efSTyler Baicar 	"AArch64 EL3 context registers",
29c6d8c8efSTyler Baicar 	"Misc. system register structure",
30c6d8c8efSTyler Baicar };
31c6d8c8efSTyler Baicar 
32301f55b1STyler Baicar static const char * const arm_err_trans_type_strs[] = {
33301f55b1STyler Baicar 	"Instruction",
34301f55b1STyler Baicar 	"Data Access",
35301f55b1STyler Baicar 	"Generic",
36301f55b1STyler Baicar };
37301f55b1STyler Baicar 
38301f55b1STyler Baicar static const char * const arm_bus_err_op_strs[] = {
39301f55b1STyler Baicar 	"Generic error (type cannot be determined)",
40301f55b1STyler Baicar 	"Generic read (type of instruction or data request cannot be determined)",
41301f55b1STyler Baicar 	"Generic write (type of instruction of data request cannot be determined)",
42301f55b1STyler Baicar 	"Data read",
43301f55b1STyler Baicar 	"Data write",
44301f55b1STyler Baicar 	"Instruction fetch",
45301f55b1STyler Baicar 	"Prefetch",
46301f55b1STyler Baicar };
47301f55b1STyler Baicar 
48301f55b1STyler Baicar static const char * const arm_cache_err_op_strs[] = {
49301f55b1STyler Baicar 	"Generic error (type cannot be determined)",
50301f55b1STyler Baicar 	"Generic read (type of instruction or data request cannot be determined)",
51301f55b1STyler Baicar 	"Generic write (type of instruction of data request cannot be determined)",
52301f55b1STyler Baicar 	"Data read",
53301f55b1STyler Baicar 	"Data write",
54301f55b1STyler Baicar 	"Instruction fetch",
55301f55b1STyler Baicar 	"Prefetch",
56301f55b1STyler Baicar 	"Eviction",
57301f55b1STyler Baicar 	"Snooping (processor initiated a cache snoop that resulted in an error)",
58301f55b1STyler Baicar 	"Snooped (processor raised a cache error caused by another processor or device snooping its cache)",
59301f55b1STyler Baicar 	"Management",
60301f55b1STyler Baicar };
61301f55b1STyler Baicar 
62301f55b1STyler Baicar static const char * const arm_tlb_err_op_strs[] = {
63301f55b1STyler Baicar 	"Generic error (type cannot be determined)",
64301f55b1STyler Baicar 	"Generic read (type of instruction or data request cannot be determined)",
65301f55b1STyler Baicar 	"Generic write (type of instruction of data request cannot be determined)",
66301f55b1STyler Baicar 	"Data read",
67301f55b1STyler Baicar 	"Data write",
68301f55b1STyler Baicar 	"Instruction fetch",
69301f55b1STyler Baicar 	"Prefetch",
70301f55b1STyler Baicar 	"Local management operation (processor initiated a TLB management operation that resulted in an error)",
71301f55b1STyler Baicar 	"External management operation (processor raised a TLB error caused by another processor or device broadcasting TLB operations)",
72301f55b1STyler Baicar };
73301f55b1STyler Baicar 
74301f55b1STyler Baicar static const char * const arm_bus_err_part_type_strs[] = {
75301f55b1STyler Baicar 	"Local processor originated request",
76301f55b1STyler Baicar 	"Local processor responded to request",
77301f55b1STyler Baicar 	"Local processor observed",
78301f55b1STyler Baicar 	"Generic",
79301f55b1STyler Baicar };
80301f55b1STyler Baicar 
81301f55b1STyler Baicar static const char * const arm_bus_err_addr_space_strs[] = {
82301f55b1STyler Baicar 	"External Memory Access",
83301f55b1STyler Baicar 	"Internal Memory Access",
84301f55b1STyler Baicar 	"Unknown",
85301f55b1STyler Baicar 	"Device Memory Access",
86301f55b1STyler Baicar };
87301f55b1STyler Baicar 
cper_print_arm_err_info(const char * pfx,u32 type,u64 error_info)88301f55b1STyler Baicar static void cper_print_arm_err_info(const char *pfx, u32 type,
89301f55b1STyler Baicar 				    u64 error_info)
90301f55b1STyler Baicar {
91301f55b1STyler Baicar 	u8 trans_type, op_type, level, participation_type, address_space;
92301f55b1STyler Baicar 	u16 mem_attributes;
93301f55b1STyler Baicar 	bool proc_context_corrupt, corrected, precise_pc, restartable_pc;
94301f55b1STyler Baicar 	bool time_out, access_mode;
95301f55b1STyler Baicar 
96301f55b1STyler Baicar 	/* If the type is unknown, bail. */
97301f55b1STyler Baicar 	if (type > CPER_ARM_MAX_TYPE)
98301f55b1STyler Baicar 		return;
99301f55b1STyler Baicar 
100301f55b1STyler Baicar 	/*
101301f55b1STyler Baicar 	 * Vendor type errors have error information values that are vendor
102301f55b1STyler Baicar 	 * specific.
103301f55b1STyler Baicar 	 */
104301f55b1STyler Baicar 	if (type == CPER_ARM_VENDOR_ERROR)
105301f55b1STyler Baicar 		return;
106301f55b1STyler Baicar 
107301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_TRANSACTION_TYPE) {
108301f55b1STyler Baicar 		trans_type = ((error_info >> CPER_ARM_ERR_TRANSACTION_SHIFT)
109301f55b1STyler Baicar 			      & CPER_ARM_ERR_TRANSACTION_MASK);
110301f55b1STyler Baicar 		if (trans_type < ARRAY_SIZE(arm_err_trans_type_strs)) {
111301f55b1STyler Baicar 			printk("%stransaction type: %s\n", pfx,
112301f55b1STyler Baicar 			       arm_err_trans_type_strs[trans_type]);
113301f55b1STyler Baicar 		}
114301f55b1STyler Baicar 	}
115301f55b1STyler Baicar 
116301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_OPERATION_TYPE) {
117301f55b1STyler Baicar 		op_type = ((error_info >> CPER_ARM_ERR_OPERATION_SHIFT)
118301f55b1STyler Baicar 			   & CPER_ARM_ERR_OPERATION_MASK);
119301f55b1STyler Baicar 		switch (type) {
120301f55b1STyler Baicar 		case CPER_ARM_CACHE_ERROR:
121301f55b1STyler Baicar 			if (op_type < ARRAY_SIZE(arm_cache_err_op_strs)) {
122301f55b1STyler Baicar 				printk("%soperation type: %s\n", pfx,
123301f55b1STyler Baicar 				       arm_cache_err_op_strs[op_type]);
124301f55b1STyler Baicar 			}
125301f55b1STyler Baicar 			break;
126301f55b1STyler Baicar 		case CPER_ARM_TLB_ERROR:
127301f55b1STyler Baicar 			if (op_type < ARRAY_SIZE(arm_tlb_err_op_strs)) {
128301f55b1STyler Baicar 				printk("%soperation type: %s\n", pfx,
129301f55b1STyler Baicar 				       arm_tlb_err_op_strs[op_type]);
130301f55b1STyler Baicar 			}
131301f55b1STyler Baicar 			break;
132301f55b1STyler Baicar 		case CPER_ARM_BUS_ERROR:
133301f55b1STyler Baicar 			if (op_type < ARRAY_SIZE(arm_bus_err_op_strs)) {
134301f55b1STyler Baicar 				printk("%soperation type: %s\n", pfx,
135301f55b1STyler Baicar 				       arm_bus_err_op_strs[op_type]);
136301f55b1STyler Baicar 			}
137301f55b1STyler Baicar 			break;
138301f55b1STyler Baicar 		}
139301f55b1STyler Baicar 	}
140301f55b1STyler Baicar 
141301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_LEVEL) {
142301f55b1STyler Baicar 		level = ((error_info >> CPER_ARM_ERR_LEVEL_SHIFT)
143301f55b1STyler Baicar 			 & CPER_ARM_ERR_LEVEL_MASK);
144301f55b1STyler Baicar 		switch (type) {
145301f55b1STyler Baicar 		case CPER_ARM_CACHE_ERROR:
146301f55b1STyler Baicar 			printk("%scache level: %d\n", pfx, level);
147301f55b1STyler Baicar 			break;
148301f55b1STyler Baicar 		case CPER_ARM_TLB_ERROR:
149301f55b1STyler Baicar 			printk("%sTLB level: %d\n", pfx, level);
150301f55b1STyler Baicar 			break;
151301f55b1STyler Baicar 		case CPER_ARM_BUS_ERROR:
152301f55b1STyler Baicar 			printk("%saffinity level at which the bus error occurred: %d\n",
153301f55b1STyler Baicar 			       pfx, level);
154301f55b1STyler Baicar 			break;
155301f55b1STyler Baicar 		}
156301f55b1STyler Baicar 	}
157301f55b1STyler Baicar 
158301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_PROC_CONTEXT_CORRUPT) {
159301f55b1STyler Baicar 		proc_context_corrupt = ((error_info >> CPER_ARM_ERR_PC_CORRUPT_SHIFT)
160301f55b1STyler Baicar 					& CPER_ARM_ERR_PC_CORRUPT_MASK);
161301f55b1STyler Baicar 		if (proc_context_corrupt)
162301f55b1STyler Baicar 			printk("%sprocessor context corrupted\n", pfx);
163301f55b1STyler Baicar 		else
164301f55b1STyler Baicar 			printk("%sprocessor context not corrupted\n", pfx);
165301f55b1STyler Baicar 	}
166301f55b1STyler Baicar 
167301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_CORRECTED) {
168301f55b1STyler Baicar 		corrected = ((error_info >> CPER_ARM_ERR_CORRECTED_SHIFT)
169301f55b1STyler Baicar 			     & CPER_ARM_ERR_CORRECTED_MASK);
170301f55b1STyler Baicar 		if (corrected)
171301f55b1STyler Baicar 			printk("%sthe error has been corrected\n", pfx);
172301f55b1STyler Baicar 		else
173301f55b1STyler Baicar 			printk("%sthe error has not been corrected\n", pfx);
174301f55b1STyler Baicar 	}
175301f55b1STyler Baicar 
176301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_PRECISE_PC) {
177301f55b1STyler Baicar 		precise_pc = ((error_info >> CPER_ARM_ERR_PRECISE_PC_SHIFT)
178301f55b1STyler Baicar 			      & CPER_ARM_ERR_PRECISE_PC_MASK);
179301f55b1STyler Baicar 		if (precise_pc)
180301f55b1STyler Baicar 			printk("%sPC is precise\n", pfx);
181301f55b1STyler Baicar 		else
182301f55b1STyler Baicar 			printk("%sPC is imprecise\n", pfx);
183301f55b1STyler Baicar 	}
184301f55b1STyler Baicar 
185301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_RESTARTABLE_PC) {
186301f55b1STyler Baicar 		restartable_pc = ((error_info >> CPER_ARM_ERR_RESTARTABLE_PC_SHIFT)
187301f55b1STyler Baicar 				  & CPER_ARM_ERR_RESTARTABLE_PC_MASK);
188301f55b1STyler Baicar 		if (restartable_pc)
189301f55b1STyler Baicar 			printk("%sProgram execution can be restarted reliably at the PC associated with the error.\n", pfx);
190301f55b1STyler Baicar 	}
191301f55b1STyler Baicar 
192301f55b1STyler Baicar 	/* The rest of the fields are specific to bus errors */
193301f55b1STyler Baicar 	if (type != CPER_ARM_BUS_ERROR)
194301f55b1STyler Baicar 		return;
195301f55b1STyler Baicar 
196301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_PARTICIPATION_TYPE) {
197301f55b1STyler Baicar 		participation_type = ((error_info >> CPER_ARM_ERR_PARTICIPATION_TYPE_SHIFT)
198301f55b1STyler Baicar 				      & CPER_ARM_ERR_PARTICIPATION_TYPE_MASK);
199301f55b1STyler Baicar 		if (participation_type < ARRAY_SIZE(arm_bus_err_part_type_strs)) {
200301f55b1STyler Baicar 			printk("%sparticipation type: %s\n", pfx,
201301f55b1STyler Baicar 			       arm_bus_err_part_type_strs[participation_type]);
202301f55b1STyler Baicar 		}
203301f55b1STyler Baicar 	}
204301f55b1STyler Baicar 
205301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_TIME_OUT) {
206301f55b1STyler Baicar 		time_out = ((error_info >> CPER_ARM_ERR_TIME_OUT_SHIFT)
207301f55b1STyler Baicar 			    & CPER_ARM_ERR_TIME_OUT_MASK);
208301f55b1STyler Baicar 		if (time_out)
209301f55b1STyler Baicar 			printk("%srequest timed out\n", pfx);
210301f55b1STyler Baicar 	}
211301f55b1STyler Baicar 
212301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_ADDRESS_SPACE) {
213301f55b1STyler Baicar 		address_space = ((error_info >> CPER_ARM_ERR_ADDRESS_SPACE_SHIFT)
214301f55b1STyler Baicar 				 & CPER_ARM_ERR_ADDRESS_SPACE_MASK);
215301f55b1STyler Baicar 		if (address_space < ARRAY_SIZE(arm_bus_err_addr_space_strs)) {
216301f55b1STyler Baicar 			printk("%saddress space: %s\n", pfx,
217301f55b1STyler Baicar 			       arm_bus_err_addr_space_strs[address_space]);
218301f55b1STyler Baicar 		}
219301f55b1STyler Baicar 	}
220301f55b1STyler Baicar 
221301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_MEM_ATTRIBUTES) {
222301f55b1STyler Baicar 		mem_attributes = ((error_info >> CPER_ARM_ERR_MEM_ATTRIBUTES_SHIFT)
223301f55b1STyler Baicar 				  & CPER_ARM_ERR_MEM_ATTRIBUTES_MASK);
224301f55b1STyler Baicar 		printk("%smemory access attributes:0x%x\n", pfx, mem_attributes);
225301f55b1STyler Baicar 	}
226301f55b1STyler Baicar 
227301f55b1STyler Baicar 	if (error_info & CPER_ARM_ERR_VALID_ACCESS_MODE) {
228301f55b1STyler Baicar 		access_mode = ((error_info >> CPER_ARM_ERR_ACCESS_MODE_SHIFT)
229301f55b1STyler Baicar 			       & CPER_ARM_ERR_ACCESS_MODE_MASK);
230301f55b1STyler Baicar 		if (access_mode)
231301f55b1STyler Baicar 			printk("%saccess mode: normal\n", pfx);
232301f55b1STyler Baicar 		else
233301f55b1STyler Baicar 			printk("%saccess mode: secure\n", pfx);
234301f55b1STyler Baicar 	}
235301f55b1STyler Baicar }
236301f55b1STyler Baicar 
cper_print_proc_arm(const char * pfx,const struct cper_sec_proc_arm * proc)237c6d8c8efSTyler Baicar void cper_print_proc_arm(const char *pfx,
238c6d8c8efSTyler Baicar 			 const struct cper_sec_proc_arm *proc)
239c6d8c8efSTyler Baicar {
240c6d8c8efSTyler Baicar 	int i, len, max_ctx_type;
241c6d8c8efSTyler Baicar 	struct cper_arm_err_info *err_info;
242c6d8c8efSTyler Baicar 	struct cper_arm_ctx_info *ctx_info;
243301f55b1STyler Baicar 	char newpfx[64], infopfx[64];
244c6d8c8efSTyler Baicar 
245c6d8c8efSTyler Baicar 	printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
246c6d8c8efSTyler Baicar 
247c6d8c8efSTyler Baicar 	len = proc->section_length - (sizeof(*proc) +
248c6d8c8efSTyler Baicar 		proc->err_info_num * (sizeof(*err_info)));
249c6d8c8efSTyler Baicar 	if (len < 0) {
250c6d8c8efSTyler Baicar 		printk("%ssection length: %d\n", pfx, proc->section_length);
251c6d8c8efSTyler Baicar 		printk("%ssection length is too small\n", pfx);
252c6d8c8efSTyler Baicar 		printk("%sfirmware-generated error record is incorrect\n", pfx);
253c6d8c8efSTyler Baicar 		printk("%sERR_INFO_NUM is %d\n", pfx, proc->err_info_num);
254c6d8c8efSTyler Baicar 		return;
255c6d8c8efSTyler Baicar 	}
256c6d8c8efSTyler Baicar 
257c6d8c8efSTyler Baicar 	if (proc->validation_bits & CPER_ARM_VALID_MPIDR)
258c6d8c8efSTyler Baicar 		printk("%sMultiprocessor Affinity Register (MPIDR): 0x%016llx\n",
259c6d8c8efSTyler Baicar 			pfx, proc->mpidr);
260c6d8c8efSTyler Baicar 
261c6d8c8efSTyler Baicar 	if (proc->validation_bits & CPER_ARM_VALID_AFFINITY_LEVEL)
262c6d8c8efSTyler Baicar 		printk("%serror affinity level: %d\n", pfx,
263c6d8c8efSTyler Baicar 			proc->affinity_level);
264c6d8c8efSTyler Baicar 
265c6d8c8efSTyler Baicar 	if (proc->validation_bits & CPER_ARM_VALID_RUNNING_STATE) {
266c6d8c8efSTyler Baicar 		printk("%srunning state: 0x%x\n", pfx, proc->running_state);
267c6d8c8efSTyler Baicar 		printk("%sPower State Coordination Interface state: %d\n",
268c6d8c8efSTyler Baicar 			pfx, proc->psci_state);
269c6d8c8efSTyler Baicar 	}
270c6d8c8efSTyler Baicar 
27175e4fd31SBorislav Petkov 	snprintf(newpfx, sizeof(newpfx), "%s ", pfx);
272c6d8c8efSTyler Baicar 
273c6d8c8efSTyler Baicar 	err_info = (struct cper_arm_err_info *)(proc + 1);
274c6d8c8efSTyler Baicar 	for (i = 0; i < proc->err_info_num; i++) {
275c6d8c8efSTyler Baicar 		printk("%sError info structure %d:\n", pfx, i);
276c6d8c8efSTyler Baicar 
277c6d8c8efSTyler Baicar 		printk("%snum errors: %d\n", pfx, err_info->multiple_error + 1);
278c6d8c8efSTyler Baicar 
279c6d8c8efSTyler Baicar 		if (err_info->validation_bits & CPER_ARM_INFO_VALID_FLAGS) {
280c6d8c8efSTyler Baicar 			if (err_info->flags & CPER_ARM_INFO_FLAGS_FIRST)
281c6d8c8efSTyler Baicar 				printk("%sfirst error captured\n", newpfx);
282c6d8c8efSTyler Baicar 			if (err_info->flags & CPER_ARM_INFO_FLAGS_LAST)
283c6d8c8efSTyler Baicar 				printk("%slast error captured\n", newpfx);
284c6d8c8efSTyler Baicar 			if (err_info->flags & CPER_ARM_INFO_FLAGS_PROPAGATED)
285c6d8c8efSTyler Baicar 				printk("%spropagated error captured\n",
286c6d8c8efSTyler Baicar 				       newpfx);
287c6d8c8efSTyler Baicar 			if (err_info->flags & CPER_ARM_INFO_FLAGS_OVERFLOW)
288c6d8c8efSTyler Baicar 				printk("%soverflow occurred, error info is incomplete\n",
289c6d8c8efSTyler Baicar 				       newpfx);
290c6d8c8efSTyler Baicar 		}
291c6d8c8efSTyler Baicar 
292c6d8c8efSTyler Baicar 		printk("%serror_type: %d, %s\n", newpfx, err_info->type,
293c6d8c8efSTyler Baicar 			err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ?
294c6d8c8efSTyler Baicar 			cper_proc_error_type_strs[err_info->type] : "unknown");
295301f55b1STyler Baicar 		if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) {
296c6d8c8efSTyler Baicar 			printk("%serror_info: 0x%016llx\n", newpfx,
297c6d8c8efSTyler Baicar 			       err_info->error_info);
29875e4fd31SBorislav Petkov 			snprintf(infopfx, sizeof(infopfx), "%s ", newpfx);
299301f55b1STyler Baicar 			cper_print_arm_err_info(infopfx, err_info->type,
300301f55b1STyler Baicar 						err_info->error_info);
301301f55b1STyler Baicar 		}
302c6d8c8efSTyler Baicar 		if (err_info->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
303c6d8c8efSTyler Baicar 			printk("%svirtual fault address: 0x%016llx\n",
304c6d8c8efSTyler Baicar 				newpfx, err_info->virt_fault_addr);
305c6d8c8efSTyler Baicar 		if (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR)
306c6d8c8efSTyler Baicar 			printk("%sphysical fault address: 0x%016llx\n",
307c6d8c8efSTyler Baicar 				newpfx, err_info->physical_fault_addr);
308c6d8c8efSTyler Baicar 		err_info += 1;
309c6d8c8efSTyler Baicar 	}
310c6d8c8efSTyler Baicar 
311c6d8c8efSTyler Baicar 	ctx_info = (struct cper_arm_ctx_info *)err_info;
312c6d8c8efSTyler Baicar 	max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
313c6d8c8efSTyler Baicar 	for (i = 0; i < proc->context_info_num; i++) {
314c6d8c8efSTyler Baicar 		int size = sizeof(*ctx_info) + ctx_info->size;
315c6d8c8efSTyler Baicar 
316c6d8c8efSTyler Baicar 		printk("%sContext info structure %d:\n", pfx, i);
317c6d8c8efSTyler Baicar 		if (len < size) {
318c6d8c8efSTyler Baicar 			printk("%ssection length is too small\n", newpfx);
319c6d8c8efSTyler Baicar 			printk("%sfirmware-generated error record is incorrect\n", pfx);
320c6d8c8efSTyler Baicar 			return;
321c6d8c8efSTyler Baicar 		}
322c6d8c8efSTyler Baicar 		if (ctx_info->type > max_ctx_type) {
323c6d8c8efSTyler Baicar 			printk("%sInvalid context type: %d (max: %d)\n",
324c6d8c8efSTyler Baicar 				newpfx, ctx_info->type, max_ctx_type);
325c6d8c8efSTyler Baicar 			return;
326c6d8c8efSTyler Baicar 		}
327c6d8c8efSTyler Baicar 		printk("%sregister context type: %s\n", newpfx,
328c6d8c8efSTyler Baicar 			arm_reg_ctx_strs[ctx_info->type]);
329c6d8c8efSTyler Baicar 		print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
330c6d8c8efSTyler Baicar 				(ctx_info + 1), ctx_info->size, 0);
331c6d8c8efSTyler Baicar 		len -= size;
332c6d8c8efSTyler Baicar 		ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + size);
333c6d8c8efSTyler Baicar 	}
334c6d8c8efSTyler Baicar 
335c6d8c8efSTyler Baicar 	if (len > 0) {
336c6d8c8efSTyler Baicar 		printk("%sVendor specific error info has %u bytes:\n", pfx,
337c6d8c8efSTyler Baicar 		       len);
338c6d8c8efSTyler Baicar 		print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, ctx_info,
339c6d8c8efSTyler Baicar 				len, true);
340c6d8c8efSTyler Baicar 	}
341c6d8c8efSTyler Baicar }
342