28 #define pr_fmt(fmt) "fadump: " fmt
30 #include <linux/string.h>
43 #include <asm/debug.h>
44 #include <asm/setup.h>
46 static struct fw_dump fw_dump;
47 static struct fadump_mem_struct fdm;
48 static const struct fadump_mem_struct *fdm_active;
63 if (depth != 1 ||
strcmp(uname,
"rtas") != 0)
70 token = of_get_flat_dt_prop(node,
"ibm,configure-kernel-dump",
NULL);
74 fw_dump.fadump_supported = 1;
75 fw_dump.ibm_configure_kernel_dump = *
token;
81 fdm_active = of_get_flat_dt_prop(node,
"ibm,kernel-dump",
NULL);
83 fw_dump.dump_active = 1;
91 sections = of_get_flat_dt_prop(node,
"ibm,configure-kernel-dump-sizes",
97 num_sections = size / (3 *
sizeof(
u32));
99 for (i = 0; i < num_sections; i++, sections += 3) {
103 case FADUMP_CPU_STATE_DATA:
104 fw_dump.cpu_state_data_size =
105 of_read_ulong(§ions[1], 2);
107 case FADUMP_HPTE_REGION:
108 fw_dump.hpte_region_size =
109 of_read_ulong(§ions[1], 2);
118 return fw_dump.dump_active;
122 static void fadump_show_config(
void)
124 pr_debug(
"Support for firmware-assisted dump (fadump): %s\n",
125 (fw_dump.fadump_supported ?
"present" :
"no support"));
127 if (!fw_dump.fadump_supported)
131 (fw_dump.fadump_enabled ?
"yes" :
"no"));
133 (fw_dump.dump_active ?
"yes" :
"no"));
135 pr_debug(
" CPU state data size: %lx\n", fw_dump.cpu_state_data_size);
136 pr_debug(
" HPTE region size : %lx\n", fw_dump.hpte_region_size);
137 pr_debug(
"Boot memory size : %lx\n", fw_dump.boot_memory_size);
140 static unsigned long init_fadump_mem_struct(
struct fadump_mem_struct *fdm,
146 memset(fdm, 0,
sizeof(
struct fadump_mem_struct));
149 fdm->header.dump_format_version = 0x00000001;
150 fdm->header.dump_num_sections = 3;
151 fdm->header.dump_status_flag = 0;
152 fdm->header.offset_first_dump_section =
153 (
u32)
offsetof(
struct fadump_mem_struct, cpu_state_data);
159 fdm->header.dd_block_size = 0;
160 fdm->header.dd_block_offset = 0;
161 fdm->header.dd_num_blocks = 0;
162 fdm->header.dd_offset_disk_path = 0;
165 fdm->header.max_time_auto = 0;
169 fdm->cpu_state_data.request_flag = FADUMP_REQUEST_FLAG;
170 fdm->cpu_state_data.source_data_type = FADUMP_CPU_STATE_DATA;
171 fdm->cpu_state_data.source_address = 0;
172 fdm->cpu_state_data.source_len = fw_dump.cpu_state_data_size;
173 fdm->cpu_state_data.destination_address =
addr;
174 addr += fw_dump.cpu_state_data_size;
177 fdm->hpte_region.request_flag = FADUMP_REQUEST_FLAG;
178 fdm->hpte_region.source_data_type = FADUMP_HPTE_REGION;
179 fdm->hpte_region.source_address = 0;
180 fdm->hpte_region.source_len = fw_dump.hpte_region_size;
181 fdm->hpte_region.destination_address =
addr;
182 addr += fw_dump.hpte_region_size;
185 fdm->rmr_region.request_flag = FADUMP_REQUEST_FLAG;
186 fdm->rmr_region.source_data_type = FADUMP_REAL_MODE_REGION;
187 fdm->rmr_region.source_address = RMA_START;
188 fdm->rmr_region.source_len = fw_dump.boot_memory_size;
189 fdm->rmr_region.destination_address =
addr;
190 addr += fw_dump.boot_memory_size;
210 static inline unsigned long fadump_calculate_reserve_size(
void)
218 if (fw_dump.reserve_bootvar)
219 return fw_dump.reserve_bootvar;
225 size = size & ~0x0FFFFFFF
UL;
231 return (size > MIN_BOOT_MEM ? size : MIN_BOOT_MEM);
238 static unsigned long get_fadump_area_size(
void)
240 unsigned long size = 0;
242 size += fw_dump.cpu_state_data_size;
243 size += fw_dump.hpte_region_size;
244 size += fw_dump.boot_memory_size;
245 size +=
sizeof(
struct fadump_crash_info_header);
246 size +=
sizeof(
struct elfhdr);
249 size +=
sizeof(
struct elf_phdr) * (memblock_num_regions(
memory) + 2);
257 unsigned long base,
size, memory_boundary;
259 if (!fw_dump.fadump_enabled)
262 if (!fw_dump.fadump_supported) {
265 fw_dump.fadump_enabled = 0;
274 fw_dump.boot_memory_size = fdm_active->rmr_region.source_len;
276 fw_dump.boot_memory_size = fadump_calculate_reserve_size();
286 size = get_fadump_area_size();
299 if (fw_dump.dump_active) {
307 base = fw_dump.boot_memory_size;
308 size = memory_boundary - base;
311 "for saving crash dump\n",
312 (
unsigned long)(size >> 20),
313 (
unsigned long)(base >> 20));
315 fw_dump.fadumphdr_addr =
316 fdm_active->rmr_region.destination_address +
317 fdm_active->rmr_region.source_len;
319 (
void *) fw_dump.fadumphdr_addr);
322 size = get_fadump_area_size();
323 base = memory_boundary -
size;
326 "for firmware-assisted dump\n",
327 (
unsigned long)(size >> 20),
328 (
unsigned long)(base >> 20));
330 fw_dump.reserve_dump_area_start = base;
331 fw_dump.reserve_dump_area_size =
size;
336 static int __init early_fadump_param(
char *
p)
342 fw_dump.fadump_enabled = 1;
343 else if (
strncmp(p,
"off", 3) == 0)
344 fw_dump.fadump_enabled = 0;
351 static int __init early_fadump_reserve_mem(
char *p)
354 fw_dump.reserve_bootvar =
memparse(p, &p);
357 early_param(
"fadump_reserve_mem", early_fadump_reserve_mem);
359 static void register_fw_dump(
struct fadump_mem_struct *fdm)
364 pr_debug(
"Registering for firmware-assisted kernel dump...\n");
368 rc =
rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1,
NULL,
369 FADUMP_REGISTER, fdm,
370 sizeof(
struct fadump_mem_struct));
381 " dump. Hardware Error(%d).\n", rc);
385 " dump. Parameter Error(%d).\n", rc);
390 fw_dump.dump_registered = 1;
395 fw_dump.dump_registered = 1;
402 struct fadump_crash_info_header *fdh =
NULL;
404 if (!fw_dump.dump_registered || !fw_dump.fadumphdr_addr)
407 fdh =
__va(fw_dump.fadumphdr_addr);
415 ppc_save_regs(&fdh->regs);
423 #define GPR_MASK 0xffffff0000000000
424 static inline int fadump_gpr_index(
u64 id)
435 str[0] = (
id >> 8) & 0xff;
443 static inline void fadump_set_regval(
struct pt_regs *
regs,
u64 reg_id,
448 i = fadump_gpr_index(reg_id);
450 regs->
gpr[
i] = (
unsigned long)reg_val;
451 else if (reg_id ==
REG_ID(
"NIA"))
453 else if (reg_id ==
REG_ID(
"MSR"))
455 else if (reg_id ==
REG_ID(
"CTR"))
457 else if (reg_id ==
REG_ID(
"LR"))
459 else if (reg_id ==
REG_ID(
"XER"))
461 else if (reg_id ==
REG_ID(
"CR"))
463 else if (reg_id ==
REG_ID(
"DAR"))
465 else if (reg_id ==
REG_ID(
"DSISR"))
469 static struct fadump_reg_entry*
470 fadump_read_registers(
struct fadump_reg_entry *reg_entry,
struct pt_regs *regs)
474 while (reg_entry->reg_id !=
REG_ID(
"CPUEND")) {
475 fadump_set_regval(regs, reg_entry->reg_id,
476 reg_entry->reg_value);
491 memcpy(buf, ¬e,
sizeof(note));
492 buf += (
sizeof(
note) + 3)/4;
494 buf += (
note.n_namesz + 3)/4;
496 buf += (
note.n_descsz + 3)/4;
501 static void fadump_final_note(
u32 *buf)
508 memcpy(buf, ¬e,
sizeof(note));
511 static u32 *fadump_regs_to_elf_notes(
u32 *buf,
struct pt_regs *regs)
515 memset(&prstatus, 0,
sizeof(prstatus));
520 elf_core_copy_kernel_regs(&prstatus.pr_reg, regs);
521 buf = fadump_append_elf_note(buf, KEXEC_CORE_NOTE_NAME,
NT_PRSTATUS,
522 &prstatus,
sizeof(prstatus));
526 static void fadump_update_elfcore_header(
char *bufp)
531 elf = (
struct elfhdr *)bufp;
532 bufp +=
sizeof(
struct elfhdr);
538 phdr->p_paddr = fw_dump.cpu_notes_buf;
539 phdr->p_offset = phdr->p_paddr;
540 phdr->p_filesz = fw_dump.cpu_notes_buf_size;
541 phdr->p_memsz = fw_dump.cpu_notes_buf_size;
546 static void *fadump_cpu_notes_buf_alloc(
unsigned long size)
559 for (i = 0; i <
count; i++)
560 SetPageReserved(page + i);
564 static void fadump_cpu_notes_buf_free(
unsigned long vaddr,
unsigned long size)
572 for (i = 0; i <
count; i++)
573 ClearPageReserved(page + i);
591 static int __init fadump_build_cpu_notes(
const struct fadump_mem_struct *fdm)
593 struct fadump_reg_save_area_header *reg_header;
594 struct fadump_reg_entry *reg_entry;
595 struct fadump_crash_info_header *fdh =
NULL;
598 u32 num_cpus, *note_buf;
600 int i, rc = 0,
cpu = 0;
602 if (!fdm->cpu_state_data.bytes_dumped)
605 addr = fdm->cpu_state_data.destination_address;
609 if (reg_header->magic_number != REGSAVE_AREA_MAGIC) {
613 pr_debug(
"--------CPU State Data------------\n");
614 pr_debug(
"Magic Number: %llx\n", reg_header->magic_number);
615 pr_debug(
"NumCpuOffset: %x\n", reg_header->num_cpu_offset);
617 vaddr += reg_header->num_cpu_offset;
618 num_cpus = *((
u32 *)(vaddr));
619 pr_debug(
"NumCpus : %u\n", num_cpus);
620 vaddr +=
sizeof(
u32);
621 reg_entry = (
struct fadump_reg_entry *)vaddr;
624 fw_dump.cpu_notes_buf_size = num_cpus *
sizeof(note_buf_t);
625 fw_dump.cpu_notes_buf_size =
PAGE_ALIGN(fw_dump.cpu_notes_buf_size);
626 note_buf = fadump_cpu_notes_buf_alloc(fw_dump.cpu_notes_buf_size);
629 "cpu notes buffer\n", fw_dump.cpu_notes_buf_size);
632 fw_dump.cpu_notes_buf =
__pa(note_buf);
634 pr_debug(
"Allocated buffer for cpu notes of size %ld at %p\n",
635 (num_cpus *
sizeof(note_buf_t)), note_buf);
637 if (fw_dump.fadumphdr_addr)
638 fdh =
__va(fw_dump.fadumphdr_addr);
640 for (i = 0; i < num_cpus; i++) {
641 if (reg_entry->reg_id !=
REG_ID(
"CPUSTRT")) {
647 cpu = reg_entry->reg_value & FADUMP_CPU_ID_MASK;
649 SKIP_TO_NEXT_CPU(reg_entry);
652 pr_debug(
"Reading register data for cpu %d...\n",
cpu);
653 if (fdh && fdh->crashing_cpu ==
cpu) {
655 note_buf = fadump_regs_to_elf_notes(note_buf, ®s);
656 SKIP_TO_NEXT_CPU(reg_entry);
659 reg_entry = fadump_read_registers(reg_entry, ®s);
660 note_buf = fadump_regs_to_elf_notes(note_buf, ®s);
663 fadump_final_note(note_buf);
665 pr_debug(
"Updating elfcore header (%llx) with cpu notes\n",
666 fdh->elfcorehdr_addr);
667 fadump_update_elfcore_header((
char *)
__va(fdh->elfcorehdr_addr));
671 fadump_cpu_notes_buf_free((
unsigned long)
__va(fw_dump.cpu_notes_buf),
672 fw_dump.cpu_notes_buf_size);
673 fw_dump.cpu_notes_buf = 0;
674 fw_dump.cpu_notes_buf_size = 0;
683 static int __init process_fadump(
const struct fadump_mem_struct *fdm_active)
685 struct fadump_crash_info_header *fdh;
688 if (!fdm_active || !fw_dump.fadumphdr_addr)
692 if ((fdm_active->header.dump_status_flag == FADUMP_ERROR_FLAG) ||
693 (fdm_active->cpu_state_data.error_flags != 0) ||
694 (fdm_active->rmr_region.error_flags != 0)) {
698 if ((fdm_active->rmr_region.bytes_dumped !=
699 fdm_active->rmr_region.source_len) ||
700 !fdm_active->cpu_state_data.bytes_dumped) {
706 fdh =
__va(fw_dump.fadumphdr_addr);
707 if (fdh->magic_number != FADUMP_CRASH_INFO_MAGIC) {
712 rc = fadump_build_cpu_notes(fdm_active);
726 static inline void fadump_add_crash_memory(
unsigned long long base,
727 unsigned long long end)
732 pr_debug(
"crash_memory_range[%d] [%#016llx-%#016llx], %#llx bytes\n",
739 static void fadump_exclude_reserved_area(
unsigned long long start,
740 unsigned long long end)
742 unsigned long long ra_start, ra_end;
744 ra_start = fw_dump.reserve_dump_area_start;
745 ra_end = ra_start + fw_dump.reserve_dump_area_size;
747 if ((ra_start < end) && (ra_end > start)) {
748 if ((start < ra_start) && (end > ra_end)) {
749 fadump_add_crash_memory(start, ra_start);
750 fadump_add_crash_memory(ra_end, end);
751 }
else if (start < ra_start) {
752 fadump_add_crash_memory(start, ra_start);
753 }
else if (ra_end < end) {
754 fadump_add_crash_memory(ra_end, end);
757 fadump_add_crash_memory(start, end);
760 static int fadump_init_elfcore_header(
char *bufp)
764 elf = (
struct elfhdr *) bufp;
765 bufp +=
sizeof(
struct elfhdr);
776 elf->e_phoff =
sizeof(
struct elfhdr);
779 elf->e_ehsize =
sizeof(
struct elfhdr);
780 elf->e_phentsize =
sizeof(
struct elf_phdr);
782 elf->e_shentsize = 0;
793 static void fadump_setup_crash_memory_ranges(
void)
795 struct memblock_region *
reg;
798 pr_debug(
"Setup crash memory ranges.\n");
807 fadump_add_crash_memory(RMA_START, fw_dump.boot_memory_size);
809 for_each_memblock(
memory, reg) {
810 start = (
unsigned long long)reg->base;
811 end = start + (
unsigned long long)reg->size;
812 if (start == RMA_START && end >= fw_dump.boot_memory_size)
813 start = fw_dump.boot_memory_size;
816 fadump_exclude_reserved_area(start, end);
825 static inline unsigned long fadump_relocate(
unsigned long paddr)
827 if (paddr > RMA_START && paddr < fw_dump.boot_memory_size)
828 return fdm.rmr_region.destination_address +
paddr;
833 static int fadump_create_elfcore_headers(
char *bufp)
839 fadump_init_elfcore_header(bufp);
840 elf = (
struct elfhdr *)bufp;
841 bufp +=
sizeof(
struct elfhdr);
873 phdr->p_offset = phdr->p_paddr;
883 unsigned long long mbase, msize;
894 phdr->p_offset = mbase;
896 if (mbase == RMA_START) {
902 phdr->p_offset = fdm.rmr_region.destination_address;
905 phdr->p_paddr = mbase;
906 phdr->p_vaddr = (
unsigned long)
__va(mbase);
907 phdr->p_filesz = msize;
908 phdr->p_memsz = msize;
917 static unsigned long init_fadump_header(
unsigned long addr)
919 struct fadump_crash_info_header *fdh;
924 fw_dump.fadumphdr_addr =
addr;
926 addr +=
sizeof(
struct fadump_crash_info_header);
928 memset(fdh, 0,
sizeof(
struct fadump_crash_info_header));
929 fdh->magic_number = FADUMP_CRASH_INFO_MAGIC;
930 fdh->elfcorehdr_addr =
addr;
937 static void register_fadump(
void)
946 if (!fw_dump.reserve_dump_area_size)
949 fadump_setup_crash_memory_ranges();
951 addr = fdm.rmr_region.destination_address + fdm.rmr_region.source_len;
953 addr = init_fadump_header(addr);
956 pr_debug(
"Creating ELF core headers at %#016lx\n", addr);
957 fadump_create_elfcore_headers(vaddr);
960 register_fw_dump(&fdm);
963 static int fadump_unregister_dump(
struct fadump_mem_struct *fdm)
968 pr_debug(
"Un-register firmware-assisted dump\n");
972 rc =
rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1,
NULL,
973 FADUMP_UNREGISTER, fdm,
974 sizeof(
struct fadump_mem_struct));
983 " unexpected error(%d).\n", rc);
986 fw_dump.dump_registered = 0;
990 static int fadump_invalidate_dump(
struct fadump_mem_struct *fdm)
995 pr_debug(
"Invalidating firmware-assisted dump registration\n");
999 rc =
rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1,
NULL,
1000 FADUMP_INVALIDATE, fdm,
1001 sizeof(
struct fadump_mem_struct));
1006 }
while (wait_time);
1010 "rgistration. unexpected error(%d).\n", rc);
1013 fw_dump.dump_active = 0;
1021 if (fw_dump.dump_active) {
1022 init_fadump_mem_struct(&fdm,
1023 fdm_active->cpu_state_data.destination_address);
1024 fadump_invalidate_dump(&fdm);
1032 static void fadump_release_memory(
unsigned long begin,
unsigned long end)
1035 unsigned long ra_start, ra_end;
1037 ra_start = fw_dump.reserve_dump_area_start;
1038 ra_end = ra_start + fw_dump.reserve_dump_area_size;
1045 if (addr <= ra_end && ((addr +
PAGE_SIZE) > ra_start))
1055 static void fadump_invalidate_release_mem(
void)
1057 unsigned long reserved_area_start, reserved_area_end;
1058 unsigned long destination_address;
1061 if (!fw_dump.dump_active) {
1066 destination_address = fdm_active->cpu_state_data.destination_address;
1074 reserved_area_start = fw_dump.reserve_dump_area_start;
1075 reserved_area_end = reserved_area_start +
1076 fw_dump.reserve_dump_area_size;
1081 fw_dump.reserve_dump_area_start = destination_address;
1082 fw_dump.reserve_dump_area_size = get_fadump_area_size();
1084 fadump_release_memory(reserved_area_start, reserved_area_end);
1085 if (fw_dump.cpu_notes_buf) {
1086 fadump_cpu_notes_buf_free(
1087 (
unsigned long)
__va(fw_dump.cpu_notes_buf),
1088 fw_dump.cpu_notes_buf_size);
1089 fw_dump.cpu_notes_buf = 0;
1090 fw_dump.cpu_notes_buf_size = 0;
1093 init_fadump_mem_struct(&fdm, fw_dump.reserve_dump_area_start);
1098 const char *buf,
size_t count)
1100 if (!fw_dump.dump_active)
1103 if (buf[0] ==
'1') {
1109 fadump_invalidate_release_mem();
1120 return sprintf(buf,
"%d\n", fw_dump.fadump_enabled);
1127 return sprintf(buf,
"%d\n", fw_dump.dump_registered);
1132 const char *buf,
size_t count)
1136 if (!fw_dump.fadump_enabled || fdm_active)
1143 if (fw_dump.dump_registered == 0) {
1148 fadump_unregister_dump(&fdm);
1151 if (fw_dump.dump_registered == 1) {
1165 return ret < 0 ? ret :
count;
1168 static int fadump_region_show(
struct seq_file *
m,
void *
private)
1170 const struct fadump_mem_struct *fdm_ptr;
1172 if (!fw_dump.fadump_enabled)
1177 fdm_ptr = fdm_active;
1184 "CPU : [%#016llx-%#016llx] %#llx bytes, "
1186 fdm_ptr->cpu_state_data.destination_address,
1187 fdm_ptr->cpu_state_data.destination_address +
1188 fdm_ptr->cpu_state_data.source_len - 1,
1189 fdm_ptr->cpu_state_data.source_len,
1190 fdm_ptr->cpu_state_data.bytes_dumped);
1192 "HPTE: [%#016llx-%#016llx] %#llx bytes, "
1194 fdm_ptr->hpte_region.destination_address,
1195 fdm_ptr->hpte_region.destination_address +
1196 fdm_ptr->hpte_region.source_len - 1,
1197 fdm_ptr->hpte_region.source_len,
1198 fdm_ptr->hpte_region.bytes_dumped);
1200 "DUMP: [%#016llx-%#016llx] %#llx bytes, "
1202 fdm_ptr->rmr_region.destination_address,
1203 fdm_ptr->rmr_region.destination_address +
1204 fdm_ptr->rmr_region.source_len - 1,
1205 fdm_ptr->rmr_region.source_len,
1206 fdm_ptr->rmr_region.bytes_dumped);
1209 (fw_dump.reserve_dump_area_start ==
1210 fdm_ptr->cpu_state_data.destination_address))
1215 " : [%#016llx-%#016llx] %#llx bytes, "
1217 (
unsigned long long)fw_dump.reserve_dump_area_start,
1218 fdm_ptr->cpu_state_data.destination_address - 1,
1219 fdm_ptr->cpu_state_data.destination_address -
1220 fw_dump.reserve_dump_area_start,
1221 fdm_ptr->cpu_state_data.destination_address -
1222 fw_dump.reserve_dump_area_start);
1231 fadump_release_memory_store);
1233 0444, fadump_enabled_show,
1236 0644, fadump_register_show,
1237 fadump_register_store);
1245 .open = fadump_region_open,
1251 static void fadump_init_files(
void)
1253 struct dentry *debugfs_file;
1259 " fadump_enabled (%d)\n", rc);
1264 " fadump_registered (%d)\n", rc);
1267 powerpc_debugfs_root,
NULL,
1268 &fadump_region_fops);
1271 " fadump_region\n");
1273 if (fw_dump.dump_active) {
1277 " fadump_release_mem (%d)\n", rc);
1287 if (!fw_dump.fadump_enabled)
1290 if (!fw_dump.fadump_supported) {
1292 " this hardware\n");
1296 fadump_show_config();
1301 if (fw_dump.dump_active) {
1306 if (process_fadump(fdm_active) < 0)
1307 fadump_invalidate_release_mem();
1310 else if (fw_dump.reserve_dump_area_size)
1311 init_fadump_mem_struct(&fdm, fw_dump.reserve_dump_area_start);
1312 fadump_init_files();