arm64: Kexec: Warning: virt_to_phys used for non-linear address
Subsystems (3)
Hello,
I am setting the following warning when loading a kdump kernel in ACPI-based aarch64 box, running upstream and linux-next (stack below against 5f703ce5c981).
virt_to_phys used for non-linear address: 00000000cf9a4e41 (0xffffffffff5e0000)
WARNING: CPU: 35 PID: 2279 at arch/arm64/mm/physaddr.c:15 __virt_to_phys (arch/arm64/mm/physaddr.c:17) Modules linked in: sunrpc(E) ipmi_ssif(E) nvidia_cspmu(E) arm_cspmu_module(E) arm_smmuv3_pmu(E) coresight_trbe(E) mlx5_ib(E) ib_uverbs(E) ipmi_devintf(E) ipmi_msghandler(E) coresight_stm(E) coresight_tmc(E) coresight_funnel(E) stm_core(E) coresight_etm4x(E) coresight(E) cppc_cpufreq(E) sch_fq_codel(E) drm(E) backlight(E) drm_panel_orientation_quirks(E) crct10dif_ce(E) sm3_ce(E) sm3(E) sha3_ce(E) sha512_ce(E) sha512_arm64(E) xhci_pci(E) xhci_hcd(E) spi_tegra210_quad(E) nbd(E) acpi_power_meter(E) loop(E) efivarfs(E) autofs4(E) Hardware name: Quanta Java Island EVT 29F0EMAZ046/Java Island, BIOS F0EJ3A01 06/03/2024 pstate: 63400009 (nZCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--) pc : __virt_to_phys (arch/arm64/mm/physaddr.c:17) lr : __virt_to_phys (arch/arm64/mm/physaddr.c:17) sp : ffff8000be1cf9f0 x29: ffff8000be1cf9f0 x28: dfff800000000000 x27: ffff800083ca9630 x26: ffff800083ca9000 x25: 1ffff000107952c6 x24: ffff0000ff1b6800 x23: 0000000000000000 x22: 0000000000001687 x21: ffff0001ecd46800 x20: ffff000103524000 x19: ffffffffff5e0000 x18: ffffffffffffffff x17: ffff8000802d07d4 x16: 2930303030653566 x15: 0000000000000001 x14: 1ffff00017c39ed8 x13: 0000000000000000 x12: 0000000000000000 x11: ffff700017c39ed9 x10: 0000000000000002 x9 : e7a4565c7b34a200 x8 : ffff800083c50000 x7 : 0000000000000001 x6 : 0000000000000001 x5 : ffff8000be1cf6a0 x4 : ffff800084a5ff40 x3 : ffff800081580960 x2 : 0000000000000001 x1 : ffff800083253340 x0 : 000000000000004f Call trace: __virt_to_phys (arch/arm64/mm/physaddr.c:17) of_kexec_alloc_and_setup_fdt (drivers/of/kexec.c:305) load_other_segments (arch/arm64/kernel/machine_kexec_file.c:162) image_load (arch/arm64/kernel/kexec_image.c:103) __arm64_sys_kexec_file_load (kernel/kexec_file.c:73 kernel/kexec_file.c:257 kernel/kexec_file.c:296 kernel/kexec_file.c:374 kernel/kexec_file.c:332 kernel/kexec_file.c:332) invoke_syscall (arch/arm64/kernel/syscall.c:? arch/arm64/kernel/syscall.c:48) el0_svc_common (./include/linux/thread_info.h:127 arch/arm64/kernel/syscall.c:141) do_el0_svc (arch/arm64/kernel/syscall.c:153) el0_svc (arch/arm64/kernel/entry-common.c:165 arch/arm64/kernel/entry-common.c:178 arch/arm64/kernel/entry-common.c:713) el0t_64_sync_handler (arch/arm64/kernel/entry-common.c:781) el0t_64_sync (arch/arm64/kernel/entry.S:598) irq event stamp: 49964 hardirqs last enabled at (49963): console_unlock (kernel/printk/printk.c:? kernel/printk/printk.c:2746 kernel/printk/printk.c:3065) hardirqs last disabled at (49964): el1_dbg (arch/arm64/kernel/entry-common.c:371 arch/arm64/kernel/entry-common.c:471) softirqs last enabled at (49942): handle_softirqs (./arch/arm64/include/asm/preempt.h:13 kernel/softirq.c:401 kernel/softirq.c:582) softirqs last disabled at (49937): __do_softirq (kernel/softirq.c:589) ---[ end trace 0000000000000000 ]---
This is happening on the following code:
/* Remove memory reservation for the current device tree. */
ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params),
fdt_totalsize(initial_boot_params));Where initial_boot_params contains a copy of the fdt allocated at init time, and as I've analyzed, it is a virtual address and can be translated by the MMU.
Since __pa() is a macro to __virt_to_phys():
#define __pa(x) __virt_to_phys((unsigned long)(x))
I am curious why this address is special that makes __virt_to_phys() unhappy.
Have you seen this before? Any tip on how to debug this further?
Thanks
Quoted 46 lines · Breno Leitao
Hello,
I am setting the following warning when loading a kdump kernel in ACPI-based aarch64 box, running upstream and linux-next (stack below against
5f703ce5c981).
virt_to_physused for non-linear address:00000000cf9a4e41(0xffffffffff5e0000)WARNING: CPU: 35 PID: 2279 at arch/arm64/mm/physaddr.c:15 __virt_to_phys (arch/arm64/mm/physaddr.c:17) Modules linked in: sunrpc(E) ipmi_ssif(E) nvidia_cspmu(E) arm_cspmu_module(E) arm_smmuv3_pmu(E) coresight_trbe(E) mlx5_ib(E) ib_uverbs(E) ipmi_devintf(E) ipmi_msghandler(E) coresight_stm(E) coresight_tmc(E) coresight_funnel(E) stm_core(E) coresight_etm4x(E) coresight(E) cppc_cpufreq(E) sch_fq_codel(E) drm(E) backlight(E) drm_panel_orientation_quirks(E) crct10dif_ce(E) sm3_ce(E) sm3(E) sha3_ce(E) sha512_ce(E) sha512_arm64(E) xhci_pci(E) xhci_hcd(E) spi_tegra210_quad(E) nbd(E) acpi_power_meter(E) loop(E) efivarfs(E) autofs4(E) Hardware name: Quanta Java Island EVT 29F0EMAZ046/Java Island, BIOS F0EJ3A01 06/03/2024 pstate: 63400009 (nZCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--) pc : __virt_to_phys (arch/arm64/mm/physaddr.c:17) lr : __virt_to_phys (arch/arm64/mm/physaddr.c:17) sp : ffff8000be1cf9f0 x29: ffff8000be1cf9f0 x28: dfff800000000000 x27: ffff800083ca9630 x26: ffff800083ca9000 x25: 1ffff000107952c6 x24: ffff0000ff1b6800 x23: 0000000000000000 x22: 0000000000001687 x21: ffff0001ecd46800 x20: ffff000103524000 x19: ffffffffff5e0000 x18: ffffffffffffffff x17: ffff8000802d07d4 x16: 2930303030653566 x15: 0000000000000001 x14: 1ffff00017c39ed8 x13: 0000000000000000 x12: 0000000000000000 x11: ffff700017c39ed9 x10: 0000000000000002 x9 : e7a4565c7b34a200 x8 : ffff800083c50000 x7 : 0000000000000001 x6 : 0000000000000001 x5 : ffff8000be1cf6a0 x4 : ffff800084a5ff40 x3 : ffff800081580960 x2 : 0000000000000001 x1 : ffff800083253340 x0 : 000000000000004f Call trace: __virt_to_phys (arch/arm64/mm/physaddr.c:17) of_kexec_alloc_and_setup_fdt (drivers/of/kexec.c:305) load_other_segments (arch/arm64/kernel/machine_kexec_file.c:162) image_load (arch/arm64/kernel/kexec_image.c:103) __arm64_sys_kexec_file_load (kernel/kexec_file.c:73 kernel/kexec_file.c:257 kernel/kexec_file.c:296 kernel/kexec_file.c:374 kernel/kexec_file.c:332 kernel/kexec_file.c:332) invoke_syscall (arch/arm64/kernel/syscall.c:? arch/arm64/kernel/syscall.c:48) el0_svc_common (./include/linux/thread_info.h:127 arch/arm64/kernel/syscall.c:141) do_el0_svc (arch/arm64/kernel/syscall.c:153) el0_svc (arch/arm64/kernel/entry-common.c:165 arch/arm64/kernel/entry-common.c:178 arch/arm64/kernel/entry-common.c:713) el0t_64_sync_handler (arch/arm64/kernel/entry-common.c:781) el0t_64_sync (arch/arm64/kernel/entry.S:598) irq event stamp: 49964 hardirqs last enabled at (49963): console_unlock (kernel/printk/printk.c:? kernel/printk/printk.c:2746 kernel/printk/printk.c:3065) hardirqs last disabled at (49964): el1_dbg (arch/arm64/kernel/entry-common.c:371 arch/arm64/kernel/entry-common.c:471) softirqs last enabled at (49942): handle_softirqs (./arch/arm64/include/asm/preempt.h:13 kernel/softirq.c:401 kernel/softirq.c:582) softirqs last disabled at (49937): __do_softirq (kernel/softirq.c:589) ---[ end trace 0000000000000000 ]---This is happening on the following code:
Quoted 8 lines
/* Remove memory reservation for the current device tree. */ ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params), fdt_totalsize(initial_boot_params));Where
initial_boot_paramscontains a copy of the fdt allocated at init time, and as I've analyzed, it is a virtual address and can be translated by the MMU.
AFAICT, on arm64 'initial_boot_params' will be a pointer to the FDT in the fixmap that we mapped in setup_machine_fdt(). So that's not a linear address, and the warning is legitimate -- the use of __pa() here will give a bogus result and we could remove a memory reservation for an unrelated address.
It looks like this is a regression due to commit:
ac10be5cdbfa8521 ("arm64: Use common of_kexec_alloc_and_setup_fdt()")
... as at that point arm64 had a fixmap'd fdt, and prior to that commit we didn't try to use __pa() on the fixmap pointer.
It looks like no-one's tested kexec_file_load() with CONFIG_DEBUG_VIRTUAL since then.
Quoted 6 lines
Since
__pa()is a macro to__virt_to_phys():#define __pa(x) __virt_to_phys((unsigned long)(x))I am curious why this address is special that makes
__virt_to_phys()unhappy.
It's a fixmap address rather than a linear-map address. Confusingly 'virt' generally means the linear map rather than any virtual address, and usually virt_to_*() only work on linear map addresses.
I'm not sure how to fix this; the major reason we fixmap the FDT is so that it can be anywhere in memory (and e.g. may not be in the linear map at all), so we can't always generate a linear map VA.
We could stash the PA at boot time, and pass this as an argument to of_kexec_alloc_and_setup_fdt().
Rob, any thoughts? I couldn't see a neat way of doing this, but maybe we could initialise an initial_boot_params_phys at setup time, with a bit of churn to early_init_dt_verify() and friends?
Mark.
Quoted 4 lines
Have you seen this before? Any tip on how to debug this further?
Thanks
Quoted 62 lines · Mark Rutland
Quoted 44 lines · Breno Leitao
I am setting the following warning when loading a kdump kernel in ACPI-based aarch64 box, running upstream and linux-next (stack below against
5f703ce5c981).
virt_to_physused for non-linear address:00000000cf9a4e41(0xffffffffff5e0000)WARNING: CPU: 35 PID: 2279 at arch/arm64/mm/physaddr.c:15 __virt_to_phys (arch/arm64/mm/physaddr.c:17) Modules linked in: sunrpc(E) ipmi_ssif(E) nvidia_cspmu(E) arm_cspmu_module(E) arm_smmuv3_pmu(E) coresight_trbe(E) mlx5_ib(E) ib_uverbs(E) ipmi_devintf(E) ipmi_msghandler(E) coresight_stm(E) coresight_tmc(E) coresight_funnel(E) stm_core(E) coresight_etm4x(E) coresight(E) cppc_cpufreq(E) sch_fq_codel(E) drm(E) backlight(E) drm_panel_orientation_quirks(E) crct10dif_ce(E) sm3_ce(E) sm3(E) sha3_ce(E) sha512_ce(E) sha512_arm64(E) xhci_pci(E) xhci_hcd(E) spi_tegra210_quad(E) nbd(E) acpi_power_meter(E) loop(E) efivarfs(E) autofs4(E) Hardware name: Quanta Java Island EVT 29F0EMAZ046/Java Island, BIOS F0EJ3A01 06/03/2024 pstate: 63400009 (nZCv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--) pc : __virt_to_phys (arch/arm64/mm/physaddr.c:17) lr : __virt_to_phys (arch/arm64/mm/physaddr.c:17) sp : ffff8000be1cf9f0 x29: ffff8000be1cf9f0 x28: dfff800000000000 x27: ffff800083ca9630 x26: ffff800083ca9000 x25: 1ffff000107952c6 x24: ffff0000ff1b6800 x23: 0000000000000000 x22: 0000000000001687 x21: ffff0001ecd46800 x20: ffff000103524000 x19: ffffffffff5e0000 x18: ffffffffffffffff x17: ffff8000802d07d4 x16: 2930303030653566 x15: 0000000000000001 x14: 1ffff00017c39ed8 x13: 0000000000000000 x12: 0000000000000000 x11: ffff700017c39ed9 x10: 0000000000000002 x9 : e7a4565c7b34a200 x8 : ffff800083c50000 x7 : 0000000000000001 x6 : 0000000000000001 x5 : ffff8000be1cf6a0 x4 : ffff800084a5ff40 x3 : ffff800081580960 x2 : 0000000000000001 x1 : ffff800083253340 x0 : 000000000000004f Call trace: __virt_to_phys (arch/arm64/mm/physaddr.c:17) of_kexec_alloc_and_setup_fdt (drivers/of/kexec.c:305) load_other_segments (arch/arm64/kernel/machine_kexec_file.c:162) image_load (arch/arm64/kernel/kexec_image.c:103) __arm64_sys_kexec_file_load (kernel/kexec_file.c:73 kernel/kexec_file.c:257 kernel/kexec_file.c:296 kernel/kexec_file.c:374 kernel/kexec_file.c:332 kernel/kexec_file.c:332) invoke_syscall (arch/arm64/kernel/syscall.c:? arch/arm64/kernel/syscall.c:48) el0_svc_common (./include/linux/thread_info.h:127 arch/arm64/kernel/syscall.c:141) do_el0_svc (arch/arm64/kernel/syscall.c:153) el0_svc (arch/arm64/kernel/entry-common.c:165 arch/arm64/kernel/entry-common.c:178 arch/arm64/kernel/entry-common.c:713) el0t_64_sync_handler (arch/arm64/kernel/entry-common.c:781) el0t_64_sync (arch/arm64/kernel/entry.S:598) irq event stamp: 49964 hardirqs last enabled at (49963): console_unlock (kernel/printk/printk.c:? kernel/printk/printk.c:2746 kernel/printk/printk.c:3065) hardirqs last disabled at (49964): el1_dbg (arch/arm64/kernel/entry-common.c:371 arch/arm64/kernel/entry-common.c:471) softirqs last enabled at (49942): handle_softirqs (./arch/arm64/include/asm/preempt.h:13 kernel/softirq.c:401 kernel/softirq.c:582) softirqs last disabled at (49937): __do_softirq (kernel/softirq.c:589) ---[ end trace 0000000000000000 ]---This is happening on the following code:
Quoted 8 lines
/* Remove memory reservation for the current device tree. */ ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params), fdt_totalsize(initial_boot_params));Where
initial_boot_paramscontains a copy of the fdt allocated at init time, and as I've analyzed, it is a virtual address and can be translated by the MMU.AFAICT, on arm64 '
initial_boot_params' will be a pointer to the FDT in the fixmap that we mapped insetup_machine_fdt(). So that's not a linear address, and the warning is legitimate -- the use of__pa()here will give a bogus result and we could remove a memory reservation for an unrelated address.It looks like this is a regression due to commit:
Quoted 7 lines
ac10be5cdbfa8521("arm64: Use commonof_kexec_alloc_and_setup_fdt()")... as at that point arm64 had a fixmap'd fdt, and prior to that commit we didn't try to use
__pa()on the fixmap pointer.It looks like no-one's tested
kexec_file_load()withCONFIG_DEBUG_VIRTUALsince then.
There's also this in early_init_fdt_reserve_self():
memblock_reserve(__pa(initial_boot_params)
but it doesn't look like we call that on arm64. However, the core FDT code is clearly assuming that the DTB is mapped in the linear map :/
Quoted 12 lines
Quoted 7 lines
Since
__pa()is a macro to__virt_to_phys():#define __pa(x) __virt_to_phys((unsigned long)(x))I am curious why this address is special that makes
__virt_to_phys()unhappy.It's a fixmap address rather than a linear-map address. Confusingly 'virt' generally means the linear map rather than any virtual address, and usually virt_to_*() only work on linear map addresses.
Quoted 6 lines
I'm not sure how to fix this; the major reason we fixmap the FDT is so that it can be anywhere in memory (and e.g. may not be in the linear map at all), so we can't always generate a linear map VA.
We could stash the PA at boot time, and pass this as an argument to
of_kexec_alloc_and_setup_fdt().
Yeah, if it was passed as an additional argument to early_init_dt_scan(), then the core could could track it. Alternatively, we'd need a helper macro to get the PA and have an arm64-variant for the fixmap (everybody else could use __pa()).
Quoted 3 lines
Rob, any thoughts? I couldn't see a neat way of doing this, but maybe we could initialise an
initial_boot_params_physat setup time, with a bit of churn toearly_init_dt_verify()and friends?
Rob?
Will
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Quoted 26 lines · Will Deacon
Quoted 13 lines · Mark Rutland
Quoted 6 lines · Breno Leitao
Since
__pa()is a macro to__virt_to_phys():#define __pa(x) __virt_to_phys((unsigned long)(x))I am curious why this address is special that makes
__virt_to_phys()unhappy.It's a fixmap address rather than a linear-map address. Confusingly 'virt' generally means the linear map rather than any virtual address, and usually virt_to_*() only work on linear map addresses.
Quoted 6 lines
I'm not sure how to fix this; the major reason we fixmap the FDT is so that it can be anywhere in memory (and e.g. may not be in the linear map at all), so we can't always generate a linear map VA.
We could stash the PA at boot time, and pass this as an argument to
of_kexec_alloc_and_setup_fdt().Yeah, if it was passed as an additional argument to
early_init_dt_scan(), then the core could could track it. Alternatively, we'd need a helper macro to get the PA and have an arm64-variant for the fixmap (everybody else could use__pa()).
Quoted 5 lines
Quoted 3 lines
Rob, any thoughts? I couldn't see a neat way of doing this, but maybe we could initialise an
initial_boot_params_physat setup time, with a bit of churn toearly_init_dt_verify()and friends?Rob?
Hello, is there anything I can do or test to have this moving?
Thanks
Quoted 27 lines · Breno Leitao
Quoted 26 lines · Will Deacon
Quoted 13 lines · Mark Rutland
Quoted 6 lines · Breno Leitao
Since
__pa()is a macro to__virt_to_phys():#define __pa(x) __virt_to_phys((unsigned long)(x))I am curious why this address is special that makes
__virt_to_phys()unhappy.It's a fixmap address rather than a linear-map address. Confusingly 'virt' generally means the linear map rather than any virtual address, and usually virt_to_*() only work on linear map addresses.
Quoted 6 lines
I'm not sure how to fix this; the major reason we fixmap the FDT is so that it can be anywhere in memory (and e.g. may not be in the linear map at all), so we can't always generate a linear map VA.
We could stash the PA at boot time, and pass this as an argument to
of_kexec_alloc_and_setup_fdt().Yeah, if it was passed as an additional argument to
early_init_dt_scan(), then the core could could track it. Alternatively, we'd need a helper macro to get the PA and have an arm64-variant for the fixmap (everybody else could use__pa()).
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Rob, any thoughts? I couldn't see a neat way of doing this, but maybe we could initialise an
initial_boot_params_physat setup time, with a bit of churn toearly_init_dt_verify()and friends?Rob?
Hello, is there anything I can do or test to have this moving?
I've not seen anything from Rob, so the best bet is probably to see if you can hack up a patch to fix it yourself and then cc the rest of us when you post it.
Will
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Quoted 34 lines · Will Deacon
Quoted 33 lines · Breno Leitao
Quoted 31 lines · Will Deacon
Quoted 13 lines · Mark Rutland
Quoted 6 lines · Breno Leitao
Since
__pa()is a macro to__virt_to_phys():#define __pa(x) __virt_to_phys((unsigned long)(x))I am curious why this address is special that makes
__virt_to_phys()unhappy.It's a fixmap address rather than a linear-map address. Confusingly 'virt' generally means the linear map rather than any virtual address, and usually virt_to_*() only work on linear map addresses.
Quoted 6 lines
I'm not sure how to fix this; the major reason we fixmap the FDT is so that it can be anywhere in memory (and e.g. may not be in the linear map at all), so we can't always generate a linear map VA.
We could stash the PA at boot time, and pass this as an argument to
of_kexec_alloc_and_setup_fdt().Yeah, if it was passed as an additional argument to
early_init_dt_scan(), then the core could could track it. Alternatively, we'd need a helper macro to get the PA and have an arm64-variant for the fixmap (everybody else could use__pa()).Quoted 3 lines
Rob, any thoughts? I couldn't see a neat way of doing this, but maybe we could initialise an
initial_boot_params_physat setup time, with a bit of churn toearly_init_dt_verify()and friends?Rob?
Quoted 8 lines
Quoted 1 line
Hello, is there anything I can do or test to have this moving?
I've not seen anything from Rob, so the best bet is probably to see if you can hack up a patch to fix it yourself and then cc the rest of us when you post it.
Will
Hi,
We are seeing this while doing kexec, so I sent a potential fix in [1].
I did print the values and they are differentinitial_boot_params_pa 0x6937a00000__pa(initial_boot_params) 0x8000125e0000
so I think a fix is necessary as we are deleting some random memory while doing kexec which could lead to very difficult to debug crashes if its something critical.
I just stashed the physical address and used it later during kexec.
I dont see anything that could convert fixmap to phys, but maybe its there and I didn't find it? The other option is to write fix_to_phys which would look something very similar to like kernel_page_present [2]? I do think the patch in [1] is much simpler, but happy to try something like [2] or anything else that is recommended.
Thanks!
Usama
[1] https://lore.kernel.org/all/[email protected]/
[2] https://elixir.bootlin.com/linux/v6.11.1/source/arch/arm64/mm/pageattr.c#L213
Quoted 4 lines
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec