From: Ma Wupeng <mawupeng1@xxxxxxxxxx> Initrd memory will be removed and then added in arm64_memblock_init() and this will cause it to lose all of its memblock flags. The lost of MEMBLOCK_MIRROR flag will lead to error log printed by find_zone_movable_pfns_for_nodes if the lower 4G range has some non-mirrored memory. In order to solve this problem, the lost MEMBLOCK_MIRROR flag will be reinstalled if the origin memblock has this flag. Signed-off-by: Ma Wupeng <mawupeng1@xxxxxxxxxx> --- arch/arm64/mm/init.c | 9 +++++++++ include/linux/memblock.h | 1 + mm/memblock.c | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 339ee84e5a61..11641f924d08 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -350,9 +350,18 @@ void __init arm64_memblock_init(void) "initrd not fully accessible via the linear mapping -- please check your bootloader ...\n")) { phys_initrd_size = 0; } else { + int flags, ret; + + ret = memblock_get_flags(base, &flags); + if (ret) + flags = 0; + memblock_remove(base, size); /* clear MEMBLOCK_ flags */ memblock_add(base, size); memblock_reserve(base, size); + + if (flags & MEMBLOCK_MIRROR) + memblock_mark_mirror(base, size); } } diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 50ad19662a32..3d6a382ac9c8 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -487,6 +487,7 @@ bool memblock_is_map_memory(phys_addr_t addr); bool memblock_is_region_memory(phys_addr_t base, phys_addr_t size); bool memblock_is_reserved(phys_addr_t addr); bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size); +int memblock_get_flags(phys_addr_t base, int *flags); void memblock_dump_all(void); diff --git a/mm/memblock.c b/mm/memblock.c index b1d2a0009733..0c5b5699af6e 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -1796,6 +1796,26 @@ int __init_memblock memblock_search_pfn_nid(unsigned long pfn, return memblock_get_region_node(&type->regions[mid]); } +/** + * memblock_get_flags - get a single memblock flags + * @base: base of memeblock to get + * + * Get the flags of memeblock with base: @base + * + * Return: + * 0 if ok, non-zero if fail + */ +int __init_memblock memblock_get_flags(phys_addr_t base, int *flags) +{ + int idx = memblock_search(&memblock.memory, base); + + if (idx == -1) + return -EINVAL; + + *flags = memblock.memory.regions[idx].flags; + return 0; +} + /** * memblock_is_region_memory - check if a region is a subset of memory * @base: base of region to check -- 2.25.1