1 /* 2 * Firmware Assisted dump: A robust mechanism to get reliable kernel crash 3 * dump with assistance from firmware. This approach does not use kexec, 4 * instead firmware assists in booting the kdump kernel while preserving 5 * memory contents. The most of the code implementation has been adapted 6 * from phyp assisted dump implementation written by Linas Vepstas and 7 * Manish Ahuja 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 * 23 * Copyright 2011 IBM Corporation 24 * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> 25 */ 26 27 #undef DEBUG 28 #define pr_fmt(fmt) "fadump: " fmt 29 30 #include <linux/string.h> 31 #include <linux/memblock.h> 32 #include <linux/delay.h> 33 #include <linux/debugfs.h> 34 #include <linux/seq_file.h> 35 #include <linux/crash_dump.h> 36 37 #include <asm/page.h> 38 #include <asm/prom.h> 39 #include <asm/rtas.h> 40 #include <asm/fadump.h> 41 42 static struct fw_dump fw_dump; 43 static struct fadump_mem_struct fdm; 44 static const struct fadump_mem_struct *fdm_active; 45 46 static DEFINE_MUTEX(fadump_mutex); 47 struct fad_crash_memory_ranges crash_memory_ranges[INIT_CRASHMEM_RANGES]; 48 int crash_mem_ranges; 49 50 /* Scan the Firmware Assisted dump configuration details. */ 51 int __init early_init_dt_scan_fw_dump(unsigned long node, 52 const char *uname, int depth, void *data) 53 { 54 __be32 *sections; 55 int i, num_sections; 56 unsigned long size; 57 const int *token; 58 59 if (depth != 1 || strcmp(uname, "rtas") != 0) 60 return 0; 61 62 /* 63 * Check if Firmware Assisted dump is supported. if yes, check 64 * if dump has been initiated on last reboot. 65 */ 66 token = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL); 67 if (!token) 68 return 0; 69 70 fw_dump.fadump_supported = 1; 71 fw_dump.ibm_configure_kernel_dump = *token; 72 73 /* 74 * The 'ibm,kernel-dump' rtas node is present only if there is 75 * dump data waiting for us. 76 */ 77 fdm_active = of_get_flat_dt_prop(node, "ibm,kernel-dump", NULL); 78 if (fdm_active) 79 fw_dump.dump_active = 1; 80 81 /* Get the sizes required to store dump data for the firmware provided 82 * dump sections. 83 * For each dump section type supported, a 32bit cell which defines 84 * the ID of a supported section followed by two 32 bit cells which 85 * gives teh size of the section in bytes. 86 */ 87 sections = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes", 88 &size); 89 90 if (!sections) 91 return 0; 92 93 num_sections = size / (3 * sizeof(u32)); 94 95 for (i = 0; i < num_sections; i++, sections += 3) { 96 u32 type = (u32)of_read_number(sections, 1); 97 98 switch (type) { 99 case FADUMP_CPU_STATE_DATA: 100 fw_dump.cpu_state_data_size = 101 of_read_ulong(§ions[1], 2); 102 break; 103 case FADUMP_HPTE_REGION: 104 fw_dump.hpte_region_size = 105 of_read_ulong(§ions[1], 2); 106 break; 107 } 108 } 109 return 1; 110 } 111 112 int is_fadump_active(void) 113 { 114 return fw_dump.dump_active; 115 } 116 117 /* Print firmware assisted dump configurations for debugging purpose. */ 118 static void fadump_show_config(void) 119 { 120 pr_debug("Support for firmware-assisted dump (fadump): %s\n", 121 (fw_dump.fadump_supported ? "present" : "no support")); 122 123 if (!fw_dump.fadump_supported) 124 return; 125 126 pr_debug("Fadump enabled : %s\n", 127 (fw_dump.fadump_enabled ? "yes" : "no")); 128 pr_debug("Dump Active : %s\n", 129 (fw_dump.dump_active ? "yes" : "no")); 130 pr_debug("Dump section sizes:\n"); 131 pr_debug(" CPU state data size: %lx\n", fw_dump.cpu_state_data_size); 132 pr_debug(" HPTE region size : %lx\n", fw_dump.hpte_region_size); 133 pr_debug("Boot memory size : %lx\n", fw_dump.boot_memory_size); 134 } 135 136 static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm, 137 unsigned long addr) 138 { 139 if (!fdm) 140 return 0; 141 142 memset(fdm, 0, sizeof(struct fadump_mem_struct)); 143 addr = addr & PAGE_MASK; 144 145 fdm->header.dump_format_version = 0x00000001; 146 fdm->header.dump_num_sections = 3; 147 fdm->header.dump_status_flag = 0; 148 fdm->header.offset_first_dump_section = 149 (u32)offsetof(struct fadump_mem_struct, cpu_state_data); 150 151 /* 152 * Fields for disk dump option. 153 * We are not using disk dump option, hence set these fields to 0. 154 */ 155 fdm->header.dd_block_size = 0; 156 fdm->header.dd_block_offset = 0; 157 fdm->header.dd_num_blocks = 0; 158 fdm->header.dd_offset_disk_path = 0; 159 160 /* set 0 to disable an automatic dump-reboot. */ 161 fdm->header.max_time_auto = 0; 162 163 /* Kernel dump sections */ 164 /* cpu state data section. */ 165 fdm->cpu_state_data.request_flag = FADUMP_REQUEST_FLAG; 166 fdm->cpu_state_data.source_data_type = FADUMP_CPU_STATE_DATA; 167 fdm->cpu_state_data.source_address = 0; 168 fdm->cpu_state_data.source_len = fw_dump.cpu_state_data_size; 169 fdm->cpu_state_data.destination_address = addr; 170 addr += fw_dump.cpu_state_data_size; 171 172 /* hpte region section */ 173 fdm->hpte_region.request_flag = FADUMP_REQUEST_FLAG; 174 fdm->hpte_region.source_data_type = FADUMP_HPTE_REGION; 175 fdm->hpte_region.source_address = 0; 176 fdm->hpte_region.source_len = fw_dump.hpte_region_size; 177 fdm->hpte_region.destination_address = addr; 178 addr += fw_dump.hpte_region_size; 179 180 /* RMA region section */ 181 fdm->rmr_region.request_flag = FADUMP_REQUEST_FLAG; 182 fdm->rmr_region.source_data_type = FADUMP_REAL_MODE_REGION; 183 fdm->rmr_region.source_address = RMA_START; 184 fdm->rmr_region.source_len = fw_dump.boot_memory_size; 185 fdm->rmr_region.destination_address = addr; 186 addr += fw_dump.boot_memory_size; 187 188 return addr; 189 } 190 191 /** 192 * fadump_calculate_reserve_size(): reserve variable boot area 5% of System RAM 193 * 194 * Function to find the largest memory size we need to reserve during early 195 * boot process. This will be the size of the memory that is required for a 196 * kernel to boot successfully. 197 * 198 * This function has been taken from phyp-assisted dump feature implementation. 199 * 200 * returns larger of 256MB or 5% rounded down to multiples of 256MB. 201 * 202 * TODO: Come up with better approach to find out more accurate memory size 203 * that is required for a kernel to boot successfully. 204 * 205 */ 206 static inline unsigned long fadump_calculate_reserve_size(void) 207 { 208 unsigned long size; 209 210 /* 211 * Check if the size is specified through fadump_reserve_mem= cmdline 212 * option. If yes, then use that. 213 */ 214 if (fw_dump.reserve_bootvar) 215 return fw_dump.reserve_bootvar; 216 217 /* divide by 20 to get 5% of value */ 218 size = memblock_end_of_DRAM() / 20; 219 220 /* round it down in multiples of 256 */ 221 size = size & ~0x0FFFFFFFUL; 222 223 /* Truncate to memory_limit. We don't want to over reserve the memory.*/ 224 if (memory_limit && size > memory_limit) 225 size = memory_limit; 226 227 return (size > MIN_BOOT_MEM ? size : MIN_BOOT_MEM); 228 } 229 230 /* 231 * Calculate the total memory size required to be reserved for 232 * firmware-assisted dump registration. 233 */ 234 static unsigned long get_fadump_area_size(void) 235 { 236 unsigned long size = 0; 237 238 size += fw_dump.cpu_state_data_size; 239 size += fw_dump.hpte_region_size; 240 size += fw_dump.boot_memory_size; 241 size += sizeof(struct fadump_crash_info_header); 242 size += sizeof(struct elfhdr); /* ELF core header.*/ 243 /* Program headers for crash memory regions. */ 244 size += sizeof(struct elf_phdr) * (memblock_num_regions(memory) + 2); 245 246 size = PAGE_ALIGN(size); 247 return size; 248 } 249 250 int __init fadump_reserve_mem(void) 251 { 252 unsigned long base, size, memory_boundary; 253 254 if (!fw_dump.fadump_enabled) 255 return 0; 256 257 if (!fw_dump.fadump_supported) { 258 printk(KERN_INFO "Firmware-assisted dump is not supported on" 259 " this hardware\n"); 260 fw_dump.fadump_enabled = 0; 261 return 0; 262 } 263 /* 264 * Initialize boot memory size 265 * If dump is active then we have already calculated the size during 266 * first kernel. 267 */ 268 if (fdm_active) 269 fw_dump.boot_memory_size = fdm_active->rmr_region.source_len; 270 else 271 fw_dump.boot_memory_size = fadump_calculate_reserve_size(); 272 273 /* 274 * Calculate the memory boundary. 275 * If memory_limit is less than actual memory boundary then reserve 276 * the memory for fadump beyond the memory_limit and adjust the 277 * memory_limit accordingly, so that the running kernel can run with 278 * specified memory_limit. 279 */ 280 if (memory_limit && memory_limit < memblock_end_of_DRAM()) { 281 size = get_fadump_area_size(); 282 if ((memory_limit + size) < memblock_end_of_DRAM()) 283 memory_limit += size; 284 else 285 memory_limit = memblock_end_of_DRAM(); 286 printk(KERN_INFO "Adjusted memory_limit for firmware-assisted" 287 " dump, now %#016llx\n", 288 (unsigned long long)memory_limit); 289 } 290 if (memory_limit) 291 memory_boundary = memory_limit; 292 else 293 memory_boundary = memblock_end_of_DRAM(); 294 295 if (fw_dump.dump_active) { 296 printk(KERN_INFO "Firmware-assisted dump is active.\n"); 297 /* 298 * If last boot has crashed then reserve all the memory 299 * above boot_memory_size so that we don't touch it until 300 * dump is written to disk by userspace tool. This memory 301 * will be released for general use once the dump is saved. 302 */ 303 base = fw_dump.boot_memory_size; 304 size = memory_boundary - base; 305 memblock_reserve(base, size); 306 printk(KERN_INFO "Reserved %ldMB of memory at %ldMB " 307 "for saving crash dump\n", 308 (unsigned long)(size >> 20), 309 (unsigned long)(base >> 20)); 310 311 fw_dump.fadumphdr_addr = 312 fdm_active->rmr_region.destination_address + 313 fdm_active->rmr_region.source_len; 314 pr_debug("fadumphdr_addr = %p\n", 315 (void *) fw_dump.fadumphdr_addr); 316 } else { 317 /* Reserve the memory at the top of memory. */ 318 size = get_fadump_area_size(); 319 base = memory_boundary - size; 320 memblock_reserve(base, size); 321 printk(KERN_INFO "Reserved %ldMB of memory at %ldMB " 322 "for firmware-assisted dump\n", 323 (unsigned long)(size >> 20), 324 (unsigned long)(base >> 20)); 325 } 326 fw_dump.reserve_dump_area_start = base; 327 fw_dump.reserve_dump_area_size = size; 328 return 1; 329 } 330 331 /* Look for fadump= cmdline option. */ 332 static int __init early_fadump_param(char *p) 333 { 334 if (!p) 335 return 1; 336 337 if (strncmp(p, "on", 2) == 0) 338 fw_dump.fadump_enabled = 1; 339 else if (strncmp(p, "off", 3) == 0) 340 fw_dump.fadump_enabled = 0; 341 342 return 0; 343 } 344 early_param("fadump", early_fadump_param); 345 346 /* Look for fadump_reserve_mem= cmdline option */ 347 static int __init early_fadump_reserve_mem(char *p) 348 { 349 if (p) 350 fw_dump.reserve_bootvar = memparse(p, &p); 351 return 0; 352 } 353 early_param("fadump_reserve_mem", early_fadump_reserve_mem); 354 355 static void register_fw_dump(struct fadump_mem_struct *fdm) 356 { 357 int rc; 358 unsigned int wait_time; 359 360 pr_debug("Registering for firmware-assisted kernel dump...\n"); 361 362 /* TODO: Add upper time limit for the delay */ 363 do { 364 rc = rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1, NULL, 365 FADUMP_REGISTER, fdm, 366 sizeof(struct fadump_mem_struct)); 367 368 wait_time = rtas_busy_delay_time(rc); 369 if (wait_time) 370 mdelay(wait_time); 371 372 } while (wait_time); 373 374 switch (rc) { 375 case -1: 376 printk(KERN_ERR "Failed to register firmware-assisted kernel" 377 " dump. Hardware Error(%d).\n", rc); 378 break; 379 case -3: 380 printk(KERN_ERR "Failed to register firmware-assisted kernel" 381 " dump. Parameter Error(%d).\n", rc); 382 break; 383 case -9: 384 printk(KERN_ERR "firmware-assisted kernel dump is already " 385 " registered."); 386 fw_dump.dump_registered = 1; 387 break; 388 case 0: 389 printk(KERN_INFO "firmware-assisted kernel dump registration" 390 " is successful\n"); 391 fw_dump.dump_registered = 1; 392 break; 393 } 394 } 395 396 /* 397 * Validate and process the dump data stored by firmware before exporting 398 * it through '/proc/vmcore'. 399 */ 400 static int __init process_fadump(const struct fadump_mem_struct *fdm_active) 401 { 402 struct fadump_crash_info_header *fdh; 403 404 if (!fdm_active || !fw_dump.fadumphdr_addr) 405 return -EINVAL; 406 407 /* Check if the dump data is valid. */ 408 if ((fdm_active->header.dump_status_flag == FADUMP_ERROR_FLAG) || 409 (fdm_active->rmr_region.error_flags != 0)) { 410 printk(KERN_ERR "Dump taken by platform is not valid\n"); 411 return -EINVAL; 412 } 413 if (fdm_active->rmr_region.bytes_dumped != 414 fdm_active->rmr_region.source_len) { 415 printk(KERN_ERR "Dump taken by platform is incomplete\n"); 416 return -EINVAL; 417 } 418 419 /* Validate the fadump crash info header */ 420 fdh = __va(fw_dump.fadumphdr_addr); 421 if (fdh->magic_number != FADUMP_CRASH_INFO_MAGIC) { 422 printk(KERN_ERR "Crash info header is not valid.\n"); 423 return -EINVAL; 424 } 425 426 /* 427 * We are done validating dump info and elfcore header is now ready 428 * to be exported. set elfcorehdr_addr so that vmcore module will 429 * export the elfcore header through '/proc/vmcore'. 430 */ 431 elfcorehdr_addr = fdh->elfcorehdr_addr; 432 433 return 0; 434 } 435 436 static inline void fadump_add_crash_memory(unsigned long long base, 437 unsigned long long end) 438 { 439 if (base == end) 440 return; 441 442 pr_debug("crash_memory_range[%d] [%#016llx-%#016llx], %#llx bytes\n", 443 crash_mem_ranges, base, end - 1, (end - base)); 444 crash_memory_ranges[crash_mem_ranges].base = base; 445 crash_memory_ranges[crash_mem_ranges].size = end - base; 446 crash_mem_ranges++; 447 } 448 449 static void fadump_exclude_reserved_area(unsigned long long start, 450 unsigned long long end) 451 { 452 unsigned long long ra_start, ra_end; 453 454 ra_start = fw_dump.reserve_dump_area_start; 455 ra_end = ra_start + fw_dump.reserve_dump_area_size; 456 457 if ((ra_start < end) && (ra_end > start)) { 458 if ((start < ra_start) && (end > ra_end)) { 459 fadump_add_crash_memory(start, ra_start); 460 fadump_add_crash_memory(ra_end, end); 461 } else if (start < ra_start) { 462 fadump_add_crash_memory(start, ra_start); 463 } else if (ra_end < end) { 464 fadump_add_crash_memory(ra_end, end); 465 } 466 } else 467 fadump_add_crash_memory(start, end); 468 } 469 470 static int fadump_init_elfcore_header(char *bufp) 471 { 472 struct elfhdr *elf; 473 474 elf = (struct elfhdr *) bufp; 475 bufp += sizeof(struct elfhdr); 476 memcpy(elf->e_ident, ELFMAG, SELFMAG); 477 elf->e_ident[EI_CLASS] = ELF_CLASS; 478 elf->e_ident[EI_DATA] = ELF_DATA; 479 elf->e_ident[EI_VERSION] = EV_CURRENT; 480 elf->e_ident[EI_OSABI] = ELF_OSABI; 481 memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); 482 elf->e_type = ET_CORE; 483 elf->e_machine = ELF_ARCH; 484 elf->e_version = EV_CURRENT; 485 elf->e_entry = 0; 486 elf->e_phoff = sizeof(struct elfhdr); 487 elf->e_shoff = 0; 488 elf->e_flags = ELF_CORE_EFLAGS; 489 elf->e_ehsize = sizeof(struct elfhdr); 490 elf->e_phentsize = sizeof(struct elf_phdr); 491 elf->e_phnum = 0; 492 elf->e_shentsize = 0; 493 elf->e_shnum = 0; 494 elf->e_shstrndx = 0; 495 496 return 0; 497 } 498 499 /* 500 * Traverse through memblock structure and setup crash memory ranges. These 501 * ranges will be used create PT_LOAD program headers in elfcore header. 502 */ 503 static void fadump_setup_crash_memory_ranges(void) 504 { 505 struct memblock_region *reg; 506 unsigned long long start, end; 507 508 pr_debug("Setup crash memory ranges.\n"); 509 crash_mem_ranges = 0; 510 /* 511 * add the first memory chunk (RMA_START through boot_memory_size) as 512 * a separate memory chunk. The reason is, at the time crash firmware 513 * will move the content of this memory chunk to different location 514 * specified during fadump registration. We need to create a separate 515 * program header for this chunk with the correct offset. 516 */ 517 fadump_add_crash_memory(RMA_START, fw_dump.boot_memory_size); 518 519 for_each_memblock(memory, reg) { 520 start = (unsigned long long)reg->base; 521 end = start + (unsigned long long)reg->size; 522 if (start == RMA_START && end >= fw_dump.boot_memory_size) 523 start = fw_dump.boot_memory_size; 524 525 /* add this range excluding the reserved dump area. */ 526 fadump_exclude_reserved_area(start, end); 527 } 528 } 529 530 static int fadump_create_elfcore_headers(char *bufp) 531 { 532 struct elfhdr *elf; 533 struct elf_phdr *phdr; 534 int i; 535 536 fadump_init_elfcore_header(bufp); 537 elf = (struct elfhdr *)bufp; 538 bufp += sizeof(struct elfhdr); 539 540 /* setup PT_LOAD sections. */ 541 542 for (i = 0; i < crash_mem_ranges; i++) { 543 unsigned long long mbase, msize; 544 mbase = crash_memory_ranges[i].base; 545 msize = crash_memory_ranges[i].size; 546 547 if (!msize) 548 continue; 549 550 phdr = (struct elf_phdr *)bufp; 551 bufp += sizeof(struct elf_phdr); 552 phdr->p_type = PT_LOAD; 553 phdr->p_flags = PF_R|PF_W|PF_X; 554 phdr->p_offset = mbase; 555 556 if (mbase == RMA_START) { 557 /* 558 * The entire RMA region will be moved by firmware 559 * to the specified destination_address. Hence set 560 * the correct offset. 561 */ 562 phdr->p_offset = fdm.rmr_region.destination_address; 563 } 564 565 phdr->p_paddr = mbase; 566 phdr->p_vaddr = (unsigned long)__va(mbase); 567 phdr->p_filesz = msize; 568 phdr->p_memsz = msize; 569 phdr->p_align = 0; 570 571 /* Increment number of program headers. */ 572 (elf->e_phnum)++; 573 } 574 return 0; 575 } 576 577 static unsigned long init_fadump_header(unsigned long addr) 578 { 579 struct fadump_crash_info_header *fdh; 580 581 if (!addr) 582 return 0; 583 584 fw_dump.fadumphdr_addr = addr; 585 fdh = __va(addr); 586 addr += sizeof(struct fadump_crash_info_header); 587 588 memset(fdh, 0, sizeof(struct fadump_crash_info_header)); 589 fdh->magic_number = FADUMP_CRASH_INFO_MAGIC; 590 fdh->elfcorehdr_addr = addr; 591 592 return addr; 593 } 594 595 static void register_fadump(void) 596 { 597 unsigned long addr; 598 void *vaddr; 599 600 /* 601 * If no memory is reserved then we can not register for firmware- 602 * assisted dump. 603 */ 604 if (!fw_dump.reserve_dump_area_size) 605 return; 606 607 fadump_setup_crash_memory_ranges(); 608 609 addr = fdm.rmr_region.destination_address + fdm.rmr_region.source_len; 610 /* Initialize fadump crash info header. */ 611 addr = init_fadump_header(addr); 612 vaddr = __va(addr); 613 614 pr_debug("Creating ELF core headers at %#016lx\n", addr); 615 fadump_create_elfcore_headers(vaddr); 616 617 /* register the future kernel dump with firmware. */ 618 register_fw_dump(&fdm); 619 } 620 621 static int fadump_unregister_dump(struct fadump_mem_struct *fdm) 622 { 623 int rc = 0; 624 unsigned int wait_time; 625 626 pr_debug("Un-register firmware-assisted dump\n"); 627 628 /* TODO: Add upper time limit for the delay */ 629 do { 630 rc = rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1, NULL, 631 FADUMP_UNREGISTER, fdm, 632 sizeof(struct fadump_mem_struct)); 633 634 wait_time = rtas_busy_delay_time(rc); 635 if (wait_time) 636 mdelay(wait_time); 637 } while (wait_time); 638 639 if (rc) { 640 printk(KERN_ERR "Failed to un-register firmware-assisted dump." 641 " unexpected error(%d).\n", rc); 642 return rc; 643 } 644 fw_dump.dump_registered = 0; 645 return 0; 646 } 647 648 static ssize_t fadump_enabled_show(struct kobject *kobj, 649 struct kobj_attribute *attr, 650 char *buf) 651 { 652 return sprintf(buf, "%d\n", fw_dump.fadump_enabled); 653 } 654 655 static ssize_t fadump_register_show(struct kobject *kobj, 656 struct kobj_attribute *attr, 657 char *buf) 658 { 659 return sprintf(buf, "%d\n", fw_dump.dump_registered); 660 } 661 662 static ssize_t fadump_register_store(struct kobject *kobj, 663 struct kobj_attribute *attr, 664 const char *buf, size_t count) 665 { 666 int ret = 0; 667 668 if (!fw_dump.fadump_enabled || fdm_active) 669 return -EPERM; 670 671 mutex_lock(&fadump_mutex); 672 673 switch (buf[0]) { 674 case '0': 675 if (fw_dump.dump_registered == 0) { 676 ret = -EINVAL; 677 goto unlock_out; 678 } 679 /* Un-register Firmware-assisted dump */ 680 fadump_unregister_dump(&fdm); 681 break; 682 case '1': 683 if (fw_dump.dump_registered == 1) { 684 ret = -EINVAL; 685 goto unlock_out; 686 } 687 /* Register Firmware-assisted dump */ 688 register_fadump(); 689 break; 690 default: 691 ret = -EINVAL; 692 break; 693 } 694 695 unlock_out: 696 mutex_unlock(&fadump_mutex); 697 return ret < 0 ? ret : count; 698 } 699 700 static int fadump_region_show(struct seq_file *m, void *private) 701 { 702 const struct fadump_mem_struct *fdm_ptr; 703 704 if (!fw_dump.fadump_enabled) 705 return 0; 706 707 if (fdm_active) 708 fdm_ptr = fdm_active; 709 else 710 fdm_ptr = &fdm; 711 712 seq_printf(m, 713 "CPU : [%#016llx-%#016llx] %#llx bytes, " 714 "Dumped: %#llx\n", 715 fdm_ptr->cpu_state_data.destination_address, 716 fdm_ptr->cpu_state_data.destination_address + 717 fdm_ptr->cpu_state_data.source_len - 1, 718 fdm_ptr->cpu_state_data.source_len, 719 fdm_ptr->cpu_state_data.bytes_dumped); 720 seq_printf(m, 721 "HPTE: [%#016llx-%#016llx] %#llx bytes, " 722 "Dumped: %#llx\n", 723 fdm_ptr->hpte_region.destination_address, 724 fdm_ptr->hpte_region.destination_address + 725 fdm_ptr->hpte_region.source_len - 1, 726 fdm_ptr->hpte_region.source_len, 727 fdm_ptr->hpte_region.bytes_dumped); 728 seq_printf(m, 729 "DUMP: [%#016llx-%#016llx] %#llx bytes, " 730 "Dumped: %#llx\n", 731 fdm_ptr->rmr_region.destination_address, 732 fdm_ptr->rmr_region.destination_address + 733 fdm_ptr->rmr_region.source_len - 1, 734 fdm_ptr->rmr_region.source_len, 735 fdm_ptr->rmr_region.bytes_dumped); 736 737 if (!fdm_active || 738 (fw_dump.reserve_dump_area_start == 739 fdm_ptr->cpu_state_data.destination_address)) 740 return 0; 741 742 /* Dump is active. Show reserved memory region. */ 743 seq_printf(m, 744 " : [%#016llx-%#016llx] %#llx bytes, " 745 "Dumped: %#llx\n", 746 (unsigned long long)fw_dump.reserve_dump_area_start, 747 fdm_ptr->cpu_state_data.destination_address - 1, 748 fdm_ptr->cpu_state_data.destination_address - 749 fw_dump.reserve_dump_area_start, 750 fdm_ptr->cpu_state_data.destination_address - 751 fw_dump.reserve_dump_area_start); 752 return 0; 753 } 754 755 static struct kobj_attribute fadump_attr = __ATTR(fadump_enabled, 756 0444, fadump_enabled_show, 757 NULL); 758 static struct kobj_attribute fadump_register_attr = __ATTR(fadump_registered, 759 0644, fadump_register_show, 760 fadump_register_store); 761 762 static int fadump_region_open(struct inode *inode, struct file *file) 763 { 764 return single_open(file, fadump_region_show, inode->i_private); 765 } 766 767 static const struct file_operations fadump_region_fops = { 768 .open = fadump_region_open, 769 .read = seq_read, 770 .llseek = seq_lseek, 771 .release = single_release, 772 }; 773 774 static void fadump_init_files(void) 775 { 776 struct dentry *debugfs_file; 777 int rc = 0; 778 779 rc = sysfs_create_file(kernel_kobj, &fadump_attr.attr); 780 if (rc) 781 printk(KERN_ERR "fadump: unable to create sysfs file" 782 " fadump_enabled (%d)\n", rc); 783 784 rc = sysfs_create_file(kernel_kobj, &fadump_register_attr.attr); 785 if (rc) 786 printk(KERN_ERR "fadump: unable to create sysfs file" 787 " fadump_registered (%d)\n", rc); 788 789 debugfs_file = debugfs_create_file("fadump_region", 0444, 790 powerpc_debugfs_root, NULL, 791 &fadump_region_fops); 792 if (!debugfs_file) 793 printk(KERN_ERR "fadump: unable to create debugfs file" 794 " fadump_region\n"); 795 return; 796 } 797 798 /* 799 * Prepare for firmware-assisted dump. 800 */ 801 int __init setup_fadump(void) 802 { 803 if (!fw_dump.fadump_enabled) 804 return 0; 805 806 if (!fw_dump.fadump_supported) { 807 printk(KERN_ERR "Firmware-assisted dump is not supported on" 808 " this hardware\n"); 809 return 0; 810 } 811 812 fadump_show_config(); 813 /* 814 * If dump data is available then see if it is valid and prepare for 815 * saving it to the disk. 816 */ 817 if (fw_dump.dump_active) 818 process_fadump(fdm_active); 819 /* Initialize the kernel dump memory structure for FAD registration. */ 820 else if (fw_dump.reserve_dump_area_size) 821 init_fadump_mem_struct(&fdm, fw_dump.reserve_dump_area_start); 822 fadump_init_files(); 823 824 return 1; 825 } 826 subsys_initcall(setup_fadump); 827