If no start address is specified for crashkernel, the current program hard code as: crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2)); This limits the candidate memory region, and may cause failure while there is enough mem for crashkernel. This patch suggests to find a suitable mem chunk by memblock_find_in_range()
Signed-off-by: Pingfan Liu <kernelf...@gmail.com> Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org> Cc: Michael Ellerman <m...@ellerman.id.au> Cc: Hari Bathini <hbath...@linux.ibm.com> Cc: Mahesh Salgaonkar <mah...@linux.vnet.ibm.com> Cc: Anton Blanchard <an...@samba.org> --- arch/powerpc/kernel/machine_kexec.c | 24 +++++++++++++++--------- arch/powerpc/kernel/prom.c | 7 +++++-- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index 63f5a93..78005bf 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c @@ -22,6 +22,9 @@ #include <asm/pgalloc.h> #include <asm/prom.h> #include <asm/sections.h> +#include <asm/mmu.h> + +#include "setup.h" void machine_kexec_mask_interrupts(void) { unsigned int i; @@ -117,6 +120,7 @@ void machine_kexec(struct kimage *image) void __init reserve_crashkernel(void) { unsigned long long crash_size, crash_base; + phys_addr_t start, up_boundary; int ret; /* use common parsing */ @@ -146,22 +150,24 @@ void __init reserve_crashkernel(void) #else if (!crashk_res.start) { #ifdef CONFIG_PPC64 - /* - * On 64bit we split the RMO in half but cap it at half of - * a small SLB (128MB) since the crash kernel needs to place - * itself and some stacks to be in the first segment. - */ - crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2)); + up_boundary = min(ppc64_bolted_size(), ppc64_rma_size); + start = memblock_find_in_range(KDUMP_KERNELBASE, up_boundary, + crash_size, PAGE_SIZE); + if (start == 0) { + pr_err("Failed to reserve memory for crashkernel!\n"); + crashk_res.start = crashk_res.end = 0; + return; + } else + crashk_res.start = start; #else crashk_res.start = KDUMP_KERNELBASE; #endif } - crash_base = PAGE_ALIGN(crashk_res.start); - if (crash_base != crashk_res.start) { + if (crashk_res.start != PAGE_ALIGN(crashk_res.start)) { printk("Crash kernel base must be aligned to 0x%lx\n", PAGE_SIZE); - crashk_res.start = crash_base; + crashk_res.start = PAGE_ALIGN(crashk_res.start); } #endif diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index cae4a78..8b2ab99 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -688,6 +688,7 @@ static void tm_init(void) { } void __init early_init_devtree(void *params) { phys_addr_t limit; + bool fadump_enabled = false; DBG(" -> early_init_devtree(%p)\n", params); @@ -737,9 +738,9 @@ void __init early_init_devtree(void *params) * If we fail to reserve memory for firmware-assisted dump then * fallback to kexec based kdump. */ - if (fadump_reserve_mem() == 0) + if (fadump_reserve_mem() == 1) + fadump_enabled = true; #endif - reserve_crashkernel(); early_reserve_mem(); /* Ensure that total memory size is page-aligned. */ @@ -761,6 +762,8 @@ void __init early_init_devtree(void *params) dt_cpu_ftrs_scan(); mmu_early_init_devtree(); + if (!fadump_enabled) + reserve_crashkernel(); /* Retrieve CPU related informations from the flat tree * (altivec support, boot CPU ID, ...) -- 2.7.4