瀏覽代碼

[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>
Andi Kleen 18 年之前
父節點
當前提交
5e58a02a8f
共有 1 個文件被更改,包括 14 次插入1 次删除
  1. 14 1
      arch/x86_64/mm/init.c

+ 14 - 1
arch/x86_64/mm/init.c

@@ -655,9 +655,22 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 
 
 void __init reserve_bootmem_generic(unsigned long phys, unsigned len) 
 void __init reserve_bootmem_generic(unsigned long phys, unsigned len) 
 { 
 { 
-	/* Should check here against the e820 map to avoid double free */ 
 #ifdef CONFIG_NUMA
 #ifdef CONFIG_NUMA
 	int nid = phys_to_nid(phys);
 	int nid = phys_to_nid(phys);
+#endif
+	unsigned long pfn = phys >> PAGE_SHIFT;
+	if (pfn >= end_pfn) {
+		/* This can happen with kdump kernels when accessing firmware
+		   tables. */
+		if (pfn < end_pfn_map)
+			return;
+		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",
+				phys, len);
+		return;
+	}
+
+	/* Should check here against the e820 map to avoid double free */
+#ifdef CONFIG_NUMA
   	reserve_bootmem_node(NODE_DATA(nid), phys, len);
   	reserve_bootmem_node(NODE_DATA(nid), phys, len);
 #else       		
 #else       		
 	reserve_bootmem(phys, len);    
 	reserve_bootmem(phys, len);