From: Huacai Chen <chenhc@xxxxxxxxxx> Traditionally, MIPS's contiguous low memory can be as less as 256M, so crashkernel=X@Y may be unable to large enough in some cases. Moreover, for the "multi numa node + sparse memory model" case, it is attempt to allocate section_mem_maps on every node. Thus, if the total memory of a node is more than 1GB, we reserve the top 128MB for the capture kernel. This 128M will be reserved only if the following conditions are met: 1. The configuration option CONFIG_KEXEC is y. 2. A valid "crashkernel=" parameter has been added to the command line. 3. The total memory of a node is greater than 1G. Signed-off-by: Huacai Chen <chenhuacai@xxxxxxxxxx> Signed-off-by: Youling Tang <tangyouling@xxxxxxxxxxx> --- v2: - New patch. arch/mips/kernel/setup.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 1bc8a9cc..af2c860 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -492,6 +492,25 @@ static void __init request_crashkernel(struct resource *res) (unsigned long)(resource_size(&crashk_res) >> 20), (unsigned long)(crashk_res.start >> 20)); } + +/* + * Traditionally, MIPS's contiguous low memory is 256M, so crashkernel=X@Y is + * unable to be large enough in some cases. Thus, if the total memory of a node + * is more than 1GB, we reserve the top 128MB for the capture kernel. + */ +static void reserve_crashm_region(int node, unsigned long s0, unsigned long e0) +{ + if (crashk_res.start == crashk_res.end) + return; + + if ((e0 - s0) <= (SZ_1G >> PAGE_SHIFT)) + return; + + s0 = e0 - (SZ_128M >> PAGE_SHIFT); + + memblock_reserve(PFN_PHYS(s0), (e0 - s0) << PAGE_SHIFT); +} + #else /* !defined(CONFIG_KEXEC) */ static void __init mips_parse_crashkernel(void) { @@ -500,6 +519,10 @@ static void __init mips_parse_crashkernel(void) static void __init request_crashkernel(struct resource *res) { } + +static void reserve_crashm_region(int node, unsigned long s0, unsigned long e0) +{ +} #endif /* !defined(CONFIG_KEXEC) */ static void __init check_kernel_sections_mem(void) @@ -627,6 +650,9 @@ static void __init bootcmdline_init(void) */ static void __init arch_mem_init(char **cmdline_p) { + unsigned int node; + unsigned long start_pfn, end_pfn; + /* call board setup routine */ plat_mem_setup(); memblock_set_bottom_up(true); @@ -666,6 +692,12 @@ static void __init arch_mem_init(char **cmdline_p) if (crashk_res.start != crashk_res.end) memblock_reserve(crashk_res.start, resource_size(&crashk_res)); #endif + + for_each_online_node(node) { + get_pfn_range_for_nid(node, &start_pfn, &end_pfn); + reserve_crashm_region(node, start_pfn, end_pfn); + } + device_tree_init(); /* -- 2.1.0 _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec