kernel: fix crashlog issues on highmem systems

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2016-08-11 17:02:32 +02:00
parent fa350d5aba
commit 9d56ec6244

View File

@ -43,7 +43,7 @@
--- /dev/null --- /dev/null
+++ b/kernel/crashlog.c +++ b/kernel/crashlog.c
@@ -0,0 +1,196 @@ @@ -0,0 +1,209 @@
+/* +/*
+ * Crash information logger + * Crash information logger
+ * Copyright (C) 2010 Felix Fietkau <nbd@nbd.name> + * Copyright (C) 2010 Felix Fietkau <nbd@nbd.name>
@ -103,40 +103,53 @@
+ +
+extern struct list_head *crashlog_modules; +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 + size - CRASHLOG_OFFSET;
+ return true;
+}
+
+#ifndef CONFIG_NO_BOOTMEM +#ifndef CONFIG_NO_BOOTMEM
+void __init crashlog_init_bootmem(bootmem_data_t *bdata) +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; + return;
+ +
+ addr = PFN_PHYS(bdata->node_low_pfn) - CRASHLOG_OFFSET; + if (reserve_bootmem(crashlog_addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) {
+ if (reserve_bootmem(addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) { + printk("Crashlog failed to allocate RAM at address 0x%lx\n",
+ printk("Crashlog failed to allocate RAM at address 0x%lx\n", addr); + crashlog_addr);
+ bdata->node_low_pfn -= CRASHLOG_PAGES; + crashlog_addr = 0;
+ addr = PFN_PHYS(bdata->node_low_pfn);
+ } + }
+ crashlog_addr = addr;
+} +}
+#endif +#endif
+ +
+#ifdef CONFIG_HAVE_MEMBLOCK +#ifdef CONFIG_HAVE_MEMBLOCK
+void __init_memblock crashlog_init_memblock(phys_addr_t addr, phys_addr_t size) +void __init_memblock crashlog_init_memblock(phys_addr_t addr, phys_addr_t size)
+{ +{
+ if (crashlog_addr) + if (!crashlog_set_addr(addr, size))
+ return; + return;
+ +
+ if (size <= CRASHLOG_OFFSET + CRASHLOG_SIZE) + if (memblock_reserve(crashlog_addr, CRASHLOG_SIZE)) {
+ return; + printk("Crashlog failed to allocate RAM at address 0x%lx\n",
+ + crashlog_addr);
+ addr += size - CRASHLOG_OFFSET; + crashlog_addr = 0;
+ if (memblock_reserve(addr, CRASHLOG_SIZE)) {
+ printk("Crashlog failed to allocate RAM at address 0x%lx\n", (unsigned long) addr);
+ return;
+ } + }
+
+ crashlog_addr = addr;
+} +}
+#endif +#endif
+ +