From: Mahesh Salgaonkar <mahesh@xxxxxxxxxxxxxxxxxx> Fix it on ppc64 also. This patch now reads the memory limit information from device-tree file and limits the crash memory ranges accordingly. Tested this patch on ppc64 with a kernel patch by Suzuki. Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com> --- kexec/arch/ppc64/crashdump-ppc64.c | 11 ++++++++++- kexec/arch/ppc64/crashdump-ppc64.h | 1 + kexec/arch/ppc64/kexec-ppc64.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletions(-) diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c index 30ef443..690b1f7 100644 --- a/kexec/arch/ppc64/crashdump-ppc64.c +++ b/kexec/arch/ppc64/crashdump-ppc64.c @@ -84,10 +84,19 @@ static unsigned long long cstart, cend; static int memory_ranges; /* - * Exclude the region that lies within crashkernel + * Exclude the region that lies within crashkernel and above the memory + * limit which is reflected by mem= kernel option. */ static void exclude_crash_region(uint64_t start, uint64_t end) { + /* If memory_limit is set then exclude the memory region above it. */ + if (memory_limit) { + if (start > memory_limit) + return; + if (end > memory_limit) + end = memory_limit; + } + if (cstart < end && cend > start) { if (start < cstart && end > cend) { crash_memory_range[memory_ranges].start = start; diff --git a/kexec/arch/ppc64/crashdump-ppc64.h b/kexec/arch/ppc64/crashdump-ppc64.h index be02213..739c61f 100644 --- a/kexec/arch/ppc64/crashdump-ppc64.h +++ b/kexec/arch/ppc64/crashdump-ppc64.h @@ -27,6 +27,7 @@ void add_usable_mem_rgns(unsigned long long base, unsigned long long size); extern uint64_t crash_base; extern uint64_t crash_size; +extern uint64_t memory_limit; extern unsigned int rtas_base; extern unsigned int rtas_size; diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c index 2f12907..189d48e 100644 --- a/kexec/arch/ppc64/kexec-ppc64.c +++ b/kexec/arch/ppc64/kexec-ppc64.c @@ -39,6 +39,7 @@ static struct memory_range *memory_range = NULL; static struct memory_range *base_memory_range = NULL; static uint64_t rmo_top; uint64_t memory_max = 0; +uint64_t memory_limit = 0; static int nr_memory_ranges, nr_exclude_ranges; uint64_t crash_base, crash_size; unsigned int rtas_base, rtas_size; @@ -408,6 +409,33 @@ static int get_devtree_details(unsigned long kexec_flags) add_usable_mem_rgns(0, crash_base + crash_size); reserve(KDUMP_BACKUP_LIMIT, crash_base-KDUMP_BACKUP_LIMIT); } + /* + * Read the first kernel's memory limit. + * If the first kernel is booted with mem= option then + * it would export "linux,memory-limit" file + * reflecting value for the same. + */ + memset(fname, 0, sizeof(fname)); + strcpy(fname, device_tree); + strcat(fname, dentry->d_name); + strcat(fname, "/linux,memory-limit"); + if ((file = fopen(fname, "r")) == NULL) { + if (errno != ENOENT) { + perror(fname); + goto error_opencdir; + } + errno = 0; + /* + * File not present. + * fall through. On older kernel this file + * is not present. + */ + } + else if (fread(&memory_limit, sizeof(uint64_t), 1, file) + != 1) { + perror(fname); + goto error_openfile; + } memset(fname, 0, sizeof(fname)); strcpy(fname, device_tree);