of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify
authorUsama Arif <usamaarif642@gmail.com>
Wed, 23 Oct 2024 17:14:26 +0000 (18:14 +0100)
committerRob Herring (Arm) <robh@kernel.org>
Tue, 29 Oct 2024 20:32:45 +0000 (15:32 -0500)
 __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 save the physical address when it is known at
boot time when calling early_init_dt_scan for arm64 and use it at kexec
time instead of converting the virtual address using __pa().

Note that arm64 doesn't need the FDT region reserved in the DT as the
kernel explicitly reserves the passed in FDT. Therefore, only a debug
warning is fixed with this change.

Reported-by: Breno Leitao <leitao@debian.org>
Suggested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Usama Arif <usamaarif642@gmail.com>
Fixes: ac10be5cdbfa ("arm64: Use common of_kexec_alloc_and_setup_fdt()")
Link: https://lore.kernel.org/r/20241023171426.452688-1-usamaarif642@gmail.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
21 files changed:
arch/arc/kernel/devtree.c
arch/arm/kernel/devtree.c
arch/arm64/kernel/setup.c
arch/csky/kernel/setup.c
arch/loongarch/kernel/setup.c
arch/microblaze/kernel/prom.c
arch/mips/kernel/prom.c
arch/mips/kernel/relocate.c
arch/nios2/kernel/prom.c
arch/openrisc/kernel/prom.c
arch/powerpc/kernel/dt_cpu_ftrs.c
arch/powerpc/kernel/prom.c
arch/powerpc/platforms/pseries/plpks.c
arch/riscv/kernel/setup.c
arch/sh/kernel/setup.c
arch/um/kernel/dtb.c
arch/x86/kernel/devicetree.c
arch/xtensa/kernel/setup.c
drivers/of/fdt.c
drivers/of/kexec.c
include/linux/of_fdt.h

index 4c9e614..cc6ac7d 100644 (file)
@@ -62,7 +62,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt)
        const struct machine_desc *mdesc;
        unsigned long dt_root;
 
-       if (!early_init_dt_scan(dt))
+       if (!early_init_dt_scan(dt, __pa(dt)))
                return NULL;
 
        mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach);
index fdb74e6..3b78966 100644 (file)
@@ -200,7 +200,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt_virt)
 
        mdesc_best = &__mach_desc_GENERIC_DT;
 
-       if (!dt_virt || !early_init_dt_verify(dt_virt))
+       if (!dt_virt || !early_init_dt_verify(dt_virt, __pa(dt_virt)))
                return NULL;
 
        mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);
index b22d28e..87f61fd 100644 (file)
@@ -175,7 +175,11 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
        if (dt_virt)
                memblock_reserve(dt_phys, size);
 
-       if (!dt_virt || !early_init_dt_scan(dt_virt)) {
+       /*
+        * dt_virt is a fixmap address, hence __pa(dt_virt) can't be used.
+        * Pass dt_phys directly.
+        */
+       if (!early_init_dt_scan(dt_virt, dt_phys)) {
                pr_crit("\n"
                        "Error: invalid device tree blob at physical address %pa (virtual address 0x%px)\n"
                        "The dtb must be 8-byte aligned and must not exceed 2 MB in size\n"
index 51012e9..fe715b7 100644 (file)
@@ -112,9 +112,9 @@ asmlinkage __visible void __init csky_start(unsigned int unused,
        pre_trap_init();
 
        if (dtb_start == NULL)
-               early_init_dt_scan(__dtb_start);
+               early_init_dt_scan(__dtb_start, __pa(dtb_start));
        else
-               early_init_dt_scan(dtb_start);
+               early_init_dt_scan(dtb_start, __pa(dtb_start));
 
        start_kernel();
 
index 00e3072..10d8782 100644 (file)
@@ -290,7 +290,7 @@ static void __init fdt_setup(void)
        if (!fdt_pointer || fdt_check_header(fdt_pointer))
                return;
 
-       early_init_dt_scan(fdt_pointer);
+       early_init_dt_scan(fdt_pointer, __pa(fdt_pointer));
        early_init_fdt_reserve_self();
 
        max_low_pfn = PFN_PHYS(memblock_end_of_DRAM());
index e424c79..76ac4cf 100644 (file)
@@ -18,7 +18,7 @@ void __init early_init_devtree(void *params)
 {
        pr_debug(" -> early_init_devtree(%p)\n", params);
 
-       early_init_dt_scan(params);
+       early_init_dt_scan(params, __pa(params));
        if (!strlen(boot_command_line))
                strscpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
 
index 6062e6f..4fd6da0 100644 (file)
@@ -41,7 +41,7 @@ char *mips_get_machine_name(void)
 
 void __init __dt_setup_arch(void *bph)
 {
-       if (!early_init_dt_scan(bph))
+       if (!early_init_dt_scan(bph, __pa(bph)))
                return;
 
        mips_set_machine_name(of_flat_dt_get_machine_name());
index 7eeeaf1..cda7983 100644 (file)
@@ -337,7 +337,7 @@ void *__init relocate_kernel(void)
 #if defined(CONFIG_USE_OF)
        /* Deal with the device tree */
        fdt = plat_get_fdt();
-       early_init_dt_scan(fdt);
+       early_init_dt_scan(fdt, __pa(fdt));
        if (boot_command_line[0]) {
                /* Boot command line was passed in device tree */
                strscpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
index 9a8393e..db04924 100644 (file)
@@ -27,7 +27,7 @@ void __init early_init_devtree(void *params)
        if (be32_to_cpup((__be32 *)CONFIG_NIOS2_DTB_PHYS_ADDR) ==
                 OF_DT_HEADER) {
                params = (void *)CONFIG_NIOS2_DTB_PHYS_ADDR;
-               early_init_dt_scan(params);
+               early_init_dt_scan(params, __pa(params));
                return;
        }
 #endif
@@ -37,5 +37,5 @@ void __init early_init_devtree(void *params)
                params = (void *)__dtb_start;
 #endif
 
-       early_init_dt_scan(params);
+       early_init_dt_scan(params, __pa(params));
 }
index 19e6008..e424e9b 100644 (file)
@@ -22,6 +22,6 @@
 
 void __init early_init_devtree(void *params)
 {
-       early_init_dt_scan(params);
+       early_init_dt_scan(params, __pa(params));
        memblock_allow_resize();
 }
index af42635..1bee15c 100644 (file)
@@ -867,7 +867,7 @@ bool __init dt_cpu_ftrs_init(void *fdt)
        using_dt_cpu_ftrs = false;
 
        /* Setup and verify the FDT, if it fails we just bail */
-       if (!early_init_dt_verify(fdt))
+       if (!early_init_dt_verify(fdt, __pa(fdt)))
                return false;
 
        if (!of_scan_flat_dt(fdt_find_cpu_features, NULL))
index 0be07ed..88cbe43 100644 (file)
@@ -791,7 +791,7 @@ void __init early_init_devtree(void *params)
        DBG(" -> early_init_devtree(%px)\n", params);
 
        /* Too early to BUG_ON(), do it by hand */
-       if (!early_init_dt_verify(params))
+       if (!early_init_dt_verify(params, __pa(params)))
                panic("BUG: Failed verifying flat device tree, bad version?");
 
        of_scan_flat_dt(early_init_dt_scan_model, NULL);
index 4a59549..b1667ed 100644 (file)
@@ -683,7 +683,7 @@ void __init plpks_early_init_devtree(void)
 out:
        fdt_nop_property(fdt, chosen_node, "ibm,plpks-pw");
        // Since we've cleared the password, we must update the FDT checksum
-       early_init_dt_verify(fdt);
+       early_init_dt_verify(fdt, __pa(fdt));
 }
 
 static __init int pseries_plpks_init(void)
index a2cde65..26c886d 100644 (file)
@@ -227,7 +227,7 @@ static void __init init_resources(void)
 static void __init parse_dtb(void)
 {
        /* Early scan of device tree from init memory */
-       if (early_init_dt_scan(dtb_early_va)) {
+       if (early_init_dt_scan(dtb_early_va, __pa(dtb_early_va))) {
                const char *name = of_flat_dt_get_machine_name();
 
                if (name) {
index 620e5cf..f2b6f16 100644 (file)
@@ -255,7 +255,7 @@ void __ref sh_fdt_init(phys_addr_t dt_phys)
        dt_virt = phys_to_virt(dt_phys);
 #endif
 
-       if (!dt_virt || !early_init_dt_scan(dt_virt)) {
+       if (!dt_virt || !early_init_dt_scan(dt_virt, __pa(dt_virt))) {
                pr_crit("Error: invalid device tree blob"
                        " at physical address %p\n", (void *)dt_phys);
 
index 4954188..8d78ced 100644 (file)
@@ -17,7 +17,7 @@ void uml_dtb_init(void)
 
        area = uml_load_file(dtb, &size);
        if (area) {
-               if (!early_init_dt_scan(area)) {
+               if (!early_init_dt_scan(area, __pa(area))) {
                        pr_err("invalid DTB %s\n", dtb);
                        memblock_free(area, size);
                        return;
index 6428087..59d23cd 100644 (file)
@@ -305,7 +305,7 @@ void __init x86_flattree_get_config(void)
                        map_len = size;
                }
 
-               early_init_dt_verify(dt);
+               early_init_dt_verify(dt, __pa(dt));
        }
 
        unflatten_and_copy_device_tree();
index bdec4a7..e51f206 100644 (file)
@@ -216,7 +216,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
 
 void __init early_init_devtree(void *params)
 {
-       early_init_dt_scan(params);
+       early_init_dt_scan(params, __pa(params));
        of_scan_flat_dt(xtensa_dt_io_area, NULL);
 
        if (!command_line[0])
index d0dbc81..d3ecf2b 100644 (file)
@@ -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
 
@@ -1134,17 +1135,18 @@ static void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
        return ptr;
 }
 
-bool __init early_init_dt_verify(void *params)
+bool __init early_init_dt_verify(void *dt_virt, phys_addr_t dt_phys)
 {
-       if (!params)
+       if (!dt_virt)
                return false;
 
        /* check device tree validity */
-       if (fdt_check_header(params))
+       if (fdt_check_header(dt_virt))
                return false;
 
        /* Setup flat device-tree pointer */
-       initial_boot_params = params;
+       initial_boot_params = dt_virt;
+       initial_boot_params_pa = dt_phys;
        of_fdt_crc32 = crc32_be(~0, initial_boot_params,
                                fdt_totalsize(initial_boot_params));
 
@@ -1171,11 +1173,11 @@ void __init early_init_dt_scan_nodes(void)
        early_init_dt_check_for_usable_mem_range();
 }
 
-bool __init early_init_dt_scan(void *params)
+bool __init early_init_dt_scan(void *dt_virt, phys_addr_t dt_phys)
 {
        bool status;
 
-       status = early_init_dt_verify(params);
+       status = early_init_dt_verify(dt_virt, dt_phys);
        if (!status)
                return false;
 
index 9ccde2f..5b92459 100644 (file)
@@ -301,7 +301,7 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
        }
 
        /* Remove memory reservation for the current device tree. */
-       ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params),
+       ret = fdt_find_and_del_mem_rsv(fdt, initial_boot_params_pa,
                                       fdt_totalsize(initial_boot_params));
        if (ret == -EINVAL) {
                pr_err("Error removing memory reservation.\n");
index d69ad5b..b8d6c0c 100644 (file)
@@ -31,6 +31,7 @@ extern void *of_fdt_unflatten_tree(const unsigned long *blob,
 extern int __initdata dt_root_addr_cells;
 extern int __initdata dt_root_size_cells;
 extern void *initial_boot_params;
+extern phys_addr_t initial_boot_params_pa;
 
 extern char __dtb_start[];
 extern char __dtb_end[];
@@ -70,8 +71,8 @@ extern u64 dt_mem_next_cell(int s, const __be32 **cellp);
 /* Early flat tree scan hooks */
 extern int early_init_dt_scan_root(void);
 
-extern bool early_init_dt_scan(void *params);
-extern bool early_init_dt_verify(void *params);
+extern bool early_init_dt_scan(void *dt_virt, phys_addr_t dt_phys);
+extern bool early_init_dt_verify(void *dt_virt, phys_addr_t dt_phys);
 extern void early_init_dt_scan_nodes(void);
 
 extern const char *of_flat_dt_get_machine_name(void);