arch/riscv/kernel/setup.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-)
From: Björn Töpel <bjorn@rivosinc.com>
The /proc/iomem represents the kernel's memory map. Regions marked
with "Reserved" tells the user that the range should not be tampered
with. Kexec-tools, when using the older kexec_load syscall relies on
the "Reserved" regions to build the memory segments, that will be the
target of the new kexec'd kernel.
The RISC-V port tries to expose all reserved regions to userland, but
some regions were not properly exposed: Regions that resided in both
the "regular" and reserved memory block, e.g. the EFI Memory Map. A
missing entry could result in reserved memory being overwritten.
It turns out, that arm64, and loongarch had a similar issue a while
back:
commit d91680e687f4 ("arm64: Fix /proc/iomem for reserved but not memory regions")
commit 50d7ba36b916 ("arm64: export memblock_reserve()d regions via /proc/iomem")
Similar to the other ports, resolve the issue by splitting the regions
in an arch initcall, since we need a working allocator.
Fixes: ffe0e5261268 ("RISC-V: Improve init_resources()")
Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
---
arch/riscv/kernel/setup.c | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index c174544eefc8..f7c9a1caa83e 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -66,6 +66,9 @@ static struct resource bss_res = { .name = "Kernel bss", };
static struct resource elfcorehdr_res = { .name = "ELF Core hdr", };
#endif
+static int num_standard_resources;
+static struct resource *standard_resources;
+
static int __init add_resource(struct resource *parent,
struct resource *res)
{
@@ -139,7 +142,7 @@ static void __init init_resources(void)
struct resource *res = NULL;
struct resource *mem_res = NULL;
size_t mem_res_sz = 0;
- int num_resources = 0, res_idx = 0;
+ int num_resources = 0, res_idx = 0, non_resv_res = 0;
int ret = 0;
/* + 1 as memblock_alloc() might increase memblock.reserved.cnt */
@@ -193,6 +196,7 @@ static void __init init_resources(void)
/* Add /memory regions to the resource tree */
for_each_mem_region(region) {
res = &mem_res[res_idx--];
+ non_resv_res++;
if (unlikely(memblock_is_nomap(region))) {
res->name = "Reserved";
@@ -210,6 +214,9 @@ static void __init init_resources(void)
goto error;
}
+ num_standard_resources = non_resv_res;
+ standard_resources = &mem_res[res_idx + 1];
+
/* Clean-up any unused pre-allocated resources */
if (res_idx >= 0)
memblock_free(mem_res, (res_idx + 1) * sizeof(*mem_res));
@@ -221,6 +228,33 @@ static void __init init_resources(void)
memblock_free(mem_res, mem_res_sz);
}
+static int __init reserve_memblock_reserved_regions(void)
+{
+ u64 i, j;
+
+ for (i = 0; i < num_standard_resources; i++) {
+ struct resource *mem = &standard_resources[i];
+ phys_addr_t r_start, r_end, mem_size = resource_size(mem);
+
+ if (!memblock_is_region_reserved(mem->start, mem_size))
+ continue;
+
+ for_each_reserved_mem_range(j, &r_start, &r_end) {
+ resource_size_t start, end;
+
+ start = max(PFN_PHYS(PFN_DOWN(r_start)), mem->start);
+ end = min(PFN_PHYS(PFN_UP(r_end)) - 1, mem->end);
+
+ if (start > mem->end || end < mem->start)
+ continue;
+
+ reserve_region_with_split(mem, start, end, "Reserved");
+ }
+ }
+
+ return 0;
+}
+arch_initcall(reserve_memblock_reserved_regions);
static void __init parse_dtb(void)
{
base-commit: a24588245776dafc227243a01bfbeb8a59bafba9
--
2.45.2
We are creating a vmcore using kexec on a Linux 6.15 RISC-V system and analyzing it with the crash tool on the host. This workflow used to work on Linux 6.14 but is now broken in 6.15. The issue is caused by a change in the kernel: In Linux 6.15, certain memblock sections are now marked as Reserved in /proc/iomem. The kexec tool excludes all Reserved regions when generating the vmcore, so these sections are missing from the dump. However, the kernel still uses addresses in these regions—for example, for IRQ pointers. Since the crash tool needs access to these memory areas to function correctly, their exclusion breaks the analysis. Pnina Feder (1): riscv: Change memblock reserved name to be recognized on kexec arch/riscv/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 2.43.0
Pnina! Pnina Feder <pnina.feder@mobileye.com> writes: > We are creating a vmcore using kexec on a Linux 6.15 RISC-V system and > analyzing it with the crash tool on the host. This workflow used to > work on Linux 6.14 but is now broken in 6.15. Thanks for reporting this! > The issue is caused by a change in the kernel: > In Linux 6.15, certain memblock sections are now marked as Reserved in > /proc/iomem. The kexec tool excludes all Reserved regions when > generating the vmcore, so these sections are missing from the dump. How are you collecting the /proc/vmcore file? A full set of commands would be helpful. > However, the kernel still uses addresses in these regions—for example, > for IRQ pointers. Since the crash tool needs access to these memory > areas to function correctly, their exclusion breaks the analysis. Wdym with "IRQ pointers"? Also, what version (sha1) of crash are you using? Thanks! Björn
Hi Bjorn,
On 09/04/2025 20:21, Björn Töpel wrote:
> From: Björn Töpel <bjorn@rivosinc.com>
>
> The /proc/iomem represents the kernel's memory map. Regions marked
> with "Reserved" tells the user that the range should not be tampered
> with. Kexec-tools, when using the older kexec_load syscall relies on
> the "Reserved" regions to build the memory segments, that will be the
> target of the new kexec'd kernel.
>
> The RISC-V port tries to expose all reserved regions to userland, but
> some regions were not properly exposed: Regions that resided in both
> the "regular" and reserved memory block, e.g. the EFI Memory Map. A
> missing entry could result in reserved memory being overwritten.
>
> It turns out, that arm64, and loongarch had a similar issue a while
> back:
>
> commit d91680e687f4 ("arm64: Fix /proc/iomem for reserved but not memory regions")
> commit 50d7ba36b916 ("arm64: export memblock_reserve()d regions via /proc/iomem")
>
> Similar to the other ports, resolve the issue by splitting the regions
> in an arch initcall, since we need a working allocator.
>
> Fixes: ffe0e5261268 ("RISC-V: Improve init_resources()")
> Signed-off-by: Björn Töpel <bjorn@rivosinc.com>
> ---
> arch/riscv/kernel/setup.c | 36 +++++++++++++++++++++++++++++++++++-
> 1 file changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
> index c174544eefc8..f7c9a1caa83e 100644
> --- a/arch/riscv/kernel/setup.c
> +++ b/arch/riscv/kernel/setup.c
> @@ -66,6 +66,9 @@ static struct resource bss_res = { .name = "Kernel bss", };
> static struct resource elfcorehdr_res = { .name = "ELF Core hdr", };
> #endif
>
> +static int num_standard_resources;
> +static struct resource *standard_resources;
> +
> static int __init add_resource(struct resource *parent,
> struct resource *res)
> {
> @@ -139,7 +142,7 @@ static void __init init_resources(void)
> struct resource *res = NULL;
> struct resource *mem_res = NULL;
> size_t mem_res_sz = 0;
> - int num_resources = 0, res_idx = 0;
> + int num_resources = 0, res_idx = 0, non_resv_res = 0;
> int ret = 0;
>
> /* + 1 as memblock_alloc() might increase memblock.reserved.cnt */
> @@ -193,6 +196,7 @@ static void __init init_resources(void)
> /* Add /memory regions to the resource tree */
> for_each_mem_region(region) {
> res = &mem_res[res_idx--];
> + non_resv_res++;
>
> if (unlikely(memblock_is_nomap(region))) {
> res->name = "Reserved";
> @@ -210,6 +214,9 @@ static void __init init_resources(void)
> goto error;
> }
>
> + num_standard_resources = non_resv_res;
> + standard_resources = &mem_res[res_idx + 1];
> +
> /* Clean-up any unused pre-allocated resources */
> if (res_idx >= 0)
> memblock_free(mem_res, (res_idx + 1) * sizeof(*mem_res));
> @@ -221,6 +228,33 @@ static void __init init_resources(void)
> memblock_free(mem_res, mem_res_sz);
> }
>
> +static int __init reserve_memblock_reserved_regions(void)
> +{
> + u64 i, j;
> +
> + for (i = 0; i < num_standard_resources; i++) {
> + struct resource *mem = &standard_resources[i];
> + phys_addr_t r_start, r_end, mem_size = resource_size(mem);
> +
> + if (!memblock_is_region_reserved(mem->start, mem_size))
> + continue;
> +
> + for_each_reserved_mem_range(j, &r_start, &r_end) {
> + resource_size_t start, end;
> +
> + start = max(PFN_PHYS(PFN_DOWN(r_start)), mem->start);
> + end = min(PFN_PHYS(PFN_UP(r_end)) - 1, mem->end);
> +
> + if (start > mem->end || end < mem->start)
> + continue;
> +
> + reserve_region_with_split(mem, start, end, "Reserved");
> + }
> + }
> +
> + return 0;
> +}
> +arch_initcall(reserve_memblock_reserved_regions);
>
> static void __init parse_dtb(void)
> {
>
> base-commit: a24588245776dafc227243a01bfbeb8a59bafba9
Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
It will be merged with other fixes in the next rc-ish!
Thanks,
Alex
memblock resreved exposes as Reserved on iomem,
kexec tool doesn't take those parts to vmcore, but
the kernel use those address and it needed when opening the vmcore.
Without this fix the crash-tool fails.
Fixes: e94eb7ea6f20 ("riscv: Properly export reserved regions in /proc/iomem")
Signed-off-by: Pnina Feder <pnina.feder@mobileye.com>
---
arch/riscv/kernel/setup.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 14888e5ea19a..16e0cebed170 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -249,7 +249,7 @@ static int __init reserve_memblock_reserved_regions(void)
if (start > mem->end || end < mem->start)
continue;
- reserve_region_with_split(mem, start, end, "Reserved");
+ reserve_region_with_split(mem, start, end, "Reserved-memblock");
}
}
--
2.43.0
© 2016 - 2026 Red Hat, Inc.