ftrace.c (230c77a5e92a29bf21e98ee35e22b0537f61c55b) ftrace.c (d7950be145c84ca5094c52bc1ad1e7f1893d0f19)
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3
4#include <linux/ftrace.h>
5#include <linux/uaccess.h>
6
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3
4#include <linux/ftrace.h>
5#include <linux/uaccess.h>
6
7extern void (*ftrace_trace_function)(unsigned long, unsigned long,
8 struct ftrace_ops*, struct pt_regs*);
7#ifdef CONFIG_FUNCTION_GRAPH_TRACER
8void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
9 unsigned long frame_pointer)
10{
11 unsigned long return_hooker = (unsigned long)&return_to_handler;
12 unsigned long old;
9
13
14 if (unlikely(atomic_read(&current->tracing_graph_pause)))
15 return;
10
16
11noinline void __naked ftrace_stub(unsigned long ip, unsigned long parent_ip,
12 struct ftrace_ops *op, struct pt_regs *regs)
13{
14 asm volatile ("\n");
15}
17 old = *parent;
16
18
17noinline void csky_mcount(unsigned long from_pc, unsigned long self_pc)
18{
19 if (ftrace_trace_function != ftrace_stub)
20 ftrace_trace_function(self_pc, from_pc, NULL, NULL);
19 if (!function_graph_enter(old, self_addr,
20 *(unsigned long *)frame_pointer, parent)) {
21 /*
22 * For csky-gcc function has sub-call:
23 * subi sp, sp, 8
24 * stw r8, (sp, 0)
25 * mov r8, sp
26 * st.w r15, (sp, 0x4)
27 * push r15
28 * jl _mcount
29 * We only need set *parent for resume
30 *
31 * For csky-gcc function has no sub-call:
32 * subi sp, sp, 4
33 * stw r8, (sp, 0)
34 * mov r8, sp
35 * push r15
36 * jl _mcount
37 * We need set *parent and *(frame_pointer + 4) for resume,
38 * because lr is resumed twice.
39 */
40 *parent = return_hooker;
41 frame_pointer += 4;
42 if (*(unsigned long *)frame_pointer == old)
43 *(unsigned long *)frame_pointer = return_hooker;
44 }
21}
45}
46#endif
22
23/* _mcount is defined in abi's mcount.S */
47
48/* _mcount is defined in abi's mcount.S */
49extern void _mcount(void);
24EXPORT_SYMBOL(_mcount);
50EXPORT_SYMBOL(_mcount);