--- /dev/null
+++ b/kernel/crashlog.c
-@@ -0,0 +1,193 @@
+@@ -0,0 +1,213 @@
+/*
+ * Crash information logger
+ * Copyright (C) 2010 Felix Fietkau <nbd@nbd.name>
+
+extern struct list_head *crashlog_modules;
+
++static bool crashlog_set_addr(phys_addr_t addr, phys_addr_t size)
++{
++ /* Limit to lower 64 MB to avoid highmem */
++ phys_addr_t limit = 64 * 1024 * 1024;
++
++ if (crashlog_addr)
++ return false;
++
++ if (addr > limit)
++ return false;
++
++ if (addr + size > limit)
++ size = limit - addr;
++
++ crashlog_addr = addr;
++
++ if (addr + size > CRASHLOG_OFFSET)
++ crashlog_addr += size - CRASHLOG_OFFSET;
++
++ return true;
++}
++
+#ifndef CONFIG_NO_BOOTMEM
+void __init crashlog_init_bootmem(bootmem_data_t *bdata)
+{
-+ unsigned long addr;
++ phys_addr_t start, end;
+
-+ if (crashlog_addr)
++ start = PFN_PHYS(bdata->node_low_pfn);
++ end = PFN_PHYS(bdata->node_min_pfn);
++ if (!crashlog_set_addr(start, end - start))
+ return;
+
-+ addr = PFN_PHYS(bdata->node_low_pfn) - CRASHLOG_OFFSET;
-+ if (reserve_bootmem(addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) {
-+ printk("Crashlog failed to allocate RAM at address 0x%lx\n", addr);
-+ bdata->node_low_pfn -= CRASHLOG_PAGES;
-+ addr = PFN_PHYS(bdata->node_low_pfn);
++ if (reserve_bootmem(crashlog_addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) {
++ printk("Crashlog failed to allocate RAM at address 0x%lx\n",
++ crashlog_addr);
++ crashlog_addr = 0;
+ }
-+ crashlog_addr = addr;
+}
+#endif
+
+#ifdef CONFIG_HAVE_MEMBLOCK
+void __init_memblock crashlog_init_memblock(phys_addr_t addr, phys_addr_t size)
+{
-+ if (crashlog_addr)
++ if (!crashlog_set_addr(addr, size))
+ return;
+
-+ addr += size - CRASHLOG_OFFSET;
-+ if (memblock_reserve(addr, CRASHLOG_SIZE)) {
-+ printk("Crashlog failed to allocate RAM at address 0x%lx\n", (unsigned long) addr);
-+ return;
++ if (memblock_reserve(crashlog_addr, CRASHLOG_SIZE)) {
++ printk("Crashlog failed to allocate RAM at address 0x%lx\n",
++ crashlog_addr);
++ crashlog_addr = 0;
+ }
-+
-+ crashlog_addr = addr;
+}
+#endif
+
+ return 0;
+}
+module_init(crashlog_init_fs);
---- a/mm/bootmem.c
-+++ b/mm/bootmem.c
-@@ -15,6 +15,7 @@
- #include <linux/export.h>
- #include <linux/kmemleak.h>
- #include <linux/range.h>
-+#include <linux/crashlog.h>
- #include <linux/memblock.h>
- #include <linux/bug.h>
- #include <linux/io.h>
-@@ -177,6 +178,7 @@ static unsigned long __init free_all_boo
- if (!bdata->node_bootmem_map)
- return 0;
-
-+ crashlog_init_bootmem(bdata);
- map = bdata->node_bootmem_map;
- start = bdata->node_min_pfn;
- end = bdata->node_low_pfn;
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -275,6 +275,9 @@ static void mod_update_bounds(struct mod
#include <asm-generic/sections.h>
#include <linux/io.h>
-@@ -541,6 +542,8 @@ int __init_memblock memblock_add_range(s
+@@ -503,6 +504,8 @@ static void __init_memblock memblock_ins
+ memblock_set_region_node(rgn, nid);
+ type->cnt++;
+ type->total_size += size;
++ if (type == &memblock.memory)
++ crashlog_init_memblock(base, size);
+ }
+
+ /**
+@@ -541,6 +544,8 @@ int __init_memblock memblock_add_range(s
type->regions[0].flags = flags;
memblock_set_region_node(&type->regions[0], nid);
type->total_size = size;
return 0;
}
repeat:
+--- a/mm/bootmem.c
++++ b/mm/bootmem.c
+@@ -15,6 +15,7 @@
+ #include <linux/export.h>
+ #include <linux/kmemleak.h>
+ #include <linux/range.h>
++#include <linux/crashlog.h>
+ #include <linux/memblock.h>
+ #include <linux/bug.h>
+ #include <linux/io.h>
+@@ -177,6 +178,7 @@ static unsigned long __init free_all_boo
+ if (!bdata->node_bootmem_map)
+ return 0;
+
++ crashlog_init_bootmem(bdata);
+ map = bdata->node_bootmem_map;
+ start = bdata->node_min_pfn;
+ end = bdata->node_low_pfn;