Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6-microblaze.git] / drivers / firmware / efi / cper-arm.c
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
21 static 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
33 static const char * const arm_err_trans_type_strs[] = {
34         "Instruction",
35         "Data Access",
36         "Generic",
37 };
38
39 static 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
49 static 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
63 static 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
75 static 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
82 static 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
89 static 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
238 void 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 }