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 #include <linux/of.h> 17 #include <linux/of_fdt.h> 18 19 #include <asm/page.h> 20 #include <asm/rtas.h> 21 #include <asm/setup.h> 22 #include <asm/fadump.h> 23 #include <asm/fadump-internal.h> 24 25 #include "rtas-fadump.h" 26 27 static struct rtas_fadump_mem_struct fdm; 28 static const struct rtas_fadump_mem_struct *fdm_active; 29 30 static void rtas_fadump_update_config(struct fw_dump *fadump_conf, 31 const struct rtas_fadump_mem_struct *fdm) 32 { 33 fadump_conf->fadumphdr_addr = (fadump_conf->boot_mem_dest_addr + 34 fadump_conf->boot_memory_size); 35 } 36 37 /* 38 * This function is called in the capture kernel to get configuration details 39 * setup in the first kernel and passed to the f/w. 40 */ 41 static void __init rtas_fadump_get_config(struct fw_dump *fadump_conf, 42 const struct rtas_fadump_mem_struct *fdm) 43 { 44 unsigned long base, size, last_end, hole_size; 45 46 last_end = 0; 47 hole_size = 0; 48 fadump_conf->boot_memory_size = 0; 49 fadump_conf->boot_mem_regs_cnt = 0; 50 pr_debug("Boot memory regions:\n"); 51 for (int i = 0; i < be16_to_cpu(fdm->header.dump_num_sections); i++) { 52 int type = be16_to_cpu(fdm->rgn[i].source_data_type); 53 u64 addr; 54 55 switch (type) { 56 case RTAS_FADUMP_CPU_STATE_DATA: 57 addr = be64_to_cpu(fdm->rgn[i].destination_address); 58 59 fadump_conf->cpu_state_dest_vaddr = (u64)__va(addr); 60 /* 61 * Start address of reserve dump area (permanent reservation) for 62 * re-registering FADump after dump capture. 63 */ 64 fadump_conf->reserve_dump_area_start = addr; 65 break; 66 case RTAS_FADUMP_HPTE_REGION: 67 /* Not processed currently. */ 68 break; 69 case RTAS_FADUMP_REAL_MODE_REGION: 70 base = be64_to_cpu(fdm->rgn[i].source_address); 71 size = be64_to_cpu(fdm->rgn[i].source_len); 72 pr_debug("\t[%03d] base: 0x%lx, size: 0x%lx\n", i, base, size); 73 if (!base) { 74 fadump_conf->boot_mem_dest_addr = 75 be64_to_cpu(fdm->rgn[i].destination_address); 76 } 77 78 fadump_conf->boot_mem_addr[fadump_conf->boot_mem_regs_cnt] = base; 79 fadump_conf->boot_mem_sz[fadump_conf->boot_mem_regs_cnt] = size; 80 fadump_conf->boot_memory_size += size; 81 hole_size += (base - last_end); 82 last_end = base + size; 83 fadump_conf->boot_mem_regs_cnt++; 84 break; 85 case RTAS_FADUMP_PARAM_AREA: 86 fadump_conf->param_area = be64_to_cpu(fdm->rgn[i].destination_address); 87 break; 88 default: 89 pr_warn("Section type %d unsupported on this kernel. Ignoring!\n", type); 90 break; 91 } 92 } 93 fadump_conf->boot_mem_top = fadump_conf->boot_memory_size + hole_size; 94 95 rtas_fadump_update_config(fadump_conf, fdm); 96 } 97 98 static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf) 99 { 100 u64 addr = fadump_conf->reserve_dump_area_start; 101 u16 sec_cnt = 0; 102 103 memset(&fdm, 0, sizeof(struct rtas_fadump_mem_struct)); 104 addr = addr & PAGE_MASK; 105 106 fdm.header.dump_format_version = cpu_to_be32(0x00000001); 107 fdm.header.dump_status_flag = 0; 108 fdm.header.offset_first_dump_section = 109 cpu_to_be32((u32)offsetof(struct rtas_fadump_mem_struct, rgn)); 110 111 /* 112 * Fields for disk dump option. 113 * We are not using disk dump option, hence set these fields to 0. 114 */ 115 fdm.header.dd_block_size = 0; 116 fdm.header.dd_block_offset = 0; 117 fdm.header.dd_num_blocks = 0; 118 fdm.header.dd_offset_disk_path = 0; 119 120 /* set 0 to disable an automatic dump-reboot. */ 121 fdm.header.max_time_auto = 0; 122 123 /* Kernel dump sections */ 124 /* cpu state data section. */ 125 fdm.rgn[sec_cnt].request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG); 126 fdm.rgn[sec_cnt].source_data_type = cpu_to_be16(RTAS_FADUMP_CPU_STATE_DATA); 127 fdm.rgn[sec_cnt].source_address = 0; 128 fdm.rgn[sec_cnt].source_len = cpu_to_be64(fadump_conf->cpu_state_data_size); 129 fdm.rgn[sec_cnt].destination_address = cpu_to_be64(addr); 130 addr += fadump_conf->cpu_state_data_size; 131 sec_cnt++; 132 133 /* hpte region section */ 134 fdm.rgn[sec_cnt].request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG); 135 fdm.rgn[sec_cnt].source_data_type = cpu_to_be16(RTAS_FADUMP_HPTE_REGION); 136 fdm.rgn[sec_cnt].source_address = 0; 137 fdm.rgn[sec_cnt].source_len = cpu_to_be64(fadump_conf->hpte_region_size); 138 fdm.rgn[sec_cnt].destination_address = cpu_to_be64(addr); 139 addr += fadump_conf->hpte_region_size; 140 sec_cnt++; 141 142 /* 143 * Align boot memory area destination address to page boundary to 144 * be able to mmap read this area in the vmcore. 145 */ 146 addr = PAGE_ALIGN(addr); 147 148 /* First boot memory region destination address */ 149 fadump_conf->boot_mem_dest_addr = addr; 150 for (int i = 0; i < fadump_conf->boot_mem_regs_cnt; i++) { 151 /* Boot memory regions */ 152 fdm.rgn[sec_cnt].request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG); 153 fdm.rgn[sec_cnt].source_data_type = cpu_to_be16(RTAS_FADUMP_REAL_MODE_REGION); 154 fdm.rgn[sec_cnt].source_address = cpu_to_be64(fadump_conf->boot_mem_addr[i]); 155 fdm.rgn[sec_cnt].source_len = cpu_to_be64(fadump_conf->boot_mem_sz[i]); 156 fdm.rgn[sec_cnt].destination_address = cpu_to_be64(addr); 157 addr += fadump_conf->boot_mem_sz[i]; 158 sec_cnt++; 159 } 160 161 /* Parameters area */ 162 if (fadump_conf->param_area) { 163 fdm.rgn[sec_cnt].request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG); 164 fdm.rgn[sec_cnt].source_data_type = cpu_to_be16(RTAS_FADUMP_PARAM_AREA); 165 fdm.rgn[sec_cnt].source_address = cpu_to_be64(fadump_conf->param_area); 166 fdm.rgn[sec_cnt].source_len = cpu_to_be64(COMMAND_LINE_SIZE); 167 fdm.rgn[sec_cnt].destination_address = cpu_to_be64(fadump_conf->param_area); 168 sec_cnt++; 169 } 170 fdm.header.dump_num_sections = cpu_to_be16(sec_cnt); 171 172 rtas_fadump_update_config(fadump_conf, &fdm); 173 174 return addr; 175 } 176 177 static u64 rtas_fadump_get_bootmem_min(void) 178 { 179 return RTAS_FADUMP_MIN_BOOT_MEM; 180 } 181 182 static int rtas_fadump_register(struct fw_dump *fadump_conf) 183 { 184 unsigned int wait_time, fdm_size; 185 int rc, err = -EIO; 186 187 /* 188 * Platform requires the exact size of the Dump Memory Structure. 189 * Avoid including any unused rgns in the calculation, as this 190 * could result in a parameter error (-3) from the platform. 191 */ 192 fdm_size = sizeof(struct rtas_fadump_section_header); 193 fdm_size += be16_to_cpu(fdm.header.dump_num_sections) * sizeof(struct rtas_fadump_section); 194 195 /* TODO: Add upper time limit for the delay */ 196 do { 197 rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1, 198 NULL, FADUMP_REGISTER, &fdm, fdm_size); 199 200 wait_time = rtas_busy_delay_time(rc); 201 if (wait_time) 202 mdelay(wait_time); 203 204 } while (wait_time); 205 206 switch (rc) { 207 case 0: 208 pr_info("Registration is successful!\n"); 209 fadump_conf->dump_registered = 1; 210 err = 0; 211 break; 212 case -1: 213 pr_err("Failed to register. Hardware Error(%d).\n", rc); 214 break; 215 case -3: 216 if (!is_fadump_reserved_mem_contiguous()) 217 pr_err("Can't have holes in reserved memory area.\n"); 218 219 pr_err("Failed to register. Parameter Error(%d).\n", rc); 220 err = -EINVAL; 221 break; 222 case -9: 223 pr_err("Already registered!\n"); 224 fadump_conf->dump_registered = 1; 225 err = -EEXIST; 226 break; 227 default: 228 pr_err("Failed to register. Unknown Error(%d).\n", rc); 229 break; 230 } 231 232 return err; 233 } 234 235 static int rtas_fadump_unregister(struct fw_dump *fadump_conf) 236 { 237 unsigned int wait_time; 238 int rc; 239 240 /* TODO: Add upper time limit for the delay */ 241 do { 242 rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1, 243 NULL, FADUMP_UNREGISTER, &fdm, 244 sizeof(struct rtas_fadump_mem_struct)); 245 246 wait_time = rtas_busy_delay_time(rc); 247 if (wait_time) 248 mdelay(wait_time); 249 } while (wait_time); 250 251 if (rc) { 252 pr_err("Failed to un-register - unexpected error(%d).\n", rc); 253 return -EIO; 254 } 255 256 fadump_conf->dump_registered = 0; 257 return 0; 258 } 259 260 static int rtas_fadump_invalidate(struct fw_dump *fadump_conf) 261 { 262 unsigned int wait_time; 263 int rc; 264 265 /* TODO: Add upper time limit for the delay */ 266 do { 267 rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1, 268 NULL, FADUMP_INVALIDATE, fdm_active, 269 sizeof(struct rtas_fadump_mem_struct)); 270 271 wait_time = rtas_busy_delay_time(rc); 272 if (wait_time) 273 mdelay(wait_time); 274 } while (wait_time); 275 276 if (rc) { 277 pr_err("Failed to invalidate - unexpected error (%d).\n", rc); 278 return -EIO; 279 } 280 281 fadump_conf->dump_active = 0; 282 fdm_active = NULL; 283 return 0; 284 } 285 286 #define RTAS_FADUMP_GPR_MASK 0xffffff0000000000 287 static inline int rtas_fadump_gpr_index(u64 id) 288 { 289 char str[3]; 290 int i = -1; 291 292 if ((id & RTAS_FADUMP_GPR_MASK) == fadump_str_to_u64("GPR")) { 293 /* get the digits at the end */ 294 id &= ~RTAS_FADUMP_GPR_MASK; 295 id >>= 24; 296 str[2] = '\0'; 297 str[1] = id & 0xff; 298 str[0] = (id >> 8) & 0xff; 299 if (kstrtoint(str, 10, &i)) 300 i = -EINVAL; 301 if (i > 31) 302 i = -1; 303 } 304 return i; 305 } 306 307 static void __init rtas_fadump_set_regval(struct pt_regs *regs, u64 reg_id, u64 reg_val) 308 { 309 int i; 310 311 i = rtas_fadump_gpr_index(reg_id); 312 if (i >= 0) 313 regs->gpr[i] = (unsigned long)reg_val; 314 else if (reg_id == fadump_str_to_u64("NIA")) 315 regs->nip = (unsigned long)reg_val; 316 else if (reg_id == fadump_str_to_u64("MSR")) 317 regs->msr = (unsigned long)reg_val; 318 else if (reg_id == fadump_str_to_u64("CTR")) 319 regs->ctr = (unsigned long)reg_val; 320 else if (reg_id == fadump_str_to_u64("LR")) 321 regs->link = (unsigned long)reg_val; 322 else if (reg_id == fadump_str_to_u64("XER")) 323 regs->xer = (unsigned long)reg_val; 324 else if (reg_id == fadump_str_to_u64("CR")) 325 regs->ccr = (unsigned long)reg_val; 326 else if (reg_id == fadump_str_to_u64("DAR")) 327 regs->dar = (unsigned long)reg_val; 328 else if (reg_id == fadump_str_to_u64("DSISR")) 329 regs->dsisr = (unsigned long)reg_val; 330 } 331 332 static struct rtas_fadump_reg_entry* __init 333 rtas_fadump_read_regs(struct rtas_fadump_reg_entry *reg_entry, 334 struct pt_regs *regs) 335 { 336 memset(regs, 0, sizeof(struct pt_regs)); 337 338 while (be64_to_cpu(reg_entry->reg_id) != fadump_str_to_u64("CPUEND")) { 339 rtas_fadump_set_regval(regs, be64_to_cpu(reg_entry->reg_id), 340 be64_to_cpu(reg_entry->reg_value)); 341 reg_entry++; 342 } 343 reg_entry++; 344 return reg_entry; 345 } 346 347 /* 348 * Read CPU state dump data and convert it into ELF notes. 349 * The CPU dump starts with magic number "REGSAVE". NumCpusOffset should be 350 * used to access the data to allow for additional fields to be added without 351 * affecting compatibility. Each list of registers for a CPU starts with 352 * "CPUSTRT" and ends with "CPUEND". Each register entry is of 16 bytes, 353 * 8 Byte ASCII identifier and 8 Byte register value. The register entry 354 * with identifier "CPUSTRT" and "CPUEND" contains 4 byte cpu id as part 355 * of register value. For more details refer to PAPR document. 356 * 357 * Only for the crashing cpu we ignore the CPU dump data and get exact 358 * state from fadump crash info structure populated by first kernel at the 359 * time of crash. 360 */ 361 static int __init rtas_fadump_build_cpu_notes(struct fw_dump *fadump_conf) 362 { 363 struct rtas_fadump_reg_save_area_header *reg_header; 364 struct fadump_crash_info_header *fdh = NULL; 365 struct rtas_fadump_reg_entry *reg_entry; 366 u32 num_cpus, *note_buf; 367 int i, rc = 0, cpu = 0; 368 struct pt_regs regs; 369 void *vaddr; 370 371 vaddr = (void *)fadump_conf->cpu_state_dest_vaddr; 372 373 reg_header = vaddr; 374 if (be64_to_cpu(reg_header->magic_number) != 375 fadump_str_to_u64("REGSAVE")) { 376 pr_err("Unable to read register save area.\n"); 377 return -ENOENT; 378 } 379 380 pr_debug("--------CPU State Data------------\n"); 381 pr_debug("Magic Number: %llx\n", be64_to_cpu(reg_header->magic_number)); 382 pr_debug("NumCpuOffset: %x\n", be32_to_cpu(reg_header->num_cpu_offset)); 383 384 vaddr += be32_to_cpu(reg_header->num_cpu_offset); 385 num_cpus = be32_to_cpu(*((__be32 *)(vaddr))); 386 pr_debug("NumCpus : %u\n", num_cpus); 387 vaddr += sizeof(u32); 388 reg_entry = (struct rtas_fadump_reg_entry *)vaddr; 389 390 rc = fadump_setup_cpu_notes_buf(num_cpus); 391 if (rc != 0) 392 return rc; 393 394 note_buf = (u32 *)fadump_conf->cpu_notes_buf_vaddr; 395 396 if (fadump_conf->fadumphdr_addr) 397 fdh = __va(fadump_conf->fadumphdr_addr); 398 399 for (i = 0; i < num_cpus; i++) { 400 if (be64_to_cpu(reg_entry->reg_id) != 401 fadump_str_to_u64("CPUSTRT")) { 402 pr_err("Unable to read CPU state data\n"); 403 rc = -ENOENT; 404 goto error_out; 405 } 406 /* Lower 4 bytes of reg_value contains logical cpu id */ 407 cpu = (be64_to_cpu(reg_entry->reg_value) & 408 RTAS_FADUMP_CPU_ID_MASK); 409 if (fdh && !cpumask_test_cpu(cpu, &fdh->cpu_mask)) { 410 RTAS_FADUMP_SKIP_TO_NEXT_CPU(reg_entry); 411 continue; 412 } 413 pr_debug("Reading register data for cpu %d...\n", cpu); 414 if (fdh && fdh->crashing_cpu == cpu) { 415 regs = fdh->regs; 416 note_buf = fadump_regs_to_elf_notes(note_buf, ®s); 417 RTAS_FADUMP_SKIP_TO_NEXT_CPU(reg_entry); 418 } else { 419 reg_entry++; 420 reg_entry = rtas_fadump_read_regs(reg_entry, ®s); 421 note_buf = fadump_regs_to_elf_notes(note_buf, ®s); 422 } 423 } 424 final_note(note_buf); 425 426 pr_debug("Updating elfcore header (%llx) with cpu notes\n", fadump_conf->elfcorehdr_addr); 427 fadump_update_elfcore_header((char *)fadump_conf->elfcorehdr_addr); 428 return 0; 429 430 error_out: 431 fadump_free_cpu_notes_buf(); 432 return rc; 433 434 } 435 436 /* 437 * Validate and process the dump data stored by the firmware, and update 438 * the CPU notes of elfcorehdr. 439 */ 440 static int __init rtas_fadump_process(struct fw_dump *fadump_conf) 441 { 442 if (!fdm_active || !fadump_conf->fadumphdr_addr) 443 return -EINVAL; 444 445 /* Check if the dump data is valid. */ 446 for (int i = 0; i < be16_to_cpu(fdm_active->header.dump_num_sections); i++) { 447 int type = be16_to_cpu(fdm_active->rgn[i].source_data_type); 448 int rc = 0; 449 450 switch (type) { 451 case RTAS_FADUMP_CPU_STATE_DATA: 452 case RTAS_FADUMP_HPTE_REGION: 453 case RTAS_FADUMP_REAL_MODE_REGION: 454 if (fdm_active->rgn[i].error_flags != 0) { 455 pr_err("Dump taken by platform is not valid (%d)\n", i); 456 rc = -EINVAL; 457 } 458 if (fdm_active->rgn[i].bytes_dumped != fdm_active->rgn[i].source_len) { 459 pr_err("Dump taken by platform is incomplete (%d)\n", i); 460 rc = -EINVAL; 461 } 462 if (rc) { 463 pr_warn("Region type: %u src addr: 0x%llx dest addr: 0x%llx\n", 464 be16_to_cpu(fdm_active->rgn[i].source_data_type), 465 be64_to_cpu(fdm_active->rgn[i].source_address), 466 be64_to_cpu(fdm_active->rgn[i].destination_address)); 467 return rc; 468 } 469 break; 470 case RTAS_FADUMP_PARAM_AREA: 471 if (fdm_active->rgn[i].bytes_dumped != fdm_active->rgn[i].source_len || 472 fdm_active->rgn[i].error_flags != 0) { 473 pr_warn("Failed to process additional parameters! Proceeding anyway..\n"); 474 fadump_conf->param_area = 0; 475 } 476 break; 477 default: 478 /* 479 * If the first/crashed kernel added a new region type that the 480 * second/fadump kernel doesn't recognize, skip it and process 481 * assuming backward compatibility. 482 */ 483 pr_warn("Unknown region found: type: %u src addr: 0x%llx dest addr: 0x%llx\n", 484 be16_to_cpu(fdm_active->rgn[i].source_data_type), 485 be64_to_cpu(fdm_active->rgn[i].source_address), 486 be64_to_cpu(fdm_active->rgn[i].destination_address)); 487 break; 488 } 489 } 490 491 return rtas_fadump_build_cpu_notes(fadump_conf); 492 } 493 494 static void rtas_fadump_region_show(struct fw_dump *fadump_conf, 495 struct seq_file *m) 496 { 497 const struct rtas_fadump_mem_struct *fdm_ptr; 498 499 if (fdm_active) 500 fdm_ptr = fdm_active; 501 else 502 fdm_ptr = &fdm; 503 504 505 for (int i = 0; i < be16_to_cpu(fdm_ptr->header.dump_num_sections); i++) { 506 int type = be16_to_cpu(fdm_ptr->rgn[i].source_data_type); 507 508 switch (type) { 509 case RTAS_FADUMP_CPU_STATE_DATA: 510 seq_printf(m, "CPU :[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n", 511 be64_to_cpu(fdm_ptr->rgn[i].destination_address), 512 be64_to_cpu(fdm_ptr->rgn[i].destination_address) + 513 be64_to_cpu(fdm_ptr->rgn[i].source_len) - 1, 514 be64_to_cpu(fdm_ptr->rgn[i].source_len), 515 be64_to_cpu(fdm_ptr->rgn[i].bytes_dumped)); 516 break; 517 case RTAS_FADUMP_HPTE_REGION: 518 seq_printf(m, "HPTE:[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n", 519 be64_to_cpu(fdm_ptr->rgn[i].destination_address), 520 be64_to_cpu(fdm_ptr->rgn[i].destination_address) + 521 be64_to_cpu(fdm_ptr->rgn[i].source_len) - 1, 522 be64_to_cpu(fdm_ptr->rgn[i].source_len), 523 be64_to_cpu(fdm_ptr->rgn[i].bytes_dumped)); 524 break; 525 case RTAS_FADUMP_REAL_MODE_REGION: 526 seq_printf(m, "DUMP: Src: %#016llx, Dest: %#016llx, ", 527 be64_to_cpu(fdm_ptr->rgn[i].source_address), 528 be64_to_cpu(fdm_ptr->rgn[i].destination_address)); 529 seq_printf(m, "Size: %#llx, Dumped: %#llx bytes\n", 530 be64_to_cpu(fdm_ptr->rgn[i].source_len), 531 be64_to_cpu(fdm_ptr->rgn[i].bytes_dumped)); 532 break; 533 case RTAS_FADUMP_PARAM_AREA: 534 seq_printf(m, "\n[%#016llx-%#016llx]: cmdline append: '%s'\n", 535 be64_to_cpu(fdm_ptr->rgn[i].destination_address), 536 be64_to_cpu(fdm_ptr->rgn[i].destination_address) + 537 be64_to_cpu(fdm_ptr->rgn[i].source_len) - 1, 538 (char *)__va(be64_to_cpu(fdm_ptr->rgn[i].destination_address))); 539 break; 540 default: 541 seq_printf(m, "Unknown region type %d : Src: %#016llx, Dest: %#016llx, ", 542 type, be64_to_cpu(fdm_ptr->rgn[i].source_address), 543 be64_to_cpu(fdm_ptr->rgn[i].destination_address)); 544 break; 545 } 546 } 547 548 /* Dump is active. Show preserved area start address. */ 549 if (fdm_active) { 550 seq_printf(m, "\nMemory above %#016llx is reserved for saving crash dump\n", 551 fadump_conf->boot_mem_top); 552 } 553 } 554 555 static void rtas_fadump_trigger(struct fadump_crash_info_header *fdh, 556 const char *msg) 557 { 558 /* Call ibm,os-term rtas call to trigger firmware assisted dump */ 559 rtas_os_term((char *)msg); 560 } 561 562 /* FADUMP_MAX_MEM_REGS or lower */ 563 static int rtas_fadump_max_boot_mem_rgns(void) 564 { 565 /* 566 * Version 1 of Kernel Assisted Dump Memory Structure (PAPR) supports 10 sections. 567 * With one each section taken for CPU state data & HPTE respectively, 8 sections 568 * can be used for boot memory regions. 569 * 570 * If new region(s) is(are) defined, maximum boot memory regions will decrease 571 * proportionally. 572 */ 573 return RTAS_FADUMP_MAX_BOOT_MEM_REGS; 574 } 575 576 static struct fadump_ops rtas_fadump_ops = { 577 .fadump_init_mem_struct = rtas_fadump_init_mem_struct, 578 .fadump_get_bootmem_min = rtas_fadump_get_bootmem_min, 579 .fadump_register = rtas_fadump_register, 580 .fadump_unregister = rtas_fadump_unregister, 581 .fadump_invalidate = rtas_fadump_invalidate, 582 .fadump_process = rtas_fadump_process, 583 .fadump_region_show = rtas_fadump_region_show, 584 .fadump_trigger = rtas_fadump_trigger, 585 .fadump_max_boot_mem_rgns = rtas_fadump_max_boot_mem_rgns, 586 }; 587 588 void __init rtas_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node) 589 { 590 int i, size, num_sections; 591 const __be32 *sections; 592 const __be32 *token; 593 594 /* 595 * Check if Firmware Assisted dump is supported. if yes, check 596 * if dump has been initiated on last reboot. 597 */ 598 token = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL); 599 if (!token) 600 return; 601 602 fadump_conf->ibm_configure_kernel_dump = be32_to_cpu(*token); 603 fadump_conf->ops = &rtas_fadump_ops; 604 fadump_conf->fadump_supported = 1; 605 fadump_conf->param_area_supported = 1; 606 607 /* Firmware supports 64-bit value for size, align it to pagesize. */ 608 fadump_conf->max_copy_size = ALIGN_DOWN(U64_MAX, PAGE_SIZE); 609 610 /* 611 * The 'ibm,kernel-dump' rtas node is present only if there is 612 * dump data waiting for us. 613 */ 614 fdm_active = of_get_flat_dt_prop(node, "ibm,kernel-dump", NULL); 615 if (fdm_active) { 616 pr_info("Firmware-assisted dump is active.\n"); 617 fadump_conf->dump_active = 1; 618 rtas_fadump_get_config(fadump_conf, (void *)__pa(fdm_active)); 619 } 620 621 /* Get the sizes required to store dump data for the firmware provided 622 * dump sections. 623 * For each dump section type supported, a 32bit cell which defines 624 * the ID of a supported section followed by two 32 bit cells which 625 * gives the size of the section in bytes. 626 */ 627 sections = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes", 628 &size); 629 630 if (!sections) 631 return; 632 633 num_sections = size / (3 * sizeof(u32)); 634 635 for (i = 0; i < num_sections; i++, sections += 3) { 636 u32 type = (u32)of_read_number(sections, 1); 637 638 switch (type) { 639 case RTAS_FADUMP_CPU_STATE_DATA: 640 fadump_conf->cpu_state_data_size = 641 of_read_ulong(§ions[1], 2); 642 break; 643 case RTAS_FADUMP_HPTE_REGION: 644 fadump_conf->hpte_region_size = 645 of_read_ulong(§ions[1], 2); 646 break; 647 } 648 } 649 } 650
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.