powerpc/fadump: setup additional parameters for dump capture kernel
[linux-block.git] / arch / powerpc / platforms / pseries / rtas-fadump.c
CommitLineData
d3833a70
HB
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>
e6f6390a
CL
16#include <linux/of.h>
17#include <linux/of_fdt.h>
d3833a70
HB
18
19#include <asm/page.h>
d3833a70 20#include <asm/rtas.h>
683eab94 21#include <asm/setup.h>
d3833a70
HB
22#include <asm/fadump.h>
23#include <asm/fadump-internal.h>
24
25#include "rtas-fadump.h"
26
41a65d16 27static struct rtas_fadump_mem_struct fdm;
f3512011 28static const struct rtas_fadump_mem_struct *fdm_active;
41a65d16
HB
29
30static void rtas_fadump_update_config(struct fw_dump *fadump_conf,
31 const struct rtas_fadump_mem_struct *fdm)
32{
41a65d16
HB
33 fadump_conf->fadumphdr_addr = (fadump_conf->boot_mem_dest_addr +
34 fadump_conf->boot_memory_size);
35}
36
f3512011
HB
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 */
e14ff96d 41static void __init rtas_fadump_get_config(struct fw_dump *fadump_conf,
f3512011
HB
42 const struct rtas_fadump_mem_struct *fdm)
43{
78d5cc15
HB
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;
683eab94
HB
85 case RTAS_FADUMP_PARAM_AREA:
86 fadump_conf->param_area = be64_to_cpu(fdm->rgn[i].destination_address);
87 break;
78d5cc15
HB
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;
f3512011
HB
94
95 rtas_fadump_update_config(fadump_conf, fdm);
96}
97
d3833a70
HB
98static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf)
99{
41a65d16 100 u64 addr = fadump_conf->reserve_dump_area_start;
78d5cc15 101 u16 sec_cnt = 0;
41a65d16
HB
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);
41a65d16
HB
107 fdm.header.dump_status_flag = 0;
108 fdm.header.offset_first_dump_section =
78d5cc15 109 cpu_to_be32((u32)offsetof(struct rtas_fadump_mem_struct, rgn));
41a65d16
HB
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. */
78d5cc15
HB
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);
41a65d16 130 addr += fadump_conf->cpu_state_data_size;
78d5cc15 131 sec_cnt++;
41a65d16
HB
132
133 /* hpte region section */
78d5cc15
HB
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);
41a65d16 139 addr += fadump_conf->hpte_region_size;
78d5cc15 140 sec_cnt++;
41a65d16 141
9cf3b3a3
HB
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
78d5cc15
HB
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 }
41a65d16 160
683eab94
HB
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 }
78d5cc15 170 fdm.header.dump_num_sections = cpu_to_be16(sec_cnt);
683eab94 171
41a65d16
HB
172 rtas_fadump_update_config(fadump_conf, &fdm);
173
174 return addr;
d3833a70
HB
175}
176
7b1b3b48
HB
177static u64 rtas_fadump_get_bootmem_min(void)
178{
179 return RTAS_FADUMP_MIN_BOOT_MEM;
180}
181
d3833a70
HB
182static int rtas_fadump_register(struct fw_dump *fadump_conf)
183{
78d5cc15 184 unsigned int wait_time, fdm_size;
41a65d16
HB
185 int rc, err = -EIO;
186
78d5cc15
HB
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
41a65d16
HB
195 /* TODO: Add upper time limit for the delay */
196 do {
197 rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
78d5cc15 198 NULL, FADUMP_REGISTER, &fdm, fdm_size);
41a65d16
HB
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:
78d5cc15 216 if (!is_fadump_reserved_mem_contiguous())
41a65d16
HB
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;
d3833a70
HB
233}
234
235static int rtas_fadump_unregister(struct fw_dump *fadump_conf)
236{
41a65d16
HB
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;
d3833a70
HB
258}
259
260static int rtas_fadump_invalidate(struct fw_dump *fadump_conf)
261{
f3512011
HB
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
287static 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
e14ff96d 307static void __init rtas_fadump_set_regval(struct pt_regs *regs, u64 reg_id, u64 reg_val)
f3512011
HB
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
e14ff96d 332static struct rtas_fadump_reg_entry* __init
f3512011
HB
333rtas_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 */
361static 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;
f3512011
HB
369 void *vaddr;
370
78d5cc15 371 vaddr = (void *)fadump_conf->cpu_state_dest_vaddr;
f3512011
HB
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);
6584cec0 409 if (fdh && !cpumask_test_cpu(cpu, &fdh->cpu_mask)) {
f3512011
HB
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, &regs);
417 RTAS_FADUMP_SKIP_TO_NEXT_CPU(reg_entry);
418 } else {
419 reg_entry++;
420 reg_entry = rtas_fadump_read_regs(reg_entry, &regs);
421 note_buf = fadump_regs_to_elf_notes(note_buf, &regs);
422 }
423 }
424 final_note(note_buf);
425
c6c5b14d
SJ
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);
f3512011
HB
428 return 0;
429
430error_out:
431 fadump_free_cpu_notes_buf();
432 return rc;
433
d3833a70
HB
434}
435
436/*
c6c5b14d
SJ
437 * Validate and process the dump data stored by the firmware, and update
438 * the CPU notes of elfcorehdr.
d3833a70
HB
439 */
440static int __init rtas_fadump_process(struct fw_dump *fadump_conf)
441{
f3512011
HB
442 if (!fdm_active || !fadump_conf->fadumphdr_addr)
443 return -EINVAL;
444
445 /* Check if the dump data is valid. */
78d5cc15
HB
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;
683eab94
HB
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;
78d5cc15
HB
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 }
f3512011
HB
489 }
490
c6c5b14d 491 return rtas_fadump_build_cpu_notes(fadump_conf);
d3833a70
HB
492}
493
494static void rtas_fadump_region_show(struct fw_dump *fadump_conf,
495 struct seq_file *m)
496{
f3512011
HB
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;
41a65d16 503
78d5cc15
HB
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;
683eab94
HB
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;
78d5cc15
HB
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 }
f3512011 547
a3ceb588 548 /* Dump is active. Show preserved area start address. */
f3512011 549 if (fdm_active) {
a3ceb588
HB
550 seq_printf(m, "\nMemory above %#016llx is reserved for saving crash dump\n",
551 fadump_conf->boot_mem_top);
f3512011 552 }
d3833a70
HB
553}
554
555static 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
78d5cc15
HB
562/* FADUMP_MAX_MEM_REGS or lower */
563static 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
d3833a70
HB
576static struct fadump_ops rtas_fadump_ops = {
577 .fadump_init_mem_struct = rtas_fadump_init_mem_struct,
7b1b3b48 578 .fadump_get_bootmem_min = rtas_fadump_get_bootmem_min,
d3833a70
HB
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,
78d5cc15 585 .fadump_max_boot_mem_rgns = rtas_fadump_max_boot_mem_rgns,
d3833a70
HB
586};
587
588void __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
683eab94
HB
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;
d3833a70 606
7dee93a9 607 /* Firmware supports 64-bit value for size, align it to pagesize. */
e96d904e 608 fadump_conf->max_copy_size = ALIGN_DOWN(U64_MAX, PAGE_SIZE);
7dee93a9 609
f3512011
HB
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
d3833a70
HB
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(&sections[1], 2);
642 break;
643 case RTAS_FADUMP_HPTE_REGION:
644 fadump_conf->hpte_region_size =
645 of_read_ulong(&sections[1], 2);
646 break;
647 }
648 }
649}