From nobody Thu Apr 2 06:32:29 2026 Received: from canpmsgout07.his.huawei.com (canpmsgout07.his.huawei.com [113.46.200.222]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1654A3644C5; Sat, 28 Mar 2026 07:41:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.222 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774683704; cv=none; b=orjkYIcHM30W2G2FnIh9nnBkC7dQjYHIzKbFNamLIGXD3C2CLRB8Rvj6QhzcF2RO23NDc7viVVU9U6QUcxKgC5XWjbqq/8ePuGxmnKi+J2h23ufiVaHSYMDAUv+VAz6pDFF1MqSopUmXy2DnpcQmN84T7TDWbp2wPnTtSQE76nE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774683704; c=relaxed/simple; bh=iNWqCWAluFKJY+Gav2vW/zGth/6+oESRCw7/O86J+lI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=VyLb7R9VQkyYQHES40jd7K7jiYJfyU93c2ZBXoLhOuqUNB5mjHprITKL12Aa/z6yTdgCJSqZqBNSmJj0zwKF3+fwXkZAGJDARKKikXLhVb6C8dKJCriIII0LNQkBG5FRX1qeCBXATEAUEqYYtNYw61lnYo7T/4rMD3Xrf0FsSYE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=ms6TEfYQ; arc=none smtp.client-ip=113.46.200.222 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="ms6TEfYQ" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=+sSWz7bnD/KV37dPjZGhcAZm3k/W/RdGCPDVup5nN9I=; b=ms6TEfYQU7f4vkAm2zx1fG1YcvGC8430Uz+xfEFHYqKuviex9FJjNxHi55c+p1aI+WzRXD4Ac HnnM0LYBq1EJCt0KkWQAQFt/C/MOaQd84Y//H4D1nYGmP/rbfHr/CW9+Wf+fL/wsVdBCHART4s7 6WZU1rQlqe6gS5FkFsCmWTI= Received: from mail.maildlp.com (unknown [172.19.163.200]) by canpmsgout07.his.huawei.com (SkyGuard) with ESMTPS id 4fjTnc4ShtzLltJ; Sat, 28 Mar 2026 15:35:32 +0800 (CST) Received: from dggpemf500011.china.huawei.com (unknown [7.185.36.131]) by mail.maildlp.com (Postfix) with ESMTPS id 2C8884055B; Sat, 28 Mar 2026 15:41:39 +0800 (CST) Received: from huawei.com (10.90.53.73) by dggpemf500011.china.huawei.com (7.185.36.131) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Sat, 28 Mar 2026 15:41:36 +0800 From: Jinjie Ruan To: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , CC: Subject: [PATCH v11 08/11] crash: Exclude crash kernel memory in crash core Date: Sat, 28 Mar 2026 15:40:10 +0800 Message-ID: <20260328074013.3589544-9-ruanjinjie@huawei.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260328074013.3589544-1-ruanjinjie@huawei.com> References: <20260328074013.3589544-1-ruanjinjie@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To dggpemf500011.china.huawei.com (7.185.36.131) Content-Type: text/plain; charset="utf-8" The crash memory alloc, and the exclude of crashk_res, crashk_low_res and crashk_cma memory are almost identical across different architectures, handling them in the crash core would eliminate a lot of duplication, so do them in the common code. To achieve the above goal, three architecture-specific functions are introduced: - arch_get_system_nr_ranges(). Pre-counts the max number of memory ranges. - arch_crash_populate_cmem(). Collects the memory ranges and fills them into cmem. - arch_crash_exclude_ranges(). Architecture's additional crash memory ranges exclusion, defaulting to empty. Acked-by: Catalin Marinas # arm64 Reviewed-by: Sourabh Jain Acked-by: Baoquan He Acked-by: Mike Rapoport (Microsoft) Signed-off-by: Jinjie Ruan --- arch/arm64/kernel/machine_kexec_file.c | 46 ++++------- arch/loongarch/kernel/machine_kexec_file.c | 46 ++++------- arch/riscv/kernel/machine_kexec_file.c | 47 +++--------- arch/x86/kernel/crash.c | 89 +++------------------- include/linux/crash_core.h | 5 ++ kernel/crash_core.c | 82 +++++++++++++++++++- 6 files changed, 136 insertions(+), 179 deletions(-) diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/mac= hine_kexec_file.c index df52ac4474c9..558408f403b5 100644 --- a/arch/arm64/kernel/machine_kexec_file.c +++ b/arch/arm64/kernel/machine_kexec_file.c @@ -40,51 +40,33 @@ int arch_kimage_file_post_load_cleanup(struct kimage *i= mage) } =20 #ifdef CONFIG_CRASH_DUMP -static int prepare_elf_headers(void **addr, unsigned long *sz) +unsigned int arch_get_system_nr_ranges(void) { - struct crash_mem *cmem; - unsigned int nr_ranges; - int ret; - u64 i; + unsigned int nr_ranges =3D 2; /* for exclusion of crashkernel region */ phys_addr_t start, end; + u64 i; =20 - nr_ranges =3D 2; /* for exclusion of crashkernel region */ for_each_mem_range(i, &start, &end) nr_ranges++; =20 - cmem =3D kmalloc_flex(*cmem, ranges, nr_ranges); - if (!cmem) - return -ENOMEM; + return nr_ranges; +} + +int arch_crash_populate_cmem(struct crash_mem *cmem) +{ + phys_addr_t start, end; + u64 i; =20 - cmem->max_nr_ranges =3D nr_ranges; - cmem->nr_ranges =3D 0; for_each_mem_range(i, &start, &end) { - if (cmem->nr_ranges >=3D cmem->max_nr_ranges) { - ret =3D -ENOMEM; - goto out; - } + if (cmem->nr_ranges >=3D cmem->max_nr_ranges) + return -ENOMEM; =20 cmem->ranges[cmem->nr_ranges].start =3D start; cmem->ranges[cmem->nr_ranges].end =3D end - 1; cmem->nr_ranges++; } =20 - /* Exclude crashkernel region */ - ret =3D crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end); - if (ret) - goto out; - - if (crashk_low_res.end) { - ret =3D crash_exclude_mem_range(cmem, crashk_low_res.start, crashk_low_r= es.end); - if (ret) - goto out; - } - - ret =3D crash_prepare_elf64_headers(cmem, true, addr, sz); - -out: - kfree(cmem); - return ret; + return 0; } #endif =20 @@ -114,7 +96,7 @@ int load_other_segments(struct kimage *image, void *headers; unsigned long headers_sz; if (image->type =3D=3D KEXEC_TYPE_CRASH) { - ret =3D prepare_elf_headers(&headers, &headers_sz); + ret =3D crash_prepare_headers(true, &headers, &headers_sz, NULL); if (ret) { pr_err("Preparing elf core header failed\n"); goto out_err; diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/ke= rnel/machine_kexec_file.c index 167392c1da33..3d0386ee18ef 100644 --- a/arch/loongarch/kernel/machine_kexec_file.c +++ b/arch/loongarch/kernel/machine_kexec_file.c @@ -56,51 +56,33 @@ static void cmdline_add_initrd(struct kimage *image, un= signed long *cmdline_tmpl } =20 #ifdef CONFIG_CRASH_DUMP - -static int prepare_elf_headers(void **addr, unsigned long *sz) +unsigned int arch_get_system_nr_ranges(void) { - int ret, nr_ranges; - uint64_t i; + int nr_ranges =3D 2; /* for exclusion of crashkernel region */ phys_addr_t start, end; - struct crash_mem *cmem; + uint64_t i; =20 - nr_ranges =3D 2; /* for exclusion of crashkernel region */ for_each_mem_range(i, &start, &end) nr_ranges++; =20 - cmem =3D kmalloc_flex(*cmem, ranges, nr_ranges); - if (!cmem) - return -ENOMEM; + return nr_ranges; +} + +int arch_crash_populate_cmem(struct crash_mem *cmem) +{ + phys_addr_t start, end; + uint64_t i; =20 - cmem->max_nr_ranges =3D nr_ranges; - cmem->nr_ranges =3D 0; for_each_mem_range(i, &start, &end) { - if (cmem->nr_ranges >=3D cmem->max_nr_ranges) { - ret =3D -ENOMEM; - goto out; - } + if (cmem->nr_ranges >=3D cmem->max_nr_ranges) + return -ENOMEM; =20 cmem->ranges[cmem->nr_ranges].start =3D start; cmem->ranges[cmem->nr_ranges].end =3D end - 1; cmem->nr_ranges++; } =20 - /* Exclude crashkernel region */ - ret =3D crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end); - if (ret < 0) - goto out; - - if (crashk_low_res.end) { - ret =3D crash_exclude_mem_range(cmem, crashk_low_res.start, crashk_low_r= es.end); - if (ret < 0) - goto out; - } - - ret =3D crash_prepare_elf64_headers(cmem, true, addr, sz); - -out: - kfree(cmem); - return ret; + return 0; } =20 /* @@ -168,7 +150,7 @@ int load_other_segments(struct kimage *image, void *headers; unsigned long headers_sz; =20 - ret =3D prepare_elf_headers(&headers, &headers_sz); + ret =3D crash_prepare_headers(true, &headers, &headers_sz, NULL); if (ret < 0) { pr_err("Preparing elf core header failed\n"); goto out_err; diff --git a/arch/riscv/kernel/machine_kexec_file.c b/arch/riscv/kernel/mac= hine_kexec_file.c index 773a1cba8ba0..bea818f75dd6 100644 --- a/arch/riscv/kernel/machine_kexec_file.c +++ b/arch/riscv/kernel/machine_kexec_file.c @@ -44,6 +44,15 @@ static int get_nr_ram_ranges_callback(struct resource *r= es, void *arg) return 0; } =20 +unsigned int arch_get_system_nr_ranges(void) +{ + unsigned int nr_ranges =3D 2; /* For exclusion of crashkernel region */ + + walk_system_ram_res(0, -1, &nr_ranges, get_nr_ram_ranges_callback); + + return nr_ranges; +} + static int prepare_elf64_ram_headers_callback(struct resource *res, void *= arg) { struct crash_mem *cmem =3D arg; @@ -58,41 +67,9 @@ static int prepare_elf64_ram_headers_callback(struct res= ource *res, void *arg) return 0; } =20 -static int prepare_elf_headers(void **addr, unsigned long *sz) +int arch_crash_populate_cmem(struct crash_mem *cmem) { - struct crash_mem *cmem; - unsigned int nr_ranges; - int ret; - - nr_ranges =3D 2; /* For exclusion of crashkernel region */ - walk_system_ram_res(0, -1, &nr_ranges, get_nr_ram_ranges_callback); - - cmem =3D kmalloc_flex(*cmem, ranges, nr_ranges); - if (!cmem) - return -ENOMEM; - - cmem->max_nr_ranges =3D nr_ranges; - cmem->nr_ranges =3D 0; - ret =3D walk_system_ram_res(0, -1, cmem, prepare_elf64_ram_headers_callba= ck); - if (ret) - goto out; - - /* Exclude crashkernel region */ - ret =3D crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end); - if (ret) - goto out; - - if (crashk_low_res.end) { - ret =3D crash_exclude_mem_range(cmem, crashk_low_res.start, crashk_low_r= es.end); - if (ret) - goto out; - } - - ret =3D crash_prepare_elf64_headers(cmem, true, addr, sz); - -out: - kfree(cmem); - return ret; + return walk_system_ram_res(0, -1, cmem, prepare_elf64_ram_headers_callbac= k); } =20 static char *setup_kdump_cmdline(struct kimage *image, char *cmdline, @@ -284,7 +261,7 @@ int load_extra_segments(struct kimage *image, unsigned = long kernel_start, if (image->type =3D=3D KEXEC_TYPE_CRASH) { void *headers; unsigned long headers_sz; - ret =3D prepare_elf_headers(&headers, &headers_sz); + ret =3D crash_prepare_headers(true, &headers, &headers_sz, NULL); if (ret) { pr_err("Preparing elf core header failed\n"); goto out; diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 7fa6d45ebe3f..8927184cce32 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -152,16 +152,8 @@ static int get_nr_ram_ranges_callback(struct resource = *res, void *arg) return 0; } =20 -/* Gather all the required information to prepare elf headers for ram regi= ons */ -static struct crash_mem *fill_up_crash_elf_data(void) +unsigned int arch_get_system_nr_ranges(void) { - unsigned int nr_ranges =3D 0; - struct crash_mem *cmem; - - walk_system_ram_res(0, -1, &nr_ranges, get_nr_ram_ranges_callback); - if (!nr_ranges) - return NULL; - /* * Exclusion of crash region, crashk_low_res and/or crashk_cma_ranges * may cause range splits. So add extra slots here. @@ -176,49 +168,16 @@ static struct crash_mem *fill_up_crash_elf_data(void) * But in order to lest the low 1M could be changed in the future, * (e.g. [start, 1M]), add a extra slot. */ - nr_ranges +=3D 3 + crashk_cma_cnt; - cmem =3D vzalloc(struct_size(cmem, ranges, nr_ranges)); - if (!cmem) - return NULL; - - cmem->max_nr_ranges =3D nr_ranges; + unsigned int nr_ranges =3D 3 + crashk_cma_cnt; =20 - return cmem; + walk_system_ram_res(0, -1, &nr_ranges, get_nr_ram_ranges_callback); + return nr_ranges; } =20 -/* - * Look for any unwanted ranges between mstart, mend and remove them. This - * might lead to split and split ranges are put in cmem->ranges[] array - */ -static int elf_header_exclude_ranges(struct crash_mem *cmem) +int arch_crash_exclude_ranges(struct crash_mem *cmem) { - int ret =3D 0; - int i; - /* Exclude the low 1M because it is always reserved */ - ret =3D crash_exclude_mem_range(cmem, 0, SZ_1M - 1); - if (ret) - return ret; - - /* Exclude crashkernel region */ - ret =3D crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end); - if (ret) - return ret; - - if (crashk_low_res.end) - ret =3D crash_exclude_mem_range(cmem, crashk_low_res.start, - crashk_low_res.end); - if (ret) - return ret; - - for (i =3D 0; i < crashk_cma_cnt; ++i) { - ret =3D crash_exclude_mem_range(cmem, crashk_cma_ranges[i].start, - crashk_cma_ranges[i].end); - if (ret) - return ret; - } - - return 0; + return crash_exclude_mem_range(cmem, 0, SZ_1M - 1); } =20 static int prepare_elf64_ram_headers_callback(struct resource *res, void *= arg) @@ -235,35 +194,9 @@ static int prepare_elf64_ram_headers_callback(struct r= esource *res, void *arg) return 0; } =20 -/* Prepare elf headers. Return addr and size */ -static int prepare_elf_headers(void **addr, unsigned long *sz, - unsigned long *nr_mem_ranges) +int arch_crash_populate_cmem(struct crash_mem *cmem) { - struct crash_mem *cmem; - int ret; - - cmem =3D fill_up_crash_elf_data(); - if (!cmem) - return -ENOMEM; - - ret =3D walk_system_ram_res(0, -1, cmem, prepare_elf64_ram_headers_callba= ck); - if (ret) - goto out; - - /* Exclude unwanted mem ranges */ - ret =3D elf_header_exclude_ranges(cmem); - if (ret) - goto out; - - /* Return the computed number of memory ranges, for hotplug usage */ - *nr_mem_ranges =3D cmem->nr_ranges; - - /* By default prepare 64bit headers */ - ret =3D crash_prepare_elf64_headers(cmem, IS_ENABLED(CONFIG_X86_64), addr= , sz); - -out: - vfree(cmem); - return ret; + return walk_system_ram_res(0, -1, cmem, prepare_elf64_ram_headers_callbac= k); } #endif =20 @@ -421,7 +354,8 @@ int crash_load_segments(struct kimage *image) .buf_max =3D ULONG_MAX, .top_down =3D false }; =20 /* Prepare elf headers and add a segment */ - ret =3D prepare_elf_headers(&kbuf.buffer, &kbuf.bufsz, &pnum); + ret =3D crash_prepare_headers(IS_ENABLED(CONFIG_X86_64), &kbuf.buffer, + &kbuf.bufsz, &pnum); if (ret) return ret; =20 @@ -532,7 +466,8 @@ void arch_crash_handle_hotplug_event(struct kimage *ima= ge, void *arg) * Create the new elfcorehdr reflecting the changes to CPU and/or * memory resources. */ - if (prepare_elf_headers(&elfbuf, &elfsz, &nr_mem_ranges)) { + if (crash_prepare_headers(IS_ENABLED(CONFIG_X86_64), &elfbuf, &elfsz, + &nr_mem_ranges)) { pr_err("unable to create new elfcorehdr"); goto out; } diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h index d35726d6a415..033b20204aca 100644 --- a/include/linux/crash_core.h +++ b/include/linux/crash_core.h @@ -66,6 +66,8 @@ extern int crash_exclude_mem_range(struct crash_mem *mem, unsigned long long mend); extern int crash_prepare_elf64_headers(struct crash_mem *mem, int need_ker= nel_map, void **addr, unsigned long *sz); +extern int crash_prepare_headers(int need_kernel_map, void **addr, + unsigned long *sz, unsigned long *nr_mem_ranges); =20 struct kimage; struct kexec_segment; @@ -83,6 +85,9 @@ int kexec_should_crash(struct task_struct *p); int kexec_crash_loaded(void); void crash_save_cpu(struct pt_regs *regs, int cpu); extern int kimage_crash_copy_vmcoreinfo(struct kimage *image); +extern unsigned int arch_get_system_nr_ranges(void); +extern int arch_crash_populate_cmem(struct crash_mem *cmem); +extern int arch_crash_exclude_ranges(struct crash_mem *cmem); =20 #else /* !CONFIG_CRASH_DUMP*/ struct pt_regs; diff --git a/kernel/crash_core.c b/kernel/crash_core.c index 2c1a3791e410..96a96e511f5a 100644 --- a/kernel/crash_core.c +++ b/kernel/crash_core.c @@ -170,9 +170,6 @@ static inline resource_size_t crash_resource_size(const= struct resource *res) return !res->end ? 0 : resource_size(res); } =20 - - - int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map, void **addr, unsigned long *sz) { @@ -274,6 +271,85 @@ int crash_prepare_elf64_headers(struct crash_mem *mem,= int need_kernel_map, return 0; } =20 +static struct crash_mem *alloc_cmem(unsigned int nr_ranges) +{ + struct crash_mem *cmem; + + cmem =3D kvzalloc_flex(*cmem, ranges, nr_ranges); + if (!cmem) + return NULL; + + cmem->max_nr_ranges =3D nr_ranges; + return cmem; +} + +unsigned int __weak arch_get_system_nr_ranges(void) { return 0; } +int __weak arch_crash_populate_cmem(struct crash_mem *cmem) { return -1; } +int __weak arch_crash_exclude_ranges(struct crash_mem *cmem) { return 0; } + +static int crash_exclude_core_ranges(struct crash_mem *cmem) +{ + int ret, i; + + /* Exclude crashkernel region */ + ret =3D crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end); + if (ret) + return ret; + + if (crashk_low_res.end) { + ret =3D crash_exclude_mem_range(cmem, crashk_low_res.start, crashk_low_r= es.end); + if (ret) + return ret; + } + + for (i =3D 0; i < crashk_cma_cnt; ++i) { + ret =3D crash_exclude_mem_range(cmem, crashk_cma_ranges[i].start, + crashk_cma_ranges[i].end); + if (ret) + return ret; + } + + return 0; +} + +int crash_prepare_headers(int need_kernel_map, void **addr, unsigned long = *sz, + unsigned long *nr_mem_ranges) +{ + unsigned int max_nr_ranges; + struct crash_mem *cmem; + int ret; + + max_nr_ranges =3D arch_get_system_nr_ranges(); + if (!max_nr_ranges) + return -ENOMEM; + + cmem =3D alloc_cmem(max_nr_ranges); + if (!cmem) + return -ENOMEM; + + ret =3D arch_crash_populate_cmem(cmem); + if (ret) + goto out; + + ret =3D crash_exclude_core_ranges(cmem); + if (ret) + goto out; + + ret =3D arch_crash_exclude_ranges(cmem); + if (ret) + goto out; + + /* Return the computed number of memory ranges, for hotplug usage */ + if (nr_mem_ranges) + *nr_mem_ranges =3D cmem->nr_ranges; + + ret =3D crash_prepare_elf64_headers(cmem, need_kernel_map, addr, sz); + +out: + kvfree(cmem); + return ret; +} + /** * crash_exclude_mem_range - exclude a mem range for existing ranges * @mem: mem->range contains an array of ranges sorted in ascending order --=20 2.34.1