Merge branch 'for-4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
[sfrench/cifs-2.6.git] / drivers / firmware / efi / cper-arm.c
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
35 static 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
47 static const char * const arm_err_trans_type_strs[] = {
48         "Instruction",
49         "Data Access",
50         "Generic",
51 };
52
53 static 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
63 static 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
77 static 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
89 static 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
96 static 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
103 static 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
252 void 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 }