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 } 357