Linux Audio

Check our new training course

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