| From de818bd4522c40ea02a81b387d2fa86f989c9623 Mon Sep 17 00:00:00 2001 |
| From: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
| Date: Tue, 17 Nov 2015 11:50:51 +0000 |
| Subject: arm64: kernel: pause/unpause function graph tracer in cpu_suspend() |
| |
| From: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
| |
| commit de818bd4522c40ea02a81b387d2fa86f989c9623 upstream. |
| |
| The function graph tracer adds instrumentation that is required to trace |
| both entry and exit of a function. In particular the function graph |
| tracer updates the "return address" of a function in order to insert |
| a trace callback on function exit. |
| |
| Kernel power management functions like cpu_suspend() are called |
| upon power down entry with functions called "finishers" that are in turn |
| called to trigger the power down sequence but they may not return to the |
| kernel through the normal return path. |
| |
| When the core resumes from low-power it returns to the cpu_suspend() |
| function through the cpu_resume path, which leaves the trace stack frame |
| set-up by the function tracer in an incosistent state upon return to the |
| kernel when tracing is enabled. |
| |
| This patch fixes the issue by pausing/resuming the function graph |
| tracer on the thread executing cpu_suspend() (ie the function call that |
| subsequently triggers the "suspend finishers"), 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. |
| |
| Fixes: 819e50e25d0c ("arm64: Add ftrace support") |
| Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
| Reported-by: Catalin Marinas <catalin.marinas@arm.com> |
| Reported-by: AKASHI Takahiro <takahiro.akashi@linaro.org> |
| Suggested-by: Steven Rostedt <rostedt@goodmis.org> |
| Acked-by: Steven Rostedt <rostedt@goodmis.org> |
| Cc: Will Deacon <will.deacon@arm.com> |
| Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/arm64/kernel/suspend.c | 10 ++++++++++ |
| 1 file changed, 10 insertions(+) |
| |
| --- a/arch/arm64/kernel/suspend.c |
| +++ b/arch/arm64/kernel/suspend.c |
| @@ -1,3 +1,4 @@ |
| +#include <linux/ftrace.h> |
| #include <linux/percpu.h> |
| #include <linux/slab.h> |
| #include <asm/cacheflush.h> |
| @@ -71,6 +72,13 @@ int cpu_suspend(unsigned long arg, int ( |
| local_dbg_save(flags); |
| |
| /* |
| + * 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(); |
| + |
| + /* |
| * mm context saved on the stack, it will be restored when |
| * the cpu comes out of reset through the identity mapped |
| * page tables, so that the thread address space is properly |
| @@ -111,6 +119,8 @@ int cpu_suspend(unsigned long arg, int ( |
| hw_breakpoint_restore(NULL); |
| } |
| |
| + unpause_graph_tracing(); |
| + |
| /* |
| * Restore pstate flags. OS lock and mdscr have been already |
| * restored, so from this point onwards, debugging is fully |