Linux Audio

Check our new training course

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