1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Firmware-Assisted Dump support on POWER platform (OPAL). 4 * 5 * Copyright 2019, Hari Bathini, IBM Corporation. 6 */ 7 8 #define pr_fmt(fmt) "opal fadump: " fmt 9 10 #include <linux/string.h> 11 #include <linux/seq_file.h> 12 #include <linux/of_fdt.h> 13 #include <linux/libfdt.h> 14 #include <linux/mm.h> 15 #include <linux/crash_dump.h> 16 17 #include <asm/page.h> 18 #include <asm/opal.h> 19 #include <asm/fadump-internal.h> 20 21 #include "opal-fadump.h" 22 23 24 #ifdef CONFIG_PRESERVE_FA_DUMP 25 /* 26 * When dump is active but PRESERVE_FA_DUMP is enabled on the kernel, 27 * ensure crash data is preserved in hope that the subsequent memory 28 * preserving kernel boot is going to process this crash data. 29 */ 30 void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node) 31 { 32 const struct opal_fadump_mem_struct *opal_fdm_active; 33 const __be32 *prop; 34 unsigned long dn; 35 u64 addr = 0; 36 s64 ret; 37 38 dn = of_get_flat_dt_subnode_by_name(node, "dump"); 39 if (dn == -FDT_ERR_NOTFOUND) 40 return; 41 42 /* 43 * Check if dump has been initiated on last reboot. 44 */ 45 prop = of_get_flat_dt_prop(dn, "mpipl-boot", NULL); 46 if (!prop) 47 return; 48 49 ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_KERNEL, &addr); 50 if ((ret != OPAL_SUCCESS) || !addr) { 51 pr_debug("Could not get Kernel metadata (%lld)\n", ret); 52 return; 53 } 54 55 /* 56 * Preserve memory only if kernel memory regions are registered 57 * with f/w for MPIPL. 58 */ 59 addr = be64_to_cpu(addr); 60 pr_debug("Kernel metadata addr: %llx\n", addr); 61 opal_fdm_active = (void *)addr; 62 if (opal_fdm_active->registered_regions == 0) 63 return; 64 65 ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_BOOT_MEM, &addr); 66 if ((ret != OPAL_SUCCESS) || !addr) { 67 pr_err("Failed to get boot memory tag (%lld)\n", ret); 68 return; 69 } 70 71 /* 72 * Memory below this address can be used for booting a 73 * capture kernel or petitboot kernel. Preserve everything 74 * above this address for processing crashdump. 75 */ 76 fadump_conf->boot_mem_top = be64_to_cpu(addr); 77 pr_debug("Preserve everything above %llx\n", fadump_conf->boot_mem_top); 78 79 pr_info("Firmware-assisted dump is active.\n"); 80 fadump_conf->dump_active = 1; 81 } 82 83 #else /* CONFIG_PRESERVE_FA_DUMP */ 84 static const struct opal_fadump_mem_struct *opal_fdm_active; 85 static const struct opal_mpipl_fadump *opal_cpu_metadata; 86 static struct opal_fadump_mem_struct *opal_fdm; 87 88 static int opal_fadump_unregister(struct fw_dump *fadump_conf); 89 90 static void opal_fadump_update_config(struct fw_dump *fadump_conf, 91 const struct opal_fadump_mem_struct *fdm) 92 { 93 pr_debug("Boot memory regions count: %d\n", fdm->region_cnt); 94 95 /* 96 * The destination address of the first boot memory region is the 97 * destination address of boot memory regions. 98 */ 99 fadump_conf->boot_mem_dest_addr = fdm->rgn[0].dest; 100 pr_debug("Destination address of boot memory regions: %#016llx\n", 101 fadump_conf->boot_mem_dest_addr); 102 103 fadump_conf->fadumphdr_addr = fdm->fadumphdr_addr; 104 } 105 106 /* 107 * This function is called in the capture kernel to get configuration details 108 * from metadata setup by the first kernel. 109 */ 110 static void opal_fadump_get_config(struct fw_dump *fadump_conf, 111 const struct opal_fadump_mem_struct *fdm) 112 { 113 int i; 114 115 if (!fadump_conf->dump_active) 116 return; 117 118 fadump_conf->boot_memory_size = 0; 119 120 pr_debug("Boot memory regions:\n"); 121 for (i = 0; i < fdm->region_cnt; i++) { 122 pr_debug("\t%d. base: 0x%llx, size: 0x%llx\n", 123 (i + 1), fdm->rgn[i].src, fdm->rgn[i].size); 124 125 fadump_conf->boot_memory_size += fdm->rgn[i].size; 126 } 127 128 /* 129 * Start address of reserve dump area (permanent reservation) for 130 * re-registering FADump after dump capture. 131 */ 132 fadump_conf->reserve_dump_area_start = fdm->rgn[0].dest; 133 134 /* 135 * Rarely, but it can so happen that system crashes before all 136 * boot memory regions are registered for MPIPL. In such 137 * cases, warn that the vmcore may not be accurate and proceed 138 * anyway as that is the best bet considering free pages, cache 139 * pages, user pages, etc are usually filtered out. 140 * 141 * Hope the memory that could not be preserved only has pages 142 * that are usually filtered out while saving the vmcore. 143 */ 144 if (fdm->region_cnt > fdm->registered_regions) { 145 pr_warn("Not all memory regions were saved!!!\n"); 146 pr_warn(" Unsaved memory regions:\n"); 147 i = fdm->registered_regions; 148 while (i < fdm->region_cnt) { 149 pr_warn("\t[%03d] base: 0x%llx, size: 0x%llx\n", 150 i, fdm->rgn[i].src, fdm->rgn[i].size); 151 i++; 152 } 153 154 pr_warn("If the unsaved regions only contain pages that are filtered out (eg. free/user pages), the vmcore should still be usable.\n"); 155 pr_warn("WARNING: If the unsaved regions contain kernel pages, the vmcore will be corrupted.\n"); 156 } 157 158 opal_fadump_update_config(fadump_conf, fdm); 159 } 160 161 /* Initialize kernel metadata */ 162 static void opal_fadump_init_metadata(struct opal_fadump_mem_struct *fdm) 163 { 164 fdm->version = OPAL_FADUMP_VERSION; 165 fdm->region_cnt = 0; 166 fdm->registered_regions = 0; 167 fdm->fadumphdr_addr = 0; 168 } 169 170 static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf) 171 { 172 int max_copy_size, cur_size, size; 173 u64 src_addr, dest_addr; 174 175 opal_fdm = __va(fadump_conf->kernel_metadata); 176 opal_fadump_init_metadata(opal_fdm); 177 178 /* 179 * Firmware supports 32-bit field for size. Align it to PAGE_SIZE 180 * and request firmware to copy multiple kernel boot memory regions. 181 */ 182 max_copy_size = _ALIGN_DOWN(U32_MAX, PAGE_SIZE); 183 184 /* Boot memory regions */ 185 src_addr = 0; 186 dest_addr = fadump_conf->reserve_dump_area_start; 187 size = fadump_conf->boot_memory_size; 188 while (size) { 189 cur_size = size > max_copy_size ? max_copy_size : size; 190 191 opal_fdm->rgn[opal_fdm->region_cnt].src = src_addr; 192 opal_fdm->rgn[opal_fdm->region_cnt].dest = dest_addr; 193 opal_fdm->rgn[opal_fdm->region_cnt].size = cur_size; 194 195 opal_fdm->region_cnt++; 196 dest_addr += cur_size; 197 src_addr += cur_size; 198 size -= cur_size; 199 } 200 201 /* 202 * Kernel metadata is passed to f/w and retrieved in capture kerenl. 203 * So, use it to save fadump header address instead of calculating it. 204 */ 205 opal_fdm->fadumphdr_addr = (opal_fdm->rgn[0].dest + 206 fadump_conf->boot_memory_size); 207 208 opal_fadump_update_config(fadump_conf, opal_fdm); 209 210 return dest_addr; 211 } 212 213 static u64 opal_fadump_get_metadata_size(void) 214 { 215 return PAGE_ALIGN(sizeof(struct opal_fadump_mem_struct)); 216 } 217 218 static int opal_fadump_setup_metadata(struct fw_dump *fadump_conf) 219 { 220 int err = 0; 221 s64 ret; 222 223 /* 224 * Use the last page(s) in FADump memory reservation for 225 * kernel metadata. 226 */ 227 fadump_conf->kernel_metadata = (fadump_conf->reserve_dump_area_start + 228 fadump_conf->reserve_dump_area_size - 229 opal_fadump_get_metadata_size()); 230 pr_info("Kernel metadata addr: %llx\n", fadump_conf->kernel_metadata); 231 232 /* Initialize kernel metadata before registering the address with f/w */ 233 opal_fdm = __va(fadump_conf->kernel_metadata); 234 opal_fadump_init_metadata(opal_fdm); 235 236 /* 237 * Register metadata address with f/w. Can be retrieved in 238 * the capture kernel. 239 */ 240 ret = opal_mpipl_register_tag(OPAL_MPIPL_TAG_KERNEL, 241 fadump_conf->kernel_metadata); 242 if (ret != OPAL_SUCCESS) { 243 pr_err("Failed to set kernel metadata tag!\n"); 244 err = -EPERM; 245 } 246 247 /* 248 * Register boot memory top address with f/w. Should be retrieved 249 * by a kernel that intends to preserve crash'ed kernel's memory. 250 */ 251 ret = opal_mpipl_register_tag(OPAL_MPIPL_TAG_BOOT_MEM, 252 fadump_conf->boot_memory_size); 253 if (ret != OPAL_SUCCESS) { 254 pr_err("Failed to set boot memory tag!\n"); 255 err = -EPERM; 256 } 257 258 return err; 259 } 260 261 static int opal_fadump_register(struct fw_dump *fadump_conf) 262 { 263 s64 rc = OPAL_PARAMETER; 264 int i, err = -EIO; 265 266 for (i = 0; i < opal_fdm->region_cnt; i++) { 267 rc = opal_mpipl_update(OPAL_MPIPL_ADD_RANGE, 268 opal_fdm->rgn[i].src, 269 opal_fdm->rgn[i].dest, 270 opal_fdm->rgn[i].size); 271 if (rc != OPAL_SUCCESS) 272 break; 273 274 opal_fdm->registered_regions++; 275 } 276 277 switch (rc) { 278 case OPAL_SUCCESS: 279 pr_info("Registration is successful!\n"); 280 fadump_conf->dump_registered = 1; 281 err = 0; 282 break; 283 case OPAL_RESOURCE: 284 /* If MAX regions limit in f/w is hit, warn and proceed. */ 285 pr_warn("%d regions could not be registered for MPIPL as MAX limit is reached!\n", 286 (opal_fdm->region_cnt - opal_fdm->registered_regions)); 287 fadump_conf->dump_registered = 1; 288 err = 0; 289 break; 290 case OPAL_PARAMETER: 291 pr_err("Failed to register. Parameter Error(%lld).\n", rc); 292 break; 293 case OPAL_HARDWARE: 294 pr_err("Support not available.\n"); 295 fadump_conf->fadump_supported = 0; 296 fadump_conf->fadump_enabled = 0; 297 break; 298 default: 299 pr_err("Failed to register. Unknown Error(%lld).\n", rc); 300 break; 301 } 302 303 /* 304 * If some regions were registered before OPAL_MPIPL_ADD_RANGE 305 * OPAL call failed, unregister all regions. 306 */ 307 if ((err < 0) && (opal_fdm->registered_regions > 0)) 308 opal_fadump_unregister(fadump_conf); 309 310 return err; 311 } 312 313 static int opal_fadump_unregister(struct fw_dump *fadump_conf) 314 { 315 s64 rc; 316 317 rc = opal_mpipl_update(OPAL_MPIPL_REMOVE_ALL, 0, 0, 0); 318 if (rc) { 319 pr_err("Failed to un-register - unexpected Error(%lld).\n", rc); 320 return -EIO; 321 } 322 323 opal_fdm->registered_regions = 0; 324 fadump_conf->dump_registered = 0; 325 return 0; 326 } 327 328 static int opal_fadump_invalidate(struct fw_dump *fadump_conf) 329 { 330 s64 rc; 331 332 rc = opal_mpipl_update(OPAL_MPIPL_FREE_PRESERVED_MEMORY, 0, 0, 0); 333 if (rc) { 334 pr_err("Failed to invalidate - unexpected Error(%lld).\n", rc); 335 return -EIO; 336 } 337 338 fadump_conf->dump_active = 0; 339 opal_fdm_active = NULL; 340 return 0; 341 } 342 343 static void opal_fadump_cleanup(struct fw_dump *fadump_conf) 344 { 345 s64 ret; 346 347 ret = opal_mpipl_register_tag(OPAL_MPIPL_TAG_KERNEL, 0); 348 if (ret != OPAL_SUCCESS) 349 pr_warn("Could not reset (%llu) kernel metadata tag!\n", ret); 350 } 351 352 static inline void opal_fadump_set_regval_regnum(struct pt_regs *regs, 353 u32 reg_type, u32 reg_num, 354 u64 reg_val) 355 { 356 if (reg_type == HDAT_FADUMP_REG_TYPE_GPR) { 357 if (reg_num < 32) 358 regs->gpr[reg_num] = reg_val; 359 return; 360 } 361 362 switch (reg_num) { 363 case SPRN_CTR: 364 regs->ctr = reg_val; 365 break; 366 case SPRN_LR: 367 regs->link = reg_val; 368 break; 369 case SPRN_XER: 370 regs->xer = reg_val; 371 break; 372 case SPRN_DAR: 373 regs->dar = reg_val; 374 break; 375 case SPRN_DSISR: 376 regs->dsisr = reg_val; 377 break; 378 case HDAT_FADUMP_REG_ID_NIP: 379 regs->nip = reg_val; 380 break; 381 case HDAT_FADUMP_REG_ID_MSR: 382 regs->msr = reg_val; 383 break; 384 case HDAT_FADUMP_REG_ID_CCR: 385 regs->ccr = reg_val; 386 break; 387 } 388 } 389 390 static inline void opal_fadump_read_regs(char *bufp, unsigned int regs_cnt, 391 unsigned int reg_entry_size, 392 struct pt_regs *regs) 393 { 394 struct hdat_fadump_reg_entry *reg_entry; 395 int i; 396 397 memset(regs, 0, sizeof(struct pt_regs)); 398 399 for (i = 0; i < regs_cnt; i++, bufp += reg_entry_size) { 400 reg_entry = (struct hdat_fadump_reg_entry *)bufp; 401 opal_fadump_set_regval_regnum(regs, 402 be32_to_cpu(reg_entry->reg_type), 403 be32_to_cpu(reg_entry->reg_num), 404 be64_to_cpu(reg_entry->reg_val)); 405 } 406 } 407 408 /* 409 * Verify if CPU state data is available. If available, do a bit of sanity 410 * checking before processing this data. 411 */ 412 static bool __init is_opal_fadump_cpu_data_valid(struct fw_dump *fadump_conf) 413 { 414 if (!opal_cpu_metadata) 415 return false; 416 417 fadump_conf->cpu_state_data_version = 418 be32_to_cpu(opal_cpu_metadata->cpu_data_version); 419 fadump_conf->cpu_state_entry_size = 420 be32_to_cpu(opal_cpu_metadata->cpu_data_size); 421 fadump_conf->cpu_state_dest_vaddr = 422 (u64)__va(be64_to_cpu(opal_cpu_metadata->region[0].dest)); 423 fadump_conf->cpu_state_data_size = 424 be64_to_cpu(opal_cpu_metadata->region[0].size); 425 426 if (fadump_conf->cpu_state_data_version != HDAT_FADUMP_CPU_DATA_VER) { 427 pr_warn("Supported CPU state data version: %u, found: %d!\n", 428 HDAT_FADUMP_CPU_DATA_VER, 429 fadump_conf->cpu_state_data_version); 430 pr_warn("WARNING: F/W using newer CPU state data format!!\n"); 431 } 432 433 if ((fadump_conf->cpu_state_dest_vaddr == 0) || 434 (fadump_conf->cpu_state_entry_size == 0) || 435 (fadump_conf->cpu_state_entry_size > 436 fadump_conf->cpu_state_data_size)) { 437 pr_err("CPU state data is invalid. Ignoring!\n"); 438 return false; 439 } 440 441 return true; 442 } 443 444 /* 445 * Convert CPU state data saved at the time of crash into ELF notes. 446 * 447 * While the crashing CPU's register data is saved by the kernel, CPU state 448 * data for all CPUs is saved by f/w. In CPU state data provided by f/w, 449 * each register entry is of 16 bytes, a numerical identifier along with 450 * a GPR/SPR flag in the first 8 bytes and the register value in the next 451 * 8 bytes. For more details refer to F/W documentation. If this data is 452 * missing or in unsupported format, append crashing CPU's register data 453 * saved by the kernel in the PT_NOTE, to have something to work with in 454 * the vmcore file. 455 */ 456 static int __init 457 opal_fadump_build_cpu_notes(struct fw_dump *fadump_conf, 458 struct fadump_crash_info_header *fdh) 459 { 460 u32 thread_pir, size_per_thread, regs_offset, regs_cnt, reg_esize; 461 struct hdat_fadump_thread_hdr *thdr; 462 bool is_cpu_data_valid = false; 463 u32 num_cpus = 1, *note_buf; 464 struct pt_regs regs; 465 char *bufp; 466 int rc, i; 467 468 if (is_opal_fadump_cpu_data_valid(fadump_conf)) { 469 size_per_thread = fadump_conf->cpu_state_entry_size; 470 num_cpus = (fadump_conf->cpu_state_data_size / size_per_thread); 471 bufp = __va(fadump_conf->cpu_state_dest_vaddr); 472 is_cpu_data_valid = true; 473 } 474 475 rc = fadump_setup_cpu_notes_buf(num_cpus); 476 if (rc != 0) 477 return rc; 478 479 note_buf = (u32 *)fadump_conf->cpu_notes_buf_vaddr; 480 if (!is_cpu_data_valid) 481 goto out; 482 483 /* 484 * Offset for register entries, entry size and registers count is 485 * duplicated in every thread header in keeping with HDAT format. 486 * Use these values from the first thread header. 487 */ 488 thdr = (struct hdat_fadump_thread_hdr *)bufp; 489 regs_offset = (offsetof(struct hdat_fadump_thread_hdr, offset) + 490 be32_to_cpu(thdr->offset)); 491 reg_esize = be32_to_cpu(thdr->esize); 492 regs_cnt = be32_to_cpu(thdr->ecnt); 493 494 pr_debug("--------CPU State Data------------\n"); 495 pr_debug("NumCpus : %u\n", num_cpus); 496 pr_debug("\tOffset: %u, Entry size: %u, Cnt: %u\n", 497 regs_offset, reg_esize, regs_cnt); 498 499 for (i = 0; i < num_cpus; i++, bufp += size_per_thread) { 500 thdr = (struct hdat_fadump_thread_hdr *)bufp; 501 502 thread_pir = be32_to_cpu(thdr->pir); 503 pr_debug("[%04d] PIR: 0x%x, core state: 0x%02x\n", 504 i, thread_pir, thdr->core_state); 505 506 /* 507 * If this is kernel initiated crash, crashing_cpu would be set 508 * appropriately and register data of the crashing CPU saved by 509 * crashing kernel. Add this saved register data of crashing CPU 510 * to elf notes and populate the pt_regs for the remaining CPUs 511 * from register state data provided by firmware. 512 */ 513 if (fdh->crashing_cpu == thread_pir) { 514 note_buf = fadump_regs_to_elf_notes(note_buf, 515 &fdh->regs); 516 pr_debug("Crashing CPU PIR: 0x%x - R1 : 0x%lx, NIP : 0x%lx\n", 517 fdh->crashing_cpu, fdh->regs.gpr[1], 518 fdh->regs.nip); 519 continue; 520 } 521 522 /* 523 * Register state data of MAX cores is provided by firmware, 524 * but some of this cores may not be active. So, while 525 * processing register state data, check core state and 526 * skip threads that belong to inactive cores. 527 */ 528 if (thdr->core_state == HDAT_FADUMP_CORE_INACTIVE) 529 continue; 530 531 opal_fadump_read_regs((bufp + regs_offset), regs_cnt, 532 reg_esize, ®s); 533 note_buf = fadump_regs_to_elf_notes(note_buf, ®s); 534 pr_debug("CPU PIR: 0x%x - R1 : 0x%lx, NIP : 0x%lx\n", 535 thread_pir, regs.gpr[1], regs.nip); 536 } 537 538 out: 539 /* 540 * CPU state data is invalid/unsupported. Try appending crashing CPU's 541 * register data, if it is saved by the kernel. 542 */ 543 if (fadump_conf->cpu_notes_buf_vaddr == (u64)note_buf) { 544 if (fdh->crashing_cpu == FADUMP_CPU_UNKNOWN) { 545 fadump_free_cpu_notes_buf(); 546 return -ENODEV; 547 } 548 549 pr_warn("WARNING: appending only crashing CPU's register data\n"); 550 note_buf = fadump_regs_to_elf_notes(note_buf, &(fdh->regs)); 551 } 552 553 final_note(note_buf); 554 555 pr_debug("Updating elfcore header (%llx) with cpu notes\n", 556 fdh->elfcorehdr_addr); 557 fadump_update_elfcore_header(__va(fdh->elfcorehdr_addr)); 558 return 0; 559 } 560 561 static int __init opal_fadump_process(struct fw_dump *fadump_conf) 562 { 563 struct fadump_crash_info_header *fdh; 564 int rc = -EINVAL; 565 566 if (!opal_fdm_active || !fadump_conf->fadumphdr_addr) 567 return rc; 568 569 /* Validate the fadump crash info header */ 570 fdh = __va(fadump_conf->fadumphdr_addr); 571 if (fdh->magic_number != FADUMP_CRASH_INFO_MAGIC) { 572 pr_err("Crash info header is not valid.\n"); 573 return rc; 574 } 575 576 rc = opal_fadump_build_cpu_notes(fadump_conf, fdh); 577 if (rc) 578 return rc; 579 580 /* 581 * We are done validating dump info and elfcore header is now ready 582 * to be exported. set elfcorehdr_addr so that vmcore module will 583 * export the elfcore header through '/proc/vmcore'. 584 */ 585 elfcorehdr_addr = fdh->elfcorehdr_addr; 586 587 return rc; 588 } 589 590 static void opal_fadump_region_show(struct fw_dump *fadump_conf, 591 struct seq_file *m) 592 { 593 const struct opal_fadump_mem_struct *fdm_ptr; 594 u64 dumped_bytes = 0; 595 int i; 596 597 if (fadump_conf->dump_active) 598 fdm_ptr = opal_fdm_active; 599 else 600 fdm_ptr = opal_fdm; 601 602 for (i = 0; i < fdm_ptr->region_cnt; i++) { 603 /* 604 * Only regions that are registered for MPIPL 605 * would have dump data. 606 */ 607 if ((fadump_conf->dump_active) && 608 (i < fdm_ptr->registered_regions)) 609 dumped_bytes = fdm_ptr->rgn[i].size; 610 611 seq_printf(m, "DUMP: Src: %#016llx, Dest: %#016llx, ", 612 fdm_ptr->rgn[i].src, fdm_ptr->rgn[i].dest); 613 seq_printf(m, "Size: %#llx, Dumped: %#llx bytes\n", 614 fdm_ptr->rgn[i].size, dumped_bytes); 615 } 616 617 /* Dump is active. Show reserved area start address. */ 618 if (fadump_conf->dump_active) { 619 seq_printf(m, "\nMemory above %#016lx is reserved for saving crash dump\n", 620 fadump_conf->reserve_dump_area_start); 621 } 622 } 623 624 static void opal_fadump_trigger(struct fadump_crash_info_header *fdh, 625 const char *msg) 626 { 627 int rc; 628 629 /* 630 * Unlike on pSeries platform, logical CPU number is not provided 631 * with architected register state data. So, store the crashing 632 * CPU's PIR instead to plug the appropriate register data for 633 * crashing CPU in the vmcore file. 634 */ 635 fdh->crashing_cpu = (u32)mfspr(SPRN_PIR); 636 637 rc = opal_cec_reboot2(OPAL_REBOOT_MPIPL, msg); 638 if (rc == OPAL_UNSUPPORTED) { 639 pr_emerg("Reboot type %d not supported.\n", 640 OPAL_REBOOT_MPIPL); 641 } else if (rc == OPAL_HARDWARE) 642 pr_emerg("No backend support for MPIPL!\n"); 643 } 644 645 static struct fadump_ops opal_fadump_ops = { 646 .fadump_init_mem_struct = opal_fadump_init_mem_struct, 647 .fadump_get_metadata_size = opal_fadump_get_metadata_size, 648 .fadump_setup_metadata = opal_fadump_setup_metadata, 649 .fadump_register = opal_fadump_register, 650 .fadump_unregister = opal_fadump_unregister, 651 .fadump_invalidate = opal_fadump_invalidate, 652 .fadump_cleanup = opal_fadump_cleanup, 653 .fadump_process = opal_fadump_process, 654 .fadump_region_show = opal_fadump_region_show, 655 .fadump_trigger = opal_fadump_trigger, 656 }; 657 658 void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node) 659 { 660 const __be32 *prop; 661 unsigned long dn; 662 u64 addr = 0; 663 s64 ret; 664 665 666 /* 667 * Check if Firmware-Assisted Dump is supported. if yes, check 668 * if dump has been initiated on last reboot. 669 */ 670 dn = of_get_flat_dt_subnode_by_name(node, "dump"); 671 if (dn == -FDT_ERR_NOTFOUND) { 672 pr_debug("FADump support is missing!\n"); 673 return; 674 } 675 676 if (!of_flat_dt_is_compatible(dn, "ibm,opal-dump")) { 677 pr_err("Support missing for this f/w version!\n"); 678 return; 679 } 680 681 fadump_conf->ops = &opal_fadump_ops; 682 fadump_conf->fadump_supported = 1; 683 684 /* 685 * Check if dump has been initiated on last reboot. 686 */ 687 prop = of_get_flat_dt_prop(dn, "mpipl-boot", NULL); 688 if (!prop) 689 return; 690 691 ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_KERNEL, &addr); 692 if ((ret != OPAL_SUCCESS) || !addr) { 693 pr_err("Failed to get Kernel metadata (%lld)\n", ret); 694 return; 695 } 696 697 addr = be64_to_cpu(addr); 698 pr_debug("Kernel metadata addr: %llx\n", addr); 699 700 opal_fdm_active = __va(addr); 701 if (opal_fdm_active->version != OPAL_FADUMP_VERSION) { 702 pr_warn("Supported kernel metadata version: %u, found: %d!\n", 703 OPAL_FADUMP_VERSION, opal_fdm_active->version); 704 pr_warn("WARNING: Kernel metadata format mismatch identified! Core file maybe corrupted..\n"); 705 } 706 707 /* Kernel regions not registered with f/w for MPIPL */ 708 if (opal_fdm_active->registered_regions == 0) { 709 opal_fdm_active = NULL; 710 return; 711 } 712 713 ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, &addr); 714 if (addr) { 715 addr = be64_to_cpu(addr); 716 pr_debug("CPU metadata addr: %llx\n", addr); 717 opal_cpu_metadata = __va(addr); 718 } 719 720 pr_info("Firmware-assisted dump is active.\n"); 721 fadump_conf->dump_active = 1; 722 opal_fadump_get_config(fadump_conf, opal_fdm_active); 723 } 724 #endif /* !CONFIG_PRESERVE_FA_DUMP */ 725