Skip to content

Commit

Permalink
of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify
Browse files Browse the repository at this point in the history
 __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: ac10be5 ("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>
  • Loading branch information
Usama Arif authored and Rob Herring (Arm) committed Oct 29, 2024
1 parent f9759e2 commit b2473a3
Show file tree
Hide file tree
Showing 21 changed files with 36 additions and 29 deletions.
2 changes: 1 addition & 1 deletion arch/arc/kernel/devtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/kernel/devtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 5 additions & 1 deletion arch/arm64/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions arch/csky/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
2 changes: 1 addition & 1 deletion arch/loongarch/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
2 changes: 1 addition & 1 deletion arch/microblaze/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion arch/mips/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
2 changes: 1 addition & 1 deletion arch/mips/kernel/relocate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions arch/nios2/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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));
}
2 changes: 1 addition & 1 deletion arch/openrisc/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/dt_cpu_ftrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/platforms/pseries/plpks.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion arch/riscv/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion arch/sh/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion arch/um/kernel/dtb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/devicetree.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion arch/xtensa/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
14 changes: 8 additions & 6 deletions drivers/of/fdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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));

Expand All @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion drivers/of/kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
5 changes: 3 additions & 2 deletions include/linux/of_fdt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit b2473a3

Please sign in to comment.