Merge tag 'sh-for-v6.6-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/glaubit...
[platform/kernel/linux-rpi.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/printk.h>
16 #include <linux/bcd.h>
17 #include <acpi/ghes.h>
18 #include <ras/ras_event.h>
19
20 static 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
32 static const char * const arm_err_trans_type_strs[] = {
33         "Instruction",
34         "Data Access",
35         "Generic",
36 };
37
38 static 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
48 static 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
62 static 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
74 static 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
81 static 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
88 static 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
237 void 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 }