On 03/10/2024 21:20, Saravana Kannan wrote: > On Thu, Oct 3, 2024 at 4:38 AM Usama Arif <usamaarif642@xxxxxxxxx> wrote: >> >> __pa() is only intended to be used for linear map addresses and using >> it for initial_boot_params which is in fixmap for arm64 will give an >> incorrect value. Hence stash the physical address when it is known at >> boot time and use it at kexec time instead of converting the virtual >> address using __pa(). >> >> Reported-by: Breno Leitao <leitao@xxxxxxxxxx> >> Suggested-by: Mark Rutland <mark.rutland@xxxxxxx> >> Signed-off-by: Usama Arif <usamaarif642@xxxxxxxxx> >> Fixes: ac10be5cdbfa ("arm64: Use common of_kexec_alloc_and_setup_fdt()") >> --- >> arch/arm64/kernel/setup.c | 8 ++++++++ >> drivers/of/fdt.c | 6 ++++++ >> drivers/of/kexec.c | 8 ++++++-- >> include/linux/of_fdt.h | 2 ++ >> 4 files changed, 22 insertions(+), 2 deletions(-) >> >> diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c >> index b22d28ec8028..a4d96f5e2e05 100644 >> --- a/arch/arm64/kernel/setup.c >> +++ b/arch/arm64/kernel/setup.c >> @@ -194,6 +194,14 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) >> /* Early fixups are done, map the FDT as read-only now */ >> fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO); >> >> + /* >> + * Save dt_phys address so that it can be used later for kexec. This >> + * is done as __pa() is only intended to be used for linear map addresses >> + * and using it for initial_boot_params which is in fixmap will give an >> + * incorrect value. >> + */ >> + set_initial_boot_params_pa(dt_phys); >> + >> name = of_flat_dt_get_machine_name(); >> if (!name) >> return; >> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c >> index 4d528c10df3a..9e312b7c246e 100644 >> --- a/drivers/of/fdt.c >> +++ b/drivers/of/fdt.c >> @@ -457,6 +457,7 @@ int __initdata dt_root_addr_cells; >> int __initdata dt_root_size_cells; >> >> void *initial_boot_params __ro_after_init; >> +phys_addr_t initial_boot_params_pa __ro_after_init; >> >> #ifdef CONFIG_OF_EARLY_FLATTREE >> >> @@ -1185,6 +1186,11 @@ bool __init early_init_dt_scan(void *params) >> return true; >> } >> >> +void __init set_initial_boot_params_pa(phys_addr_t params) >> +{ >> + initial_boot_params_pa = params; >> +} >> + >> static void *__init copy_device_tree(void *fdt) >> { >> int size; >> diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c >> index 9ccde2fd77cb..ca9f27b27f71 100644 >> --- a/drivers/of/kexec.c >> +++ b/drivers/of/kexec.c >> @@ -300,8 +300,12 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image, >> goto out; >> } >> >> - /* Remove memory reservation for the current device tree. */ >> - ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params), >> + /* Remove memory reservation for the current device tree. >> + * For arm64, initial_boot_params is a fixmap address, hence __pa(), >> + * can't be used to get the physical address. >> + */ >> + ret = fdt_find_and_del_mem_rsv(fdt, IS_ENABLED(CONFIG_ARM64) ? >> + initial_boot_params_pa : __pa(initial_boot_params), >> fdt_totalsize(initial_boot_params)); > > Not sure about the correctness of the patch (not a kexec expert) but > no need to do all of this inside a function parameter. Just create a > variable and use it here. > > -Saravana > Thanks, will do in the next revision.