.. | .. |
---|
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)) |
---|
224 | 230 | graph_trace_open(iter); |
---|
225 | | - |
---|
| 231 | + else |
---|
| 232 | + iter->private = NULL; |
---|
226 | 233 | } |
---|
227 | 234 | |
---|
228 | 235 | static void irqsoff_trace_close(struct trace_iterator *iter) |
---|
.. | .. |
---|
233 | 240 | |
---|
234 | 241 | #define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_CPU | \ |
---|
235 | 242 | TRACE_GRAPH_PRINT_PROC | \ |
---|
236 | | - TRACE_GRAPH_PRINT_ABS_TIME | \ |
---|
| 243 | + TRACE_GRAPH_PRINT_REL_TIME | \ |
---|
237 | 244 | TRACE_GRAPH_PRINT_DURATION) |
---|
238 | 245 | |
---|
239 | 246 | static enum print_line_t irqsoff_print_line(struct trace_iterator *iter) |
---|
.. | .. |
---|
272 | 279 | #else |
---|
273 | 280 | #define __trace_function trace_function |
---|
274 | 281 | |
---|
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 | 282 | static enum print_line_t irqsoff_print_line(struct trace_iterator *iter) |
---|
283 | 283 | { |
---|
284 | 284 | return TRACE_TYPE_UNHANDLED; |
---|
.. | .. |
---|
288 | 288 | static void irqsoff_trace_close(struct trace_iterator *iter) { } |
---|
289 | 289 | |
---|
290 | 290 | #ifdef CONFIG_FUNCTION_TRACER |
---|
291 | | -static void irqsoff_graph_return(struct ftrace_graph_ret *trace) { } |
---|
292 | 291 | static void irqsoff_print_header(struct seq_file *s) |
---|
293 | 292 | { |
---|
294 | 293 | trace_default_header(s); |
---|
.. | .. |
---|
368 | 367 | __trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc); |
---|
369 | 368 | } |
---|
370 | 369 | |
---|
371 | | -static inline void |
---|
| 370 | +static nokprobe_inline void |
---|
372 | 371 | start_critical_timing(unsigned long ip, unsigned long parent_ip, int pc) |
---|
373 | 372 | { |
---|
374 | 373 | int cpu; |
---|
.. | .. |
---|
384 | 383 | if (per_cpu(tracing_cpu, cpu)) |
---|
385 | 384 | return; |
---|
386 | 385 | |
---|
387 | | - data = per_cpu_ptr(tr->trace_buffer.data, cpu); |
---|
| 386 | + data = per_cpu_ptr(tr->array_buffer.data, cpu); |
---|
388 | 387 | |
---|
389 | 388 | if (unlikely(!data) || atomic_read(&data->disabled)) |
---|
390 | 389 | return; |
---|
.. | .. |
---|
404 | 403 | atomic_dec(&data->disabled); |
---|
405 | 404 | } |
---|
406 | 405 | |
---|
407 | | -static inline void |
---|
| 406 | +static nokprobe_inline void |
---|
408 | 407 | stop_critical_timing(unsigned long ip, unsigned long parent_ip, int pc) |
---|
409 | 408 | { |
---|
410 | 409 | int cpu; |
---|
.. | .. |
---|
422 | 421 | if (!tracer_enabled || !tracing_is_enabled()) |
---|
423 | 422 | return; |
---|
424 | 423 | |
---|
425 | | - data = per_cpu_ptr(tr->trace_buffer.data, cpu); |
---|
| 424 | + data = per_cpu_ptr(tr->array_buffer.data, cpu); |
---|
426 | 425 | |
---|
427 | 426 | if (unlikely(!data) || |
---|
428 | 427 | !data->critical_start || atomic_read(&data->disabled)) |
---|
.. | .. |
---|
446 | 445 | start_critical_timing(CALLER_ADDR0, CALLER_ADDR1, pc); |
---|
447 | 446 | } |
---|
448 | 447 | EXPORT_SYMBOL_GPL(start_critical_timings); |
---|
| 448 | +NOKPROBE_SYMBOL(start_critical_timings); |
---|
449 | 449 | |
---|
450 | 450 | void stop_critical_timings(void) |
---|
451 | 451 | { |
---|
.. | .. |
---|
455 | 455 | stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1, pc); |
---|
456 | 456 | } |
---|
457 | 457 | EXPORT_SYMBOL_GPL(stop_critical_timings); |
---|
| 458 | +NOKPROBE_SYMBOL(stop_critical_timings); |
---|
458 | 459 | |
---|
459 | 460 | #ifdef CONFIG_FUNCTION_TRACER |
---|
460 | 461 | static bool function_enabled; |
---|
.. | .. |
---|
468 | 469 | return 0; |
---|
469 | 470 | |
---|
470 | 471 | if (graph) |
---|
471 | | - ret = register_ftrace_graph(&irqsoff_graph_return, |
---|
472 | | - &irqsoff_graph_entry); |
---|
| 472 | + ret = register_ftrace_graph(&fgraph_ops); |
---|
473 | 473 | else |
---|
474 | 474 | ret = register_ftrace_function(tr->ops); |
---|
475 | 475 | |
---|
.. | .. |
---|
485 | 485 | return; |
---|
486 | 486 | |
---|
487 | 487 | if (graph) |
---|
488 | | - unregister_ftrace_graph(); |
---|
| 488 | + unregister_ftrace_graph(&fgraph_ops); |
---|
489 | 489 | else |
---|
490 | 490 | unregister_ftrace_function(tr->ops); |
---|
491 | 491 | |
---|
.. | .. |
---|
563 | 563 | /* non overwrite screws up the latency tracers */ |
---|
564 | 564 | set_tracer_flag(tr, TRACE_ITER_OVERWRITE, 1); |
---|
565 | 565 | set_tracer_flag(tr, TRACE_ITER_LATENCY_FMT, 1); |
---|
| 566 | + /* without pause, we will produce garbage if another latency occurs */ |
---|
| 567 | + set_tracer_flag(tr, TRACE_ITER_PAUSE_ON_TRACE, 1); |
---|
566 | 568 | |
---|
567 | 569 | tr->max_latency = 0; |
---|
568 | 570 | irqsoff_trace = tr; |
---|
.. | .. |
---|
584 | 586 | { |
---|
585 | 587 | int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT; |
---|
586 | 588 | int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE; |
---|
| 589 | + int pause_flag = save_flags & TRACE_ITER_PAUSE_ON_TRACE; |
---|
587 | 590 | |
---|
588 | 591 | stop_irqsoff_tracer(tr, is_graph(tr)); |
---|
589 | 592 | |
---|
590 | 593 | set_tracer_flag(tr, TRACE_ITER_LATENCY_FMT, lat_flag); |
---|
591 | 594 | set_tracer_flag(tr, TRACE_ITER_OVERWRITE, overwrite_flag); |
---|
| 595 | + set_tracer_flag(tr, TRACE_ITER_PAUSE_ON_TRACE, pause_flag); |
---|
592 | 596 | ftrace_reset_array_ops(tr); |
---|
593 | 597 | |
---|
594 | 598 | irqsoff_busy = false; |
---|
.. | .. |
---|
615 | 619 | if (!preempt_trace(pc) && irq_trace()) |
---|
616 | 620 | stop_critical_timing(a0, a1, pc); |
---|
617 | 621 | } |
---|
| 622 | +NOKPROBE_SYMBOL(tracer_hardirqs_on); |
---|
618 | 623 | |
---|
619 | 624 | void tracer_hardirqs_off(unsigned long a0, unsigned long a1) |
---|
620 | 625 | { |
---|
.. | .. |
---|
623 | 628 | if (!preempt_trace(pc) && irq_trace()) |
---|
624 | 629 | start_critical_timing(a0, a1, pc); |
---|
625 | 630 | } |
---|
| 631 | +NOKPROBE_SYMBOL(tracer_hardirqs_off); |
---|
626 | 632 | |
---|
627 | 633 | static int irqsoff_tracer_init(struct trace_array *tr) |
---|
628 | 634 | { |
---|