aboutsummaryrefslogtreecommitdiffstats
path: root/arch/csky/kernel/ftrace.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2019-07-10 23:24:10 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2019-07-10 23:24:10 -0700
commit597473720f4dc69749542bfcfed4a927a43d935e (patch)
tree711bf773910fb93d1dd9120c633adc807685e0d8 /arch/csky/kernel/ftrace.c
parentInput: atmel_mxt_ts - fix leak in mxt_update_cfg() (diff)
parentInput: gpio_keys_polled - allow specifying name of input device (diff)
downloadlinux-dev-597473720f4dc69749542bfcfed4a927a43d935e.tar.xz
linux-dev-597473720f4dc69749542bfcfed4a927a43d935e.zip
Merge branch 'next' into for-linus
Prepare input updates for 5.3 merge window.
Diffstat (limited to 'arch/csky/kernel/ftrace.c')
-rw-r--r--arch/csky/kernel/ftrace.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/arch/csky/kernel/ftrace.c b/arch/csky/kernel/ftrace.c
new file mode 100644
index 000000000000..274c431f1810
--- /dev/null
+++ b/arch/csky/kernel/ftrace.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+
+#include <linux/ftrace.h>
+#include <linux/uaccess.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+ unsigned long frame_pointer)
+{
+ unsigned long return_hooker = (unsigned long)&return_to_handler;
+ unsigned long old;
+
+ if (unlikely(atomic_read(&current->tracing_graph_pause)))
+ return;
+
+ old = *parent;
+
+ if (!function_graph_enter(old, self_addr,
+ *(unsigned long *)frame_pointer, parent)) {
+ /*
+ * For csky-gcc function has sub-call:
+ * subi sp, sp, 8
+ * stw r8, (sp, 0)
+ * mov r8, sp
+ * st.w r15, (sp, 0x4)
+ * push r15
+ * jl _mcount
+ * We only need set *parent for resume
+ *
+ * For csky-gcc function has no sub-call:
+ * subi sp, sp, 4
+ * stw r8, (sp, 0)
+ * mov r8, sp
+ * push r15
+ * jl _mcount
+ * We need set *parent and *(frame_pointer + 4) for resume,
+ * because lr is resumed twice.
+ */
+ *parent = return_hooker;
+ frame_pointer += 4;
+ if (*(unsigned long *)frame_pointer == old)
+ *(unsigned long *)frame_pointer = return_hooker;
+ }
+}
+#endif
+
+/* _mcount is defined in abi's mcount.S */
+extern void _mcount(void);
+EXPORT_SYMBOL(_mcount);