Skip to content

Commit 50d7ba3

Browse files
James Morsewildea01
authored andcommitted
arm64: export memblock_reserve()d regions via /proc/iomem
There has been some confusion around what is necessary to prevent kexec overwriting important memory regions. memblock: reserve, or nomap? Only memblock nomap regions are reported via /proc/iomem, kexec's user-space doesn't know about memblock_reserve()d regions. Until commit f56ab9a ("efi/arm: Don't mark ACPI reclaim memory as MEMBLOCK_NOMAP") the ACPI tables were nomap, now they are reserved and thus possible for kexec to overwrite with the new kernel or initrd. But this was always broken, as the UEFI memory map is also reserved and not marked as nomap. Exporting both nomap and reserved memblock types is a nuisance as they live in different memblock structures which we can't walk at the same time. Take a second walk over memblock.reserved and add new 'reserved' subnodes for the memblock_reserved() regions that aren't already described by the existing code. (e.g. Kernel Code) We use reserve_region_with_split() to find the gaps in existing named regions. This handles the gap between 'kernel code' and 'kernel data' which is memblock_reserve()d, but already partially described by request_standard_resources(). e.g.: | 80000000-dfffffff : System RAM | 80080000-80ffffff : Kernel code | 81000000-8158ffff : reserved | 81590000-8237efff : Kernel data | a0000000-dfffffff : Crash kernel | e00f0000-f949ffff : System RAM reserve_region_with_split needs kzalloc() which isn't available when request_standard_resources() is called, use an initcall. Reported-by: Bhupesh Sharma <bhsharma@redhat.com> Reported-by: Tyler Baicar <tbaicar@codeaurora.org> Suggested-by: Akashi Takahiro <takahiro.akashi@linaro.org> Signed-off-by: James Morse <james.morse@arm.com> Fixes: d28f6df ("arm64/kexec: Add core kexec support") Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> CC: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
1 parent c931d34 commit 50d7ba3

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

arch/arm64/kernel/setup.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,44 @@ static void __init request_standard_resources(void)
241241
}
242242
}
243243

244+
static int __init reserve_memblock_reserved_regions(void)
245+
{
246+
phys_addr_t start, end, roundup_end = 0;
247+
struct resource *mem, *res;
248+
u64 i;
249+
250+
for_each_reserved_mem_region(i, &start, &end) {
251+
if (end <= roundup_end)
252+
continue; /* done already */
253+
254+
start = __pfn_to_phys(PFN_DOWN(start));
255+
end = __pfn_to_phys(PFN_UP(end)) - 1;
256+
roundup_end = end;
257+
258+
res = kzalloc(sizeof(*res), GFP_ATOMIC);
259+
if (WARN_ON(!res))
260+
return -ENOMEM;
261+
res->start = start;
262+
res->end = end;
263+
res->name = "reserved";
264+
res->flags = IORESOURCE_MEM;
265+
266+
mem = request_resource_conflict(&iomem_resource, res);
267+
/*
268+
* We expected memblock_reserve() regions to conflict with
269+
* memory created by request_standard_resources().
270+
*/
271+
if (WARN_ON_ONCE(!mem))
272+
continue;
273+
kfree(res);
274+
275+
reserve_region_with_split(mem, start, end, "reserved");
276+
}
277+
278+
return 0;
279+
}
280+
arch_initcall(reserve_memblock_reserved_regions);
281+
244282
u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
245283

246284
void __init setup_arch(char **cmdline_p)

0 commit comments

Comments
 (0)