diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c index e7451743b87e..d79047d9ebb6 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -527,6 +527,13 @@ static phys_addr_t __init kho_get_mem_map_phys(const void *fdt) return get_unaligned((const u64 *)mem_ptr); } +static void __init *kho_get_mem_map(const void *fdt) +{ + phys_addr_t phys = kho_get_mem_map_phys(fdt); + + return phys ? phys_to_virt(phys) : NULL; +} + /* * With KHO enabled, memory can become fragmented because KHO regions may * be anywhere in physical address space. The scratch regions give us a @@ -1332,6 +1339,7 @@ struct kho_in { char previous_release[__NEW_UTS_LEN + 1]; u32 kexec_count; struct kho_debugfs dbg; + struct kho_radix_tree radix_tree; }; static struct kho_in kho_in = { @@ -1411,24 +1419,20 @@ EXPORT_SYMBOL_GPL(kho_retrieve_subtree); static int __init kho_mem_retrieve(const void *fdt) { - struct kho_radix_tree tree; - const phys_addr_t *mem; - int len; + void *mem_map = kho_get_mem_map(fdt); - /* Retrieve the KHO radix tree from passed-in FDT. */ - mem = fdt_getprop(fdt, 0, KHO_FDT_MEMORY_MAP_PROP_NAME, &len); - - if (!mem || len != sizeof(*mem)) { - pr_err("failed to get preserved KHO memory tree\n"); - return -ENOENT; - } - - if (!*mem) + /* + * kho_get_mem_map() should always succeed. If it fails, kho_populate() + * catches that and never sets kho_in.scratch_phys, which stops memory + * retrieval. + */ + if (WARN_ON(!mem_map)) return -EINVAL; - tree.root = phys_to_virt(*mem); - mutex_init(&tree.lock); - return kho_radix_walk_tree(&tree, kho_preserved_memory_reserve); + kho_in.radix_tree.root = mem_map; + mutex_init(&kho_in.radix_tree.lock); + return kho_radix_walk_tree(&kho_in.radix_tree, + kho_preserved_memory_reserve); } static __init int kho_out_fdt_setup(void) @@ -1635,8 +1639,10 @@ void __init kho_memory_init(void) if (kho_in.scratch_phys) { kho_scratch = phys_to_virt(kho_in.scratch_phys); - if (kho_mem_retrieve(kho_get_fdt())) + if (kho_mem_retrieve(kho_get_fdt())) { kho_in.fdt_phys = 0; + kho_in.radix_tree.root = NULL; + } } else { kho_reserve_scratch(); }