diff options
Diffstat (limited to 'arch/sparc/kernel/ftrace.c')
| -rw-r--r-- | arch/sparc/kernel/ftrace.c | 60 | 
1 files changed, 59 insertions, 1 deletions
diff --git a/arch/sparc/kernel/ftrace.c b/arch/sparc/kernel/ftrace.c index 9103a56b39e8..03ab022e51c5 100644 --- a/arch/sparc/kernel/ftrace.c +++ b/arch/sparc/kernel/ftrace.c @@ -13,7 +13,7 @@ static const u32 ftrace_nop = 0x01000000;  static u32 ftrace_call_replace(unsigned long ip, unsigned long addr)  { -	static u32 call; +	u32 call;  	s32 off;  	off = ((s32)addr - (s32)ip); @@ -91,3 +91,61 @@ int __init ftrace_dyn_arch_init(void *data)  	return 0;  }  #endif + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + +#ifdef CONFIG_DYNAMIC_FTRACE +extern void ftrace_graph_call(void); + +int ftrace_enable_ftrace_graph_caller(void) +{ +	unsigned long ip = (unsigned long)(&ftrace_graph_call); +	u32 old, new; + +	old = *(u32 *) &ftrace_graph_call; +	new = ftrace_call_replace(ip, (unsigned long) &ftrace_graph_caller); +	return ftrace_modify_code(ip, old, new); +} + +int ftrace_disable_ftrace_graph_caller(void) +{ +	unsigned long ip = (unsigned long)(&ftrace_graph_call); +	u32 old, new; + +	old = *(u32 *) &ftrace_graph_call; +	new = ftrace_call_replace(ip, (unsigned long) &ftrace_stub); + +	return ftrace_modify_code(ip, old, new); +} + +#endif /* !CONFIG_DYNAMIC_FTRACE */ + +/* + * Hook the return address and push it in the stack of return addrs + * in current thread info. + */ +unsigned long prepare_ftrace_return(unsigned long parent, +				    unsigned long self_addr, +				    unsigned long frame_pointer) +{ +	unsigned long return_hooker = (unsigned long) &return_to_handler; +	struct ftrace_graph_ent trace; + +	if (unlikely(atomic_read(¤t->tracing_graph_pause))) +		return parent + 8UL; + +	if (ftrace_push_return_trace(parent, self_addr, &trace.depth, +				     frame_pointer) == -EBUSY) +		return parent + 8UL; + +	trace.func = self_addr; + +	/* Only trace if the calling function expects to */ +	if (!ftrace_graph_entry(&trace)) { +		current->curr_ret_stack--; +		return parent + 8UL; +	} + +	return return_hooker; +} +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */  | 
