summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHari Bathini <hbathini@linux.ibm.com>2018-08-06 22:42:54 +0200
committerMichael Ellerman <mpe@ellerman.id.au>2018-08-10 14:12:34 +0200
commitced1bf52f47783135b985d2aacf53fa77fd72e2e (patch)
tree4ba5324c17d3e526cb5e4e2a6b4fc0537ab98ce5
parentpowerpc/fadump: handle crash memory ranges array index overflow (diff)
downloadlinux-ced1bf52f47783135b985d2aacf53fa77fd72e2e.tar.xz
linux-ced1bf52f47783135b985d2aacf53fa77fd72e2e.zip
powerpc/fadump: merge adjacent memory ranges to reduce PT_LOAD segements
With dynamic memory allocation support for crash memory ranges array, there is no hard limit on the no. of crash memory ranges kernel could export, but program headers count could overflow in the /proc/vmcore ELF file while exporting each memory range as PT_LOAD segment. Reduce the likelihood of a such scenario, by folding adjacent crash memory ranges which minimizes the total number of PT_LOAD segments. Signed-off-by: Hari Bathini <hbathini@linux.ibm.com> Reviewed-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/kernel/fadump.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 958eb5cd2a9e..986ec476fd5d 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -908,22 +908,41 @@ static int allocate_crash_memory_ranges(void)
static inline int fadump_add_crash_memory(unsigned long long base,
unsigned long long end)
{
+ u64 start, size;
+ bool is_adjacent = false;
+
if (base == end)
return 0;
- if (crash_mem_ranges == max_crash_mem_ranges) {
- int ret;
+ /*
+ * Fold adjacent memory ranges to bring down the memory ranges/
+ * PT_LOAD segments count.
+ */
+ if (crash_mem_ranges) {
+ start = crash_memory_ranges[crash_mem_ranges - 1].base;
+ size = crash_memory_ranges[crash_mem_ranges - 1].size;
- ret = allocate_crash_memory_ranges();
- if (ret)
- return ret;
+ if ((start + size) == base)
+ is_adjacent = true;
+ }
+ if (!is_adjacent) {
+ /* resize the array on reaching the limit */
+ if (crash_mem_ranges == max_crash_mem_ranges) {
+ int ret;
+
+ ret = allocate_crash_memory_ranges();
+ if (ret)
+ return ret;
+ }
+
+ start = base;
+ crash_memory_ranges[crash_mem_ranges].base = start;
+ crash_mem_ranges++;
}
+ crash_memory_ranges[crash_mem_ranges - 1].size = (end - start);
pr_debug("crash_memory_range[%d] [%#016llx-%#016llx], %#llx bytes\n",
- crash_mem_ranges, base, end - 1, (end - base));
- crash_memory_ranges[crash_mem_ranges].base = base;
- crash_memory_ranges[crash_mem_ranges].size = end - base;
- crash_mem_ranges++;
+ (crash_mem_ranges - 1), start, end - 1, (end - start));
return 0;
}
@@ -999,6 +1018,14 @@ static int fadump_setup_crash_memory_ranges(void)
pr_debug("Setup crash memory ranges.\n");
crash_mem_ranges = 0;
+
+ /* allocate memory for crash memory ranges for the first time */
+ if (!max_crash_mem_ranges) {
+ ret = allocate_crash_memory_ranges();
+ if (ret)
+ return ret;
+ }
+
/*
* add the first memory chunk (RMA_START through boot_memory_size) as
* a separate memory chunk. The reason is, at the time crash firmware