xref: /openbmc/linux/arch/csky/kernel/ftrace.c (revision a2818ee4)
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 
7 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
8 void 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;
13 
14 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
15 		return;
16 
17 	old = *parent;
18 
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 	}
45 }
46 #endif
47 
48 /* _mcount is defined in abi's mcount.S */
49 extern void _mcount(void);
50 EXPORT_SYMBOL(_mcount);
51