提交 50d7ba36 编写于 作者: J James Morse 提交者: Will Deacon

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 f56ab9a5 ("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: NBhupesh Sharma <bhsharma@redhat.com>
Reported-by: NTyler Baicar <tbaicar@codeaurora.org>
Suggested-by: NAkashi Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: NJames Morse <james.morse@arm.com>
Fixes: d28f6df1 ("arm64/kexec: Add core kexec support")
Reviewed-by: NArd Biesheuvel <ard.biesheuvel@linaro.org>
CC: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: NWill Deacon <will.deacon@arm.com>
上级 c931d34e
...@@ -241,6 +241,44 @@ static void __init request_standard_resources(void) ...@@ -241,6 +241,44 @@ static void __init request_standard_resources(void)
} }
} }
static int __init reserve_memblock_reserved_regions(void)
{
phys_addr_t start, end, roundup_end = 0;
struct resource *mem, *res;
u64 i;
for_each_reserved_mem_region(i, &start, &end) {
if (end <= roundup_end)
continue; /* done already */
start = __pfn_to_phys(PFN_DOWN(start));
end = __pfn_to_phys(PFN_UP(end)) - 1;
roundup_end = end;
res = kzalloc(sizeof(*res), GFP_ATOMIC);
if (WARN_ON(!res))
return -ENOMEM;
res->start = start;
res->end = end;
res->name = "reserved";
res->flags = IORESOURCE_MEM;
mem = request_resource_conflict(&iomem_resource, res);
/*
* We expected memblock_reserve() regions to conflict with
* memory created by request_standard_resources().
*/
if (WARN_ON_ONCE(!mem))
continue;
kfree(res);
reserve_region_with_split(mem, start, end, "reserved");
}
return 0;
}
arch_initcall(reserve_memblock_reserved_regions);
u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID }; u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
void __init setup_arch(char **cmdline_p) void __init setup_arch(char **cmdline_p)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册