Skip to content

Commit e94eb7e

Browse files
bjorn-rivosAlexandre Ghiti
authored andcommitted
riscv: Properly export reserved regions in /proc/iomem
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 d91680e ("arm64: Fix /proc/iomem for reserved but not memory regions") commit 50d7ba3 ("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: ffe0e52 ("RISC-V: Improve init_resources()") Signed-off-by: Björn Töpel <bjorn@rivosinc.com> Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com> Link: https://lore.kernel.org/r/20250409182129.634415-1-bjorn@kernel.org Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
1 parent 4410160 commit e94eb7e

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

arch/riscv/kernel/setup.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ static struct resource bss_res = { .name = "Kernel bss", };
6666
static struct resource elfcorehdr_res = { .name = "ELF Core hdr", };
6767
#endif
6868

69+
static int num_standard_resources;
70+
static struct resource *standard_resources;
71+
6972
static int __init add_resource(struct resource *parent,
7073
struct resource *res)
7174
{
@@ -139,7 +142,7 @@ static void __init init_resources(void)
139142
struct resource *res = NULL;
140143
struct resource *mem_res = NULL;
141144
size_t mem_res_sz = 0;
142-
int num_resources = 0, res_idx = 0;
145+
int num_resources = 0, res_idx = 0, non_resv_res = 0;
143146
int ret = 0;
144147

145148
/* + 1 as memblock_alloc() might increase memblock.reserved.cnt */
@@ -193,6 +196,7 @@ static void __init init_resources(void)
193196
/* Add /memory regions to the resource tree */
194197
for_each_mem_region(region) {
195198
res = &mem_res[res_idx--];
199+
non_resv_res++;
196200

197201
if (unlikely(memblock_is_nomap(region))) {
198202
res->name = "Reserved";
@@ -210,6 +214,9 @@ static void __init init_resources(void)
210214
goto error;
211215
}
212216

217+
num_standard_resources = non_resv_res;
218+
standard_resources = &mem_res[res_idx + 1];
219+
213220
/* Clean-up any unused pre-allocated resources */
214221
if (res_idx >= 0)
215222
memblock_free(mem_res, (res_idx + 1) * sizeof(*mem_res));
@@ -221,6 +228,33 @@ static void __init init_resources(void)
221228
memblock_free(mem_res, mem_res_sz);
222229
}
223230

231+
static int __init reserve_memblock_reserved_regions(void)
232+
{
233+
u64 i, j;
234+
235+
for (i = 0; i < num_standard_resources; i++) {
236+
struct resource *mem = &standard_resources[i];
237+
phys_addr_t r_start, r_end, mem_size = resource_size(mem);
238+
239+
if (!memblock_is_region_reserved(mem->start, mem_size))
240+
continue;
241+
242+
for_each_reserved_mem_range(j, &r_start, &r_end) {
243+
resource_size_t start, end;
244+
245+
start = max(PFN_PHYS(PFN_DOWN(r_start)), mem->start);
246+
end = min(PFN_PHYS(PFN_UP(r_end)) - 1, mem->end);
247+
248+
if (start > mem->end || end < mem->start)
249+
continue;
250+
251+
reserve_region_with_split(mem, start, end, "Reserved");
252+
}
253+
}
254+
255+
return 0;
256+
}
257+
arch_initcall(reserve_memblock_reserved_regions);
224258

225259
static void __init parse_dtb(void)
226260
{

0 commit comments

Comments
 (0)