linux/arch/powerpc/platforms/pseries/rtas-fadump.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Firmware-Assisted Dump support on POWERVM platform.
   4 *
   5 * Copyright 2011, Mahesh Salgaonkar, IBM Corporation.
   6 * Copyright 2019, Hari Bathini, IBM Corporation.
   7 */
   8
   9#define pr_fmt(fmt) "rtas fadump: " fmt
  10
  11#include <linux/string.h>
  12#include <linux/memblock.h>
  13#include <linux/delay.h>
  14#include <linux/seq_file.h>
  15#include <linux/crash_dump.h>
  16
  17#include <asm/page.h>
  18#include <asm/prom.h>
  19#include <asm/rtas.h>
  20#include <asm/fadump.h>
  21#include <asm/fadump-internal.h>
  22
  23#include "rtas-fadump.h"
  24
  25static struct rtas_fadump_mem_struct fdm;
  26static const struct rtas_fadump_mem_struct *fdm_active;
  27
  28static void rtas_fadump_update_config(struct fw_dump *fadump_conf,
  29                                      const struct rtas_fadump_mem_struct *fdm)
  30{
  31        fadump_conf->boot_mem_dest_addr =
  32                be64_to_cpu(fdm->rmr_region.destination_address);
  33
  34        fadump_conf->fadumphdr_addr = (fadump_conf->boot_mem_dest_addr +
  35                                       fadump_conf->boot_memory_size);
  36}
  37
  38/*
  39 * This function is called in the capture kernel to get configuration details
  40 * setup in the first kernel and passed to the f/w.
  41 */
  42static void rtas_fadump_get_config(struct fw_dump *fadump_conf,
  43                                   const struct rtas_fadump_mem_struct *fdm)
  44{
  45        fadump_conf->boot_mem_addr[0] =
  46                be64_to_cpu(fdm->rmr_region.source_address);
  47        fadump_conf->boot_mem_sz[0] = be64_to_cpu(fdm->rmr_region.source_len);
  48        fadump_conf->boot_memory_size = fadump_conf->boot_mem_sz[0];
  49
  50        fadump_conf->boot_mem_top = fadump_conf->boot_memory_size;
  51        fadump_conf->boot_mem_regs_cnt = 1;
  52
  53        /*
  54         * Start address of reserve dump area (permanent reservation) for
  55         * re-registering FADump after dump capture.
  56         */
  57        fadump_conf->reserve_dump_area_start =
  58                be64_to_cpu(fdm->cpu_state_data.destination_address);
  59
  60        rtas_fadump_update_config(fadump_conf, fdm);
  61}
  62
  63static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf)
  64{
  65        u64 addr = fadump_conf->reserve_dump_area_start;
  66
  67        memset(&fdm, 0, sizeof(struct rtas_fadump_mem_struct));
  68        addr = addr & PAGE_MASK;
  69
  70        fdm.header.dump_format_version = cpu_to_be32(0x00000001);
  71        fdm.header.dump_num_sections = cpu_to_be16(3);
  72        fdm.header.dump_status_flag = 0;
  73        fdm.header.offset_first_dump_section =
  74                cpu_to_be32((u32)offsetof(struct rtas_fadump_mem_struct,
  75                                          cpu_state_data));
  76
  77        /*
  78         * Fields for disk dump option.
  79         * We are not using disk dump option, hence set these fields to 0.
  80         */
  81        fdm.header.dd_block_size = 0;
  82        fdm.header.dd_block_offset = 0;
  83        fdm.header.dd_num_blocks = 0;
  84        fdm.header.dd_offset_disk_path = 0;
  85
  86        /* set 0 to disable an automatic dump-reboot. */
  87        fdm.header.max_time_auto = 0;
  88
  89        /* Kernel dump sections */
  90        /* cpu state data section. */
  91        fdm.cpu_state_data.request_flag =
  92                cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
  93        fdm.cpu_state_data.source_data_type =
  94                cpu_to_be16(RTAS_FADUMP_CPU_STATE_DATA);
  95        fdm.cpu_state_data.source_address = 0;
  96        fdm.cpu_state_data.source_len =
  97                cpu_to_be64(fadump_conf->cpu_state_data_size);
  98        fdm.cpu_state_data.destination_address = cpu_to_be64(addr);
  99        addr += fadump_conf->cpu_state_data_size;
 100
 101        /* hpte region section */
 102        fdm.hpte_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
 103        fdm.hpte_region.source_data_type =
 104                cpu_to_be16(RTAS_FADUMP_HPTE_REGION);
 105        fdm.hpte_region.source_address = 0;
 106        fdm.hpte_region.source_len =
 107                cpu_to_be64(fadump_conf->hpte_region_size);
 108        fdm.hpte_region.destination_address = cpu_to_be64(addr);
 109        addr += fadump_conf->hpte_region_size;
 110
 111        /* RMA region section */
 112        fdm.rmr_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
 113        fdm.rmr_region.source_data_type =
 114                cpu_to_be16(RTAS_FADUMP_REAL_MODE_REGION);
 115        fdm.rmr_region.source_address = cpu_to_be64(0);
 116        fdm.rmr_region.source_len = cpu_to_be64(fadump_conf->boot_memory_size);
 117        fdm.rmr_region.destination_address = cpu_to_be64(addr);
 118        addr += fadump_conf->boot_memory_size;
 119
 120        rtas_fadump_update_config(fadump_conf, &fdm);
 121
 122        return addr;
 123}
 124
 125static u64 rtas_fadump_get_bootmem_min(void)
 126{
 127        return RTAS_FADUMP_MIN_BOOT_MEM;
 128}
 129
 130static int rtas_fadump_register(struct fw_dump *fadump_conf)
 131{
 132        unsigned int wait_time;
 133        int rc, err = -EIO;
 134
 135        /* TODO: Add upper time limit for the delay */
 136        do {
 137                rc =  rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
 138                                NULL, FADUMP_REGISTER, &fdm,
 139                                sizeof(struct rtas_fadump_mem_struct));
 140
 141                wait_time = rtas_busy_delay_time(rc);
 142                if (wait_time)
 143                        mdelay(wait_time);
 144
 145        } while (wait_time);
 146
 147        switch (rc) {
 148        case 0:
 149                pr_info("Registration is successful!\n");
 150                fadump_conf->dump_registered = 1;
 151                err = 0;
 152                break;
 153        case -1:
 154                pr_err("Failed to register. Hardware Error(%d).\n", rc);
 155                break;
 156        case -3:
 157                if (!is_fadump_boot_mem_contiguous())
 158                        pr_err("Can't have holes in boot memory area.\n");
 159                else if (!is_fadump_reserved_mem_contiguous())
 160                        pr_err("Can't have holes in reserved memory area.\n");
 161
 162                pr_err("Failed to register. Parameter Error(%d).\n", rc);
 163                err = -EINVAL;
 164                break;
 165        case -9:
 166                pr_err("Already registered!\n");
 167                fadump_conf->dump_registered = 1;
 168                err = -EEXIST;
 169                break;
 170        default:
 171                pr_err("Failed to register. Unknown Error(%d).\n", rc);
 172                break;
 173        }
 174
 175        return err;
 176}
 177
 178static int rtas_fadump_unregister(struct fw_dump *fadump_conf)
 179{
 180        unsigned int wait_time;
 181        int rc;
 182
 183        /* TODO: Add upper time limit for the delay */
 184        do {
 185                rc =  rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
 186                                NULL, FADUMP_UNREGISTER, &fdm,
 187                                sizeof(struct rtas_fadump_mem_struct));
 188
 189                wait_time = rtas_busy_delay_time(rc);
 190                if (wait_time)
 191                        mdelay(wait_time);
 192        } while (wait_time);
 193
 194        if (rc) {
 195                pr_err("Failed to un-register - unexpected error(%d).\n", rc);
 196                return -EIO;
 197        }
 198
 199        fadump_conf->dump_registered = 0;
 200        return 0;
 201}
 202
 203static int rtas_fadump_invalidate(struct fw_dump *fadump_conf)
 204{
 205        unsigned int wait_time;
 206        int rc;
 207
 208        /* TODO: Add upper time limit for the delay */
 209        do {
 210                rc =  rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
 211                                NULL, FADUMP_INVALIDATE, fdm_active,
 212                                sizeof(struct rtas_fadump_mem_struct));
 213
 214                wait_time = rtas_busy_delay_time(rc);
 215                if (wait_time)
 216                        mdelay(wait_time);
 217        } while (wait_time);
 218
 219        if (rc) {
 220                pr_err("Failed to invalidate - unexpected error (%d).\n", rc);
 221                return -EIO;
 222        }
 223
 224        fadump_conf->dump_active = 0;
 225        fdm_active = NULL;
 226        return 0;
 227}
 228
 229#define RTAS_FADUMP_GPR_MASK            0xffffff0000000000
 230static inline int rtas_fadump_gpr_index(u64 id)
 231{
 232        char str[3];
 233        int i = -1;
 234
 235        if ((id & RTAS_FADUMP_GPR_MASK) == fadump_str_to_u64("GPR")) {
 236                /* get the digits at the end */
 237                id &= ~RTAS_FADUMP_GPR_MASK;
 238                id >>= 24;
 239                str[2] = '\0';
 240                str[1] = id & 0xff;
 241                str[0] = (id >> 8) & 0xff;
 242                if (kstrtoint(str, 10, &i))
 243                        i = -EINVAL;
 244                if (i > 31)
 245                        i = -1;
 246        }
 247        return i;
 248}
 249
 250static void rtas_fadump_set_regval(struct pt_regs *regs, u64 reg_id, u64 reg_val)
 251{
 252        int i;
 253
 254        i = rtas_fadump_gpr_index(reg_id);
 255        if (i >= 0)
 256                regs->gpr[i] = (unsigned long)reg_val;
 257        else if (reg_id == fadump_str_to_u64("NIA"))
 258                regs->nip = (unsigned long)reg_val;
 259        else if (reg_id == fadump_str_to_u64("MSR"))
 260                regs->msr = (unsigned long)reg_val;
 261        else if (reg_id == fadump_str_to_u64("CTR"))
 262                regs->ctr = (unsigned long)reg_val;
 263        else if (reg_id == fadump_str_to_u64("LR"))
 264                regs->link = (unsigned long)reg_val;
 265        else if (reg_id == fadump_str_to_u64("XER"))
 266                regs->xer = (unsigned long)reg_val;
 267        else if (reg_id == fadump_str_to_u64("CR"))
 268                regs->ccr = (unsigned long)reg_val;
 269        else if (reg_id == fadump_str_to_u64("DAR"))
 270                regs->dar = (unsigned long)reg_val;
 271        else if (reg_id == fadump_str_to_u64("DSISR"))
 272                regs->dsisr = (unsigned long)reg_val;
 273}
 274
 275static struct rtas_fadump_reg_entry*
 276rtas_fadump_read_regs(struct rtas_fadump_reg_entry *reg_entry,
 277                      struct pt_regs *regs)
 278{
 279        memset(regs, 0, sizeof(struct pt_regs));
 280
 281        while (be64_to_cpu(reg_entry->reg_id) != fadump_str_to_u64("CPUEND")) {
 282                rtas_fadump_set_regval(regs, be64_to_cpu(reg_entry->reg_id),
 283                                       be64_to_cpu(reg_entry->reg_value));
 284                reg_entry++;
 285        }
 286        reg_entry++;
 287        return reg_entry;
 288}
 289
 290/*
 291 * Read CPU state dump data and convert it into ELF notes.
 292 * The CPU dump starts with magic number "REGSAVE". NumCpusOffset should be
 293 * used to access the data to allow for additional fields to be added without
 294 * affecting compatibility. Each list of registers for a CPU starts with
 295 * "CPUSTRT" and ends with "CPUEND". Each register entry is of 16 bytes,
 296 * 8 Byte ASCII identifier and 8 Byte register value. The register entry
 297 * with identifier "CPUSTRT" and "CPUEND" contains 4 byte cpu id as part
 298 * of register value. For more details refer to PAPR document.
 299 *
 300 * Only for the crashing cpu we ignore the CPU dump data and get exact
 301 * state from fadump crash info structure populated by first kernel at the
 302 * time of crash.
 303 */
 304static int __init rtas_fadump_build_cpu_notes(struct fw_dump *fadump_conf)
 305{
 306        struct rtas_fadump_reg_save_area_header *reg_header;
 307        struct fadump_crash_info_header *fdh = NULL;
 308        struct rtas_fadump_reg_entry *reg_entry;
 309        u32 num_cpus, *note_buf;
 310        int i, rc = 0, cpu = 0;
 311        struct pt_regs regs;
 312        unsigned long addr;
 313        void *vaddr;
 314
 315        addr = be64_to_cpu(fdm_active->cpu_state_data.destination_address);
 316        vaddr = __va(addr);
 317
 318        reg_header = vaddr;
 319        if (be64_to_cpu(reg_header->magic_number) !=
 320            fadump_str_to_u64("REGSAVE")) {
 321                pr_err("Unable to read register save area.\n");
 322                return -ENOENT;
 323        }
 324
 325        pr_debug("--------CPU State Data------------\n");
 326        pr_debug("Magic Number: %llx\n", be64_to_cpu(reg_header->magic_number));
 327        pr_debug("NumCpuOffset: %x\n", be32_to_cpu(reg_header->num_cpu_offset));
 328
 329        vaddr += be32_to_cpu(reg_header->num_cpu_offset);
 330        num_cpus = be32_to_cpu(*((__be32 *)(vaddr)));
 331        pr_debug("NumCpus     : %u\n", num_cpus);
 332        vaddr += sizeof(u32);
 333        reg_entry = (struct rtas_fadump_reg_entry *)vaddr;
 334
 335        rc = fadump_setup_cpu_notes_buf(num_cpus);
 336        if (rc != 0)
 337                return rc;
 338
 339        note_buf = (u32 *)fadump_conf->cpu_notes_buf_vaddr;
 340
 341        if (fadump_conf->fadumphdr_addr)
 342                fdh = __va(fadump_conf->fadumphdr_addr);
 343
 344        for (i = 0; i < num_cpus; i++) {
 345                if (be64_to_cpu(reg_entry->reg_id) !=
 346                    fadump_str_to_u64("CPUSTRT")) {
 347                        pr_err("Unable to read CPU state data\n");
 348                        rc = -ENOENT;
 349                        goto error_out;
 350                }
 351                /* Lower 4 bytes of reg_value contains logical cpu id */
 352                cpu = (be64_to_cpu(reg_entry->reg_value) &
 353                       RTAS_FADUMP_CPU_ID_MASK);
 354                if (fdh && !cpumask_test_cpu(cpu, &fdh->online_mask)) {
 355                        RTAS_FADUMP_SKIP_TO_NEXT_CPU(reg_entry);
 356                        continue;
 357                }
 358                pr_debug("Reading register data for cpu %d...\n", cpu);
 359                if (fdh && fdh->crashing_cpu == cpu) {
 360                        regs = fdh->regs;
 361                        note_buf = fadump_regs_to_elf_notes(note_buf, &regs);
 362                        RTAS_FADUMP_SKIP_TO_NEXT_CPU(reg_entry);
 363                } else {
 364                        reg_entry++;
 365                        reg_entry = rtas_fadump_read_regs(reg_entry, &regs);
 366                        note_buf = fadump_regs_to_elf_notes(note_buf, &regs);
 367                }
 368        }
 369        final_note(note_buf);
 370
 371        if (fdh) {
 372                pr_debug("Updating elfcore header (%llx) with cpu notes\n",
 373                         fdh->elfcorehdr_addr);
 374                fadump_update_elfcore_header(__va(fdh->elfcorehdr_addr));
 375        }
 376        return 0;
 377
 378error_out:
 379        fadump_free_cpu_notes_buf();
 380        return rc;
 381
 382}
 383
 384/*
 385 * Validate and process the dump data stored by firmware before exporting
 386 * it through '/proc/vmcore'.
 387 */
 388static int __init rtas_fadump_process(struct fw_dump *fadump_conf)
 389{
 390        struct fadump_crash_info_header *fdh;
 391        int rc = 0;
 392
 393        if (!fdm_active || !fadump_conf->fadumphdr_addr)
 394                return -EINVAL;
 395
 396        /* Check if the dump data is valid. */
 397        if ((be16_to_cpu(fdm_active->header.dump_status_flag) ==
 398                        RTAS_FADUMP_ERROR_FLAG) ||
 399                        (fdm_active->cpu_state_data.error_flags != 0) ||
 400                        (fdm_active->rmr_region.error_flags != 0)) {
 401                pr_err("Dump taken by platform is not valid\n");
 402                return -EINVAL;
 403        }
 404        if ((fdm_active->rmr_region.bytes_dumped !=
 405                        fdm_active->rmr_region.source_len) ||
 406                        !fdm_active->cpu_state_data.bytes_dumped) {
 407                pr_err("Dump taken by platform is incomplete\n");
 408                return -EINVAL;
 409        }
 410
 411        /* Validate the fadump crash info header */
 412        fdh = __va(fadump_conf->fadumphdr_addr);
 413        if (fdh->magic_number != FADUMP_CRASH_INFO_MAGIC) {
 414                pr_err("Crash info header is not valid.\n");
 415                return -EINVAL;
 416        }
 417
 418        rc = rtas_fadump_build_cpu_notes(fadump_conf);
 419        if (rc)
 420                return rc;
 421
 422        /*
 423         * We are done validating dump info and elfcore header is now ready
 424         * to be exported. set elfcorehdr_addr so that vmcore module will
 425         * export the elfcore header through '/proc/vmcore'.
 426         */
 427        elfcorehdr_addr = fdh->elfcorehdr_addr;
 428
 429        return 0;
 430}
 431
 432static void rtas_fadump_region_show(struct fw_dump *fadump_conf,
 433                                    struct seq_file *m)
 434{
 435        const struct rtas_fadump_section *cpu_data_section;
 436        const struct rtas_fadump_mem_struct *fdm_ptr;
 437
 438        if (fdm_active)
 439                fdm_ptr = fdm_active;
 440        else
 441                fdm_ptr = &fdm;
 442
 443        cpu_data_section = &(fdm_ptr->cpu_state_data);
 444        seq_printf(m, "CPU :[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
 445                   be64_to_cpu(cpu_data_section->destination_address),
 446                   be64_to_cpu(cpu_data_section->destination_address) +
 447                   be64_to_cpu(cpu_data_section->source_len) - 1,
 448                   be64_to_cpu(cpu_data_section->source_len),
 449                   be64_to_cpu(cpu_data_section->bytes_dumped));
 450
 451        seq_printf(m, "HPTE:[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
 452                   be64_to_cpu(fdm_ptr->hpte_region.destination_address),
 453                   be64_to_cpu(fdm_ptr->hpte_region.destination_address) +
 454                   be64_to_cpu(fdm_ptr->hpte_region.source_len) - 1,
 455                   be64_to_cpu(fdm_ptr->hpte_region.source_len),
 456                   be64_to_cpu(fdm_ptr->hpte_region.bytes_dumped));
 457
 458        seq_printf(m, "DUMP: Src: %#016llx, Dest: %#016llx, ",
 459                   be64_to_cpu(fdm_ptr->rmr_region.source_address),
 460                   be64_to_cpu(fdm_ptr->rmr_region.destination_address));
 461        seq_printf(m, "Size: %#llx, Dumped: %#llx bytes\n",
 462                   be64_to_cpu(fdm_ptr->rmr_region.source_len),
 463                   be64_to_cpu(fdm_ptr->rmr_region.bytes_dumped));
 464
 465        /* Dump is active. Show reserved area start address. */
 466        if (fdm_active) {
 467                seq_printf(m, "\nMemory above %#016lx is reserved for saving crash dump\n",
 468                           fadump_conf->reserve_dump_area_start);
 469        }
 470}
 471
 472static void rtas_fadump_trigger(struct fadump_crash_info_header *fdh,
 473                                const char *msg)
 474{
 475        /* Call ibm,os-term rtas call to trigger firmware assisted dump */
 476        rtas_os_term((char *)msg);
 477}
 478
 479static struct fadump_ops rtas_fadump_ops = {
 480        .fadump_init_mem_struct         = rtas_fadump_init_mem_struct,
 481        .fadump_get_bootmem_min         = rtas_fadump_get_bootmem_min,
 482        .fadump_register                = rtas_fadump_register,
 483        .fadump_unregister              = rtas_fadump_unregister,
 484        .fadump_invalidate              = rtas_fadump_invalidate,
 485        .fadump_process                 = rtas_fadump_process,
 486        .fadump_region_show             = rtas_fadump_region_show,
 487        .fadump_trigger                 = rtas_fadump_trigger,
 488};
 489
 490void __init rtas_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
 491{
 492        int i, size, num_sections;
 493        const __be32 *sections;
 494        const __be32 *token;
 495
 496        /*
 497         * Check if Firmware Assisted dump is supported. if yes, check
 498         * if dump has been initiated on last reboot.
 499         */
 500        token = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL);
 501        if (!token)
 502                return;
 503
 504        fadump_conf->ibm_configure_kernel_dump = be32_to_cpu(*token);
 505        fadump_conf->ops                = &rtas_fadump_ops;
 506        fadump_conf->fadump_supported   = 1;
 507
 508        /* Firmware supports 64-bit value for size, align it to pagesize. */
 509        fadump_conf->max_copy_size = ALIGN_DOWN(U64_MAX, PAGE_SIZE);
 510
 511        /*
 512         * The 'ibm,kernel-dump' rtas node is present only if there is
 513         * dump data waiting for us.
 514         */
 515        fdm_active = of_get_flat_dt_prop(node, "ibm,kernel-dump", NULL);
 516        if (fdm_active) {
 517                pr_info("Firmware-assisted dump is active.\n");
 518                fadump_conf->dump_active = 1;
 519                rtas_fadump_get_config(fadump_conf, (void *)__pa(fdm_active));
 520        }
 521
 522        /* Get the sizes required to store dump data for the firmware provided
 523         * dump sections.
 524         * For each dump section type supported, a 32bit cell which defines
 525         * the ID of a supported section followed by two 32 bit cells which
 526         * gives the size of the section in bytes.
 527         */
 528        sections = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes",
 529                                        &size);
 530
 531        if (!sections)
 532                return;
 533
 534        num_sections = size / (3 * sizeof(u32));
 535
 536        for (i = 0; i < num_sections; i++, sections += 3) {
 537                u32 type = (u32)of_read_number(sections, 1);
 538
 539                switch (type) {
 540                case RTAS_FADUMP_CPU_STATE_DATA:
 541                        fadump_conf->cpu_state_data_size =
 542                                        of_read_ulong(&sections[1], 2);
 543                        break;
 544                case RTAS_FADUMP_HPTE_REGION:
 545                        fadump_conf->hpte_region_size =
 546                                        of_read_ulong(&sections[1], 2);
 547                        break;
 548                }
 549        }
 550}
 551