]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/firmware/efi/cper-arm.c
4afbfed52163ed5c1b02bf2f016f5f442abfb11d
[mirror_ubuntu-bionic-kernel.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 void cper_print_proc_arm(const char *pfx,
48 const struct cper_sec_proc_arm *proc)
49 {
50 int i, len, max_ctx_type;
51 struct cper_arm_err_info *err_info;
52 struct cper_arm_ctx_info *ctx_info;
53 char newpfx[64];
54
55 printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
56
57 len = proc->section_length - (sizeof(*proc) +
58 proc->err_info_num * (sizeof(*err_info)));
59 if (len < 0) {
60 printk("%ssection length: %d\n", pfx, proc->section_length);
61 printk("%ssection length is too small\n", pfx);
62 printk("%sfirmware-generated error record is incorrect\n", pfx);
63 printk("%sERR_INFO_NUM is %d\n", pfx, proc->err_info_num);
64 return;
65 }
66
67 if (proc->validation_bits & CPER_ARM_VALID_MPIDR)
68 printk("%sMultiprocessor Affinity Register (MPIDR): 0x%016llx\n",
69 pfx, proc->mpidr);
70
71 if (proc->validation_bits & CPER_ARM_VALID_AFFINITY_LEVEL)
72 printk("%serror affinity level: %d\n", pfx,
73 proc->affinity_level);
74
75 if (proc->validation_bits & CPER_ARM_VALID_RUNNING_STATE) {
76 printk("%srunning state: 0x%x\n", pfx, proc->running_state);
77 printk("%sPower State Coordination Interface state: %d\n",
78 pfx, proc->psci_state);
79 }
80
81 snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
82
83 err_info = (struct cper_arm_err_info *)(proc + 1);
84 for (i = 0; i < proc->err_info_num; i++) {
85 printk("%sError info structure %d:\n", pfx, i);
86
87 printk("%snum errors: %d\n", pfx, err_info->multiple_error + 1);
88
89 if (err_info->validation_bits & CPER_ARM_INFO_VALID_FLAGS) {
90 if (err_info->flags & CPER_ARM_INFO_FLAGS_FIRST)
91 printk("%sfirst error captured\n", newpfx);
92 if (err_info->flags & CPER_ARM_INFO_FLAGS_LAST)
93 printk("%slast error captured\n", newpfx);
94 if (err_info->flags & CPER_ARM_INFO_FLAGS_PROPAGATED)
95 printk("%spropagated error captured\n",
96 newpfx);
97 if (err_info->flags & CPER_ARM_INFO_FLAGS_OVERFLOW)
98 printk("%soverflow occurred, error info is incomplete\n",
99 newpfx);
100 }
101
102 printk("%serror_type: %d, %s\n", newpfx, err_info->type,
103 err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ?
104 cper_proc_error_type_strs[err_info->type] : "unknown");
105 if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO)
106 printk("%serror_info: 0x%016llx\n", newpfx,
107 err_info->error_info);
108 if (err_info->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
109 printk("%svirtual fault address: 0x%016llx\n",
110 newpfx, err_info->virt_fault_addr);
111 if (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR)
112 printk("%sphysical fault address: 0x%016llx\n",
113 newpfx, err_info->physical_fault_addr);
114 err_info += 1;
115 }
116
117 ctx_info = (struct cper_arm_ctx_info *)err_info;
118 max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
119 for (i = 0; i < proc->context_info_num; i++) {
120 int size = sizeof(*ctx_info) + ctx_info->size;
121
122 printk("%sContext info structure %d:\n", pfx, i);
123 if (len < size) {
124 printk("%ssection length is too small\n", newpfx);
125 printk("%sfirmware-generated error record is incorrect\n", pfx);
126 return;
127 }
128 if (ctx_info->type > max_ctx_type) {
129 printk("%sInvalid context type: %d (max: %d)\n",
130 newpfx, ctx_info->type, max_ctx_type);
131 return;
132 }
133 printk("%sregister context type: %s\n", newpfx,
134 arm_reg_ctx_strs[ctx_info->type]);
135 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
136 (ctx_info + 1), ctx_info->size, 0);
137 len -= size;
138 ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + size);
139 }
140
141 if (len > 0) {
142 printk("%sVendor specific error info has %u bytes:\n", pfx,
143 len);
144 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, ctx_info,
145 len, true);
146 }
147 }