of/fdt: add dt_phys arg to early_init_dt_scan and early_init_dt_verify

__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: ac10be5cdb ("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>
This commit is contained in:
Usama Arif 2024-10-23 18:14:26 +01:00 committed by Rob Herring (Arm)
parent f9759e2b57
commit b2473a3597
21 changed files with 36 additions and 29 deletions

View 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);

View 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);

View 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"

View 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();

View 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());

View 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);

View 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());

View 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);

View 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));
}

View 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();
}

View 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))

View 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);

View 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)

View 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) {

View 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);

View 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;

View 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();

View 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])

View 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;

View 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");

View 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);