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.13.7
  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}