kernel: fix crashlog regression on x86

Check memblock regions for sufficient size before attempting to use
them. Allow checks for multiple memblock regions until a suitable one is
found.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2016-07-30 12:18:08 +02:00
parent 50e7c1f79d
commit 9a3852bf8c

View file

@ -43,7 +43,7 @@
--- /dev/null --- /dev/null
+++ b/kernel/crashlog.c +++ b/kernel/crashlog.c
@@ -0,0 +1,193 @@ @@ -0,0 +1,196 @@
+/* +/*
+ * Crash information logger + * Crash information logger
+ * Copyright (C) 2010 Felix Fietkau <nbd@nbd.name> + * Copyright (C) 2010 Felix Fietkau <nbd@nbd.name>
@ -127,6 +127,9 @@
+ if (crashlog_addr) + if (crashlog_addr)
+ return; + return;
+ +
+ if (size <= CRASHLOG_OFFSET + CRASHLOG_SIZE)
+ return;
+
+ addr += size - CRASHLOG_OFFSET; + addr += size - CRASHLOG_OFFSET;
+ if (memblock_reserve(addr, CRASHLOG_SIZE)) { + if (memblock_reserve(addr, CRASHLOG_SIZE)) {
+ printk("Crashlog failed to allocate RAM at address 0x%lx\n", (unsigned long) addr); + printk("Crashlog failed to allocate RAM at address 0x%lx\n", (unsigned long) addr);
@ -237,24 +240,6 @@
+ return 0; + return 0;
+} +}
+module_init(crashlog_init_fs); +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 --- a/kernel/module.c
+++ b/kernel/module.c +++ b/kernel/module.c
@@ -275,6 +275,9 @@ static void mod_update_bounds(struct mod @@ -275,6 +275,9 @@ static void mod_update_bounds(struct mod
@ -277,7 +262,16 @@
#include <asm-generic/sections.h> #include <asm-generic/sections.h>
#include <linux/io.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; type->regions[0].flags = flags;
memblock_set_region_node(&type->regions[0], nid); memblock_set_region_node(&type->regions[0], nid);
type->total_size = size; type->total_size = size;
@ -286,3 +280,21 @@
return 0; return 0;
} }
repeat: 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;