From: "louis.wang" <liang26812@xxxxxxxxx> [ Upstream commit 8252ca87c7a2111502ee13994956f8c309faad7f ] Enabling function_graph tracer on ARM causes kernel panic, because the function graph tracer updates the "return address" of a function in order to insert a trace callback on function exit, it saves the function's original return address in a return trace stack, but cpu_suspend() may not return through the normal return path. cpu_suspend() will resume directly via the cpu_resume path, but the return trace stack has been set-up by the subfunctions of cpu_suspend(), which makes the "return address" inconsistent with cpu_suspend(). This patch refers to Commit de818bd4522c40ea02a81b387d2fa86f989c9623 ("arm64: kernel: pause/unpause function graph tracer in cpu_suspend()"), fixes the issue by pausing/resuming the function graph tracer on the thread executing cpu_suspend(), so that the function graph tracer state is kept consistent across functions that enter power down states and never return by effectively disabling graph tracer while they are executing. Signed-off-by: louis.wang <liang26812@xxxxxxxxx> Signed-off-by: Russell King <rmk+kernel@xxxxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> --- arch/arm/kernel/suspend.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index 24bd20564be7..43f0a3ebf390 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include <linux/ftrace.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/mm_types.h> @@ -25,6 +26,13 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) if (!idmap_pgd) return -EINVAL; + /* + * Function graph tracer state gets incosistent when the kernel + * calls functions that never return (aka suspend finishers) hence + * disable graph tracing during their execution. + */ + pause_graph_tracing(); + /* * Provide a temporary page table with an identity mapping for * the MMU-enable code, required for resuming. On successful @@ -32,6 +40,9 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) * back to the correct page tables. */ ret = __cpu_suspend(arg, fn, __mpidr); + + unpause_graph_tracing(); + if (ret == 0) { cpu_switch_mm(mm->pgd, mm); local_flush_bp_all(); @@ -45,7 +56,13 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) { u32 __mpidr = cpu_logical_map(smp_processor_id()); - return __cpu_suspend(arg, fn, __mpidr); + int ret; + + pause_graph_tracing(); + ret = __cpu_suspend(arg, fn, __mpidr); + unpause_graph_tracing(); + + return ret; } #define idmap_pgd NULL #endif -- 2.30.2