mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00:00
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:
parent
f9759e2b57
commit
b2473a3597
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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])
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user