[PATCH] x86-64: Handle reserve_bootmem_generic beyond end_pfn

This can happen on kexec kernels with some configurations, in particularly
on Unisys ES7000 systems.

Analysis by Amul Shah

Cc: Amul Shah <amul.shah@unisys.com>

Signed-off-by: Andi Kleen <ak@suse.de>

authored by Andi Kleen and committed by Andi Kleen 5e58a02a 51d67a48

+14 -1
+14 -1
arch/x86_64/mm/init.c
··· 655 656 void __init reserve_bootmem_generic(unsigned long phys, unsigned len) 657 { 658 - /* Should check here against the e820 map to avoid double free */ 659 #ifdef CONFIG_NUMA 660 int nid = phys_to_nid(phys); 661 reserve_bootmem_node(NODE_DATA(nid), phys, len); 662 #else 663 reserve_bootmem(phys, len);
··· 655 656 void __init reserve_bootmem_generic(unsigned long phys, unsigned len) 657 { 658 #ifdef CONFIG_NUMA 659 int nid = phys_to_nid(phys); 660 + #endif 661 + unsigned long pfn = phys >> PAGE_SHIFT; 662 + if (pfn >= end_pfn) { 663 + /* This can happen with kdump kernels when accessing firmware 664 + tables. */ 665 + if (pfn < end_pfn_map) 666 + return; 667 + printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n", 668 + phys, len); 669 + return; 670 + } 671 + 672 + /* Should check here against the e820 map to avoid double free */ 673 + #ifdef CONFIG_NUMA 674 reserve_bootmem_node(NODE_DATA(nid), phys, len); 675 #else 676 reserve_bootmem(phys, len);