aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-01-30 13:42:39 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-01-30 13:42:39 -0500
commitb8dbf73086085f1973d3ae66f709e78c077fed05 (patch)
treeb6bfe33415352b93e01778b5cc5c41c271656e28
parentd772794637451c424729dd71690d7ac158523108 (diff)
parenta5c03c31af2291f13689d11760c0b59fb70c9a5a (diff)
Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI updates from Ingo Molnar: "The biggest change in this cycle was the addition of ARM CPER error decoding when printing EFI errors into the kernel log. There are also misc smaller updates: documentation update, cleanups and an EFI memory map permissions quirk" * 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/efi: Clarify that reset attack mitigation needs appropriate userspace efi: Parse ARM error information value efi: Move ARM CPER code to new file efi: Use PTR_ERR_OR_ZERO() arm64/efi: Ignore EFI_MEMORY_XP attribute if RP and/or WP are set efi/capsule-loader: Fix pr_err() string to end with newline
-rw-r--r--arch/arm64/kernel/efi.c4
-rw-r--r--drivers/firmware/efi/Kconfig10
-rw-r--r--drivers/firmware/efi/Makefile1
-rw-r--r--drivers/firmware/efi/capsule-loader.c2
-rw-r--r--drivers/firmware/efi/cper-arm.c356
-rw-r--r--drivers/firmware/efi/cper.c122
-rw-r--r--drivers/firmware/efi/efi.c2
-rw-r--r--include/linux/cper.h48
8 files changed, 422 insertions, 123 deletions
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 82cd07592519..f85ac58d08a3 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -48,7 +48,9 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
48 return pgprot_val(PAGE_KERNEL_ROX); 48 return pgprot_val(PAGE_KERNEL_ROX);
49 49
50 /* RW- */ 50 /* RW- */
51 if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE) 51 if (((attr & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP)) ==
52 EFI_MEMORY_XP) ||
53 type != EFI_RUNTIME_SERVICES_CODE)
52 return pgprot_val(PAGE_KERNEL); 54 return pgprot_val(PAGE_KERNEL);
53 55
54 /* RWX */ 56 /* RWX */
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 2b4c39fdfa91..6047ed4e8a3d 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -159,13 +159,21 @@ config RESET_ATTACK_MITIGATION
159 using the TCG Platform Reset Attack Mitigation specification. This 159 using the TCG Platform Reset Attack Mitigation specification. This
160 protects against an attacker forcibly rebooting the system while it 160 protects against an attacker forcibly rebooting the system while it
161 still contains secrets in RAM, booting another OS and extracting the 161 still contains secrets in RAM, booting another OS and extracting the
162 secrets. 162 secrets. This should only be enabled when userland is configured to
163 clear the MemoryOverwriteRequest flag on clean shutdown after secrets
164 have been evicted, since otherwise it will trigger even on clean
165 reboots.
163 166
164endmenu 167endmenu
165 168
166config UEFI_CPER 169config UEFI_CPER
167 bool 170 bool
168 171
172config UEFI_CPER_ARM
173 bool
174 depends on UEFI_CPER && ( ARM || ARM64 )
175 default y
176
169config EFI_DEV_PATH_PARSER 177config EFI_DEV_PATH_PARSER
170 bool 178 bool
171 depends on ACPI 179 depends on ACPI
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 269501dfba53..a3e73d6e8a43 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -30,3 +30,4 @@ arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o
30obj-$(CONFIG_ARM) += $(arm-obj-y) 30obj-$(CONFIG_ARM) += $(arm-obj-y)
31obj-$(CONFIG_ARM64) += $(arm-obj-y) 31obj-$(CONFIG_ARM64) += $(arm-obj-y)
32obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o 32obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o
33obj-$(CONFIG_UEFI_CPER_ARM) += cper-arm.o
diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c
index 055e2e8f985a..e456f4602df1 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -45,7 +45,7 @@ int __efi_capsule_setup_info(struct capsule_info *cap_info)
45 pages_needed = ALIGN(cap_info->total_size, PAGE_SIZE) / PAGE_SIZE; 45 pages_needed = ALIGN(cap_info->total_size, PAGE_SIZE) / PAGE_SIZE;
46 46
47 if (pages_needed == 0) { 47 if (pages_needed == 0) {
48 pr_err("invalid capsule size"); 48 pr_err("invalid capsule size\n");
49 return -EINVAL; 49 return -EINVAL;
50 } 50 }
51 51
diff --git a/drivers/firmware/efi/cper-arm.c b/drivers/firmware/efi/cper-arm.c
new file mode 100644
index 000000000000..698e5c8e0c8d
--- /dev/null
+++ b/drivers/firmware/efi/cper-arm.c
@@ -0,0 +1,356 @@
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
35static 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
47static const char * const arm_err_trans_type_strs[] = {
48 "Instruction",
49 "Data Access",
50 "Generic",
51};
52
53static 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
63static 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
77static 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
89static 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
96static 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
103static 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
252void 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}
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index d2fcafcea07e..c165933ebf38 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -122,7 +122,7 @@ static const char * const proc_isa_strs[] = {
122 "ARM A64", 122 "ARM A64",
123}; 123};
124 124
125static const char * const proc_error_type_strs[] = { 125const char * const cper_proc_error_type_strs[] = {
126 "cache error", 126 "cache error",
127 "TLB error", 127 "TLB error",
128 "bus error", 128 "bus error",
@@ -157,8 +157,8 @@ static void cper_print_proc_generic(const char *pfx,
157 if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) { 157 if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) {
158 printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type); 158 printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type);
159 cper_print_bits(pfx, proc->proc_error_type, 159 cper_print_bits(pfx, proc->proc_error_type,
160 proc_error_type_strs, 160 cper_proc_error_type_strs,
161 ARRAY_SIZE(proc_error_type_strs)); 161 ARRAY_SIZE(cper_proc_error_type_strs));
162 } 162 }
163 if (proc->validation_bits & CPER_PROC_VALID_OPERATION) 163 if (proc->validation_bits & CPER_PROC_VALID_OPERATION)
164 printk("%s""operation: %d, %s\n", pfx, proc->operation, 164 printk("%s""operation: %d, %s\n", pfx, proc->operation,
@@ -188,122 +188,6 @@ static void cper_print_proc_generic(const char *pfx,
188 printk("%s""IP: 0x%016llx\n", pfx, proc->ip); 188 printk("%s""IP: 0x%016llx\n", pfx, proc->ip);
189} 189}
190 190
191#if defined(CONFIG_ARM64) || defined(CONFIG_ARM)
192static const char * const arm_reg_ctx_strs[] = {
193 "AArch32 general purpose registers",
194 "AArch32 EL1 context registers",
195 "AArch32 EL2 context registers",
196 "AArch32 secure context registers",
197 "AArch64 general purpose registers",
198 "AArch64 EL1 context registers",
199 "AArch64 EL2 context registers",
200 "AArch64 EL3 context registers",
201 "Misc. system register structure",
202};
203
204static void cper_print_proc_arm(const char *pfx,
205 const struct cper_sec_proc_arm *proc)
206{
207 int i, len, max_ctx_type;
208 struct cper_arm_err_info *err_info;
209 struct cper_arm_ctx_info *ctx_info;
210 char newpfx[64];
211
212 printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
213
214 len = proc->section_length - (sizeof(*proc) +
215 proc->err_info_num * (sizeof(*err_info)));
216 if (len < 0) {
217 printk("%ssection length: %d\n", pfx, proc->section_length);
218 printk("%ssection length is too small\n", pfx);
219 printk("%sfirmware-generated error record is incorrect\n", pfx);
220 printk("%sERR_INFO_NUM is %d\n", pfx, proc->err_info_num);
221 return;
222 }
223
224 if (proc->validation_bits & CPER_ARM_VALID_MPIDR)
225 printk("%sMultiprocessor Affinity Register (MPIDR): 0x%016llx\n",
226 pfx, proc->mpidr);
227
228 if (proc->validation_bits & CPER_ARM_VALID_AFFINITY_LEVEL)
229 printk("%serror affinity level: %d\n", pfx,
230 proc->affinity_level);
231
232 if (proc->validation_bits & CPER_ARM_VALID_RUNNING_STATE) {
233 printk("%srunning state: 0x%x\n", pfx, proc->running_state);
234 printk("%sPower State Coordination Interface state: %d\n",
235 pfx, proc->psci_state);
236 }
237
238 snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
239
240 err_info = (struct cper_arm_err_info *)(proc + 1);
241 for (i = 0; i < proc->err_info_num; i++) {
242 printk("%sError info structure %d:\n", pfx, i);
243
244 printk("%snum errors: %d\n", pfx, err_info->multiple_error + 1);
245
246 if (err_info->validation_bits & CPER_ARM_INFO_VALID_FLAGS) {
247 if (err_info->flags & CPER_ARM_INFO_FLAGS_FIRST)
248 printk("%sfirst error captured\n", newpfx);
249 if (err_info->flags & CPER_ARM_INFO_FLAGS_LAST)
250 printk("%slast error captured\n", newpfx);
251 if (err_info->flags & CPER_ARM_INFO_FLAGS_PROPAGATED)
252 printk("%spropagated error captured\n",
253 newpfx);
254 if (err_info->flags & CPER_ARM_INFO_FLAGS_OVERFLOW)
255 printk("%soverflow occurred, error info is incomplete\n",
256 newpfx);
257 }
258
259 printk("%serror_type: %d, %s\n", newpfx, err_info->type,
260 err_info->type < ARRAY_SIZE(proc_error_type_strs) ?
261 proc_error_type_strs[err_info->type] : "unknown");
262 if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO)
263 printk("%serror_info: 0x%016llx\n", newpfx,
264 err_info->error_info);
265 if (err_info->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
266 printk("%svirtual fault address: 0x%016llx\n",
267 newpfx, err_info->virt_fault_addr);
268 if (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR)
269 printk("%sphysical fault address: 0x%016llx\n",
270 newpfx, err_info->physical_fault_addr);
271 err_info += 1;
272 }
273
274 ctx_info = (struct cper_arm_ctx_info *)err_info;
275 max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
276 for (i = 0; i < proc->context_info_num; i++) {
277 int size = sizeof(*ctx_info) + ctx_info->size;
278
279 printk("%sContext info structure %d:\n", pfx, i);
280 if (len < size) {
281 printk("%ssection length is too small\n", newpfx);
282 printk("%sfirmware-generated error record is incorrect\n", pfx);
283 return;
284 }
285 if (ctx_info->type > max_ctx_type) {
286 printk("%sInvalid context type: %d (max: %d)\n",
287 newpfx, ctx_info->type, max_ctx_type);
288 return;
289 }
290 printk("%sregister context type: %s\n", newpfx,
291 arm_reg_ctx_strs[ctx_info->type]);
292 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
293 (ctx_info + 1), ctx_info->size, 0);
294 len -= size;
295 ctx_info = (struct cper_arm_ctx_info *)((long)ctx_info + size);
296 }
297
298 if (len > 0) {
299 printk("%sVendor specific error info has %u bytes:\n", pfx,
300 len);
301 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, ctx_info,
302 len, true);
303 }
304}
305#endif
306
307static const char * const mem_err_type_strs[] = { 191static const char * const mem_err_type_strs[] = {
308 "unknown", 192 "unknown",
309 "no error", 193 "no error",
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 557a47829d03..8ce70c2e73d5 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -608,7 +608,7 @@ static int __init efi_load_efivars(void)
608 return 0; 608 return 0;
609 609
610 pdev = platform_device_register_simple("efivars", 0, NULL, 0); 610 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
611 return IS_ERR(pdev) ? PTR_ERR(pdev) : 0; 611 return PTR_ERR_OR_ZERO(pdev);
612} 612}
613device_initcall(efi_load_efivars); 613device_initcall(efi_load_efivars);
614#endif 614#endif
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 723e952fde0d..d14ef4e77c8a 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -275,6 +275,50 @@ enum {
275#define CPER_ARM_INFO_FLAGS_PROPAGATED BIT(2) 275#define CPER_ARM_INFO_FLAGS_PROPAGATED BIT(2)
276#define CPER_ARM_INFO_FLAGS_OVERFLOW BIT(3) 276#define CPER_ARM_INFO_FLAGS_OVERFLOW BIT(3)
277 277
278#define CPER_ARM_CACHE_ERROR 0
279#define CPER_ARM_TLB_ERROR 1
280#define CPER_ARM_BUS_ERROR 2
281#define CPER_ARM_VENDOR_ERROR 3
282#define CPER_ARM_MAX_TYPE CPER_ARM_VENDOR_ERROR
283
284#define CPER_ARM_ERR_VALID_TRANSACTION_TYPE BIT(0)
285#define CPER_ARM_ERR_VALID_OPERATION_TYPE BIT(1)
286#define CPER_ARM_ERR_VALID_LEVEL BIT(2)
287#define CPER_ARM_ERR_VALID_PROC_CONTEXT_CORRUPT BIT(3)
288#define CPER_ARM_ERR_VALID_CORRECTED BIT(4)
289#define CPER_ARM_ERR_VALID_PRECISE_PC BIT(5)
290#define CPER_ARM_ERR_VALID_RESTARTABLE_PC BIT(6)
291#define CPER_ARM_ERR_VALID_PARTICIPATION_TYPE BIT(7)
292#define CPER_ARM_ERR_VALID_TIME_OUT BIT(8)
293#define CPER_ARM_ERR_VALID_ADDRESS_SPACE BIT(9)
294#define CPER_ARM_ERR_VALID_MEM_ATTRIBUTES BIT(10)
295#define CPER_ARM_ERR_VALID_ACCESS_MODE BIT(11)
296
297#define CPER_ARM_ERR_TRANSACTION_SHIFT 16
298#define CPER_ARM_ERR_TRANSACTION_MASK GENMASK(1,0)
299#define CPER_ARM_ERR_OPERATION_SHIFT 18
300#define CPER_ARM_ERR_OPERATION_MASK GENMASK(3,0)
301#define CPER_ARM_ERR_LEVEL_SHIFT 22
302#define CPER_ARM_ERR_LEVEL_MASK GENMASK(2,0)
303#define CPER_ARM_ERR_PC_CORRUPT_SHIFT 25
304#define CPER_ARM_ERR_PC_CORRUPT_MASK GENMASK(0,0)
305#define CPER_ARM_ERR_CORRECTED_SHIFT 26
306#define CPER_ARM_ERR_CORRECTED_MASK GENMASK(0,0)
307#define CPER_ARM_ERR_PRECISE_PC_SHIFT 27
308#define CPER_ARM_ERR_PRECISE_PC_MASK GENMASK(0,0)
309#define CPER_ARM_ERR_RESTARTABLE_PC_SHIFT 28
310#define CPER_ARM_ERR_RESTARTABLE_PC_MASK GENMASK(0,0)
311#define CPER_ARM_ERR_PARTICIPATION_TYPE_SHIFT 29
312#define CPER_ARM_ERR_PARTICIPATION_TYPE_MASK GENMASK(1,0)
313#define CPER_ARM_ERR_TIME_OUT_SHIFT 31
314#define CPER_ARM_ERR_TIME_OUT_MASK GENMASK(0,0)
315#define CPER_ARM_ERR_ADDRESS_SPACE_SHIFT 32
316#define CPER_ARM_ERR_ADDRESS_SPACE_MASK GENMASK(1,0)
317#define CPER_ARM_ERR_MEM_ATTRIBUTES_SHIFT 34
318#define CPER_ARM_ERR_MEM_ATTRIBUTES_MASK GENMASK(8,0)
319#define CPER_ARM_ERR_ACCESS_MODE_SHIFT 43
320#define CPER_ARM_ERR_ACCESS_MODE_MASK GENMASK(0,0)
321
278/* 322/*
279 * All tables and structs must be byte-packed to match CPER 323 * All tables and structs must be byte-packed to match CPER
280 * specification, since the tables are provided by the system BIOS 324 * specification, since the tables are provided by the system BIOS
@@ -494,6 +538,8 @@ struct cper_sec_pcie {
494/* Reset to default packing */ 538/* Reset to default packing */
495#pragma pack() 539#pragma pack()
496 540
541extern const char * const cper_proc_error_type_strs[4];
542
497u64 cper_next_record_id(void); 543u64 cper_next_record_id(void);
498const char *cper_severity_str(unsigned int); 544const char *cper_severity_str(unsigned int);
499const char *cper_mem_err_type_str(unsigned int); 545const char *cper_mem_err_type_str(unsigned int);
@@ -503,5 +549,7 @@ void cper_mem_err_pack(const struct cper_sec_mem_err *,
503 struct cper_mem_err_compact *); 549 struct cper_mem_err_compact *);
504const char *cper_mem_err_unpack(struct trace_seq *, 550const char *cper_mem_err_unpack(struct trace_seq *,
505 struct cper_mem_err_compact *); 551 struct cper_mem_err_compact *);
552void cper_print_proc_arm(const char *pfx,
553 const struct cper_sec_proc_arm *proc);
506 554
507#endif 555#endif