.. | .. |
---|
14 | 14 | #include <linux/uaccess.h> |
---|
15 | 15 | #include <linux/module.h> |
---|
16 | 16 | #include <linux/ftrace.h> |
---|
| 17 | +#include <linux/kprobes.h> |
---|
17 | 18 | |
---|
18 | 19 | #include "trace.h" |
---|
19 | 20 | |
---|
.. | .. |
---|
121 | 122 | if (!irqs_disabled_flags(*flags) && !preempt_count()) |
---|
122 | 123 | return 0; |
---|
123 | 124 | |
---|
124 | | - *data = per_cpu_ptr(tr->trace_buffer.data, cpu); |
---|
| 125 | + *data = per_cpu_ptr(tr->array_buffer.data, cpu); |
---|
125 | 126 | disabled = atomic_inc_return(&(*data)->disabled); |
---|
126 | 127 | |
---|
127 | 128 | if (likely(disabled == 1)) |
---|
.. | .. |
---|
166 | 167 | per_cpu(tracing_cpu, cpu) = 0; |
---|
167 | 168 | |
---|
168 | 169 | tr->max_latency = 0; |
---|
169 | | - tracing_reset_online_cpus(&irqsoff_trace->trace_buffer); |
---|
| 170 | + tracing_reset_online_cpus(&irqsoff_trace->array_buffer); |
---|
170 | 171 | |
---|
171 | 172 | return start_irqsoff_tracer(irqsoff_trace, set); |
---|
172 | 173 | } |
---|
.. | .. |
---|
218 | 219 | atomic_dec(&data->disabled); |
---|
219 | 220 | } |
---|
220 | 221 | |
---|
| 222 | +static struct fgraph_ops fgraph_ops = { |
---|
| 223 | + .entryfunc = &irqsoff_graph_entry, |
---|
| 224 | + .retfunc = &irqsoff_graph_return, |
---|
| 225 | +}; |
---|
| 226 | + |
---|
221 | 227 | static void irqsoff_trace_open(struct trace_iterator *iter) |
---|
222 | 228 | { |
---|
223 | 229 | if (is_graph(iter->tr)) |
---|
.. | .. |
---|
233 | 239 | |
---|
234 | 240 | #define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_CPU | \ |
---|
235 | 241 | TRACE_GRAPH_PRINT_PROC | \ |
---|
236 | | - TRACE_GRAPH_PRINT_ABS_TIME | \ |
---|
| 242 | + TRACE_GRAPH_PRINT_REL_TIME | \ |
---|
237 | 243 | TRACE_GRAPH_PRINT_DURATION) |
---|
238 | 244 | |
---|
239 | 245 | static enum print_line_t irqsoff_print_line(struct trace_iterator *iter) |
---|
.. | .. |
---|
272 | 278 | #else |
---|
273 | 279 | #define __trace_function trace_function |
---|
274 | 280 | |
---|
275 | | -#ifdef CONFIG_FUNCTION_TRACER |
---|
276 | | -static int irqsoff_graph_entry(struct ftrace_graph_ent *trace) |
---|
277 | | -{ |
---|
278 | | - return -1; |
---|
279 | | -} |
---|
280 | | -#endif |
---|
281 | | - |
---|
282 | 281 | static enum print_line_t irqsoff_print_line(struct trace_iterator *iter) |
---|
283 | 282 | { |
---|
284 | 283 | return TRACE_TYPE_UNHANDLED; |
---|
.. | .. |
---|
288 | 287 | static void irqsoff_trace_close(struct trace_iterator *iter) { } |
---|
289 | 288 | |
---|
290 | 289 | #ifdef CONFIG_FUNCTION_TRACER |
---|
291 | | -static void irqsoff_graph_return(struct ftrace_graph_ret *trace) { } |
---|
292 | 290 | static void irqsoff_print_header(struct seq_file *s) |
---|
293 | 291 | { |
---|
294 | 292 | trace_default_header(s); |
---|
.. | .. |
---|
368 | 366 | __trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc); |
---|
369 | 367 | } |
---|
370 | 368 | |
---|
371 | | -static inline void |
---|
| 369 | +static nokprobe_inline void |
---|
372 | 370 | start_critical_timing(unsigned long ip, unsigned long parent_ip, int pc) |
---|
373 | 371 | { |
---|
374 | 372 | int cpu; |
---|
.. | .. |
---|
384 | 382 | if (per_cpu(tracing_cpu, cpu)) |
---|
385 | 383 | return; |
---|
386 | 384 | |
---|
387 | | - data = per_cpu_ptr(tr->trace_buffer.data, cpu); |
---|
| 385 | + data = per_cpu_ptr(tr->array_buffer.data, cpu); |
---|
388 | 386 | |
---|
389 | 387 | if (unlikely(!data) || atomic_read(&data->disabled)) |
---|
390 | 388 | return; |
---|
.. | .. |
---|
404 | 402 | atomic_dec(&data->disabled); |
---|
405 | 403 | } |
---|
406 | 404 | |
---|
407 | | -static inline void |
---|
| 405 | +static nokprobe_inline void |
---|
408 | 406 | stop_critical_timing(unsigned long ip, unsigned long parent_ip, int pc) |
---|
409 | 407 | { |
---|
410 | 408 | int cpu; |
---|
.. | .. |
---|
422 | 420 | if (!tracer_enabled || !tracing_is_enabled()) |
---|
423 | 421 | return; |
---|
424 | 422 | |
---|
425 | | - data = per_cpu_ptr(tr->trace_buffer.data, cpu); |
---|
| 423 | + data = per_cpu_ptr(tr->array_buffer.data, cpu); |
---|
426 | 424 | |
---|
427 | 425 | if (unlikely(!data) || |
---|
428 | 426 | !data->critical_start || atomic_read(&data->disabled)) |
---|
.. | .. |
---|
446 | 444 | start_critical_timing(CALLER_ADDR0, CALLER_ADDR1, pc); |
---|
447 | 445 | } |
---|
448 | 446 | EXPORT_SYMBOL_GPL(start_critical_timings); |
---|
| 447 | +NOKPROBE_SYMBOL(start_critical_timings); |
---|
449 | 448 | |
---|
450 | 449 | void stop_critical_timings(void) |
---|
451 | 450 | { |
---|
.. | .. |
---|
455 | 454 | stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1, pc); |
---|
456 | 455 | } |
---|
457 | 456 | EXPORT_SYMBOL_GPL(stop_critical_timings); |
---|
| 457 | +NOKPROBE_SYMBOL(stop_critical_timings); |
---|
458 | 458 | |
---|
459 | 459 | #ifdef CONFIG_FUNCTION_TRACER |
---|
460 | 460 | static bool function_enabled; |
---|
.. | .. |
---|
468 | 468 | return 0; |
---|
469 | 469 | |
---|
470 | 470 | if (graph) |
---|
471 | | - ret = register_ftrace_graph(&irqsoff_graph_return, |
---|
472 | | - &irqsoff_graph_entry); |
---|
| 471 | + ret = register_ftrace_graph(&fgraph_ops); |
---|
473 | 472 | else |
---|
474 | 473 | ret = register_ftrace_function(tr->ops); |
---|
475 | 474 | |
---|
.. | .. |
---|
485 | 484 | return; |
---|
486 | 485 | |
---|
487 | 486 | if (graph) |
---|
488 | | - unregister_ftrace_graph(); |
---|
| 487 | + unregister_ftrace_graph(&fgraph_ops); |
---|
489 | 488 | else |
---|
490 | 489 | unregister_ftrace_function(tr->ops); |
---|
491 | 490 | |
---|
.. | .. |
---|
563 | 562 | /* non overwrite screws up the latency tracers */ |
---|
564 | 563 | set_tracer_flag(tr, TRACE_ITER_OVERWRITE, 1); |
---|
565 | 564 | set_tracer_flag(tr, TRACE_ITER_LATENCY_FMT, 1); |
---|
| 565 | + /* without pause, we will produce garbage if another latency occurs */ |
---|
| 566 | + set_tracer_flag(tr, TRACE_ITER_PAUSE_ON_TRACE, 1); |
---|
566 | 567 | |
---|
567 | 568 | tr->max_latency = 0; |
---|
568 | 569 | irqsoff_trace = tr; |
---|
.. | .. |
---|
584 | 585 | { |
---|
585 | 586 | int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT; |
---|
586 | 587 | int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE; |
---|
| 588 | + int pause_flag = save_flags & TRACE_ITER_PAUSE_ON_TRACE; |
---|
587 | 589 | |
---|
588 | 590 | stop_irqsoff_tracer(tr, is_graph(tr)); |
---|
589 | 591 | |
---|
590 | 592 | set_tracer_flag(tr, TRACE_ITER_LATENCY_FMT, lat_flag); |
---|
591 | 593 | set_tracer_flag(tr, TRACE_ITER_OVERWRITE, overwrite_flag); |
---|
| 594 | + set_tracer_flag(tr, TRACE_ITER_PAUSE_ON_TRACE, pause_flag); |
---|
592 | 595 | ftrace_reset_array_ops(tr); |
---|
593 | 596 | |
---|
594 | 597 | irqsoff_busy = false; |
---|
.. | .. |
---|
615 | 618 | if (!preempt_trace(pc) && irq_trace()) |
---|
616 | 619 | stop_critical_timing(a0, a1, pc); |
---|
617 | 620 | } |
---|
| 621 | +NOKPROBE_SYMBOL(tracer_hardirqs_on); |
---|
618 | 622 | |
---|
619 | 623 | void tracer_hardirqs_off(unsigned long a0, unsigned long a1) |
---|
620 | 624 | { |
---|
.. | .. |
---|
623 | 627 | if (!preempt_trace(pc) && irq_trace()) |
---|
624 | 628 | start_critical_timing(a0, a1, pc); |
---|
625 | 629 | } |
---|
| 630 | +NOKPROBE_SYMBOL(tracer_hardirqs_off); |
---|
626 | 631 | |
---|
627 | 632 | static int irqsoff_tracer_init(struct trace_array *tr) |
---|
628 | 633 | { |
---|