aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTyler Baicar <tbaicar@codeaurora.org>2018-01-02 13:10:42 -0500
committerIngo Molnar <mingo@kernel.org>2018-01-03 08:03:48 -0500
commit301f55b1a9177132d2b9ce8a90bf0ae4b37bb850 (patch)
tree17395972e0ae7cbd568c7b1d01a9ccd2574b4eb1
parentc6d8c8ef1d0d94fdae9f5d72982963db89f9cdad (diff)
efi: Parse ARM error information value
ARM errors just print out the error information value, then the value needs to be manually decoded as per the UEFI spec. Add decoding of the ARM error information value so that the kernel logs capture all of the valid information at first glance. ARM error information value decoding is captured in UEFI 2.7 spec tables 263-265. Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Arvind Yadav <arvind.yadav.cs@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Matt Fleming <matt@codeblueprint.co.uk> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephen Boyd <sboyd@codeaurora.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Vasyl Gomonovych <gomonovych@gmail.com> Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20180102181042.19074-6-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--drivers/firmware/efi/cper-arm.c213
-rw-r--r--include/linux/cper.h44
2 files changed, 255 insertions, 2 deletions
diff --git a/drivers/firmware/efi/cper-arm.c b/drivers/firmware/efi/cper-arm.c
index 4afbfed52163..698e5c8e0c8d 100644
--- a/drivers/firmware/efi/cper-arm.c
+++ b/drivers/firmware/efi/cper-arm.c
@@ -44,13 +44,218 @@ static const char * const arm_reg_ctx_strs[] = {
44 "Misc. system register structure", 44 "Misc. system register structure",
45}; 45};
46 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
47void cper_print_proc_arm(const char *pfx, 252void cper_print_proc_arm(const char *pfx,
48 const struct cper_sec_proc_arm *proc) 253 const struct cper_sec_proc_arm *proc)
49{ 254{
50 int i, len, max_ctx_type; 255 int i, len, max_ctx_type;
51 struct cper_arm_err_info *err_info; 256 struct cper_arm_err_info *err_info;
52 struct cper_arm_ctx_info *ctx_info; 257 struct cper_arm_ctx_info *ctx_info;
53 char newpfx[64]; 258 char newpfx[64], infopfx[64];
54 259
55 printk("%sMIDR: 0x%016llx\n", pfx, proc->midr); 260 printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
56 261
@@ -102,9 +307,13 @@ void cper_print_proc_arm(const char *pfx,
102 printk("%serror_type: %d, %s\n", newpfx, err_info->type, 307 printk("%serror_type: %d, %s\n", newpfx, err_info->type,
103 err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ? 308 err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ?
104 cper_proc_error_type_strs[err_info->type] : "unknown"); 309 cper_proc_error_type_strs[err_info->type] : "unknown");
105 if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) 310 if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) {
106 printk("%serror_info: 0x%016llx\n", newpfx, 311 printk("%serror_info: 0x%016llx\n", newpfx,
107 err_info->error_info); 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 }
108 if (err_info->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR) 317 if (err_info->validation_bits & CPER_ARM_INFO_VALID_VIRT_ADDR)
109 printk("%svirtual fault address: 0x%016llx\n", 318 printk("%svirtual fault address: 0x%016llx\n",
110 newpfx, err_info->virt_fault_addr); 319 newpfx, err_info->virt_fault_addr);
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 3299e43c76eb..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