From a299e168cc8d702840e359ee2873ce8022e860a3 Mon Sep 17 00:00:00 2001 From: Youling Tang Date: Fri, 26 May 2023 10:25:54 +0800 Subject: [PATCH] LoongArch: kdump: Add high memory reservation LoongArch inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7A8UR -------------------------------- Reserve high memory for the capture kernel to avoid kdump operation failure on 3C5000 machines with old firmware. Signed-off-by: Youling Tang Change-Id: Iacf0c56b2cdb86e66dd7568168e1c97e472c4e3a Signed-off-by: Hongchen Zhang (cherry picked from commit d7b62011afc8f97cf2c1bba9577a8a056bf6e3d2) --- arch/loongarch/kernel/setup.c | 49 ++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index fd39844347b5..85f597917c6f 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -306,13 +306,49 @@ static void __init arch_parse_crashkernel(void) * memory area used by the previous production kernel should be reserved to * avoid destroy to the captured data. */ -static void reserve_oldmem_region(void) +static void reserve_oldmem_region(int node, unsigned long s0, unsigned long e0) { #ifdef CONFIG_CRASH_DUMP + unsigned long s1, e1; + if (!is_kdump_kernel()) return; - memblock_cap_memory_range(crashmem_start, crashmem_size); + if ((e0 - s0) > (SZ_1G >> PAGE_SHIFT)) + e0 = e0 - (SZ_512M >> PAGE_SHIFT); + + /* crashmem_start is crashk_res reserved by primary production kernel */ + s1 = PFN_UP(crashmem_start); + e1 = PFN_DOWN(crashmem_start + crashmem_size); + + if (s1 == 0) + return; + + if (node == 0) { + memblock_reserve(PFN_PHYS(s0), (s1 - s0) << PAGE_SHIFT); + memblock_reserve(PFN_PHYS(e1), (e0 - e1) << PAGE_SHIFT); + } else { + memblock_reserve(PFN_PHYS(s0), (e0 - s0) << PAGE_SHIFT); + } +#endif +} + +/* Traditionally, LoongArch'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 512MB for the capture kernel + */ +static void reserve_crashm_region(int node, unsigned long s0, unsigned long e0) +{ +#ifdef CONFIG_KEXEC + if (crashk_res.start == crashk_res.end) + return; + + if ((e0 - s0) <= (SZ_1G >> PAGE_SHIFT)) + return; + + s0 = e0 - (SZ_512M >> PAGE_SHIFT); + + memblock_reserve(PFN_PHYS(s0), (e0 - s0) << PAGE_SHIFT); #endif } @@ -356,9 +392,16 @@ static void __init check_kernel_sections_mem(void) */ static void __init arch_mem_init(char **cmdline_p) { + unsigned int node; + unsigned long start_pfn, end_pfn; + arch_reserve_vmcore(); arch_parse_crashkernel(); - reserve_oldmem_region(); + for_each_online_node(node) { + get_pfn_range_for_nid(node, &start_pfn, &end_pfn); + reserve_crashm_region(node, start_pfn, end_pfn); + reserve_oldmem_region(node, start_pfn, end_pfn); + } if (usermem) pr_info("User-defined physical RAM map overwrite\n"); -- Gitee