1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/ring_buffer.h>
14#include <linux/debugfs.h>
15#include <linux/uaccess.h>
16#include <linux/ftrace.h>
17#include <linux/slab.h>
18#include <linux/fs.h>
19
20#include "trace.h"
21
22static void tracing_start_function_trace(struct trace_array *tr);
23static void tracing_stop_function_trace(struct trace_array *tr);
24static void
25function_trace_call(unsigned long ip, unsigned long parent_ip,
26 struct ftrace_ops *op, struct pt_regs *pt_regs);
27static void
28function_stack_trace_call(unsigned long ip, unsigned long parent_ip,
29 struct ftrace_ops *op, struct pt_regs *pt_regs);
30static struct tracer_flags func_flags;
31
32
33enum {
34 TRACE_FUNC_OPT_STACK = 0x1,
35};
36
37static int allocate_ftrace_ops(struct trace_array *tr)
38{
39 struct ftrace_ops *ops;
40
41 ops = kzalloc(sizeof(*ops), GFP_KERNEL);
42 if (!ops)
43 return -ENOMEM;
44
45
46 ops->func = function_trace_call;
47 ops->flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_PID;
48
49 tr->ops = ops;
50 ops->private = tr;
51 return 0;
52}
53
54
55int ftrace_create_function_files(struct trace_array *tr,
56 struct dentry *parent)
57{
58 int ret;
59
60
61
62
63
64 if (tr->flags & TRACE_ARRAY_FL_GLOBAL)
65 return 0;
66
67 ret = allocate_ftrace_ops(tr);
68 if (ret)
69 return ret;
70
71 ftrace_create_filter_files(tr->ops, parent);
72
73 return 0;
74}
75
76void ftrace_destroy_function_files(struct trace_array *tr)
77{
78 ftrace_destroy_filter_files(tr->ops);
79 kfree(tr->ops);
80 tr->ops = NULL;
81}
82
83static int function_trace_init(struct trace_array *tr)
84{
85 ftrace_func_t func;
86
87
88
89
90
91
92 if (!tr->ops)
93 return -ENOMEM;
94
95
96 if (tr->flags & TRACE_ARRAY_FL_GLOBAL &&
97 func_flags.val & TRACE_FUNC_OPT_STACK)
98 func = function_stack_trace_call;
99 else
100 func = function_trace_call;
101
102 ftrace_init_array_ops(tr, func);
103
104 tr->trace_buffer.cpu = get_cpu();
105 put_cpu();
106
107 tracing_start_cmdline_record();
108 tracing_start_function_trace(tr);
109 return 0;
110}
111
112static void function_trace_reset(struct trace_array *tr)
113{
114 tracing_stop_function_trace(tr);
115 tracing_stop_cmdline_record();
116 ftrace_reset_array_ops(tr);
117}
118
119static void function_trace_start(struct trace_array *tr)
120{
121 tracing_reset_online_cpus(&tr->trace_buffer);
122}
123
124static void
125function_trace_call(unsigned long ip, unsigned long parent_ip,
126 struct ftrace_ops *op, struct pt_regs *pt_regs)
127{
128 struct trace_array *tr = op->private;
129 struct trace_array_cpu *data;
130 unsigned long flags;
131 int bit;
132 int cpu;
133 int pc;
134
135 if (unlikely(!tr->function_enabled))
136 return;
137
138 pc = preempt_count();
139 preempt_disable_notrace();
140
141 bit = trace_test_and_set_recursion(TRACE_FTRACE_START, TRACE_FTRACE_MAX);
142 if (bit < 0)
143 goto out;
144
145 cpu = smp_processor_id();
146 data = per_cpu_ptr(tr->trace_buffer.data, cpu);
147 if (!atomic_read(&data->disabled)) {
148 local_save_flags(flags);
149 trace_function(tr, ip, parent_ip, flags, pc);
150 }
151 trace_clear_recursion(bit);
152
153 out:
154 preempt_enable_notrace();
155}
156
157#ifdef CONFIG_UNWINDER_ORC
158
159
160
161
162
163
164#define STACK_SKIP 2
165#else
166
167
168
169
170
171
172#define STACK_SKIP 3
173#endif
174
175static void
176function_stack_trace_call(unsigned long ip, unsigned long parent_ip,
177 struct ftrace_ops *op, struct pt_regs *pt_regs)
178{
179 struct trace_array *tr = op->private;
180 struct trace_array_cpu *data;
181 unsigned long flags;
182 long disabled;
183 int cpu;
184 int pc;
185
186 if (unlikely(!tr->function_enabled))
187 return;
188
189
190
191
192
193 local_irq_save(flags);
194 cpu = raw_smp_processor_id();
195 data = per_cpu_ptr(tr->trace_buffer.data, cpu);
196 disabled = atomic_inc_return(&data->disabled);
197
198 if (likely(disabled == 1)) {
199 pc = preempt_count();
200 trace_function(tr, ip, parent_ip, flags, pc);
201 __trace_stack(tr, flags, STACK_SKIP, pc);
202 }
203
204 atomic_dec(&data->disabled);
205 local_irq_restore(flags);
206}
207
208static struct tracer_opt func_opts[] = {
209#ifdef CONFIG_STACKTRACE
210 { TRACER_OPT(func_stack_trace, TRACE_FUNC_OPT_STACK) },
211#endif
212 { }
213};
214
215static struct tracer_flags func_flags = {
216 .val = 0,
217 .opts = func_opts
218};
219
220static void tracing_start_function_trace(struct trace_array *tr)
221{
222 tr->function_enabled = 0;
223 register_ftrace_function(tr->ops);
224 tr->function_enabled = 1;
225}
226
227static void tracing_stop_function_trace(struct trace_array *tr)
228{
229 tr->function_enabled = 0;
230 unregister_ftrace_function(tr->ops);
231}
232
233static struct tracer function_trace;
234
235static int
236func_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
237{
238 switch (bit) {
239 case TRACE_FUNC_OPT_STACK:
240
241 if (!!set == !!(func_flags.val & TRACE_FUNC_OPT_STACK))
242 break;
243
244
245 if (tr->current_trace != &function_trace)
246 break;
247
248 unregister_ftrace_function(tr->ops);
249
250 if (set) {
251 tr->ops->func = function_stack_trace_call;
252 register_ftrace_function(tr->ops);
253 } else {
254 tr->ops->func = function_trace_call;
255 register_ftrace_function(tr->ops);
256 }
257
258 break;
259 default:
260 return -EINVAL;
261 }
262
263 return 0;
264}
265
266static struct tracer function_trace __tracer_data =
267{
268 .name = "function",
269 .init = function_trace_init,
270 .reset = function_trace_reset,
271 .start = function_trace_start,
272 .flags = &func_flags,
273 .set_flag = func_set_flag,
274 .allow_instances = true,
275#ifdef CONFIG_FTRACE_SELFTEST
276 .selftest = trace_selftest_startup_function,
277#endif
278};
279
280#ifdef CONFIG_DYNAMIC_FTRACE
281static void update_traceon_count(struct ftrace_probe_ops *ops,
282 unsigned long ip,
283 struct trace_array *tr, bool on,
284 void *data)
285{
286 struct ftrace_func_mapper *mapper = data;
287 long *count;
288 long old_count;
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319 count = (long *)ftrace_func_mapper_find_ip(mapper, ip);
320 old_count = *count;
321
322 if (old_count <= 0)
323 return;
324
325
326 smp_rmb();
327
328 if (on == !!tracer_tracing_is_on(tr))
329 return;
330
331 if (on)
332 tracer_tracing_on(tr);
333 else
334 tracer_tracing_off(tr);
335
336
337 smp_wmb();
338
339 *count = old_count - 1;
340}
341
342static void
343ftrace_traceon_count(unsigned long ip, unsigned long parent_ip,
344 struct trace_array *tr, struct ftrace_probe_ops *ops,
345 void *data)
346{
347 update_traceon_count(ops, ip, tr, 1, data);
348}
349
350static void
351ftrace_traceoff_count(unsigned long ip, unsigned long parent_ip,
352 struct trace_array *tr, struct ftrace_probe_ops *ops,
353 void *data)
354{
355 update_traceon_count(ops, ip, tr, 0, data);
356}
357
358static void
359ftrace_traceon(unsigned long ip, unsigned long parent_ip,
360 struct trace_array *tr, struct ftrace_probe_ops *ops,
361 void *data)
362{
363 if (tracer_tracing_is_on(tr))
364 return;
365
366 tracer_tracing_on(tr);
367}
368
369static void
370ftrace_traceoff(unsigned long ip, unsigned long parent_ip,
371 struct trace_array *tr, struct ftrace_probe_ops *ops,
372 void *data)
373{
374 if (!tracer_tracing_is_on(tr))
375 return;
376
377 tracer_tracing_off(tr);
378}
379
380#ifdef CONFIG_UNWINDER_ORC
381
382
383
384
385
386
387
388#define FTRACE_STACK_SKIP 3
389#else
390
391
392
393
394
395
396
397
398
399#define FTRACE_STACK_SKIP 5
400#endif
401
402static __always_inline void trace_stack(struct trace_array *tr)
403{
404 unsigned long flags;
405 int pc;
406
407 local_save_flags(flags);
408 pc = preempt_count();
409
410 __trace_stack(tr, flags, FTRACE_STACK_SKIP, pc);
411}
412
413static void
414ftrace_stacktrace(unsigned long ip, unsigned long parent_ip,
415 struct trace_array *tr, struct ftrace_probe_ops *ops,
416 void *data)
417{
418 trace_stack(tr);
419}
420
421static void
422ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip,
423 struct trace_array *tr, struct ftrace_probe_ops *ops,
424 void *data)
425{
426 struct ftrace_func_mapper *mapper = data;
427 long *count;
428 long old_count;
429 long new_count;
430
431 if (!tracing_is_on())
432 return;
433
434
435 if (!mapper) {
436 trace_stack(tr);
437 return;
438 }
439
440 count = (long *)ftrace_func_mapper_find_ip(mapper, ip);
441
442
443
444
445
446 do {
447 old_count = *count;
448
449 if (!old_count)
450 return;
451
452 new_count = old_count - 1;
453 new_count = cmpxchg(count, old_count, new_count);
454 if (new_count == old_count)
455 trace_stack(tr);
456
457 if (!tracing_is_on())
458 return;
459
460 } while (new_count != old_count);
461}
462
463static int update_count(struct ftrace_probe_ops *ops, unsigned long ip,
464 void *data)
465{
466 struct ftrace_func_mapper *mapper = data;
467 long *count = NULL;
468
469 if (mapper)
470 count = (long *)ftrace_func_mapper_find_ip(mapper, ip);
471
472 if (count) {
473 if (*count <= 0)
474 return 0;
475 (*count)--;
476 }
477
478 return 1;
479}
480
481static void
482ftrace_dump_probe(unsigned long ip, unsigned long parent_ip,
483 struct trace_array *tr, struct ftrace_probe_ops *ops,
484 void *data)
485{
486 if (update_count(ops, ip, data))
487 ftrace_dump(DUMP_ALL);
488}
489
490
491static void
492ftrace_cpudump_probe(unsigned long ip, unsigned long parent_ip,
493 struct trace_array *tr, struct ftrace_probe_ops *ops,
494 void *data)
495{
496 if (update_count(ops, ip, data))
497 ftrace_dump(DUMP_ORIG);
498}
499
500static int
501ftrace_probe_print(const char *name, struct seq_file *m,
502 unsigned long ip, struct ftrace_probe_ops *ops,
503 void *data)
504{
505 struct ftrace_func_mapper *mapper = data;
506 long *count = NULL;
507
508 seq_printf(m, "%ps:%s", (void *)ip, name);
509
510 if (mapper)
511 count = (long *)ftrace_func_mapper_find_ip(mapper, ip);
512
513 if (count)
514 seq_printf(m, ":count=%ld\n", *count);
515 else
516 seq_puts(m, ":unlimited\n");
517
518 return 0;
519}
520
521static int
522ftrace_traceon_print(struct seq_file *m, unsigned long ip,
523 struct ftrace_probe_ops *ops,
524 void *data)
525{
526 return ftrace_probe_print("traceon", m, ip, ops, data);
527}
528
529static int
530ftrace_traceoff_print(struct seq_file *m, unsigned long ip,
531 struct ftrace_probe_ops *ops, void *data)
532{
533 return ftrace_probe_print("traceoff", m, ip, ops, data);
534}
535
536static int
537ftrace_stacktrace_print(struct seq_file *m, unsigned long ip,
538 struct ftrace_probe_ops *ops, void *data)
539{
540 return ftrace_probe_print("stacktrace", m, ip, ops, data);
541}
542
543static int
544ftrace_dump_print(struct seq_file *m, unsigned long ip,
545 struct ftrace_probe_ops *ops, void *data)
546{
547 return ftrace_probe_print("dump", m, ip, ops, data);
548}
549
550static int
551ftrace_cpudump_print(struct seq_file *m, unsigned long ip,
552 struct ftrace_probe_ops *ops, void *data)
553{
554 return ftrace_probe_print("cpudump", m, ip, ops, data);
555}
556
557
558static int
559ftrace_count_init(struct ftrace_probe_ops *ops, struct trace_array *tr,
560 unsigned long ip, void *init_data, void **data)
561{
562 struct ftrace_func_mapper *mapper = *data;
563
564 if (!mapper) {
565 mapper = allocate_ftrace_func_mapper();
566 if (!mapper)
567 return -ENOMEM;
568 *data = mapper;
569 }
570
571 return ftrace_func_mapper_add_ip(mapper, ip, init_data);
572}
573
574static void
575ftrace_count_free(struct ftrace_probe_ops *ops, struct trace_array *tr,
576 unsigned long ip, void *data)
577{
578 struct ftrace_func_mapper *mapper = data;
579
580 if (!ip) {
581 free_ftrace_func_mapper(mapper, NULL);
582 return;
583 }
584
585 ftrace_func_mapper_remove_ip(mapper, ip);
586}
587
588static struct ftrace_probe_ops traceon_count_probe_ops = {
589 .func = ftrace_traceon_count,
590 .print = ftrace_traceon_print,
591 .init = ftrace_count_init,
592 .free = ftrace_count_free,
593};
594
595static struct ftrace_probe_ops traceoff_count_probe_ops = {
596 .func = ftrace_traceoff_count,
597 .print = ftrace_traceoff_print,
598 .init = ftrace_count_init,
599 .free = ftrace_count_free,
600};
601
602static struct ftrace_probe_ops stacktrace_count_probe_ops = {
603 .func = ftrace_stacktrace_count,
604 .print = ftrace_stacktrace_print,
605 .init = ftrace_count_init,
606 .free = ftrace_count_free,
607};
608
609static struct ftrace_probe_ops dump_probe_ops = {
610 .func = ftrace_dump_probe,
611 .print = ftrace_dump_print,
612 .init = ftrace_count_init,
613 .free = ftrace_count_free,
614};
615
616static struct ftrace_probe_ops cpudump_probe_ops = {
617 .func = ftrace_cpudump_probe,
618 .print = ftrace_cpudump_print,
619};
620
621static struct ftrace_probe_ops traceon_probe_ops = {
622 .func = ftrace_traceon,
623 .print = ftrace_traceon_print,
624};
625
626static struct ftrace_probe_ops traceoff_probe_ops = {
627 .func = ftrace_traceoff,
628 .print = ftrace_traceoff_print,
629};
630
631static struct ftrace_probe_ops stacktrace_probe_ops = {
632 .func = ftrace_stacktrace,
633 .print = ftrace_stacktrace_print,
634};
635
636static int
637ftrace_trace_probe_callback(struct trace_array *tr,
638 struct ftrace_probe_ops *ops,
639 struct ftrace_hash *hash, char *glob,
640 char *cmd, char *param, int enable)
641{
642 void *count = (void *)-1;
643 char *number;
644 int ret;
645
646
647 if (!enable)
648 return -EINVAL;
649
650 if (glob[0] == '!')
651 return unregister_ftrace_function_probe_func(glob+1, tr, ops);
652
653 if (!param)
654 goto out_reg;
655
656 number = strsep(¶m, ":");
657
658 if (!strlen(number))
659 goto out_reg;
660
661
662
663
664
665 ret = kstrtoul(number, 0, (unsigned long *)&count);
666 if (ret)
667 return ret;
668
669 out_reg:
670 ret = register_ftrace_function_probe(glob, tr, ops, count);
671
672 return ret < 0 ? ret : 0;
673}
674
675static int
676ftrace_trace_onoff_callback(struct trace_array *tr, struct ftrace_hash *hash,
677 char *glob, char *cmd, char *param, int enable)
678{
679 struct ftrace_probe_ops *ops;
680
681 if (!tr)
682 return -ENODEV;
683
684
685 if (strcmp(cmd, "traceon") == 0)
686 ops = param ? &traceon_count_probe_ops : &traceon_probe_ops;
687 else
688 ops = param ? &traceoff_count_probe_ops : &traceoff_probe_ops;
689
690 return ftrace_trace_probe_callback(tr, ops, hash, glob, cmd,
691 param, enable);
692}
693
694static int
695ftrace_stacktrace_callback(struct trace_array *tr, struct ftrace_hash *hash,
696 char *glob, char *cmd, char *param, int enable)
697{
698 struct ftrace_probe_ops *ops;
699
700 if (!tr)
701 return -ENODEV;
702
703 ops = param ? &stacktrace_count_probe_ops : &stacktrace_probe_ops;
704
705 return ftrace_trace_probe_callback(tr, ops, hash, glob, cmd,
706 param, enable);
707}
708
709static int
710ftrace_dump_callback(struct trace_array *tr, struct ftrace_hash *hash,
711 char *glob, char *cmd, char *param, int enable)
712{
713 struct ftrace_probe_ops *ops;
714
715 if (!tr)
716 return -ENODEV;
717
718 ops = &dump_probe_ops;
719
720
721 return ftrace_trace_probe_callback(tr, ops, hash, glob, cmd,
722 "1", enable);
723}
724
725static int
726ftrace_cpudump_callback(struct trace_array *tr, struct ftrace_hash *hash,
727 char *glob, char *cmd, char *param, int enable)
728{
729 struct ftrace_probe_ops *ops;
730
731 if (!tr)
732 return -ENODEV;
733
734 ops = &cpudump_probe_ops;
735
736
737 return ftrace_trace_probe_callback(tr, ops, hash, glob, cmd,
738 "1", enable);
739}
740
741static struct ftrace_func_command ftrace_traceon_cmd = {
742 .name = "traceon",
743 .func = ftrace_trace_onoff_callback,
744};
745
746static struct ftrace_func_command ftrace_traceoff_cmd = {
747 .name = "traceoff",
748 .func = ftrace_trace_onoff_callback,
749};
750
751static struct ftrace_func_command ftrace_stacktrace_cmd = {
752 .name = "stacktrace",
753 .func = ftrace_stacktrace_callback,
754};
755
756static struct ftrace_func_command ftrace_dump_cmd = {
757 .name = "dump",
758 .func = ftrace_dump_callback,
759};
760
761static struct ftrace_func_command ftrace_cpudump_cmd = {
762 .name = "cpudump",
763 .func = ftrace_cpudump_callback,
764};
765
766static int __init init_func_cmd_traceon(void)
767{
768 int ret;
769
770 ret = register_ftrace_command(&ftrace_traceoff_cmd);
771 if (ret)
772 return ret;
773
774 ret = register_ftrace_command(&ftrace_traceon_cmd);
775 if (ret)
776 goto out_free_traceoff;
777
778 ret = register_ftrace_command(&ftrace_stacktrace_cmd);
779 if (ret)
780 goto out_free_traceon;
781
782 ret = register_ftrace_command(&ftrace_dump_cmd);
783 if (ret)
784 goto out_free_stacktrace;
785
786 ret = register_ftrace_command(&ftrace_cpudump_cmd);
787 if (ret)
788 goto out_free_dump;
789
790 return 0;
791
792 out_free_dump:
793 unregister_ftrace_command(&ftrace_dump_cmd);
794 out_free_stacktrace:
795 unregister_ftrace_command(&ftrace_stacktrace_cmd);
796 out_free_traceon:
797 unregister_ftrace_command(&ftrace_traceon_cmd);
798 out_free_traceoff:
799 unregister_ftrace_command(&ftrace_traceoff_cmd);
800
801 return ret;
802}
803#else
804static inline int init_func_cmd_traceon(void)
805{
806 return 0;
807}
808#endif
809
810__init int init_function_trace(void)
811{
812 init_func_cmd_traceon();
813 return register_tracer(&function_trace);
814}
815