aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/fadump.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/fadump.c')
-rw-r--r--arch/powerpc/kernel/fadump.c154
1 files changed, 129 insertions, 25 deletions
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 761b28b1427d..45a8d0be1c96 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -35,6 +35,7 @@
35#include <linux/kobject.h> 35#include <linux/kobject.h>
36#include <linux/sysfs.h> 36#include <linux/sysfs.h>
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/cma.h>
38 39
39#include <asm/debugfs.h> 40#include <asm/debugfs.h>
40#include <asm/page.h> 41#include <asm/page.h>
@@ -46,6 +47,9 @@
46static struct fw_dump fw_dump; 47static struct fw_dump fw_dump;
47static struct fadump_mem_struct fdm; 48static struct fadump_mem_struct fdm;
48static const struct fadump_mem_struct *fdm_active; 49static const struct fadump_mem_struct *fdm_active;
50#ifdef CONFIG_CMA
51static struct cma *fadump_cma;
52#endif
49 53
50static DEFINE_MUTEX(fadump_mutex); 54static DEFINE_MUTEX(fadump_mutex);
51struct fad_crash_memory_ranges *crash_memory_ranges; 55struct fad_crash_memory_ranges *crash_memory_ranges;
@@ -53,6 +57,67 @@ int crash_memory_ranges_size;
53int crash_mem_ranges; 57int crash_mem_ranges;
54int max_crash_mem_ranges; 58int max_crash_mem_ranges;
55 59
60#ifdef CONFIG_CMA
61/*
62 * fadump_cma_init() - Initialize CMA area from a fadump reserved memory
63 *
64 * This function initializes CMA area from fadump reserved memory.
65 * The total size of fadump reserved memory covers for boot memory size
66 * + cpu data size + hpte size and metadata.
67 * Initialize only the area equivalent to boot memory size for CMA use.
68 * The reamining portion of fadump reserved memory will be not given
69 * to CMA and pages for thoes will stay reserved. boot memory size is
70 * aligned per CMA requirement to satisy cma_init_reserved_mem() call.
71 * But for some reason even if it fails we still have the memory reservation
72 * with us and we can still continue doing fadump.
73 */
74int __init fadump_cma_init(void)
75{
76 unsigned long long base, size;
77 int rc;
78
79 if (!fw_dump.fadump_enabled)
80 return 0;
81
82 /*
83 * Do not use CMA if user has provided fadump=nocma kernel parameter.
84 * Return 1 to continue with fadump old behaviour.
85 */
86 if (fw_dump.nocma)
87 return 1;
88
89 base = fw_dump.reserve_dump_area_start;
90 size = fw_dump.boot_memory_size;
91
92 if (!size)
93 return 0;
94
95 rc = cma_init_reserved_mem(base, size, 0, "fadump_cma", &fadump_cma);
96 if (rc) {
97 pr_err("Failed to init cma area for firmware-assisted dump,%d\n", rc);
98 /*
99 * Though the CMA init has failed we still have memory
100 * reservation with us. The reserved memory will be
101 * blocked from production system usage. Hence return 1,
102 * so that we can continue with fadump.
103 */
104 return 1;
105 }
106
107 /*
108 * So we now have successfully initialized cma area for fadump.
109 */
110 pr_info("Initialized 0x%lx bytes cma area at %ldMB from 0x%lx "
111 "bytes of memory reserved for firmware-assisted dump\n",
112 cma_get_size(fadump_cma),
113 (unsigned long)cma_get_base(fadump_cma) >> 20,
114 fw_dump.reserve_dump_area_size);
115 return 1;
116}
117#else
118static int __init fadump_cma_init(void) { return 1; }
119#endif /* CONFIG_CMA */
120
56/* Scan the Firmware Assisted dump configuration details. */ 121/* Scan the Firmware Assisted dump configuration details. */
57int __init early_init_dt_scan_fw_dump(unsigned long node, 122int __init early_init_dt_scan_fw_dump(unsigned long node,
58 const char *uname, int depth, void *data) 123 const char *uname, int depth, void *data)
@@ -118,13 +183,19 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
118 183
119/* 184/*
120 * If fadump is registered, check if the memory provided 185 * If fadump is registered, check if the memory provided
121 * falls within boot memory area. 186 * falls within boot memory area and reserved memory area.
122 */ 187 */
123int is_fadump_boot_memory_area(u64 addr, ulong size) 188int is_fadump_memory_area(u64 addr, ulong size)
124{ 189{
190 u64 d_start = fw_dump.reserve_dump_area_start;
191 u64 d_end = d_start + fw_dump.reserve_dump_area_size;
192
125 if (!fw_dump.dump_registered) 193 if (!fw_dump.dump_registered)
126 return 0; 194 return 0;
127 195
196 if (((addr + size) > d_start) && (addr <= d_end))
197 return 1;
198
128 return (addr + size) > RMA_START && addr <= fw_dump.boot_memory_size; 199 return (addr + size) > RMA_START && addr <= fw_dump.boot_memory_size;
129} 200}
130 201
@@ -172,6 +243,35 @@ static int is_boot_memory_area_contiguous(void)
172 return ret; 243 return ret;
173} 244}
174 245
246/*
247 * Returns true, if there are no holes in reserved memory area,
248 * false otherwise.
249 */
250static bool is_reserved_memory_area_contiguous(void)
251{
252 struct memblock_region *reg;
253 unsigned long start, end;
254 unsigned long d_start = fw_dump.reserve_dump_area_start;
255 unsigned long d_end = d_start + fw_dump.reserve_dump_area_size;
256
257 for_each_memblock(memory, reg) {
258 start = max(d_start, (unsigned long)reg->base);
259 end = min(d_end, (unsigned long)(reg->base + reg->size));
260 if (d_start < end) {
261 /* Memory hole from d_start to start */
262 if (start > d_start)
263 break;
264
265 if (end == d_end)
266 return true;
267
268 d_start = end + 1;
269 }
270 }
271
272 return false;
273}
274
175/* Print firmware assisted dump configurations for debugging purpose. */ 275/* Print firmware assisted dump configurations for debugging purpose. */
176static void fadump_show_config(void) 276static void fadump_show_config(void)
177{ 277{
@@ -378,8 +478,15 @@ int __init fadump_reserve_mem(void)
378 */ 478 */
379 if (fdm_active) 479 if (fdm_active)
380 fw_dump.boot_memory_size = be64_to_cpu(fdm_active->rmr_region.source_len); 480 fw_dump.boot_memory_size = be64_to_cpu(fdm_active->rmr_region.source_len);
381 else 481 else {
382 fw_dump.boot_memory_size = fadump_calculate_reserve_size(); 482 fw_dump.boot_memory_size = fadump_calculate_reserve_size();
483#ifdef CONFIG_CMA
484 if (!fw_dump.nocma)
485 fw_dump.boot_memory_size =
486 ALIGN(fw_dump.boot_memory_size,
487 FADUMP_CMA_ALIGNMENT);
488#endif
489 }
383 490
384 /* 491 /*
385 * Calculate the memory boundary. 492 * Calculate the memory boundary.
@@ -426,8 +533,9 @@ int __init fadump_reserve_mem(void)
426 fw_dump.fadumphdr_addr = 533 fw_dump.fadumphdr_addr =
427 be64_to_cpu(fdm_active->rmr_region.destination_address) + 534 be64_to_cpu(fdm_active->rmr_region.destination_address) +
428 be64_to_cpu(fdm_active->rmr_region.source_len); 535 be64_to_cpu(fdm_active->rmr_region.source_len);
429 pr_debug("fadumphdr_addr = %p\n", 536 pr_debug("fadumphdr_addr = %pa\n", &fw_dump.fadumphdr_addr);
430 (void *) fw_dump.fadumphdr_addr); 537 fw_dump.reserve_dump_area_start = base;
538 fw_dump.reserve_dump_area_size = size;
431 } else { 539 } else {
432 size = get_fadump_area_size(); 540 size = get_fadump_area_size();
433 541
@@ -455,10 +563,11 @@ int __init fadump_reserve_mem(void)
455 (unsigned long)(size >> 20), 563 (unsigned long)(size >> 20),
456 (unsigned long)(base >> 20), 564 (unsigned long)(base >> 20),
457 (unsigned long)(memblock_phys_mem_size() >> 20)); 565 (unsigned long)(memblock_phys_mem_size() >> 20));
458 }
459 566
460 fw_dump.reserve_dump_area_start = base; 567 fw_dump.reserve_dump_area_start = base;
461 fw_dump.reserve_dump_area_size = size; 568 fw_dump.reserve_dump_area_size = size;
569 return fadump_cma_init();
570 }
462 return 1; 571 return 1;
463} 572}
464 573
@@ -477,6 +586,10 @@ static int __init early_fadump_param(char *p)
477 fw_dump.fadump_enabled = 1; 586 fw_dump.fadump_enabled = 1;
478 else if (strncmp(p, "off", 3) == 0) 587 else if (strncmp(p, "off", 3) == 0)
479 fw_dump.fadump_enabled = 0; 588 fw_dump.fadump_enabled = 0;
589 else if (strncmp(p, "nocma", 5) == 0) {
590 fw_dump.fadump_enabled = 1;
591 fw_dump.nocma = 1;
592 }
480 593
481 return 0; 594 return 0;
482} 595}
@@ -525,8 +638,10 @@ static int register_fw_dump(struct fadump_mem_struct *fdm)
525 break; 638 break;
526 case -3: 639 case -3:
527 if (!is_boot_memory_area_contiguous()) 640 if (!is_boot_memory_area_contiguous())
528 pr_err("Can't have holes in boot memory area while " 641 pr_err("Can't have holes in boot memory area while registering fadump\n");
529 "registering fadump\n"); 642 else if (!is_reserved_memory_area_contiguous())
643 pr_err("Can't have holes in reserved memory area while"
644 " registering fadump\n");
530 645
531 printk(KERN_ERR "Failed to register firmware-assisted kernel" 646 printk(KERN_ERR "Failed to register firmware-assisted kernel"
532 " dump. Parameter Error(%d).\n", rc); 647 " dump. Parameter Error(%d).\n", rc);
@@ -1229,7 +1344,7 @@ static int fadump_unregister_dump(struct fadump_mem_struct *fdm)
1229 return 0; 1344 return 0;
1230} 1345}
1231 1346
1232static int fadump_invalidate_dump(struct fadump_mem_struct *fdm) 1347static int fadump_invalidate_dump(const struct fadump_mem_struct *fdm)
1233{ 1348{
1234 int rc = 0; 1349 int rc = 0;
1235 unsigned int wait_time; 1350 unsigned int wait_time;
@@ -1260,9 +1375,8 @@ void fadump_cleanup(void)
1260{ 1375{
1261 /* Invalidate the registration only if dump is active. */ 1376 /* Invalidate the registration only if dump is active. */
1262 if (fw_dump.dump_active) { 1377 if (fw_dump.dump_active) {
1263 init_fadump_mem_struct(&fdm, 1378 /* pass the same memory dump structure provided by platform */
1264 be64_to_cpu(fdm_active->cpu_state_data.destination_address)); 1379 fadump_invalidate_dump(fdm_active);
1265 fadump_invalidate_dump(&fdm);
1266 } else if (fw_dump.dump_registered) { 1380 } else if (fw_dump.dump_registered) {
1267 /* Un-register Firmware-assisted dump if it was registered. */ 1381 /* Un-register Firmware-assisted dump if it was registered. */
1268 fadump_unregister_dump(&fdm); 1382 fadump_unregister_dump(&fdm);
@@ -1531,17 +1645,7 @@ static struct kobj_attribute fadump_register_attr = __ATTR(fadump_registered,
1531 0644, fadump_register_show, 1645 0644, fadump_register_show,
1532 fadump_register_store); 1646 fadump_register_store);
1533 1647
1534static int fadump_region_open(struct inode *inode, struct file *file) 1648DEFINE_SHOW_ATTRIBUTE(fadump_region);
1535{
1536 return single_open(file, fadump_region_show, inode->i_private);
1537}
1538
1539static const struct file_operations fadump_region_fops = {
1540 .open = fadump_region_open,
1541 .read = seq_read,
1542 .llseek = seq_lseek,
1543 .release = single_release,
1544};
1545 1649
1546static void fadump_init_files(void) 1650static void fadump_init_files(void)
1547{ 1651{