root/arch/powerpc/platforms/powernv/opal-fadump.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. opal_fadump_dt_scan
  2. opal_fadump_update_config
  3. opal_fadump_get_config
  4. opal_fadump_init_metadata
  5. opal_fadump_init_mem_struct
  6. opal_fadump_get_metadata_size
  7. opal_fadump_setup_metadata
  8. opal_fadump_get_bootmem_min
  9. opal_fadump_register
  10. opal_fadump_unregister
  11. opal_fadump_invalidate
  12. opal_fadump_cleanup
  13. is_opal_fadump_cpu_data_valid
  14. opal_fadump_build_cpu_notes
  15. opal_fadump_process
  16. opal_fadump_region_show
  17. opal_fadump_trigger
  18. opal_fadump_dt_scan

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

/* [<][>][^][v][top][bottom][index][help] */