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(¤t->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