提交 8252ca87 编写于 作者: L louis.wang 提交者: Russell King

ARM: 9066/1: ftrace: pause/unpause function graph tracer in cpu_suspend()

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 de818bd4
("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: Nlouis.wang <liang26812@gmail.com>
Signed-off-by: NRussell King <rmk+kernel@armlinux.org.uk>
上级 a506bd57
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/ftrace.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm_types.h> #include <linux/mm_types.h>
...@@ -25,6 +26,13 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ...@@ -25,6 +26,13 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
if (!idmap_pgd) if (!idmap_pgd)
return -EINVAL; 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 * Provide a temporary page table with an identity mapping for
* the MMU-enable code, required for resuming. On successful * the MMU-enable code, required for resuming. On successful
...@@ -32,6 +40,9 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ...@@ -32,6 +40,9 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
* back to the correct page tables. * back to the correct page tables.
*/ */
ret = __cpu_suspend(arg, fn, __mpidr); ret = __cpu_suspend(arg, fn, __mpidr);
unpause_graph_tracing();
if (ret == 0) { if (ret == 0) {
cpu_switch_mm(mm->pgd, mm); cpu_switch_mm(mm->pgd, mm);
local_flush_bp_all(); local_flush_bp_all();
...@@ -45,7 +56,13 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ...@@ -45,7 +56,13 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
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()); 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 #define idmap_pgd NULL
#endif #endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册