in kernel/ftrace.c [22:67]
void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
{
unsigned long old;
int faulted;
unsigned long return_hooker = (unsigned long)
&return_to_handler;
if (unlikely(ftrace_graph_is_dead()))
return;
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
return;
/*
* Protect against fault, even if it shouldn't
* happen. This tool is too much intrusive to
* ignore such a protection.
*/
asm volatile(" 1: lwi %0, %2, 0;" \
"2: swi %3, %2, 0;" \
" addik %1, r0, 0;" \
"3:" \
" .section .fixup, \"ax\";" \
"4: brid 3b;" \
" addik %1, r0, 1;" \
" .previous;" \
" .section __ex_table,\"a\";" \
" .word 1b,4b;" \
" .word 2b,4b;" \
" .previous;" \
: "=&r" (old), "=r" (faulted)
: "r" (parent), "r" (return_hooker)
);
flush_dcache_range((u32)parent, (u32)parent + 4);
flush_icache_range((u32)parent, (u32)parent + 4);
if (unlikely(faulted)) {
ftrace_graph_stop();
WARN_ON(1);
return;
}
if (function_graph_enter(old, self_addr, 0, NULL))
*parent = old;
}