0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) "rtas fadump: " fmt
0010
0011 #include <linux/string.h>
0012 #include <linux/memblock.h>
0013 #include <linux/delay.h>
0014 #include <linux/seq_file.h>
0015 #include <linux/crash_dump.h>
0016 #include <linux/of.h>
0017 #include <linux/of_fdt.h>
0018
0019 #include <asm/page.h>
0020 #include <asm/rtas.h>
0021 #include <asm/fadump.h>
0022 #include <asm/fadump-internal.h>
0023
0024 #include "rtas-fadump.h"
0025
0026 static struct rtas_fadump_mem_struct fdm;
0027 static const struct rtas_fadump_mem_struct *fdm_active;
0028
0029 static void rtas_fadump_update_config(struct fw_dump *fadump_conf,
0030 const struct rtas_fadump_mem_struct *fdm)
0031 {
0032 fadump_conf->boot_mem_dest_addr =
0033 be64_to_cpu(fdm->rmr_region.destination_address);
0034
0035 fadump_conf->fadumphdr_addr = (fadump_conf->boot_mem_dest_addr +
0036 fadump_conf->boot_memory_size);
0037 }
0038
0039
0040
0041
0042
0043 static void __init rtas_fadump_get_config(struct fw_dump *fadump_conf,
0044 const struct rtas_fadump_mem_struct *fdm)
0045 {
0046 fadump_conf->boot_mem_addr[0] =
0047 be64_to_cpu(fdm->rmr_region.source_address);
0048 fadump_conf->boot_mem_sz[0] = be64_to_cpu(fdm->rmr_region.source_len);
0049 fadump_conf->boot_memory_size = fadump_conf->boot_mem_sz[0];
0050
0051 fadump_conf->boot_mem_top = fadump_conf->boot_memory_size;
0052 fadump_conf->boot_mem_regs_cnt = 1;
0053
0054
0055
0056
0057
0058 fadump_conf->reserve_dump_area_start =
0059 be64_to_cpu(fdm->cpu_state_data.destination_address);
0060
0061 rtas_fadump_update_config(fadump_conf, fdm);
0062 }
0063
0064 static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf)
0065 {
0066 u64 addr = fadump_conf->reserve_dump_area_start;
0067
0068 memset(&fdm, 0, sizeof(struct rtas_fadump_mem_struct));
0069 addr = addr & PAGE_MASK;
0070
0071 fdm.header.dump_format_version = cpu_to_be32(0x00000001);
0072 fdm.header.dump_num_sections = cpu_to_be16(3);
0073 fdm.header.dump_status_flag = 0;
0074 fdm.header.offset_first_dump_section =
0075 cpu_to_be32((u32)offsetof(struct rtas_fadump_mem_struct,
0076 cpu_state_data));
0077
0078
0079
0080
0081
0082 fdm.header.dd_block_size = 0;
0083 fdm.header.dd_block_offset = 0;
0084 fdm.header.dd_num_blocks = 0;
0085 fdm.header.dd_offset_disk_path = 0;
0086
0087
0088 fdm.header.max_time_auto = 0;
0089
0090
0091
0092 fdm.cpu_state_data.request_flag =
0093 cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
0094 fdm.cpu_state_data.source_data_type =
0095 cpu_to_be16(RTAS_FADUMP_CPU_STATE_DATA);
0096 fdm.cpu_state_data.source_address = 0;
0097 fdm.cpu_state_data.source_len =
0098 cpu_to_be64(fadump_conf->cpu_state_data_size);
0099 fdm.cpu_state_data.destination_address = cpu_to_be64(addr);
0100 addr += fadump_conf->cpu_state_data_size;
0101
0102
0103 fdm.hpte_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
0104 fdm.hpte_region.source_data_type =
0105 cpu_to_be16(RTAS_FADUMP_HPTE_REGION);
0106 fdm.hpte_region.source_address = 0;
0107 fdm.hpte_region.source_len =
0108 cpu_to_be64(fadump_conf->hpte_region_size);
0109 fdm.hpte_region.destination_address = cpu_to_be64(addr);
0110 addr += fadump_conf->hpte_region_size;
0111
0112
0113
0114
0115
0116 addr = PAGE_ALIGN(addr);
0117
0118
0119 fdm.rmr_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
0120 fdm.rmr_region.source_data_type =
0121 cpu_to_be16(RTAS_FADUMP_REAL_MODE_REGION);
0122 fdm.rmr_region.source_address = cpu_to_be64(0);
0123 fdm.rmr_region.source_len = cpu_to_be64(fadump_conf->boot_memory_size);
0124 fdm.rmr_region.destination_address = cpu_to_be64(addr);
0125 addr += fadump_conf->boot_memory_size;
0126
0127 rtas_fadump_update_config(fadump_conf, &fdm);
0128
0129 return addr;
0130 }
0131
0132 static u64 rtas_fadump_get_bootmem_min(void)
0133 {
0134 return RTAS_FADUMP_MIN_BOOT_MEM;
0135 }
0136
0137 static int rtas_fadump_register(struct fw_dump *fadump_conf)
0138 {
0139 unsigned int wait_time;
0140 int rc, err = -EIO;
0141
0142
0143 do {
0144 rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
0145 NULL, FADUMP_REGISTER, &fdm,
0146 sizeof(struct rtas_fadump_mem_struct));
0147
0148 wait_time = rtas_busy_delay_time(rc);
0149 if (wait_time)
0150 mdelay(wait_time);
0151
0152 } while (wait_time);
0153
0154 switch (rc) {
0155 case 0:
0156 pr_info("Registration is successful!\n");
0157 fadump_conf->dump_registered = 1;
0158 err = 0;
0159 break;
0160 case -1:
0161 pr_err("Failed to register. Hardware Error(%d).\n", rc);
0162 break;
0163 case -3:
0164 if (!is_fadump_boot_mem_contiguous())
0165 pr_err("Can't have holes in boot memory area.\n");
0166 else if (!is_fadump_reserved_mem_contiguous())
0167 pr_err("Can't have holes in reserved memory area.\n");
0168
0169 pr_err("Failed to register. Parameter Error(%d).\n", rc);
0170 err = -EINVAL;
0171 break;
0172 case -9:
0173 pr_err("Already registered!\n");
0174 fadump_conf->dump_registered = 1;
0175 err = -EEXIST;
0176 break;
0177 default:
0178 pr_err("Failed to register. Unknown Error(%d).\n", rc);
0179 break;
0180 }
0181
0182 return err;
0183 }
0184
0185 static int rtas_fadump_unregister(struct fw_dump *fadump_conf)
0186 {
0187 unsigned int wait_time;
0188 int rc;
0189
0190
0191 do {
0192 rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
0193 NULL, FADUMP_UNREGISTER, &fdm,
0194 sizeof(struct rtas_fadump_mem_struct));
0195
0196 wait_time = rtas_busy_delay_time(rc);
0197 if (wait_time)
0198 mdelay(wait_time);
0199 } while (wait_time);
0200
0201 if (rc) {
0202 pr_err("Failed to un-register - unexpected error(%d).\n", rc);
0203 return -EIO;
0204 }
0205
0206 fadump_conf->dump_registered = 0;
0207 return 0;
0208 }
0209
0210 static int rtas_fadump_invalidate(struct fw_dump *fadump_conf)
0211 {
0212 unsigned int wait_time;
0213 int rc;
0214
0215
0216 do {
0217 rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
0218 NULL, FADUMP_INVALIDATE, fdm_active,
0219 sizeof(struct rtas_fadump_mem_struct));
0220
0221 wait_time = rtas_busy_delay_time(rc);
0222 if (wait_time)
0223 mdelay(wait_time);
0224 } while (wait_time);
0225
0226 if (rc) {
0227 pr_err("Failed to invalidate - unexpected error (%d).\n", rc);
0228 return -EIO;
0229 }
0230
0231 fadump_conf->dump_active = 0;
0232 fdm_active = NULL;
0233 return 0;
0234 }
0235
0236 #define RTAS_FADUMP_GPR_MASK 0xffffff0000000000
0237 static inline int rtas_fadump_gpr_index(u64 id)
0238 {
0239 char str[3];
0240 int i = -1;
0241
0242 if ((id & RTAS_FADUMP_GPR_MASK) == fadump_str_to_u64("GPR")) {
0243
0244 id &= ~RTAS_FADUMP_GPR_MASK;
0245 id >>= 24;
0246 str[2] = '\0';
0247 str[1] = id & 0xff;
0248 str[0] = (id >> 8) & 0xff;
0249 if (kstrtoint(str, 10, &i))
0250 i = -EINVAL;
0251 if (i > 31)
0252 i = -1;
0253 }
0254 return i;
0255 }
0256
0257 static void __init rtas_fadump_set_regval(struct pt_regs *regs, u64 reg_id, u64 reg_val)
0258 {
0259 int i;
0260
0261 i = rtas_fadump_gpr_index(reg_id);
0262 if (i >= 0)
0263 regs->gpr[i] = (unsigned long)reg_val;
0264 else if (reg_id == fadump_str_to_u64("NIA"))
0265 regs->nip = (unsigned long)reg_val;
0266 else if (reg_id == fadump_str_to_u64("MSR"))
0267 regs->msr = (unsigned long)reg_val;
0268 else if (reg_id == fadump_str_to_u64("CTR"))
0269 regs->ctr = (unsigned long)reg_val;
0270 else if (reg_id == fadump_str_to_u64("LR"))
0271 regs->link = (unsigned long)reg_val;
0272 else if (reg_id == fadump_str_to_u64("XER"))
0273 regs->xer = (unsigned long)reg_val;
0274 else if (reg_id == fadump_str_to_u64("CR"))
0275 regs->ccr = (unsigned long)reg_val;
0276 else if (reg_id == fadump_str_to_u64("DAR"))
0277 regs->dar = (unsigned long)reg_val;
0278 else if (reg_id == fadump_str_to_u64("DSISR"))
0279 regs->dsisr = (unsigned long)reg_val;
0280 }
0281
0282 static struct rtas_fadump_reg_entry* __init
0283 rtas_fadump_read_regs(struct rtas_fadump_reg_entry *reg_entry,
0284 struct pt_regs *regs)
0285 {
0286 memset(regs, 0, sizeof(struct pt_regs));
0287
0288 while (be64_to_cpu(reg_entry->reg_id) != fadump_str_to_u64("CPUEND")) {
0289 rtas_fadump_set_regval(regs, be64_to_cpu(reg_entry->reg_id),
0290 be64_to_cpu(reg_entry->reg_value));
0291 reg_entry++;
0292 }
0293 reg_entry++;
0294 return reg_entry;
0295 }
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311 static int __init rtas_fadump_build_cpu_notes(struct fw_dump *fadump_conf)
0312 {
0313 struct rtas_fadump_reg_save_area_header *reg_header;
0314 struct fadump_crash_info_header *fdh = NULL;
0315 struct rtas_fadump_reg_entry *reg_entry;
0316 u32 num_cpus, *note_buf;
0317 int i, rc = 0, cpu = 0;
0318 struct pt_regs regs;
0319 unsigned long addr;
0320 void *vaddr;
0321
0322 addr = be64_to_cpu(fdm_active->cpu_state_data.destination_address);
0323 vaddr = __va(addr);
0324
0325 reg_header = vaddr;
0326 if (be64_to_cpu(reg_header->magic_number) !=
0327 fadump_str_to_u64("REGSAVE")) {
0328 pr_err("Unable to read register save area.\n");
0329 return -ENOENT;
0330 }
0331
0332 pr_debug("--------CPU State Data------------\n");
0333 pr_debug("Magic Number: %llx\n", be64_to_cpu(reg_header->magic_number));
0334 pr_debug("NumCpuOffset: %x\n", be32_to_cpu(reg_header->num_cpu_offset));
0335
0336 vaddr += be32_to_cpu(reg_header->num_cpu_offset);
0337 num_cpus = be32_to_cpu(*((__be32 *)(vaddr)));
0338 pr_debug("NumCpus : %u\n", num_cpus);
0339 vaddr += sizeof(u32);
0340 reg_entry = (struct rtas_fadump_reg_entry *)vaddr;
0341
0342 rc = fadump_setup_cpu_notes_buf(num_cpus);
0343 if (rc != 0)
0344 return rc;
0345
0346 note_buf = (u32 *)fadump_conf->cpu_notes_buf_vaddr;
0347
0348 if (fadump_conf->fadumphdr_addr)
0349 fdh = __va(fadump_conf->fadumphdr_addr);
0350
0351 for (i = 0; i < num_cpus; i++) {
0352 if (be64_to_cpu(reg_entry->reg_id) !=
0353 fadump_str_to_u64("CPUSTRT")) {
0354 pr_err("Unable to read CPU state data\n");
0355 rc = -ENOENT;
0356 goto error_out;
0357 }
0358
0359 cpu = (be64_to_cpu(reg_entry->reg_value) &
0360 RTAS_FADUMP_CPU_ID_MASK);
0361 if (fdh && !cpumask_test_cpu(cpu, &fdh->cpu_mask)) {
0362 RTAS_FADUMP_SKIP_TO_NEXT_CPU(reg_entry);
0363 continue;
0364 }
0365 pr_debug("Reading register data for cpu %d...\n", cpu);
0366 if (fdh && fdh->crashing_cpu == cpu) {
0367 regs = fdh->regs;
0368 note_buf = fadump_regs_to_elf_notes(note_buf, ®s);
0369 RTAS_FADUMP_SKIP_TO_NEXT_CPU(reg_entry);
0370 } else {
0371 reg_entry++;
0372 reg_entry = rtas_fadump_read_regs(reg_entry, ®s);
0373 note_buf = fadump_regs_to_elf_notes(note_buf, ®s);
0374 }
0375 }
0376 final_note(note_buf);
0377
0378 if (fdh) {
0379 pr_debug("Updating elfcore header (%llx) with cpu notes\n",
0380 fdh->elfcorehdr_addr);
0381 fadump_update_elfcore_header(__va(fdh->elfcorehdr_addr));
0382 }
0383 return 0;
0384
0385 error_out:
0386 fadump_free_cpu_notes_buf();
0387 return rc;
0388
0389 }
0390
0391
0392
0393
0394
0395 static int __init rtas_fadump_process(struct fw_dump *fadump_conf)
0396 {
0397 struct fadump_crash_info_header *fdh;
0398 int rc = 0;
0399
0400 if (!fdm_active || !fadump_conf->fadumphdr_addr)
0401 return -EINVAL;
0402
0403
0404 if ((be16_to_cpu(fdm_active->header.dump_status_flag) ==
0405 RTAS_FADUMP_ERROR_FLAG) ||
0406 (fdm_active->cpu_state_data.error_flags != 0) ||
0407 (fdm_active->rmr_region.error_flags != 0)) {
0408 pr_err("Dump taken by platform is not valid\n");
0409 return -EINVAL;
0410 }
0411 if ((fdm_active->rmr_region.bytes_dumped !=
0412 fdm_active->rmr_region.source_len) ||
0413 !fdm_active->cpu_state_data.bytes_dumped) {
0414 pr_err("Dump taken by platform is incomplete\n");
0415 return -EINVAL;
0416 }
0417
0418
0419 fdh = __va(fadump_conf->fadumphdr_addr);
0420 if (fdh->magic_number != FADUMP_CRASH_INFO_MAGIC) {
0421 pr_err("Crash info header is not valid.\n");
0422 return -EINVAL;
0423 }
0424
0425 rc = rtas_fadump_build_cpu_notes(fadump_conf);
0426 if (rc)
0427 return rc;
0428
0429
0430
0431
0432
0433
0434 elfcorehdr_addr = fdh->elfcorehdr_addr;
0435
0436 return 0;
0437 }
0438
0439 static void rtas_fadump_region_show(struct fw_dump *fadump_conf,
0440 struct seq_file *m)
0441 {
0442 const struct rtas_fadump_section *cpu_data_section;
0443 const struct rtas_fadump_mem_struct *fdm_ptr;
0444
0445 if (fdm_active)
0446 fdm_ptr = fdm_active;
0447 else
0448 fdm_ptr = &fdm;
0449
0450 cpu_data_section = &(fdm_ptr->cpu_state_data);
0451 seq_printf(m, "CPU :[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
0452 be64_to_cpu(cpu_data_section->destination_address),
0453 be64_to_cpu(cpu_data_section->destination_address) +
0454 be64_to_cpu(cpu_data_section->source_len) - 1,
0455 be64_to_cpu(cpu_data_section->source_len),
0456 be64_to_cpu(cpu_data_section->bytes_dumped));
0457
0458 seq_printf(m, "HPTE:[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
0459 be64_to_cpu(fdm_ptr->hpte_region.destination_address),
0460 be64_to_cpu(fdm_ptr->hpte_region.destination_address) +
0461 be64_to_cpu(fdm_ptr->hpte_region.source_len) - 1,
0462 be64_to_cpu(fdm_ptr->hpte_region.source_len),
0463 be64_to_cpu(fdm_ptr->hpte_region.bytes_dumped));
0464
0465 seq_printf(m, "DUMP: Src: %#016llx, Dest: %#016llx, ",
0466 be64_to_cpu(fdm_ptr->rmr_region.source_address),
0467 be64_to_cpu(fdm_ptr->rmr_region.destination_address));
0468 seq_printf(m, "Size: %#llx, Dumped: %#llx bytes\n",
0469 be64_to_cpu(fdm_ptr->rmr_region.source_len),
0470 be64_to_cpu(fdm_ptr->rmr_region.bytes_dumped));
0471
0472
0473 if (fdm_active) {
0474 seq_printf(m, "\nMemory above %#016llx is reserved for saving crash dump\n",
0475 fadump_conf->boot_mem_top);
0476 }
0477 }
0478
0479 static void rtas_fadump_trigger(struct fadump_crash_info_header *fdh,
0480 const char *msg)
0481 {
0482
0483 rtas_os_term((char *)msg);
0484 }
0485
0486 static struct fadump_ops rtas_fadump_ops = {
0487 .fadump_init_mem_struct = rtas_fadump_init_mem_struct,
0488 .fadump_get_bootmem_min = rtas_fadump_get_bootmem_min,
0489 .fadump_register = rtas_fadump_register,
0490 .fadump_unregister = rtas_fadump_unregister,
0491 .fadump_invalidate = rtas_fadump_invalidate,
0492 .fadump_process = rtas_fadump_process,
0493 .fadump_region_show = rtas_fadump_region_show,
0494 .fadump_trigger = rtas_fadump_trigger,
0495 };
0496
0497 void __init rtas_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
0498 {
0499 int i, size, num_sections;
0500 const __be32 *sections;
0501 const __be32 *token;
0502
0503
0504
0505
0506
0507 token = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL);
0508 if (!token)
0509 return;
0510
0511 fadump_conf->ibm_configure_kernel_dump = be32_to_cpu(*token);
0512 fadump_conf->ops = &rtas_fadump_ops;
0513 fadump_conf->fadump_supported = 1;
0514
0515
0516 fadump_conf->max_copy_size = ALIGN_DOWN(U64_MAX, PAGE_SIZE);
0517
0518
0519
0520
0521
0522 fdm_active = of_get_flat_dt_prop(node, "ibm,kernel-dump", NULL);
0523 if (fdm_active) {
0524 pr_info("Firmware-assisted dump is active.\n");
0525 fadump_conf->dump_active = 1;
0526 rtas_fadump_get_config(fadump_conf, (void *)__pa(fdm_active));
0527 }
0528
0529
0530
0531
0532
0533
0534
0535 sections = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes",
0536 &size);
0537
0538 if (!sections)
0539 return;
0540
0541 num_sections = size / (3 * sizeof(u32));
0542
0543 for (i = 0; i < num_sections; i++, sections += 3) {
0544 u32 type = (u32)of_read_number(sections, 1);
0545
0546 switch (type) {
0547 case RTAS_FADUMP_CPU_STATE_DATA:
0548 fadump_conf->cpu_state_data_size =
0549 of_read_ulong(§ions[1], 2);
0550 break;
0551 case RTAS_FADUMP_HPTE_REGION:
0552 fadump_conf->hpte_region_size =
0553 of_read_ulong(§ions[1], 2);
0554 break;
0555 }
0556 }
0557 }