There are two kinds of notation to represent a map: inclusive and exclusive. Here are the examples: 1) [mem 0x0000000100000000-0x000000013fffffff] 2) [mem 0x0000000100000000-0x0000000140000000] 1) is inclusive and 2) is exclusive. In case of 1), the pfn calculated from the end address belongs to the map, while in case of 2), it doesn't. The variable saved_max_pfn is exclusive, but the condition of sanity check in read_oldmem() wrongly treats it as inclusive, i.e. if (pfn > saved_max_pfn) return read; This should have been if (pfn >= saved_max_pfn) return read; Currently, architecture mips, powerpc and s390 noticed this fact and treat saved_max_pfn as inclusive. $ git grep ".*saved_max_pfn.*" ./ arch/ia64/kernel/efi.c: /* saved_max_pfn should ignore max_addr= command line arg */ arch/ia64/kernel/efi.c: if (saved_max_pfn < (efi_md_end(md) >> PAGE_SHIFT)) arch/ia64/kernel/efi.c: saved_max_pfn = (efi_md_end(md) >> PAGE_SHIFT); arch/mips/kernel/crash_dump.c: saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1; arch/powerpc/kernel/crash_dump.c: saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1; arch/s390/kernel/setup.c: saved_max_pfn = PFN_DOWN(OLDMEM_BASE) - 1; arch/s390/kernel/setup.c: saved_max_pfn = PFN_DOWN(real_memory_size) - 1; arch/x86/kernel/e820.c: saved_max_pfn = e820_end_of_ram_pfn(); arch/x86/kernel/pci-calgary_64.c: saved_max_pfn : max_pfn) * PAGE_SIZE); drivers/char/mem.c: if (pfn > saved_max_pfn) include/linux/crash_dump.h:extern unsigned long saved_max_pfn; kernel/crash_dump.c:unsigned long saved_max_pfn; In kexec-tools, both mips and s390 increments the corresponding saved_max_mem. From the above, the existing firmware for powerpc is expected to being exporting memory mapping as exclusive. Hence, it's possible to rewrite saved_max_pfn in kernel side uniformly so it's treated as exclusive. Signed-off-by: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com> --- kexec/arch/ppc/crashdump-powerpc.c | 2 +- kexec/arch/ppc64/crashdump-ppc64.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kexec/arch/ppc/crashdump-powerpc.c b/kexec/arch/ppc/crashdump-powerpc.c index eee5b37..1122c18 100644 --- a/kexec/arch/ppc/crashdump-powerpc.c +++ b/kexec/arch/ppc/crashdump-powerpc.c @@ -230,7 +230,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges) */ for (i = 0; i < memory_ranges; i++) if (saved_max_mem < crash_memory_range[i].end) - saved_max_mem = crash_memory_range[i].end; + saved_max_mem = crash_memory_range[i].end + 1; *range = crash_memory_range; *ranges = memory_ranges; diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c index 49cab12..743fc15 100644 --- a/kexec/arch/ppc64/crashdump-ppc64.c +++ b/kexec/arch/ppc64/crashdump-ppc64.c @@ -309,7 +309,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges) */ for (i = 0; i < memory_ranges; i++) if (saved_max_mem < crash_memory_range[i].end) - saved_max_mem = crash_memory_range[i].end; + saved_max_mem = crash_memory_range[i].end + 1; *range = crash_memory_range; *ranges = memory_ranges; -- 1.7.7.6