blob: 5cbddb59e99f5a4fd76cc1ff453a29a84a6d1010 [file] [log] [blame]
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +02001/*
2 * Infrastructure for profiling code inserted by 'gcc -pg'.
3 *
4 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
5 * Copyright (C) 2004-2008 Ingo Molnar <mingo@redhat.com>
6 *
7 * Originally ported from the -rt patch by:
8 * Copyright (C) 2007 Arnaldo Carvalho de Melo <acme@redhat.com>
9 *
10 * Based on code in the latency_tracer, that is:
11 *
12 * Copyright (C) 2004-2006 Ingo Molnar
13 * Copyright (C) 2004 William Lee Irwin III
14 */
15
Steven Rostedt3d083392008-05-12 21:20:42 +020016#include <linux/stop_machine.h>
17#include <linux/clocksource.h>
18#include <linux/kallsyms.h>
Steven Rostedt5072c592008-05-12 21:20:43 +020019#include <linux/seq_file.h>
20#include <linux/debugfs.h>
Steven Rostedt3d083392008-05-12 21:20:42 +020021#include <linux/hardirq.h>
Ingo Molnar2d8b8202008-02-23 16:55:50 +010022#include <linux/kthread.h>
Steven Rostedt5072c592008-05-12 21:20:43 +020023#include <linux/uaccess.h>
Abhishek Sagarf22f9a82008-06-21 23:50:29 +053024#include <linux/kprobes.h>
Ingo Molnar2d8b8202008-02-23 16:55:50 +010025#include <linux/ftrace.h>
Steven Rostedtb0fc4942008-05-12 21:20:43 +020026#include <linux/sysctl.h>
Steven Rostedt5072c592008-05-12 21:20:43 +020027#include <linux/ctype.h>
Steven Rostedt3d083392008-05-12 21:20:42 +020028#include <linux/list.h>
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +020029
Abhishek Sagar395a59d2008-06-21 23:47:27 +053030#include <asm/ftrace.h>
31
Steven Rostedt3d083392008-05-12 21:20:42 +020032#include "trace.h"
33
Steven Rostedt69128962008-10-23 09:33:03 -040034#define FTRACE_WARN_ON(cond) \
35 do { \
36 if (WARN_ON(cond)) \
37 ftrace_kill(); \
38 } while (0)
39
40#define FTRACE_WARN_ON_ONCE(cond) \
41 do { \
42 if (WARN_ON_ONCE(cond)) \
43 ftrace_kill(); \
44 } while (0)
45
Steven Rostedt4eebcc82008-05-12 21:20:48 +020046/* ftrace_enabled is a method to turn ftrace on or off */
47int ftrace_enabled __read_mostly;
Steven Rostedtd61f82d2008-05-12 21:20:43 +020048static int last_ftrace_enabled;
Steven Rostedtb0fc4942008-05-12 21:20:43 +020049
Steven Rostedt4eebcc82008-05-12 21:20:48 +020050/*
51 * ftrace_disabled is set when an anomaly is discovered.
52 * ftrace_disabled is much stronger than ftrace_enabled.
53 */
54static int ftrace_disabled __read_mostly;
55
Steven Rostedt3d083392008-05-12 21:20:42 +020056static DEFINE_SPINLOCK(ftrace_lock);
Steven Rostedtb0fc4942008-05-12 21:20:43 +020057static DEFINE_MUTEX(ftrace_sysctl_lock);
58
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +020059static struct ftrace_ops ftrace_list_end __read_mostly =
60{
61 .func = ftrace_stub,
62};
63
64static struct ftrace_ops *ftrace_list __read_mostly = &ftrace_list_end;
65ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
66
Ingo Molnarf2252932008-05-22 10:37:48 +020067static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +020068{
69 struct ftrace_ops *op = ftrace_list;
70
71 /* in case someone actually ports this to alpha! */
72 read_barrier_depends();
73
74 while (op != &ftrace_list_end) {
75 /* silly alpha */
76 read_barrier_depends();
77 op->func(ip, parent_ip);
78 op = op->next;
79 };
80}
81
82/**
Steven Rostedt3d083392008-05-12 21:20:42 +020083 * clear_ftrace_function - reset the ftrace function
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +020084 *
Steven Rostedt3d083392008-05-12 21:20:42 +020085 * This NULLs the ftrace function and in essence stops
86 * tracing. There may be lag
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +020087 */
Steven Rostedt3d083392008-05-12 21:20:42 +020088void clear_ftrace_function(void)
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +020089{
Steven Rostedt3d083392008-05-12 21:20:42 +020090 ftrace_trace_function = ftrace_stub;
91}
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +020092
Ingo Molnare309b412008-05-12 21:20:51 +020093static int __register_ftrace_function(struct ftrace_ops *ops)
Steven Rostedt3d083392008-05-12 21:20:42 +020094{
Steven Rostedt99ecdc42008-08-15 21:40:05 -040095 /* should not be called from interrupt context */
Steven Rostedt3d083392008-05-12 21:20:42 +020096 spin_lock(&ftrace_lock);
97
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +020098 ops->next = ftrace_list;
99 /*
100 * We are entering ops into the ftrace_list but another
101 * CPU might be walking that list. We need to make sure
102 * the ops->next pointer is valid before another CPU sees
103 * the ops pointer included into the ftrace_list.
104 */
105 smp_wmb();
106 ftrace_list = ops;
Steven Rostedt3d083392008-05-12 21:20:42 +0200107
Steven Rostedtb0fc4942008-05-12 21:20:43 +0200108 if (ftrace_enabled) {
109 /*
110 * For one func, simply call it directly.
111 * For more than one func, call the chain.
112 */
113 if (ops->next == &ftrace_list_end)
114 ftrace_trace_function = ops->func;
115 else
116 ftrace_trace_function = ftrace_list_func;
117 }
Steven Rostedt3d083392008-05-12 21:20:42 +0200118
119 spin_unlock(&ftrace_lock);
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +0200120
121 return 0;
122}
123
Ingo Molnare309b412008-05-12 21:20:51 +0200124static int __unregister_ftrace_function(struct ftrace_ops *ops)
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +0200125{
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +0200126 struct ftrace_ops **p;
127 int ret = 0;
128
Steven Rostedt99ecdc42008-08-15 21:40:05 -0400129 /* should not be called from interrupt context */
Steven Rostedt3d083392008-05-12 21:20:42 +0200130 spin_lock(&ftrace_lock);
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +0200131
132 /*
Steven Rostedt3d083392008-05-12 21:20:42 +0200133 * If we are removing the last function, then simply point
134 * to the ftrace_stub.
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +0200135 */
136 if (ftrace_list == ops && ops->next == &ftrace_list_end) {
137 ftrace_trace_function = ftrace_stub;
138 ftrace_list = &ftrace_list_end;
139 goto out;
140 }
141
142 for (p = &ftrace_list; *p != &ftrace_list_end; p = &(*p)->next)
143 if (*p == ops)
144 break;
145
146 if (*p != ops) {
147 ret = -1;
148 goto out;
149 }
150
151 *p = (*p)->next;
152
Steven Rostedtb0fc4942008-05-12 21:20:43 +0200153 if (ftrace_enabled) {
154 /* If we only have one func left, then call that directly */
155 if (ftrace_list == &ftrace_list_end ||
156 ftrace_list->next == &ftrace_list_end)
157 ftrace_trace_function = ftrace_list->func;
158 }
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +0200159
160 out:
Steven Rostedt3d083392008-05-12 21:20:42 +0200161 spin_unlock(&ftrace_lock);
162
163 return ret;
164}
165
166#ifdef CONFIG_DYNAMIC_FTRACE
Steven Rostedt99ecdc42008-08-15 21:40:05 -0400167#ifndef CONFIG_FTRACE_MCOUNT_RECORD
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400168# error Dynamic ftrace depends on MCOUNT_RECORD
Steven Rostedt99ecdc42008-08-15 21:40:05 -0400169#endif
170
Steven Noonan71c67d52008-09-20 01:00:37 -0700171/*
172 * Since MCOUNT_ADDR may point to mcount itself, we do not want
173 * to get it confused by reading a reference in the code as we
174 * are parsing on objcopy output of text. Use a variable for
175 * it instead.
176 */
177static unsigned long mcount_addr = MCOUNT_ADDR;
178
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200179enum {
180 FTRACE_ENABLE_CALLS = (1 << 0),
181 FTRACE_DISABLE_CALLS = (1 << 1),
182 FTRACE_UPDATE_TRACE_FUNC = (1 << 2),
183 FTRACE_ENABLE_MCOUNT = (1 << 3),
184 FTRACE_DISABLE_MCOUNT = (1 << 4),
185};
186
Steven Rostedt5072c592008-05-12 21:20:43 +0200187static int ftrace_filtered;
Abhishek Sagarecea6562008-06-21 23:47:53 +0530188static int tracing_on;
Steven Rostedt5072c592008-05-12 21:20:43 +0200189
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400190static LIST_HEAD(ftrace_new_addrs);
Steven Rostedt3d083392008-05-12 21:20:42 +0200191
Steven Rostedt41c52c02008-05-22 11:46:33 -0400192static DEFINE_MUTEX(ftrace_regex_lock);
Steven Rostedt3d083392008-05-12 21:20:42 +0200193
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200194struct ftrace_page {
195 struct ftrace_page *next;
David Milleraa5e5ce2008-05-13 22:06:56 -0700196 unsigned long index;
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200197 struct dyn_ftrace records[];
David Milleraa5e5ce2008-05-13 22:06:56 -0700198};
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200199
200#define ENTRIES_PER_PAGE \
201 ((PAGE_SIZE - sizeof(struct ftrace_page)) / sizeof(struct dyn_ftrace))
202
203/* estimate from running different kernels */
204#define NR_TO_INIT 10000
205
206static struct ftrace_page *ftrace_pages_start;
207static struct ftrace_page *ftrace_pages;
208
Steven Rostedt37ad5082008-05-12 21:20:48 +0200209static struct dyn_ftrace *ftrace_free_records;
210
Abhishek Sagarecea6562008-06-21 23:47:53 +0530211
212#ifdef CONFIG_KPROBES
Ingo Molnarf17845e2008-10-24 12:47:10 +0200213
214static int frozen_record_count;
215
Abhishek Sagarecea6562008-06-21 23:47:53 +0530216static inline void freeze_record(struct dyn_ftrace *rec)
217{
218 if (!(rec->flags & FTRACE_FL_FROZEN)) {
219 rec->flags |= FTRACE_FL_FROZEN;
220 frozen_record_count++;
221 }
222}
223
224static inline void unfreeze_record(struct dyn_ftrace *rec)
225{
226 if (rec->flags & FTRACE_FL_FROZEN) {
227 rec->flags &= ~FTRACE_FL_FROZEN;
228 frozen_record_count--;
229 }
230}
231
232static inline int record_frozen(struct dyn_ftrace *rec)
233{
234 return rec->flags & FTRACE_FL_FROZEN;
235}
236#else
237# define freeze_record(rec) ({ 0; })
238# define unfreeze_record(rec) ({ 0; })
239# define record_frozen(rec) ({ 0; })
240#endif /* CONFIG_KPROBES */
241
Ingo Molnare309b412008-05-12 21:20:51 +0200242static void ftrace_free_rec(struct dyn_ftrace *rec)
Steven Rostedt37ad5082008-05-12 21:20:48 +0200243{
Steven Rostedt37ad5082008-05-12 21:20:48 +0200244 rec->ip = (unsigned long)ftrace_free_records;
245 ftrace_free_records = rec;
246 rec->flags |= FTRACE_FL_FREE;
247}
248
Steven Rostedtfed19392008-08-14 22:47:19 -0400249void ftrace_release(void *start, unsigned long size)
250{
251 struct dyn_ftrace *rec;
252 struct ftrace_page *pg;
253 unsigned long s = (unsigned long)start;
254 unsigned long e = s + size;
255 int i;
256
Steven Rostedt00fd61a2008-08-15 21:40:04 -0400257 if (ftrace_disabled || !start)
Steven Rostedtfed19392008-08-14 22:47:19 -0400258 return;
259
Steven Rostedt99ecdc42008-08-15 21:40:05 -0400260 /* should not be called from interrupt context */
Steven Rostedtfed19392008-08-14 22:47:19 -0400261 spin_lock(&ftrace_lock);
262
263 for (pg = ftrace_pages_start; pg; pg = pg->next) {
264 for (i = 0; i < pg->index; i++) {
265 rec = &pg->records[i];
266
267 if ((rec->ip >= s) && (rec->ip < e))
268 ftrace_free_rec(rec);
269 }
270 }
271 spin_unlock(&ftrace_lock);
Steven Rostedtfed19392008-08-14 22:47:19 -0400272}
273
Ingo Molnare309b412008-05-12 21:20:51 +0200274static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200275{
Steven Rostedt37ad5082008-05-12 21:20:48 +0200276 struct dyn_ftrace *rec;
277
278 /* First check for freed records */
279 if (ftrace_free_records) {
280 rec = ftrace_free_records;
281
Steven Rostedt37ad5082008-05-12 21:20:48 +0200282 if (unlikely(!(rec->flags & FTRACE_FL_FREE))) {
Steven Rostedt69128962008-10-23 09:33:03 -0400283 FTRACE_WARN_ON_ONCE(1);
Steven Rostedt37ad5082008-05-12 21:20:48 +0200284 ftrace_free_records = NULL;
285 return NULL;
286 }
287
288 ftrace_free_records = (void *)rec->ip;
289 memset(rec, 0, sizeof(*rec));
290 return rec;
291 }
292
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200293 if (ftrace_pages->index == ENTRIES_PER_PAGE) {
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400294 if (!ftrace_pages->next) {
295 /* allocate another page */
296 ftrace_pages->next =
297 (void *)get_zeroed_page(GFP_KERNEL);
298 if (!ftrace_pages->next)
299 return NULL;
300 }
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200301 ftrace_pages = ftrace_pages->next;
302 }
303
304 return &ftrace_pages->records[ftrace_pages->index++];
305}
306
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400307static struct dyn_ftrace *
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200308ftrace_record_ip(unsigned long ip)
Steven Rostedt3d083392008-05-12 21:20:42 +0200309{
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400310 struct dyn_ftrace *rec;
Steven Rostedt3d083392008-05-12 21:20:42 +0200311
Steven Rostedt4eebcc82008-05-12 21:20:48 +0200312 if (!ftrace_enabled || ftrace_disabled)
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400313 return NULL;
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200314
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400315 rec = ftrace_alloc_dyn_node(ip);
316 if (!rec)
317 return NULL;
Steven Rostedt3d083392008-05-12 21:20:42 +0200318
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400319 rec->ip = ip;
Steven Rostedt3d083392008-05-12 21:20:42 +0200320
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400321 list_add(&rec->list, &ftrace_new_addrs);
Steven Rostedt3d083392008-05-12 21:20:42 +0200322
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400323 return rec;
Steven Rostedt3d083392008-05-12 21:20:42 +0200324}
325
Steven Rostedtcaf8cde2008-05-12 21:20:50 +0200326#define FTRACE_ADDR ((long)(ftrace_caller))
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200327
Abhishek Sagar0eb96702008-06-01 21:47:30 +0530328static int
Steven Rostedt5072c592008-05-12 21:20:43 +0200329__ftrace_replace_code(struct dyn_ftrace *rec,
330 unsigned char *old, unsigned char *new, int enable)
331{
Steven Rostedt41c52c02008-05-22 11:46:33 -0400332 unsigned long ip, fl;
Steven Rostedt5072c592008-05-12 21:20:43 +0200333
334 ip = rec->ip;
335
336 if (ftrace_filtered && enable) {
Steven Rostedt5072c592008-05-12 21:20:43 +0200337 /*
338 * If filtering is on:
339 *
340 * If this record is set to be filtered and
341 * is enabled then do nothing.
342 *
343 * If this record is set to be filtered and
344 * it is not enabled, enable it.
345 *
346 * If this record is not set to be filtered
347 * and it is not enabled do nothing.
348 *
Steven Rostedt41c52c02008-05-22 11:46:33 -0400349 * If this record is set not to trace then
350 * do nothing.
351 *
Abhishek Sagara4500b82008-06-14 11:59:39 +0530352 * If this record is set not to trace and
353 * it is enabled then disable it.
354 *
Steven Rostedt5072c592008-05-12 21:20:43 +0200355 * If this record is not set to be filtered and
356 * it is enabled, disable it.
357 */
Abhishek Sagara4500b82008-06-14 11:59:39 +0530358
359 fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE |
360 FTRACE_FL_ENABLED);
Steven Rostedt5072c592008-05-12 21:20:43 +0200361
362 if ((fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) ||
Abhishek Sagara4500b82008-06-14 11:59:39 +0530363 (fl == (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE)) ||
364 !fl || (fl == FTRACE_FL_NOTRACE))
Abhishek Sagar0eb96702008-06-01 21:47:30 +0530365 return 0;
Steven Rostedt5072c592008-05-12 21:20:43 +0200366
367 /*
368 * If it is enabled disable it,
369 * otherwise enable it!
370 */
Abhishek Sagara4500b82008-06-14 11:59:39 +0530371 if (fl & FTRACE_FL_ENABLED) {
Steven Rostedt5072c592008-05-12 21:20:43 +0200372 /* swap new and old */
373 new = old;
374 old = ftrace_call_replace(ip, FTRACE_ADDR);
375 rec->flags &= ~FTRACE_FL_ENABLED;
376 } else {
377 new = ftrace_call_replace(ip, FTRACE_ADDR);
378 rec->flags |= FTRACE_FL_ENABLED;
379 }
380 } else {
381
Steven Rostedt41c52c02008-05-22 11:46:33 -0400382 if (enable) {
383 /*
384 * If this record is set not to trace and is
385 * not enabled, do nothing.
386 */
387 fl = rec->flags & (FTRACE_FL_NOTRACE | FTRACE_FL_ENABLED);
388 if (fl == FTRACE_FL_NOTRACE)
Abhishek Sagar0eb96702008-06-01 21:47:30 +0530389 return 0;
Steven Rostedt41c52c02008-05-22 11:46:33 -0400390
Steven Rostedt5072c592008-05-12 21:20:43 +0200391 new = ftrace_call_replace(ip, FTRACE_ADDR);
Steven Rostedt41c52c02008-05-22 11:46:33 -0400392 } else
Steven Rostedt5072c592008-05-12 21:20:43 +0200393 old = ftrace_call_replace(ip, FTRACE_ADDR);
394
395 if (enable) {
396 if (rec->flags & FTRACE_FL_ENABLED)
Abhishek Sagar0eb96702008-06-01 21:47:30 +0530397 return 0;
Steven Rostedt5072c592008-05-12 21:20:43 +0200398 rec->flags |= FTRACE_FL_ENABLED;
399 } else {
400 if (!(rec->flags & FTRACE_FL_ENABLED))
Abhishek Sagar0eb96702008-06-01 21:47:30 +0530401 return 0;
Steven Rostedt5072c592008-05-12 21:20:43 +0200402 rec->flags &= ~FTRACE_FL_ENABLED;
403 }
404 }
405
Abhishek Sagar0eb96702008-06-01 21:47:30 +0530406 return ftrace_modify_code(ip, old, new);
Steven Rostedt5072c592008-05-12 21:20:43 +0200407}
408
Ingo Molnare309b412008-05-12 21:20:51 +0200409static void ftrace_replace_code(int enable)
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200410{
Abhishek Sagar0eb96702008-06-01 21:47:30 +0530411 int i, failed;
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200412 unsigned char *new = NULL, *old = NULL;
413 struct dyn_ftrace *rec;
414 struct ftrace_page *pg;
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200415
Steven Rostedt5072c592008-05-12 21:20:43 +0200416 if (enable)
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200417 old = ftrace_nop_replace();
418 else
419 new = ftrace_nop_replace();
420
421 for (pg = ftrace_pages_start; pg; pg = pg->next) {
422 for (i = 0; i < pg->index; i++) {
423 rec = &pg->records[i];
424
425 /* don't modify code that has already faulted */
426 if (rec->flags & FTRACE_FL_FAILED)
427 continue;
428
Abhishek Sagarf22f9a82008-06-21 23:50:29 +0530429 /* ignore updates to this record's mcount site */
Abhishek Sagar98a05ed2008-06-26 22:51:51 +0530430 if (get_kprobe((void *)rec->ip)) {
431 freeze_record(rec);
Abhishek Sagarf22f9a82008-06-21 23:50:29 +0530432 continue;
Abhishek Sagar98a05ed2008-06-26 22:51:51 +0530433 } else {
434 unfreeze_record(rec);
435 }
Abhishek Sagarf22f9a82008-06-21 23:50:29 +0530436
Abhishek Sagar0eb96702008-06-01 21:47:30 +0530437 failed = __ftrace_replace_code(rec, old, new, enable);
438 if (failed && (rec->flags & FTRACE_FL_CONVERTED)) {
439 rec->flags |= FTRACE_FL_FAILED;
440 if ((system_state == SYSTEM_BOOTING) ||
Abhishek Sagar34078a52008-06-03 08:33:41 +0530441 !core_kernel_text(rec->ip)) {
Abhishek Sagar0eb96702008-06-01 21:47:30 +0530442 ftrace_free_rec(rec);
443 }
444 }
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200445 }
446 }
447}
448
Steven Rostedt05736a42008-09-22 14:55:47 -0700449static void print_ip_ins(const char *fmt, unsigned char *p)
450{
451 int i;
452
453 printk(KERN_CONT "%s", fmt);
454
455 for (i = 0; i < MCOUNT_INSN_SIZE; i++)
456 printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
457}
458
Abhishek Sagar492a7ea2008-05-25 00:10:04 +0530459static int
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200460ftrace_code_disable(struct dyn_ftrace *rec)
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200461{
462 unsigned long ip;
463 unsigned char *nop, *call;
Steven Rostedt593eb8a2008-10-23 09:32:59 -0400464 int ret;
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200465
466 ip = rec->ip;
467
468 nop = ftrace_nop_replace();
Steven Rostedt3b47bfc2008-08-27 23:24:15 -0400469 call = ftrace_call_replace(ip, mcount_addr);
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200470
Steven Rostedt593eb8a2008-10-23 09:32:59 -0400471 ret = ftrace_modify_code(ip, call, nop);
472 if (ret) {
473 switch (ret) {
474 case -EFAULT:
Steven Rostedt69128962008-10-23 09:33:03 -0400475 FTRACE_WARN_ON_ONCE(1);
Steven Rostedt05736a42008-09-22 14:55:47 -0700476 pr_info("ftrace faulted on modifying ");
477 print_ip_sym(ip);
478 break;
Steven Rostedt593eb8a2008-10-23 09:32:59 -0400479 case -EINVAL:
Steven Rostedt69128962008-10-23 09:33:03 -0400480 FTRACE_WARN_ON_ONCE(1);
Steven Rostedt05736a42008-09-22 14:55:47 -0700481 pr_info("ftrace failed to modify ");
482 print_ip_sym(ip);
483 print_ip_ins(" expected: ", call);
484 print_ip_ins(" actual: ", (unsigned char *)ip);
485 print_ip_ins(" replace: ", nop);
486 printk(KERN_CONT "\n");
487 break;
Steven Rostedt593eb8a2008-10-23 09:32:59 -0400488 case -EPERM:
Steven Rostedt69128962008-10-23 09:33:03 -0400489 FTRACE_WARN_ON_ONCE(1);
Steven Rostedt593eb8a2008-10-23 09:32:59 -0400490 pr_info("ftrace faulted on writing ");
491 print_ip_sym(ip);
492 break;
493 default:
Steven Rostedt69128962008-10-23 09:33:03 -0400494 FTRACE_WARN_ON_ONCE(1);
Steven Rostedt593eb8a2008-10-23 09:32:59 -0400495 pr_info("ftrace faulted on unknown error ");
496 print_ip_sym(ip);
Steven Rostedt05736a42008-09-22 14:55:47 -0700497 }
498
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200499 rec->flags |= FTRACE_FL_FAILED;
Abhishek Sagar492a7ea2008-05-25 00:10:04 +0530500 return 0;
Steven Rostedt37ad5082008-05-12 21:20:48 +0200501 }
Abhishek Sagar492a7ea2008-05-25 00:10:04 +0530502 return 1;
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200503}
504
Ingo Molnare309b412008-05-12 21:20:51 +0200505static int __ftrace_modify_code(void *data)
Steven Rostedt3d083392008-05-12 21:20:42 +0200506{
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200507 int *command = data;
508
Steven Rostedtad90c0e2008-05-27 20:48:37 -0400509 if (*command & FTRACE_ENABLE_CALLS) {
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200510 ftrace_replace_code(1);
Abhishek Sagarecea6562008-06-21 23:47:53 +0530511 tracing_on = 1;
512 } else if (*command & FTRACE_DISABLE_CALLS) {
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200513 ftrace_replace_code(0);
Abhishek Sagarecea6562008-06-21 23:47:53 +0530514 tracing_on = 0;
515 }
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200516
517 if (*command & FTRACE_UPDATE_TRACE_FUNC)
518 ftrace_update_ftrace_func(ftrace_trace_function);
519
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200520 return 0;
Steven Rostedt3d083392008-05-12 21:20:42 +0200521}
522
Ingo Molnare309b412008-05-12 21:20:51 +0200523static void ftrace_run_update_code(int command)
Steven Rostedt3d083392008-05-12 21:20:42 +0200524{
Rusty Russell784e2d72008-07-28 12:16:31 -0500525 stop_machine(__ftrace_modify_code, &command, NULL);
Steven Rostedt3d083392008-05-12 21:20:42 +0200526}
527
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200528static ftrace_func_t saved_ftrace_func;
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400529static int ftrace_start;
530static DEFINE_MUTEX(ftrace_start_lock);
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200531
Ingo Molnare309b412008-05-12 21:20:51 +0200532static void ftrace_startup(void)
Steven Rostedt3d083392008-05-12 21:20:42 +0200533{
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200534 int command = 0;
535
Steven Rostedt4eebcc82008-05-12 21:20:48 +0200536 if (unlikely(ftrace_disabled))
537 return;
538
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400539 mutex_lock(&ftrace_start_lock);
540 ftrace_start++;
541 if (ftrace_start == 1)
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200542 command |= FTRACE_ENABLE_CALLS;
Steven Rostedt3d083392008-05-12 21:20:42 +0200543
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200544 if (saved_ftrace_func != ftrace_trace_function) {
545 saved_ftrace_func = ftrace_trace_function;
546 command |= FTRACE_UPDATE_TRACE_FUNC;
547 }
548
549 if (!command || !ftrace_enabled)
550 goto out;
551
552 ftrace_run_update_code(command);
Steven Rostedt3d083392008-05-12 21:20:42 +0200553 out:
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400554 mutex_unlock(&ftrace_start_lock);
Steven Rostedt3d083392008-05-12 21:20:42 +0200555}
556
Ingo Molnare309b412008-05-12 21:20:51 +0200557static void ftrace_shutdown(void)
Steven Rostedt3d083392008-05-12 21:20:42 +0200558{
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200559 int command = 0;
560
Steven Rostedt4eebcc82008-05-12 21:20:48 +0200561 if (unlikely(ftrace_disabled))
562 return;
563
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400564 mutex_lock(&ftrace_start_lock);
565 ftrace_start--;
566 if (!ftrace_start)
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200567 command |= FTRACE_DISABLE_CALLS;
568
569 if (saved_ftrace_func != ftrace_trace_function) {
570 saved_ftrace_func = ftrace_trace_function;
571 command |= FTRACE_UPDATE_TRACE_FUNC;
572 }
573
574 if (!command || !ftrace_enabled)
Steven Rostedt3d083392008-05-12 21:20:42 +0200575 goto out;
576
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200577 ftrace_run_update_code(command);
Steven Rostedt3d083392008-05-12 21:20:42 +0200578 out:
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400579 mutex_unlock(&ftrace_start_lock);
Steven Rostedt3d083392008-05-12 21:20:42 +0200580}
581
Ingo Molnare309b412008-05-12 21:20:51 +0200582static void ftrace_startup_sysctl(void)
Steven Rostedtb0fc4942008-05-12 21:20:43 +0200583{
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200584 int command = FTRACE_ENABLE_MCOUNT;
585
Steven Rostedt4eebcc82008-05-12 21:20:48 +0200586 if (unlikely(ftrace_disabled))
587 return;
588
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400589 mutex_lock(&ftrace_start_lock);
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200590 /* Force update next time */
591 saved_ftrace_func = NULL;
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400592 /* ftrace_start is true if we want ftrace running */
593 if (ftrace_start)
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200594 command |= FTRACE_ENABLE_CALLS;
595
596 ftrace_run_update_code(command);
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400597 mutex_unlock(&ftrace_start_lock);
Steven Rostedtb0fc4942008-05-12 21:20:43 +0200598}
599
Ingo Molnare309b412008-05-12 21:20:51 +0200600static void ftrace_shutdown_sysctl(void)
Steven Rostedtb0fc4942008-05-12 21:20:43 +0200601{
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200602 int command = FTRACE_DISABLE_MCOUNT;
603
Steven Rostedt4eebcc82008-05-12 21:20:48 +0200604 if (unlikely(ftrace_disabled))
605 return;
606
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400607 mutex_lock(&ftrace_start_lock);
608 /* ftrace_start is true if ftrace is running */
609 if (ftrace_start)
Steven Rostedtd61f82d2008-05-12 21:20:43 +0200610 command |= FTRACE_DISABLE_CALLS;
611
612 ftrace_run_update_code(command);
Steven Rostedtcb7be3b2008-10-23 09:33:05 -0400613 mutex_unlock(&ftrace_start_lock);
Steven Rostedtb0fc4942008-05-12 21:20:43 +0200614}
615
Steven Rostedt3d083392008-05-12 21:20:42 +0200616static cycle_t ftrace_update_time;
617static unsigned long ftrace_update_cnt;
618unsigned long ftrace_update_tot_cnt;
619
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400620static int ftrace_update_code(void)
Steven Rostedt3d083392008-05-12 21:20:42 +0200621{
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400622 struct dyn_ftrace *p, *t;
Abhishek Sagarf22f9a82008-06-21 23:50:29 +0530623 cycle_t start, stop;
Steven Rostedt3d083392008-05-12 21:20:42 +0200624
Ingo Molnar750ed1a2008-05-12 21:20:46 +0200625 start = ftrace_now(raw_smp_processor_id());
Steven Rostedt3d083392008-05-12 21:20:42 +0200626 ftrace_update_cnt = 0;
627
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400628 list_for_each_entry_safe(p, t, &ftrace_new_addrs, list) {
Abhishek Sagarf22f9a82008-06-21 23:50:29 +0530629
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400630 /* If something went wrong, bail without enabling anything */
631 if (unlikely(ftrace_disabled))
632 return -1;
Steven Rostedt3d083392008-05-12 21:20:42 +0200633
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400634 list_del_init(&p->list);
Abhishek Sagar0eb96702008-06-01 21:47:30 +0530635
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400636 /* convert record (i.e, patch mcount-call with NOP) */
637 if (ftrace_code_disable(p)) {
638 p->flags |= FTRACE_FL_CONVERTED;
639 ftrace_update_cnt++;
640 } else
641 ftrace_free_rec(p);
Steven Rostedt3d083392008-05-12 21:20:42 +0200642 }
643
Ingo Molnar750ed1a2008-05-12 21:20:46 +0200644 stop = ftrace_now(raw_smp_processor_id());
Steven Rostedt3d083392008-05-12 21:20:42 +0200645 ftrace_update_time = stop - start;
646 ftrace_update_tot_cnt += ftrace_update_cnt;
647
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +0200648 return 0;
649}
650
Steven Rostedt68bf21a2008-08-14 15:45:08 -0400651static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200652{
653 struct ftrace_page *pg;
654 int cnt;
655 int i;
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200656
657 /* allocate a few pages */
658 ftrace_pages_start = (void *)get_zeroed_page(GFP_KERNEL);
659 if (!ftrace_pages_start)
660 return -1;
661
662 /*
663 * Allocate a few more pages.
664 *
665 * TODO: have some parser search vmlinux before
666 * final linking to find all calls to ftrace.
667 * Then we can:
668 * a) know how many pages to allocate.
669 * and/or
670 * b) set up the table then.
671 *
672 * The dynamic code is still necessary for
673 * modules.
674 */
675
676 pg = ftrace_pages = ftrace_pages_start;
677
Steven Rostedt68bf21a2008-08-14 15:45:08 -0400678 cnt = num_to_init / ENTRIES_PER_PAGE;
Steven Rostedt08f5ac902008-10-23 09:33:07 -0400679 pr_info("ftrace: allocating %ld entries in %d pages\n",
Steven Rostedt68bf21a2008-08-14 15:45:08 -0400680 num_to_init, cnt);
Steven Rostedt3c1720f2008-05-12 21:20:43 +0200681
682 for (i = 0; i < cnt; i++) {
683 pg->next = (void *)get_zeroed_page(GFP_KERNEL);
684
685 /* If we fail, we'll try later anyway */
686 if (!pg->next)
687 break;
688
689 pg = pg->next;
690 }
691
692 return 0;
693}
694
Steven Rostedt5072c592008-05-12 21:20:43 +0200695enum {
696 FTRACE_ITER_FILTER = (1 << 0),
697 FTRACE_ITER_CONT = (1 << 1),
Steven Rostedt41c52c02008-05-22 11:46:33 -0400698 FTRACE_ITER_NOTRACE = (1 << 2),
Abhishek Sagareb9a7bf2008-06-01 21:47:54 +0530699 FTRACE_ITER_FAILURES = (1 << 3),
Steven Rostedt5072c592008-05-12 21:20:43 +0200700};
701
702#define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
703
704struct ftrace_iterator {
705 loff_t pos;
706 struct ftrace_page *pg;
707 unsigned idx;
708 unsigned flags;
709 unsigned char buffer[FTRACE_BUFF_MAX+1];
710 unsigned buffer_idx;
711 unsigned filtered;
712};
713
Ingo Molnare309b412008-05-12 21:20:51 +0200714static void *
Steven Rostedt5072c592008-05-12 21:20:43 +0200715t_next(struct seq_file *m, void *v, loff_t *pos)
716{
717 struct ftrace_iterator *iter = m->private;
718 struct dyn_ftrace *rec = NULL;
719
720 (*pos)++;
721
Steven Rostedt99ecdc42008-08-15 21:40:05 -0400722 /* should not be called from interrupt context */
723 spin_lock(&ftrace_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +0200724 retry:
725 if (iter->idx >= iter->pg->index) {
726 if (iter->pg->next) {
727 iter->pg = iter->pg->next;
728 iter->idx = 0;
729 goto retry;
730 }
731 } else {
732 rec = &iter->pg->records[iter->idx++];
Steven Rostedta9fdda32008-08-14 22:47:17 -0400733 if ((rec->flags & FTRACE_FL_FREE) ||
734
735 (!(iter->flags & FTRACE_ITER_FAILURES) &&
Abhishek Sagareb9a7bf2008-06-01 21:47:54 +0530736 (rec->flags & FTRACE_FL_FAILED)) ||
737
738 ((iter->flags & FTRACE_ITER_FAILURES) &&
Steven Rostedta9fdda32008-08-14 22:47:17 -0400739 !(rec->flags & FTRACE_FL_FAILED)) ||
Abhishek Sagareb9a7bf2008-06-01 21:47:54 +0530740
Steven Rostedtf10ed362008-11-07 22:36:02 -0500741 ((iter->flags & FTRACE_ITER_FILTER) &&
742 !(rec->flags & FTRACE_FL_FILTER)) ||
743
Steven Rostedt41c52c02008-05-22 11:46:33 -0400744 ((iter->flags & FTRACE_ITER_NOTRACE) &&
745 !(rec->flags & FTRACE_FL_NOTRACE))) {
Steven Rostedt5072c592008-05-12 21:20:43 +0200746 rec = NULL;
747 goto retry;
748 }
749 }
Steven Rostedt99ecdc42008-08-15 21:40:05 -0400750 spin_unlock(&ftrace_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +0200751
752 iter->pos = *pos;
753
754 return rec;
755}
756
757static void *t_start(struct seq_file *m, loff_t *pos)
758{
759 struct ftrace_iterator *iter = m->private;
760 void *p = NULL;
761 loff_t l = -1;
762
763 if (*pos != iter->pos) {
764 for (p = t_next(m, p, &l); p && l < *pos; p = t_next(m, p, &l))
765 ;
766 } else {
767 l = *pos;
768 p = t_next(m, p, &l);
769 }
770
771 return p;
772}
773
774static void t_stop(struct seq_file *m, void *p)
775{
776}
777
778static int t_show(struct seq_file *m, void *v)
779{
780 struct dyn_ftrace *rec = v;
781 char str[KSYM_SYMBOL_LEN];
782
783 if (!rec)
784 return 0;
785
786 kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
787
788 seq_printf(m, "%s\n", str);
789
790 return 0;
791}
792
793static struct seq_operations show_ftrace_seq_ops = {
794 .start = t_start,
795 .next = t_next,
796 .stop = t_stop,
797 .show = t_show,
798};
799
Ingo Molnare309b412008-05-12 21:20:51 +0200800static int
Steven Rostedt5072c592008-05-12 21:20:43 +0200801ftrace_avail_open(struct inode *inode, struct file *file)
802{
803 struct ftrace_iterator *iter;
804 int ret;
805
Steven Rostedt4eebcc82008-05-12 21:20:48 +0200806 if (unlikely(ftrace_disabled))
807 return -ENODEV;
808
Steven Rostedt5072c592008-05-12 21:20:43 +0200809 iter = kzalloc(sizeof(*iter), GFP_KERNEL);
810 if (!iter)
811 return -ENOMEM;
812
813 iter->pg = ftrace_pages_start;
814 iter->pos = -1;
815
816 ret = seq_open(file, &show_ftrace_seq_ops);
817 if (!ret) {
818 struct seq_file *m = file->private_data;
Ingo Molnar4bf39a92008-05-12 21:20:46 +0200819
Steven Rostedt5072c592008-05-12 21:20:43 +0200820 m->private = iter;
Ingo Molnar4bf39a92008-05-12 21:20:46 +0200821 } else {
Steven Rostedt5072c592008-05-12 21:20:43 +0200822 kfree(iter);
Ingo Molnar4bf39a92008-05-12 21:20:46 +0200823 }
Steven Rostedt5072c592008-05-12 21:20:43 +0200824
825 return ret;
826}
827
828int ftrace_avail_release(struct inode *inode, struct file *file)
829{
830 struct seq_file *m = (struct seq_file *)file->private_data;
831 struct ftrace_iterator *iter = m->private;
832
833 seq_release(inode, file);
834 kfree(iter);
Ingo Molnar4bf39a92008-05-12 21:20:46 +0200835
Steven Rostedt5072c592008-05-12 21:20:43 +0200836 return 0;
837}
838
Abhishek Sagareb9a7bf2008-06-01 21:47:54 +0530839static int
840ftrace_failures_open(struct inode *inode, struct file *file)
841{
842 int ret;
843 struct seq_file *m;
844 struct ftrace_iterator *iter;
845
846 ret = ftrace_avail_open(inode, file);
847 if (!ret) {
848 m = (struct seq_file *)file->private_data;
849 iter = (struct ftrace_iterator *)m->private;
850 iter->flags = FTRACE_ITER_FAILURES;
851 }
852
853 return ret;
854}
855
856
Steven Rostedt41c52c02008-05-22 11:46:33 -0400857static void ftrace_filter_reset(int enable)
Steven Rostedt5072c592008-05-12 21:20:43 +0200858{
859 struct ftrace_page *pg;
860 struct dyn_ftrace *rec;
Steven Rostedt41c52c02008-05-22 11:46:33 -0400861 unsigned long type = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
Steven Rostedt5072c592008-05-12 21:20:43 +0200862 unsigned i;
863
Steven Rostedt99ecdc42008-08-15 21:40:05 -0400864 /* should not be called from interrupt context */
865 spin_lock(&ftrace_lock);
Steven Rostedt41c52c02008-05-22 11:46:33 -0400866 if (enable)
867 ftrace_filtered = 0;
Steven Rostedt5072c592008-05-12 21:20:43 +0200868 pg = ftrace_pages_start;
869 while (pg) {
870 for (i = 0; i < pg->index; i++) {
871 rec = &pg->records[i];
872 if (rec->flags & FTRACE_FL_FAILED)
873 continue;
Steven Rostedt41c52c02008-05-22 11:46:33 -0400874 rec->flags &= ~type;
Steven Rostedt5072c592008-05-12 21:20:43 +0200875 }
876 pg = pg->next;
877 }
Steven Rostedt99ecdc42008-08-15 21:40:05 -0400878 spin_unlock(&ftrace_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +0200879}
880
Ingo Molnare309b412008-05-12 21:20:51 +0200881static int
Steven Rostedt41c52c02008-05-22 11:46:33 -0400882ftrace_regex_open(struct inode *inode, struct file *file, int enable)
Steven Rostedt5072c592008-05-12 21:20:43 +0200883{
884 struct ftrace_iterator *iter;
885 int ret = 0;
886
Steven Rostedt4eebcc82008-05-12 21:20:48 +0200887 if (unlikely(ftrace_disabled))
888 return -ENODEV;
889
Steven Rostedt5072c592008-05-12 21:20:43 +0200890 iter = kzalloc(sizeof(*iter), GFP_KERNEL);
891 if (!iter)
892 return -ENOMEM;
893
Steven Rostedt41c52c02008-05-22 11:46:33 -0400894 mutex_lock(&ftrace_regex_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +0200895 if ((file->f_mode & FMODE_WRITE) &&
896 !(file->f_flags & O_APPEND))
Steven Rostedt41c52c02008-05-22 11:46:33 -0400897 ftrace_filter_reset(enable);
Steven Rostedt5072c592008-05-12 21:20:43 +0200898
899 if (file->f_mode & FMODE_READ) {
900 iter->pg = ftrace_pages_start;
901 iter->pos = -1;
Steven Rostedt41c52c02008-05-22 11:46:33 -0400902 iter->flags = enable ? FTRACE_ITER_FILTER :
903 FTRACE_ITER_NOTRACE;
Steven Rostedt5072c592008-05-12 21:20:43 +0200904
905 ret = seq_open(file, &show_ftrace_seq_ops);
906 if (!ret) {
907 struct seq_file *m = file->private_data;
908 m->private = iter;
909 } else
910 kfree(iter);
911 } else
912 file->private_data = iter;
Steven Rostedt41c52c02008-05-22 11:46:33 -0400913 mutex_unlock(&ftrace_regex_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +0200914
915 return ret;
916}
917
Steven Rostedt41c52c02008-05-22 11:46:33 -0400918static int
919ftrace_filter_open(struct inode *inode, struct file *file)
920{
921 return ftrace_regex_open(inode, file, 1);
922}
923
924static int
925ftrace_notrace_open(struct inode *inode, struct file *file)
926{
927 return ftrace_regex_open(inode, file, 0);
928}
929
Ingo Molnare309b412008-05-12 21:20:51 +0200930static ssize_t
Steven Rostedt41c52c02008-05-22 11:46:33 -0400931ftrace_regex_read(struct file *file, char __user *ubuf,
Steven Rostedt5072c592008-05-12 21:20:43 +0200932 size_t cnt, loff_t *ppos)
933{
934 if (file->f_mode & FMODE_READ)
935 return seq_read(file, ubuf, cnt, ppos);
936 else
937 return -EPERM;
938}
939
Ingo Molnare309b412008-05-12 21:20:51 +0200940static loff_t
Steven Rostedt41c52c02008-05-22 11:46:33 -0400941ftrace_regex_lseek(struct file *file, loff_t offset, int origin)
Steven Rostedt5072c592008-05-12 21:20:43 +0200942{
943 loff_t ret;
944
945 if (file->f_mode & FMODE_READ)
946 ret = seq_lseek(file, offset, origin);
947 else
948 file->f_pos = ret = 1;
949
950 return ret;
951}
952
953enum {
954 MATCH_FULL,
955 MATCH_FRONT_ONLY,
956 MATCH_MIDDLE_ONLY,
957 MATCH_END_ONLY,
958};
959
Ingo Molnare309b412008-05-12 21:20:51 +0200960static void
Steven Rostedt41c52c02008-05-22 11:46:33 -0400961ftrace_match(unsigned char *buff, int len, int enable)
Steven Rostedt5072c592008-05-12 21:20:43 +0200962{
963 char str[KSYM_SYMBOL_LEN];
964 char *search = NULL;
965 struct ftrace_page *pg;
966 struct dyn_ftrace *rec;
967 int type = MATCH_FULL;
Steven Rostedt41c52c02008-05-22 11:46:33 -0400968 unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
Steven Rostedt5072c592008-05-12 21:20:43 +0200969 unsigned i, match = 0, search_len = 0;
970
971 for (i = 0; i < len; i++) {
972 if (buff[i] == '*') {
973 if (!i) {
974 search = buff + i + 1;
975 type = MATCH_END_ONLY;
976 search_len = len - (i + 1);
977 } else {
978 if (type == MATCH_END_ONLY) {
979 type = MATCH_MIDDLE_ONLY;
980 } else {
981 match = i;
982 type = MATCH_FRONT_ONLY;
983 }
984 buff[i] = 0;
985 break;
986 }
987 }
988 }
989
Steven Rostedt99ecdc42008-08-15 21:40:05 -0400990 /* should not be called from interrupt context */
991 spin_lock(&ftrace_lock);
Steven Rostedt41c52c02008-05-22 11:46:33 -0400992 if (enable)
993 ftrace_filtered = 1;
Steven Rostedt5072c592008-05-12 21:20:43 +0200994 pg = ftrace_pages_start;
995 while (pg) {
996 for (i = 0; i < pg->index; i++) {
997 int matched = 0;
998 char *ptr;
999
1000 rec = &pg->records[i];
1001 if (rec->flags & FTRACE_FL_FAILED)
1002 continue;
1003 kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
1004 switch (type) {
1005 case MATCH_FULL:
1006 if (strcmp(str, buff) == 0)
1007 matched = 1;
1008 break;
1009 case MATCH_FRONT_ONLY:
1010 if (memcmp(str, buff, match) == 0)
1011 matched = 1;
1012 break;
1013 case MATCH_MIDDLE_ONLY:
1014 if (strstr(str, search))
1015 matched = 1;
1016 break;
1017 case MATCH_END_ONLY:
1018 ptr = strstr(str, search);
1019 if (ptr && (ptr[search_len] == 0))
1020 matched = 1;
1021 break;
1022 }
1023 if (matched)
Steven Rostedt41c52c02008-05-22 11:46:33 -04001024 rec->flags |= flag;
Steven Rostedt5072c592008-05-12 21:20:43 +02001025 }
1026 pg = pg->next;
1027 }
Steven Rostedt99ecdc42008-08-15 21:40:05 -04001028 spin_unlock(&ftrace_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +02001029}
1030
Ingo Molnare309b412008-05-12 21:20:51 +02001031static ssize_t
Steven Rostedt41c52c02008-05-22 11:46:33 -04001032ftrace_regex_write(struct file *file, const char __user *ubuf,
1033 size_t cnt, loff_t *ppos, int enable)
Steven Rostedt5072c592008-05-12 21:20:43 +02001034{
1035 struct ftrace_iterator *iter;
1036 char ch;
1037 size_t read = 0;
1038 ssize_t ret;
1039
1040 if (!cnt || cnt < 0)
1041 return 0;
1042
Steven Rostedt41c52c02008-05-22 11:46:33 -04001043 mutex_lock(&ftrace_regex_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +02001044
1045 if (file->f_mode & FMODE_READ) {
1046 struct seq_file *m = file->private_data;
1047 iter = m->private;
1048 } else
1049 iter = file->private_data;
1050
1051 if (!*ppos) {
1052 iter->flags &= ~FTRACE_ITER_CONT;
1053 iter->buffer_idx = 0;
1054 }
1055
1056 ret = get_user(ch, ubuf++);
1057 if (ret)
1058 goto out;
1059 read++;
1060 cnt--;
1061
1062 if (!(iter->flags & ~FTRACE_ITER_CONT)) {
1063 /* skip white space */
1064 while (cnt && isspace(ch)) {
1065 ret = get_user(ch, ubuf++);
1066 if (ret)
1067 goto out;
1068 read++;
1069 cnt--;
1070 }
1071
Steven Rostedt5072c592008-05-12 21:20:43 +02001072 if (isspace(ch)) {
1073 file->f_pos += read;
1074 ret = read;
1075 goto out;
1076 }
1077
1078 iter->buffer_idx = 0;
1079 }
1080
1081 while (cnt && !isspace(ch)) {
1082 if (iter->buffer_idx < FTRACE_BUFF_MAX)
1083 iter->buffer[iter->buffer_idx++] = ch;
1084 else {
1085 ret = -EINVAL;
1086 goto out;
1087 }
1088 ret = get_user(ch, ubuf++);
1089 if (ret)
1090 goto out;
1091 read++;
1092 cnt--;
1093 }
1094
1095 if (isspace(ch)) {
1096 iter->filtered++;
1097 iter->buffer[iter->buffer_idx] = 0;
Steven Rostedt41c52c02008-05-22 11:46:33 -04001098 ftrace_match(iter->buffer, iter->buffer_idx, enable);
Steven Rostedt5072c592008-05-12 21:20:43 +02001099 iter->buffer_idx = 0;
1100 } else
1101 iter->flags |= FTRACE_ITER_CONT;
1102
1103
1104 file->f_pos += read;
1105
1106 ret = read;
1107 out:
Steven Rostedt41c52c02008-05-22 11:46:33 -04001108 mutex_unlock(&ftrace_regex_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +02001109
1110 return ret;
1111}
1112
Steven Rostedt41c52c02008-05-22 11:46:33 -04001113static ssize_t
1114ftrace_filter_write(struct file *file, const char __user *ubuf,
1115 size_t cnt, loff_t *ppos)
1116{
1117 return ftrace_regex_write(file, ubuf, cnt, ppos, 1);
1118}
1119
1120static ssize_t
1121ftrace_notrace_write(struct file *file, const char __user *ubuf,
1122 size_t cnt, loff_t *ppos)
1123{
1124 return ftrace_regex_write(file, ubuf, cnt, ppos, 0);
1125}
1126
1127static void
1128ftrace_set_regex(unsigned char *buf, int len, int reset, int enable)
1129{
1130 if (unlikely(ftrace_disabled))
1131 return;
1132
1133 mutex_lock(&ftrace_regex_lock);
1134 if (reset)
1135 ftrace_filter_reset(enable);
1136 if (buf)
1137 ftrace_match(buf, len, enable);
1138 mutex_unlock(&ftrace_regex_lock);
1139}
1140
Steven Rostedt77a2b372008-05-12 21:20:45 +02001141/**
1142 * ftrace_set_filter - set a function to filter on in ftrace
1143 * @buf - the string that holds the function filter text.
1144 * @len - the length of the string.
1145 * @reset - non zero to reset all filters before applying this filter.
1146 *
1147 * Filters denote which functions should be enabled when tracing is enabled.
1148 * If @buf is NULL and reset is set, all functions will be enabled for tracing.
1149 */
Ingo Molnare309b412008-05-12 21:20:51 +02001150void ftrace_set_filter(unsigned char *buf, int len, int reset)
Steven Rostedt77a2b372008-05-12 21:20:45 +02001151{
Steven Rostedt41c52c02008-05-22 11:46:33 -04001152 ftrace_set_regex(buf, len, reset, 1);
1153}
Steven Rostedt4eebcc82008-05-12 21:20:48 +02001154
Steven Rostedt41c52c02008-05-22 11:46:33 -04001155/**
1156 * ftrace_set_notrace - set a function to not trace in ftrace
1157 * @buf - the string that holds the function notrace text.
1158 * @len - the length of the string.
1159 * @reset - non zero to reset all filters before applying this filter.
1160 *
1161 * Notrace Filters denote which functions should not be enabled when tracing
1162 * is enabled. If @buf is NULL and reset is set, all functions will be enabled
1163 * for tracing.
1164 */
1165void ftrace_set_notrace(unsigned char *buf, int len, int reset)
1166{
1167 ftrace_set_regex(buf, len, reset, 0);
Steven Rostedt77a2b372008-05-12 21:20:45 +02001168}
1169
Ingo Molnare309b412008-05-12 21:20:51 +02001170static int
Steven Rostedt41c52c02008-05-22 11:46:33 -04001171ftrace_regex_release(struct inode *inode, struct file *file, int enable)
Steven Rostedt5072c592008-05-12 21:20:43 +02001172{
1173 struct seq_file *m = (struct seq_file *)file->private_data;
1174 struct ftrace_iterator *iter;
1175
Steven Rostedt41c52c02008-05-22 11:46:33 -04001176 mutex_lock(&ftrace_regex_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +02001177 if (file->f_mode & FMODE_READ) {
1178 iter = m->private;
1179
1180 seq_release(inode, file);
1181 } else
1182 iter = file->private_data;
1183
1184 if (iter->buffer_idx) {
1185 iter->filtered++;
1186 iter->buffer[iter->buffer_idx] = 0;
Steven Rostedt41c52c02008-05-22 11:46:33 -04001187 ftrace_match(iter->buffer, iter->buffer_idx, enable);
Steven Rostedt5072c592008-05-12 21:20:43 +02001188 }
1189
1190 mutex_lock(&ftrace_sysctl_lock);
Steven Rostedtcb7be3b2008-10-23 09:33:05 -04001191 mutex_lock(&ftrace_start_lock);
Steven Rostedt82043272008-11-18 23:57:14 -05001192 if (ftrace_start && ftrace_enabled)
Steven Rostedt5072c592008-05-12 21:20:43 +02001193 ftrace_run_update_code(FTRACE_ENABLE_CALLS);
Steven Rostedtcb7be3b2008-10-23 09:33:05 -04001194 mutex_unlock(&ftrace_start_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +02001195 mutex_unlock(&ftrace_sysctl_lock);
1196
1197 kfree(iter);
Steven Rostedt41c52c02008-05-22 11:46:33 -04001198 mutex_unlock(&ftrace_regex_lock);
Steven Rostedt5072c592008-05-12 21:20:43 +02001199 return 0;
1200}
1201
Steven Rostedt41c52c02008-05-22 11:46:33 -04001202static int
1203ftrace_filter_release(struct inode *inode, struct file *file)
1204{
1205 return ftrace_regex_release(inode, file, 1);
1206}
1207
1208static int
1209ftrace_notrace_release(struct inode *inode, struct file *file)
1210{
1211 return ftrace_regex_release(inode, file, 0);
1212}
1213
Steven Rostedt5072c592008-05-12 21:20:43 +02001214static struct file_operations ftrace_avail_fops = {
1215 .open = ftrace_avail_open,
1216 .read = seq_read,
1217 .llseek = seq_lseek,
1218 .release = ftrace_avail_release,
1219};
1220
Abhishek Sagareb9a7bf2008-06-01 21:47:54 +05301221static struct file_operations ftrace_failures_fops = {
1222 .open = ftrace_failures_open,
1223 .read = seq_read,
1224 .llseek = seq_lseek,
1225 .release = ftrace_avail_release,
1226};
1227
Steven Rostedt5072c592008-05-12 21:20:43 +02001228static struct file_operations ftrace_filter_fops = {
1229 .open = ftrace_filter_open,
Steven Rostedt41c52c02008-05-22 11:46:33 -04001230 .read = ftrace_regex_read,
Steven Rostedt5072c592008-05-12 21:20:43 +02001231 .write = ftrace_filter_write,
Steven Rostedt41c52c02008-05-22 11:46:33 -04001232 .llseek = ftrace_regex_lseek,
Steven Rostedt5072c592008-05-12 21:20:43 +02001233 .release = ftrace_filter_release,
1234};
1235
Steven Rostedt41c52c02008-05-22 11:46:33 -04001236static struct file_operations ftrace_notrace_fops = {
1237 .open = ftrace_notrace_open,
1238 .read = ftrace_regex_read,
1239 .write = ftrace_notrace_write,
1240 .llseek = ftrace_regex_lseek,
1241 .release = ftrace_notrace_release,
1242};
1243
Steven Rostedt5072c592008-05-12 21:20:43 +02001244static __init int ftrace_init_debugfs(void)
1245{
1246 struct dentry *d_tracer;
1247 struct dentry *entry;
1248
1249 d_tracer = tracing_init_dentry();
1250
1251 entry = debugfs_create_file("available_filter_functions", 0444,
1252 d_tracer, NULL, &ftrace_avail_fops);
1253 if (!entry)
1254 pr_warning("Could not create debugfs "
1255 "'available_filter_functions' entry\n");
1256
Abhishek Sagareb9a7bf2008-06-01 21:47:54 +05301257 entry = debugfs_create_file("failures", 0444,
1258 d_tracer, NULL, &ftrace_failures_fops);
1259 if (!entry)
1260 pr_warning("Could not create debugfs 'failures' entry\n");
1261
Steven Rostedt5072c592008-05-12 21:20:43 +02001262 entry = debugfs_create_file("set_ftrace_filter", 0644, d_tracer,
1263 NULL, &ftrace_filter_fops);
1264 if (!entry)
1265 pr_warning("Could not create debugfs "
1266 "'set_ftrace_filter' entry\n");
Steven Rostedt41c52c02008-05-22 11:46:33 -04001267
1268 entry = debugfs_create_file("set_ftrace_notrace", 0644, d_tracer,
1269 NULL, &ftrace_notrace_fops);
1270 if (!entry)
1271 pr_warning("Could not create debugfs "
1272 "'set_ftrace_notrace' entry\n");
Steven Rostedtad90c0e2008-05-27 20:48:37 -04001273
Steven Rostedt5072c592008-05-12 21:20:43 +02001274 return 0;
1275}
1276
1277fs_initcall(ftrace_init_debugfs);
1278
Steven Rostedt68bf21a2008-08-14 15:45:08 -04001279static int ftrace_convert_nops(unsigned long *start,
1280 unsigned long *end)
1281{
1282 unsigned long *p;
1283 unsigned long addr;
1284 unsigned long flags;
1285
Steven Rostedt08f5ac902008-10-23 09:33:07 -04001286 mutex_lock(&ftrace_start_lock);
Steven Rostedt68bf21a2008-08-14 15:45:08 -04001287 p = start;
1288 while (p < end) {
1289 addr = ftrace_call_adjust(*p++);
1290 ftrace_record_ip(addr);
Steven Rostedt68bf21a2008-08-14 15:45:08 -04001291 }
1292
Steven Rostedt08f5ac902008-10-23 09:33:07 -04001293 /* disable interrupts to prevent kstop machine */
Steven Rostedt68bf21a2008-08-14 15:45:08 -04001294 local_irq_save(flags);
Steven Rostedt08f5ac902008-10-23 09:33:07 -04001295 ftrace_update_code();
Steven Rostedt68bf21a2008-08-14 15:45:08 -04001296 local_irq_restore(flags);
Steven Rostedt08f5ac902008-10-23 09:33:07 -04001297 mutex_unlock(&ftrace_start_lock);
Steven Rostedt68bf21a2008-08-14 15:45:08 -04001298
1299 return 0;
1300}
1301
Steven Rostedt90d595f2008-08-14 15:45:09 -04001302void ftrace_init_module(unsigned long *start, unsigned long *end)
1303{
Steven Rostedt00fd61a2008-08-15 21:40:04 -04001304 if (ftrace_disabled || start == end)
Steven Rostedtfed19392008-08-14 22:47:19 -04001305 return;
Steven Rostedt90d595f2008-08-14 15:45:09 -04001306 ftrace_convert_nops(start, end);
1307}
1308
Steven Rostedt68bf21a2008-08-14 15:45:08 -04001309extern unsigned long __start_mcount_loc[];
1310extern unsigned long __stop_mcount_loc[];
1311
1312void __init ftrace_init(void)
1313{
1314 unsigned long count, addr, flags;
1315 int ret;
1316
1317 /* Keep the ftrace pointer to the stub */
1318 addr = (unsigned long)ftrace_stub;
1319
1320 local_irq_save(flags);
1321 ftrace_dyn_arch_init(&addr);
1322 local_irq_restore(flags);
1323
1324 /* ftrace_dyn_arch_init places the return code in addr */
1325 if (addr)
1326 goto failed;
1327
1328 count = __stop_mcount_loc - __start_mcount_loc;
1329
1330 ret = ftrace_dyn_table_alloc(count);
1331 if (ret)
1332 goto failed;
1333
1334 last_ftrace_enabled = ftrace_enabled = 1;
1335
1336 ret = ftrace_convert_nops(__start_mcount_loc,
1337 __stop_mcount_loc);
1338
1339 return;
1340 failed:
1341 ftrace_disabled = 1;
1342}
Steven Rostedt68bf21a2008-08-14 15:45:08 -04001343
Steven Rostedt3d083392008-05-12 21:20:42 +02001344#else
Frederic Weisbecker0b6e4d52008-10-28 20:17:38 +01001345
1346static int __init ftrace_nodyn_init(void)
1347{
1348 ftrace_enabled = 1;
1349 return 0;
1350}
1351device_initcall(ftrace_nodyn_init);
1352
Ingo Molnarc7aafc52008-05-12 21:20:45 +02001353# define ftrace_startup() do { } while (0)
1354# define ftrace_shutdown() do { } while (0)
1355# define ftrace_startup_sysctl() do { } while (0)
1356# define ftrace_shutdown_sysctl() do { } while (0)
Steven Rostedt3d083392008-05-12 21:20:42 +02001357#endif /* CONFIG_DYNAMIC_FTRACE */
1358
1359/**
Steven Rostedt81adbdc2008-10-23 09:33:02 -04001360 * ftrace_kill - kill ftrace
Steven Rostedta2bb6a32008-07-10 20:58:15 -04001361 *
1362 * This function should be used by panic code. It stops ftrace
1363 * but in a not so nice way. If you need to simply kill ftrace
1364 * from a non-atomic section, use ftrace_kill.
1365 */
Steven Rostedt81adbdc2008-10-23 09:33:02 -04001366void ftrace_kill(void)
Steven Rostedta2bb6a32008-07-10 20:58:15 -04001367{
1368 ftrace_disabled = 1;
1369 ftrace_enabled = 0;
Steven Rostedta2bb6a32008-07-10 20:58:15 -04001370 clear_ftrace_function();
1371}
1372
1373/**
Steven Rostedt3d083392008-05-12 21:20:42 +02001374 * register_ftrace_function - register a function for profiling
1375 * @ops - ops structure that holds the function for profiling.
1376 *
1377 * Register a function to be called by all functions in the
1378 * kernel.
1379 *
1380 * Note: @ops->func and all the functions it calls must be labeled
1381 * with "notrace", otherwise it will go into a
1382 * recursive loop.
1383 */
1384int register_ftrace_function(struct ftrace_ops *ops)
1385{
Steven Rostedtb0fc4942008-05-12 21:20:43 +02001386 int ret;
1387
Steven Rostedt4eebcc82008-05-12 21:20:48 +02001388 if (unlikely(ftrace_disabled))
1389 return -1;
1390
Steven Rostedtb0fc4942008-05-12 21:20:43 +02001391 mutex_lock(&ftrace_sysctl_lock);
Steven Rostedtb0fc4942008-05-12 21:20:43 +02001392 ret = __register_ftrace_function(ops);
Steven Rostedtd61f82d2008-05-12 21:20:43 +02001393 ftrace_startup();
Steven Rostedtb0fc4942008-05-12 21:20:43 +02001394 mutex_unlock(&ftrace_sysctl_lock);
1395
1396 return ret;
Steven Rostedt3d083392008-05-12 21:20:42 +02001397}
1398
1399/**
1400 * unregister_ftrace_function - unresgister a function for profiling.
1401 * @ops - ops structure that holds the function to unregister
1402 *
1403 * Unregister a function that was added to be called by ftrace profiling.
1404 */
1405int unregister_ftrace_function(struct ftrace_ops *ops)
1406{
1407 int ret;
1408
Steven Rostedtb0fc4942008-05-12 21:20:43 +02001409 mutex_lock(&ftrace_sysctl_lock);
Steven Rostedt3d083392008-05-12 21:20:42 +02001410 ret = __unregister_ftrace_function(ops);
Steven Rostedtd61f82d2008-05-12 21:20:43 +02001411 ftrace_shutdown();
Steven Rostedtb0fc4942008-05-12 21:20:43 +02001412 mutex_unlock(&ftrace_sysctl_lock);
1413
1414 return ret;
1415}
1416
Ingo Molnare309b412008-05-12 21:20:51 +02001417int
Steven Rostedtb0fc4942008-05-12 21:20:43 +02001418ftrace_enable_sysctl(struct ctl_table *table, int write,
Steven Rostedt5072c592008-05-12 21:20:43 +02001419 struct file *file, void __user *buffer, size_t *lenp,
Steven Rostedtb0fc4942008-05-12 21:20:43 +02001420 loff_t *ppos)
1421{
1422 int ret;
1423
Steven Rostedt4eebcc82008-05-12 21:20:48 +02001424 if (unlikely(ftrace_disabled))
1425 return -ENODEV;
1426
Steven Rostedtb0fc4942008-05-12 21:20:43 +02001427 mutex_lock(&ftrace_sysctl_lock);
1428
Steven Rostedt5072c592008-05-12 21:20:43 +02001429 ret = proc_dointvec(table, write, file, buffer, lenp, ppos);
Steven Rostedtb0fc4942008-05-12 21:20:43 +02001430
1431 if (ret || !write || (last_ftrace_enabled == ftrace_enabled))
1432 goto out;
1433
1434 last_ftrace_enabled = ftrace_enabled;
1435
1436 if (ftrace_enabled) {
1437
1438 ftrace_startup_sysctl();
1439
1440 /* we are starting ftrace again */
1441 if (ftrace_list != &ftrace_list_end) {
1442 if (ftrace_list->next == &ftrace_list_end)
1443 ftrace_trace_function = ftrace_list->func;
1444 else
1445 ftrace_trace_function = ftrace_list_func;
1446 }
1447
1448 } else {
1449 /* stopping ftrace calls (just send to ftrace_stub) */
1450 ftrace_trace_function = ftrace_stub;
1451
1452 ftrace_shutdown_sysctl();
1453 }
1454
1455 out:
1456 mutex_unlock(&ftrace_sysctl_lock);
Steven Rostedt3d083392008-05-12 21:20:42 +02001457 return ret;
Arnaldo Carvalho de Melo16444a82008-05-12 21:20:42 +02001458}
Ingo Molnarf17845e2008-10-24 12:47:10 +02001459