~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/parisc/kernel/ftrace.c

Version: ~ [ linux-5.8-rc3 ] ~ [ linux-5.7.5 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.48 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.129 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.185 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.228 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.228 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Code for tracing calls in Linux kernel.
  3  * Copyright (C) 2009 Helge Deller <deller@gmx.de>
  4  *
  5  * based on code for x86 which is:
  6  * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
  7  *
  8  * future possible enhancements:
  9  *      - add CONFIG_DYNAMIC_FTRACE
 10  *      - add CONFIG_STACK_TRACER
 11  */
 12 
 13 #include <linux/init.h>
 14 #include <linux/ftrace.h>
 15 
 16 #include <asm/sections.h>
 17 #include <asm/ftrace.h>
 18 
 19 
 20 
 21 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 22 
 23 /* Add a function return address to the trace stack on thread info.*/
 24 static int push_return_trace(unsigned long ret, unsigned long long time,
 25                                 unsigned long func, int *depth)
 26 {
 27         int index;
 28 
 29         if (!current->ret_stack)
 30                 return -EBUSY;
 31 
 32         /* The return trace stack is full */
 33         if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) {
 34                 atomic_inc(&current->trace_overrun);
 35                 return -EBUSY;
 36         }
 37 
 38         index = ++current->curr_ret_stack;
 39         barrier();
 40         current->ret_stack[index].ret = ret;
 41         current->ret_stack[index].func = func;
 42         current->ret_stack[index].calltime = time;
 43         *depth = index;
 44 
 45         return 0;
 46 }
 47 
 48 /* Retrieve a function return address to the trace stack on thread info.*/
 49 static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret)
 50 {
 51         int index;
 52 
 53         index = current->curr_ret_stack;
 54 
 55         if (unlikely(index < 0)) {
 56                 ftrace_graph_stop();
 57                 WARN_ON(1);
 58                 /* Might as well panic, otherwise we have no where to go */
 59                 *ret = (unsigned long)
 60                         dereference_function_descriptor(&panic);
 61                 return;
 62         }
 63 
 64         *ret = current->ret_stack[index].ret;
 65         trace->func = current->ret_stack[index].func;
 66         trace->calltime = current->ret_stack[index].calltime;
 67         trace->overrun = atomic_read(&current->trace_overrun);
 68         trace->depth = index;
 69         barrier();
 70         current->curr_ret_stack--;
 71 
 72 }
 73 
 74 /*
 75  * Send the trace to the ring-buffer.
 76  * @return the original return address.
 77  */
 78 unsigned long ftrace_return_to_handler(unsigned long retval0,
 79                                        unsigned long retval1)
 80 {
 81         struct ftrace_graph_ret trace;
 82         unsigned long ret;
 83 
 84         pop_return_trace(&trace, &ret);
 85         trace.rettime = local_clock();
 86         ftrace_graph_return(&trace);
 87 
 88         if (unlikely(!ret)) {
 89                 ftrace_graph_stop();
 90                 WARN_ON(1);
 91                 /* Might as well panic. What else to do? */
 92                 ret = (unsigned long)
 93                         dereference_function_descriptor(&panic);
 94         }
 95 
 96         /* HACK: we hand over the old functions' return values
 97            in %r23 and %r24. Assembly in entry.S will take care
 98            and move those to their final registers %ret0 and %ret1 */
 99         asm( "copy %0, %%r23 \n\t"
100              "copy %1, %%r24 \n" : : "r" (retval0), "r" (retval1) );
101 
102         return ret;
103 }
104 
105 /*
106  * Hook the return address and push it in the stack of return addrs
107  * in current thread info.
108  */
109 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
110 {
111         unsigned long old;
112         unsigned long long calltime;
113         struct ftrace_graph_ent trace;
114 
115         if (unlikely(ftrace_graph_is_dead()))
116                 return;
117 
118         if (unlikely(atomic_read(&current->tracing_graph_pause)))
119                 return;
120 
121         old = *parent;
122         *parent = (unsigned long)
123                   dereference_function_descriptor(&return_to_handler);
124 
125         if (unlikely(!__kernel_text_address(old))) {
126                 ftrace_graph_stop();
127                 *parent = old;
128                 WARN_ON(1);
129                 return;
130         }
131 
132         calltime = local_clock();
133 
134         if (push_return_trace(old, calltime,
135                                 self_addr, &trace.depth) == -EBUSY) {
136                 *parent = old;
137                 return;
138         }
139 
140         trace.func = self_addr;
141 
142         /* Only trace if the calling function expects to */
143         if (!ftrace_graph_entry(&trace)) {
144                 current->curr_ret_stack--;
145                 *parent = old;
146         }
147 }
148 
149 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
150 
151 
152 void ftrace_function_trampoline(unsigned long parent,
153                                 unsigned long self_addr,
154                                 unsigned long org_sp_gr3)
155 {
156         extern ftrace_func_t ftrace_trace_function;
157 
158         if (ftrace_trace_function != ftrace_stub) {
159                 ftrace_trace_function(parent, self_addr);
160                 return;
161         }
162 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
163         if (ftrace_graph_entry && ftrace_graph_return) {
164                 unsigned long sp;
165                 unsigned long *parent_rp;
166 
167                 asm volatile ("copy %%r30, %0" : "=r"(sp));
168                 /* sanity check: is stack pointer which we got from
169                    assembler function in entry.S in a reasonable
170                    range compared to current stack pointer? */
171                 if ((sp - org_sp_gr3) > 0x400)
172                         return;
173 
174                 /* calculate pointer to %rp in stack */
175                 parent_rp = (unsigned long *) org_sp_gr3 - 0x10;
176                 /* sanity check: parent_rp should hold parent */
177                 if (*parent_rp != parent)
178                         return;
179                 
180                 prepare_ftrace_return(parent_rp, self_addr);
181                 return;
182         }
183 #endif
184 }
185 
186 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp