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