1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * UEFI Common Platform Error Record (CPER) support 4 * 5 * Copyright (C) 2010, Intel Corp. 6 * Author: Huang Ying <ying.huang@intel.com> 7 * 8 * CPER is the format used to describe platform hardware error by 9 * various tables, such as ERST, BERT and HEST etc. 10 * 11 * For more information about CPER, please refer to Appendix N of UEFI 12 * Specification version 2.4. 13 */ 14 15 #include <linux/bitmap.h> 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/time.h> 19 #include <linux/cper.h> 20 #include <linux/dmi.h> 21 #include <linux/acpi.h> 22 #include <linux/pci.h> 23 #include <linux/aer.h> 24 #include <linux/printk.h> 25 #include <linux/bcd.h> 26 #include <acpi/ghes.h> 27 #include <ras/ras_event.h> 28 #include <cxl/event.h> 29 30 /* 31 * CPER record ID need to be unique even after reboot, because record 32 * ID is used as index for ERST storage, while CPER records from 33 * multiple boot may co-exist in ERST. 34 */ 35 u64 cper_next_record_id(void) 36 { 37 static atomic64_t seq; 38 39 if (!atomic64_read(&seq)) { 40 time64_t time = ktime_get_real_seconds(); 41 42 /* 43 * This code is unlikely to still be needed in year 2106, 44 * but just in case, let's use a few more bits for timestamps 45 * after y2038 to be sure they keep increasing monotonically 46 * for the next few hundred years... 47 */ 48 if (time < 0x80000000) 49 atomic64_set(&seq, (ktime_get_real_seconds()) << 32); 50 else 51 atomic64_set(&seq, 0x8000000000000000ull | 52 ktime_get_real_seconds() << 24); 53 } 54 55 return atomic64_inc_return(&seq); 56 } 57 EXPORT_SYMBOL_GPL(cper_next_record_id); 58 59 static const char * const severity_strs[] = { 60 "recoverable", 61 "fatal", 62 "corrected", 63 "info", 64 }; 65 66 const char *cper_severity_str(unsigned int severity) 67 { 68 return severity < ARRAY_SIZE(severity_strs) ? 69 severity_strs[severity] : "unknown"; 70 } 71 EXPORT_SYMBOL_GPL(cper_severity_str); 72 73 /** 74 * cper_print_bits - print strings for set bits 75 * @pfx: prefix for each line, including log level and prefix string 76 * @bits: bit mask 77 * @strs: string array, indexed by bit position 78 * @strs_size: size of the string array: @strs 79 * 80 * For each set bit in @bits, print the corresponding string in @strs. 81 * If the output length is longer than 80, multiple line will be 82 * printed, with @pfx is printed at the beginning of each line. 83 */ 84 void cper_print_bits(const char *pfx, unsigned int bits, 85 const char * const strs[], unsigned int strs_size) 86 { 87 int i, len = 0; 88 const char *str; 89 char buf[84]; 90 91 for (i = 0; i < strs_size; i++) { 92 if (!(bits & (1U << i))) 93 continue; 94 str = strs[i]; 95 if (!str) 96 continue; 97 if (len && len + strlen(str) + 2 > 80) { 98 printk("%s\n", buf); 99 len = 0; 100 } 101 if (!len) 102 len = snprintf(buf, sizeof(buf), "%s%s", pfx, str); 103 else 104 len += scnprintf(buf+len, sizeof(buf)-len, ", %s", str); 105 } 106 if (len) 107 printk("%s\n", buf); 108 } 109 110 /** 111 * cper_bits_to_str - return a string for set bits 112 * @buf: buffer to store the output string 113 * @buf_size: size of the output string buffer 114 * @bits: bit mask 115 * @strs: string array, indexed by bit position 116 * @strs_size: size of the string array: @strs 117 * 118 * Add to @buf the bitmask in hexadecimal. Then, for each set bit in @bits, 119 * add the corresponding string describing the bit in @strs to @buf. 120 * 121 * A typical example is:: 122 * 123 * const char * const bits[] = { 124 * "bit 3 name", 125 * "bit 4 name", 126 * "bit 5 name", 127 * }; 128 * char str[120]; 129 * unsigned int bitmask = BIT(3) | BIT(5); 130 * #define MASK GENMASK(5,3) 131 * 132 * cper_bits_to_str(str, sizeof(str), FIELD_GET(MASK, bitmask), 133 * bits, ARRAY_SIZE(bits)); 134 * 135 * The above code fills the string ``str`` with ``bit 3 name|bit 5 name``. 136 * 137 * Return: number of bytes stored or an error code if lower than zero. 138 */ 139 int cper_bits_to_str(char *buf, int buf_size, unsigned long bits, 140 const char * const strs[], unsigned int strs_size) 141 { 142 int len = buf_size; 143 char *str = buf; 144 int i, size; 145 146 *buf = '\0'; 147 148 for_each_set_bit(i, &bits, strs_size) { 149 if (!(bits & BIT_ULL(i))) 150 continue; 151 152 if (*buf && len > 0) { 153 *str = '|'; 154 len--; 155 str++; 156 } 157 158 size = strscpy(str, strs[i], len); 159 if (size < 0) 160 return size; 161 162 len -= size; 163 str += size; 164 } 165 return buf_size - len; 166 } 167 EXPORT_SYMBOL_GPL(cper_bits_to_str); 168 169 static const char * const proc_type_strs[] = { 170 "IA32/X64", 171 "IA64", 172 "ARM", 173 }; 174 175 static const char * const proc_isa_strs[] = { 176 "IA32", 177 "IA64", 178 "X64", 179 "ARM A32/T32", 180 "ARM A64", 181 }; 182 183 const char * const cper_proc_error_type_strs[] = { 184 "cache error", 185 "TLB error", 186 "bus error", 187 "micro-architectural error", 188 }; 189 190 static const char * const proc_op_strs[] = { 191 "unknown or generic", 192 "data read", 193 "data write", 194 "instruction execution", 195 }; 196 197 static const char * const proc_flag_strs[] = { 198 "restartable", 199 "precise IP", 200 "overflow", 201 "corrected", 202 }; 203 204 static void cper_print_proc_generic(const char *pfx, 205 const struct cper_sec_proc_generic *proc) 206 { 207 if (proc->validation_bits & CPER_PROC_VALID_TYPE) 208 printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type, 209 proc->proc_type < ARRAY_SIZE(proc_type_strs) ? 210 proc_type_strs[proc->proc_type] : "unknown"); 211 if (proc->validation_bits & CPER_PROC_VALID_ISA) 212 printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa, 213 proc->proc_isa < ARRAY_SIZE(proc_isa_strs) ? 214 proc_isa_strs[proc->proc_isa] : "unknown"); 215 if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) { 216 printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type); 217 cper_print_bits(pfx, proc->proc_error_type, 218 cper_proc_error_type_strs, 219 ARRAY_SIZE(cper_proc_error_type_strs)); 220 } 221 if (proc->validation_bits & CPER_PROC_VALID_OPERATION) 222 printk("%s""operation: %d, %s\n", pfx, proc->operation, 223 proc->operation < ARRAY_SIZE(proc_op_strs) ? 224 proc_op_strs[proc->operation] : "unknown"); 225 if (proc->validation_bits & CPER_PROC_VALID_FLAGS) { 226 printk("%s""flags: 0x%02x\n", pfx, proc->flags); 227 cper_print_bits(pfx, proc->flags, proc_flag_strs, 228 ARRAY_SIZE(proc_flag_strs)); 229 } 230 if (proc->validation_bits & CPER_PROC_VALID_LEVEL) 231 printk("%s""level: %d\n", pfx, proc->level); 232 if (proc->validation_bits & CPER_PROC_VALID_VERSION) 233 printk("%s""version_info: 0x%016llx\n", pfx, proc->cpu_version); 234 if (proc->validation_bits & CPER_PROC_VALID_ID) 235 printk("%s""processor_id: 0x%016llx\n", pfx, proc->proc_id); 236 if (proc->validation_bits & CPER_PROC_VALID_TARGET_ADDRESS) 237 printk("%s""target_address: 0x%016llx\n", 238 pfx, proc->target_addr); 239 if (proc->validation_bits & CPER_PROC_VALID_REQUESTOR_ID) 240 printk("%s""requestor_id: 0x%016llx\n", 241 pfx, proc->requestor_id); 242 if (proc->validation_bits & CPER_PROC_VALID_RESPONDER_ID) 243 printk("%s""responder_id: 0x%016llx\n", 244 pfx, proc->responder_id); 245 if (proc->validation_bits & CPER_PROC_VALID_IP) 246 printk("%s""IP: 0x%016llx\n", pfx, proc->ip); 247 } 248 249 static const char * const mem_err_type_strs[] = { 250 "unknown", 251 "no error", 252 "single-bit ECC", 253 "multi-bit ECC", 254 "single-symbol chipkill ECC", 255 "multi-symbol chipkill ECC", 256 "master abort", 257 "target abort", 258 "parity error", 259 "watchdog timeout", 260 "invalid address", 261 "mirror Broken", 262 "memory sparing", 263 "scrub corrected error", 264 "scrub uncorrected error", 265 "physical memory map-out event", 266 }; 267 268 const char *cper_mem_err_type_str(unsigned int etype) 269 { 270 return etype < ARRAY_SIZE(mem_err_type_strs) ? 271 mem_err_type_strs[etype] : "unknown"; 272 } 273 EXPORT_SYMBOL_GPL(cper_mem_err_type_str); 274 275 const char *cper_mem_err_status_str(u64 status) 276 { 277 switch ((status >> 8) & 0xff) { 278 case 1: return "Error detected internal to the component"; 279 case 4: return "Storage error in DRAM memory"; 280 case 5: return "Storage error in TLB"; 281 case 6: return "Storage error in cache"; 282 case 7: return "Error in one or more functional units"; 283 case 8: return "Component failed self test"; 284 case 9: return "Overflow or undervalue of internal queue"; 285 case 16: return "Error detected in the bus"; 286 case 17: return "Virtual address not found on IO-TLB or IO-PDIR"; 287 case 18: return "Improper access error"; 288 case 19: return "Access to a memory address which is not mapped to any component"; 289 case 20: return "Loss of Lockstep"; 290 case 21: return "Response not associated with a request"; 291 case 22: return "Bus parity error - must also set the A, C, or D Bits"; 292 case 23: return "Detection of a protocol error"; 293 case 24: return "Detection of a PATH_ERROR"; 294 case 25: return "Bus operation timeout"; 295 case 26: return "A read was issued to data that has been poisoned"; 296 default: return "Reserved"; 297 } 298 } 299 EXPORT_SYMBOL_GPL(cper_mem_err_status_str); 300 301 int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg) 302 { 303 u32 len, n; 304 305 if (!msg) 306 return 0; 307 308 n = 0; 309 len = CPER_REC_LEN; 310 if (mem->validation_bits & CPER_MEM_VALID_NODE) 311 n += scnprintf(msg + n, len - n, "node:%d ", mem->node); 312 if (mem->validation_bits & CPER_MEM_VALID_CARD) 313 n += scnprintf(msg + n, len - n, "card:%d ", mem->card); 314 if (mem->validation_bits & CPER_MEM_VALID_MODULE) 315 n += scnprintf(msg + n, len - n, "module:%d ", mem->module); 316 if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER) 317 n += scnprintf(msg + n, len - n, "rank:%d ", mem->rank); 318 if (mem->validation_bits & CPER_MEM_VALID_BANK) 319 n += scnprintf(msg + n, len - n, "bank:%d ", mem->bank); 320 if (mem->validation_bits & CPER_MEM_VALID_BANK_GROUP) 321 n += scnprintf(msg + n, len - n, "bank_group:%d ", 322 mem->bank >> CPER_MEM_BANK_GROUP_SHIFT); 323 if (mem->validation_bits & CPER_MEM_VALID_BANK_ADDRESS) 324 n += scnprintf(msg + n, len - n, "bank_address:%d ", 325 mem->bank & CPER_MEM_BANK_ADDRESS_MASK); 326 if (mem->validation_bits & CPER_MEM_VALID_DEVICE) 327 n += scnprintf(msg + n, len - n, "device:%d ", mem->device); 328 if (mem->validation_bits & (CPER_MEM_VALID_ROW | CPER_MEM_VALID_ROW_EXT)) { 329 u32 row = mem->row; 330 331 row |= cper_get_mem_extension(mem->validation_bits, mem->extended); 332 n += scnprintf(msg + n, len - n, "row:%d ", row); 333 } 334 if (mem->validation_bits & CPER_MEM_VALID_COLUMN) 335 n += scnprintf(msg + n, len - n, "column:%d ", mem->column); 336 if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION) 337 n += scnprintf(msg + n, len - n, "bit_position:%d ", 338 mem->bit_pos); 339 if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID) 340 n += scnprintf(msg + n, len - n, "requestor_id:0x%016llx ", 341 mem->requestor_id); 342 if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID) 343 n += scnprintf(msg + n, len - n, "responder_id:0x%016llx ", 344 mem->responder_id); 345 if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID) 346 n += scnprintf(msg + n, len - n, "target_id:0x%016llx ", 347 mem->target_id); 348 if (mem->validation_bits & CPER_MEM_VALID_CHIP_ID) 349 n += scnprintf(msg + n, len - n, "chip_id:%d ", 350 mem->extended >> CPER_MEM_CHIP_ID_SHIFT); 351 352 return n; 353 } 354 EXPORT_SYMBOL_GPL(cper_mem_err_location); 355 356 int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg) 357 { 358 u32 len, n; 359 const char *bank = NULL, *device = NULL; 360 361 if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE)) 362 return 0; 363 364 len = CPER_REC_LEN; 365 dmi_memdev_name(mem->mem_dev_handle, &bank, &device); 366 if (bank && device) 367 n = snprintf(msg, len, "DIMM location: %s %s ", bank, device); 368 else 369 n = snprintf(msg, len, 370 "DIMM location: not present. DMI handle: 0x%.4x ", 371 mem->mem_dev_handle); 372 373 return n; 374 } 375 EXPORT_SYMBOL_GPL(cper_dimm_err_location); 376 377 void cper_mem_err_pack(const struct cper_sec_mem_err *mem, 378 struct cper_mem_err_compact *cmem) 379 { 380 cmem->validation_bits = mem->validation_bits; 381 cmem->node = mem->node; 382 cmem->card = mem->card; 383 cmem->module = mem->module; 384 cmem->bank = mem->bank; 385 cmem->device = mem->device; 386 cmem->row = mem->row; 387 cmem->column = mem->column; 388 cmem->bit_pos = mem->bit_pos; 389 cmem->requestor_id = mem->requestor_id; 390 cmem->responder_id = mem->responder_id; 391 cmem->target_id = mem->target_id; 392 393 /* 394 * These four sit past the end of the UEFI 2.1/2.2 layout, which older 395 * firmware still emits, so reading them unconditionally runs off a 396 * short record. Every consumer of the compact record gates them on the 397 * same validation bits, so leave them zero when firmware does not 398 * claim them. 399 */ 400 cmem->extended = 0; 401 cmem->rank = 0; 402 cmem->mem_array_handle = 0; 403 cmem->mem_dev_handle = 0; 404 405 if (mem->validation_bits & 406 (CPER_MEM_VALID_ROW_EXT | CPER_MEM_VALID_CHIP_ID)) 407 cmem->extended = mem->extended; 408 if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER) 409 cmem->rank = mem->rank; 410 if (mem->validation_bits & CPER_MEM_VALID_CARD_HANDLE) 411 cmem->mem_array_handle = mem->mem_array_handle; 412 if (mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) 413 cmem->mem_dev_handle = mem->mem_dev_handle; 414 } 415 EXPORT_SYMBOL_GPL(cper_mem_err_pack); 416 417 const char *cper_mem_err_unpack(struct trace_seq *p, 418 struct cper_mem_err_compact *cmem) 419 { 420 const char *ret = trace_seq_buffer_ptr(p); 421 char rcd_decode_str[CPER_REC_LEN]; 422 423 if (cper_mem_err_location(cmem, rcd_decode_str)) 424 trace_seq_printf(p, "%s", rcd_decode_str); 425 if (cper_dimm_err_location(cmem, rcd_decode_str)) 426 trace_seq_printf(p, "%s", rcd_decode_str); 427 trace_seq_putc(p, '\0'); 428 429 return ret; 430 } 431 432 static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem, 433 int len) 434 { 435 struct cper_mem_err_compact cmem; 436 char rcd_decode_str[CPER_REC_LEN]; 437 438 /* Don't trust UEFI 2.1/2.2 structure with bad validation bits */ 439 if (len == sizeof(struct cper_sec_mem_err_old) && 440 (mem->validation_bits & ~(CPER_MEM_VALID_RANK_NUMBER - 1))) { 441 pr_err(FW_WARN "valid bits set for fields beyond structure\n"); 442 return; 443 } 444 if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS) 445 printk("%s error_status: %s (0x%016llx)\n", 446 pfx, cper_mem_err_status_str(mem->error_status), 447 mem->error_status); 448 if (mem->validation_bits & CPER_MEM_VALID_PA) 449 printk("%s""physical_address: 0x%016llx\n", 450 pfx, mem->physical_addr); 451 if (mem->validation_bits & CPER_MEM_VALID_PA_MASK) 452 printk("%s""physical_address_mask: 0x%016llx\n", 453 pfx, mem->physical_addr_mask); 454 cper_mem_err_pack(mem, &cmem); 455 if (cper_mem_err_location(&cmem, rcd_decode_str)) 456 printk("%s%s\n", pfx, rcd_decode_str); 457 if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) { 458 u8 etype = mem->error_type; 459 printk("%s""error_type: %d, %s\n", pfx, etype, 460 cper_mem_err_type_str(etype)); 461 } 462 if (cper_dimm_err_location(&cmem, rcd_decode_str)) 463 printk("%s%s\n", pfx, rcd_decode_str); 464 } 465 466 static const char * const pcie_port_type_strs[] = { 467 "PCIe end point", 468 "legacy PCI end point", 469 "unknown", 470 "unknown", 471 "root port", 472 "upstream switch port", 473 "downstream switch port", 474 "PCIe to PCI/PCI-X bridge", 475 "PCI/PCI-X to PCIe bridge", 476 "root complex integrated endpoint device", 477 "root complex event collector", 478 }; 479 480 static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, 481 const struct acpi_hest_generic_data *gdata) 482 { 483 if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) 484 printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, 485 pcie->port_type < ARRAY_SIZE(pcie_port_type_strs) ? 486 pcie_port_type_strs[pcie->port_type] : "unknown"); 487 if (pcie->validation_bits & CPER_PCIE_VALID_VERSION) 488 printk("%s""version: %d.%d\n", pfx, 489 pcie->version.major, pcie->version.minor); 490 if (pcie->validation_bits & CPER_PCIE_VALID_COMMAND_STATUS) 491 printk("%s""command: 0x%04x, status: 0x%04x\n", pfx, 492 pcie->command, pcie->status); 493 if (pcie->validation_bits & CPER_PCIE_VALID_DEVICE_ID) { 494 const __u8 *p; 495 printk("%s""device_id: %04x:%02x:%02x.%x\n", pfx, 496 pcie->device_id.segment, pcie->device_id.bus, 497 pcie->device_id.device, pcie->device_id.function); 498 printk("%s""slot: %d\n", pfx, 499 pcie->device_id.slot >> CPER_PCIE_SLOT_SHIFT); 500 printk("%s""secondary_bus: 0x%02x\n", pfx, 501 pcie->device_id.secondary_bus); 502 printk("%s""vendor_id: 0x%04x, device_id: 0x%04x\n", pfx, 503 pcie->device_id.vendor_id, pcie->device_id.device_id); 504 p = pcie->device_id.class_code; 505 printk("%s""class_code: %02x%02x%02x\n", pfx, p[2], p[1], p[0]); 506 } 507 if (pcie->validation_bits & CPER_PCIE_VALID_SERIAL_NUMBER) 508 printk("%s""serial number: 0x%04x, 0x%04x\n", pfx, 509 pcie->serial_number.lower, pcie->serial_number.upper); 510 if (pcie->validation_bits & CPER_PCIE_VALID_BRIDGE_CONTROL_STATUS) 511 printk( 512 "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", 513 pfx, pcie->bridge.secondary_status, pcie->bridge.control); 514 515 /* 516 * Print all valid AER info. Record may be from BERT (boot-time) or GHES (run-time). 517 * 518 * Fatal errors call __ghes_panic() before AER handler prints this. 519 */ 520 if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) { 521 struct aer_capability_regs *aer; 522 523 aer = (struct aer_capability_regs *)pcie->aer_info; 524 printk("%saer_cor_status: 0x%08x, aer_cor_mask: 0x%08x\n", 525 pfx, aer->cor_status, aer->cor_mask); 526 printk("%saer_uncor_status: 0x%08x, aer_uncor_mask: 0x%08x\n", 527 pfx, aer->uncor_status, aer->uncor_mask); 528 printk("%saer_uncor_severity: 0x%08x\n", 529 pfx, aer->uncor_severity); 530 printk("%sTLP Header: %08x %08x %08x %08x\n", pfx, 531 aer->header_log.dw[0], aer->header_log.dw[1], 532 aer->header_log.dw[2], aer->header_log.dw[3]); 533 } 534 } 535 536 static const char * const fw_err_rec_type_strs[] = { 537 "IPF SAL Error Record", 538 "SOC Firmware Error Record Type1 (Legacy CrashLog Support)", 539 "SOC Firmware Error Record Type2", 540 }; 541 542 static void cper_print_fw_err(const char *pfx, 543 struct acpi_hest_generic_data *gdata, 544 const struct cper_sec_fw_err_rec_ref *fw_err) 545 { 546 void *buf = acpi_hest_get_payload(gdata); 547 u32 offset, length = gdata->error_data_length; 548 549 printk("%s""Firmware Error Record Type: %s\n", pfx, 550 fw_err->record_type < ARRAY_SIZE(fw_err_rec_type_strs) ? 551 fw_err_rec_type_strs[fw_err->record_type] : "unknown"); 552 printk("%s""Revision: %d\n", pfx, fw_err->revision); 553 554 /* Record Type based on UEFI 2.7 */ 555 if (fw_err->revision == 0) { 556 printk("%s""Record Identifier: %08llx\n", pfx, 557 fw_err->record_identifier); 558 } else if (fw_err->revision == 2) { 559 printk("%s""Record Identifier: %pUl\n", pfx, 560 &fw_err->record_identifier_guid); 561 } 562 563 /* 564 * The FW error record may contain trailing data beyond the 565 * structure defined by the specification. As the fields 566 * defined (and hence the offset of any trailing data) vary 567 * with the revision, set the offset to account for this 568 * variation. 569 */ 570 if (fw_err->revision == 0) { 571 /* record_identifier_guid not defined */ 572 offset = offsetof(struct cper_sec_fw_err_rec_ref, 573 record_identifier_guid); 574 } else if (fw_err->revision == 1) { 575 /* record_identifier not defined */ 576 offset = offsetof(struct cper_sec_fw_err_rec_ref, 577 record_identifier); 578 } else { 579 offset = sizeof(*fw_err); 580 } 581 if (offset > length) { 582 printk("%s""error section length is too small: offset=%d, length=%d\n", 583 pfx, offset, length); 584 return; 585 } 586 587 buf += offset; 588 length -= offset; 589 590 print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, buf, length, true); 591 } 592 593 static void cper_print_tstamp(const char *pfx, 594 struct acpi_hest_generic_data_v300 *gdata) 595 { 596 __u8 hour, min, sec, day, mon, year, century, *timestamp; 597 598 if (gdata->validation_bits & ACPI_HEST_GEN_VALID_TIMESTAMP) { 599 timestamp = (__u8 *)&(gdata->time_stamp); 600 sec = bcd2bin(timestamp[0]); 601 min = bcd2bin(timestamp[1]); 602 hour = bcd2bin(timestamp[2]); 603 day = bcd2bin(timestamp[4]); 604 mon = bcd2bin(timestamp[5]); 605 year = bcd2bin(timestamp[6]); 606 century = bcd2bin(timestamp[7]); 607 608 printk("%s%ststamp: %02d%02d-%02d-%02d %02d:%02d:%02d\n", pfx, 609 (timestamp[3] & 0x1 ? "precise " : "imprecise "), 610 century, year, mon, day, hour, min, sec); 611 } 612 } 613 614 struct ignore_section { 615 guid_t guid; 616 const char *name; 617 }; 618 619 static const struct ignore_section ignore_sections[] = { 620 { .guid = CPER_SEC_CXL_GEN_MEDIA_GUID, .name = "CXL General Media Event" }, 621 { .guid = CPER_SEC_CXL_DRAM_GUID, .name = "CXL DRAM Event" }, 622 { .guid = CPER_SEC_CXL_MEM_MODULE_GUID, .name = "CXL Memory Module Event" }, 623 }; 624 625 static void 626 cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata, 627 int sec_no) 628 { 629 guid_t *sec_type = (guid_t *)gdata->section_type; 630 __u16 severity; 631 char newpfx[64]; 632 633 if (acpi_hest_get_version(gdata) >= 3) 634 cper_print_tstamp(pfx, (struct acpi_hest_generic_data_v300 *)gdata); 635 636 severity = gdata->error_severity; 637 printk("%s""Error %d, type: %s\n", pfx, sec_no, 638 cper_severity_str(severity)); 639 if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) 640 printk("%s""fru_id: %pUl\n", pfx, gdata->fru_id); 641 if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) 642 printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text); 643 644 snprintf(newpfx, sizeof(newpfx), "%s ", pfx); 645 646 for (int i = 0; i < ARRAY_SIZE(ignore_sections); i++) { 647 if (guid_equal(sec_type, &ignore_sections[i].guid)) { 648 printk("%ssection_type: %s\n", newpfx, ignore_sections[i].name); 649 return; 650 } 651 } 652 653 if (guid_equal(sec_type, &CPER_SEC_PROC_GENERIC)) { 654 struct cper_sec_proc_generic *proc_err = acpi_hest_get_payload(gdata); 655 656 printk("%s""section_type: general processor error\n", newpfx); 657 if (gdata->error_data_length >= sizeof(*proc_err)) 658 cper_print_proc_generic(newpfx, proc_err); 659 else 660 goto err_section_too_small; 661 } else if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) { 662 struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata); 663 664 printk("%s""section_type: memory error\n", newpfx); 665 if (gdata->error_data_length >= 666 sizeof(struct cper_sec_mem_err_old)) 667 cper_print_mem(newpfx, mem_err, 668 gdata->error_data_length); 669 else 670 goto err_section_too_small; 671 } else if (guid_equal(sec_type, &CPER_SEC_PCIE)) { 672 struct cper_sec_pcie *pcie = acpi_hest_get_payload(gdata); 673 674 printk("%s""section_type: PCIe error\n", newpfx); 675 if (gdata->error_data_length >= sizeof(*pcie)) 676 cper_print_pcie(newpfx, pcie, gdata); 677 else 678 goto err_section_too_small; 679 #if defined(CONFIG_ARM64) || defined(CONFIG_ARM) 680 } else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) { 681 struct cper_sec_proc_arm *arm_err = acpi_hest_get_payload(gdata); 682 683 printk("%ssection_type: ARM processor error\n", newpfx); 684 if (gdata->error_data_length >= sizeof(*arm_err)) 685 cper_print_proc_arm(newpfx, arm_err, 686 gdata->error_data_length); 687 else 688 goto err_section_too_small; 689 #endif 690 #if defined(CONFIG_UEFI_CPER_X86) 691 } else if (guid_equal(sec_type, &CPER_SEC_PROC_IA)) { 692 struct cper_sec_proc_ia *ia_err = acpi_hest_get_payload(gdata); 693 694 printk("%ssection_type: IA32/X64 processor error\n", newpfx); 695 if (gdata->error_data_length >= sizeof(*ia_err)) 696 cper_print_proc_ia(newpfx, ia_err); 697 else 698 goto err_section_too_small; 699 #endif 700 } else if (guid_equal(sec_type, &CPER_SEC_FW_ERR_REC_REF)) { 701 struct cper_sec_fw_err_rec_ref *fw_err = acpi_hest_get_payload(gdata); 702 703 printk("%ssection_type: Firmware Error Record Reference\n", 704 newpfx); 705 /* The minimal FW Error Record contains 16 bytes */ 706 if (gdata->error_data_length >= SZ_16) 707 cper_print_fw_err(newpfx, gdata, fw_err); 708 else 709 goto err_section_too_small; 710 } else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) { 711 struct cxl_cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata); 712 713 printk("%ssection_type: CXL Protocol Error\n", newpfx); 714 if (gdata->error_data_length >= sizeof(*prot_err)) 715 cxl_cper_print_prot_err(newpfx, prot_err); 716 else 717 goto err_section_too_small; 718 } else { 719 const void *err = acpi_hest_get_payload(gdata); 720 721 printk("%ssection type: unknown, %pUl\n", newpfx, sec_type); 722 printk("%ssection length: %#x\n", newpfx, 723 gdata->error_data_length); 724 print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, err, 725 gdata->error_data_length, true); 726 } 727 728 return; 729 730 err_section_too_small: 731 pr_err(FW_WARN "error section length is too small\n"); 732 } 733 734 void cper_estatus_print(const char *pfx, 735 const struct acpi_hest_generic_status *estatus) 736 { 737 struct acpi_hest_generic_data *gdata; 738 int sec_no = 0; 739 char newpfx[64]; 740 __u16 severity; 741 742 severity = estatus->error_severity; 743 if (severity == CPER_SEV_CORRECTED) 744 printk("%s%s\n", pfx, 745 "It has been corrected by h/w " 746 "and requires no further action"); 747 printk("%s""event severity: %s\n", pfx, cper_severity_str(severity)); 748 snprintf(newpfx, sizeof(newpfx), "%s ", pfx); 749 750 apei_estatus_for_each_section(estatus, gdata) { 751 cper_estatus_print_section(newpfx, gdata, sec_no); 752 sec_no++; 753 } 754 } 755 EXPORT_SYMBOL_GPL(cper_estatus_print); 756 757 int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus) 758 { 759 if (estatus->data_length && 760 estatus->data_length < sizeof(struct acpi_hest_generic_data)) 761 return -EINVAL; 762 if (estatus->raw_data_length && 763 estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length) 764 return -EINVAL; 765 766 /* 767 * cper_estatus_len() sums these into a u32, and a wrapped sum reads 768 * back smaller than the record. Reject a length that cannot be 769 * expressed so no caller is handed the short value. 770 */ 771 if ((u64)sizeof(*estatus) + estatus->data_length > U32_MAX) 772 return -EINVAL; 773 if (estatus->raw_data_length && 774 (u64)estatus->raw_data_offset + estatus->raw_data_length > U32_MAX) 775 return -EINVAL; 776 777 return 0; 778 } 779 EXPORT_SYMBOL_GPL(cper_estatus_check_header); 780 781 int cper_estatus_check(const struct acpi_hest_generic_status *estatus) 782 { 783 struct acpi_hest_generic_data *gdata; 784 unsigned int data_len; 785 int rc; 786 787 rc = cper_estatus_check_header(estatus); 788 if (rc) 789 return rc; 790 791 data_len = estatus->data_length; 792 793 apei_estatus_for_each_section(estatus, gdata) { 794 int record_size; 795 796 /* 797 * The <acpi/ghes.h> helpers sum these as a signed int, so a 798 * huge error_data_length wraps small rather than large and the 799 * walk then advances by that wrapped value. Reject a size an 800 * int cannot carry. 801 */ 802 if (check_add_overflow(acpi_hest_get_size(gdata), 803 gdata->error_data_length, &record_size)) 804 return -EINVAL; 805 806 if (record_size > data_len) 807 return -EINVAL; 808 809 data_len -= record_size; 810 } 811 if (data_len) 812 return -EINVAL; 813 814 return 0; 815 } 816 EXPORT_SYMBOL_GPL(cper_estatus_check); 817