^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Function graph tracer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2008-2009 Frederic Weisbecker <fweisbec@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Mostly borrowed from function tracer which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * is Copyright (c) Steven Rostedt <srostedt@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/ftrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "trace_output.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* When set, irq functions will be ignored */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static int ftrace_graph_skip_irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct fgraph_cpu_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) pid_t last_pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int depth_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int ignore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned long enter_funcs[FTRACE_RETFUNC_DEPTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct fgraph_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct fgraph_cpu_data __percpu *cpu_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* Place to preserve last processed entry. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct ftrace_graph_ent_entry ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct ftrace_graph_ret_entry ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define TRACE_GRAPH_INDENT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) unsigned int fgraph_max_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static struct tracer_opt trace_opts[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Display overruns? (for self-debug purpose) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) { TRACER_OPT(funcgraph-overrun, TRACE_GRAPH_PRINT_OVERRUN) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* Display CPU ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) { TRACER_OPT(funcgraph-cpu, TRACE_GRAPH_PRINT_CPU) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* Display Overhead ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { TRACER_OPT(funcgraph-overhead, TRACE_GRAPH_PRINT_OVERHEAD) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Display proc name/pid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { TRACER_OPT(funcgraph-proc, TRACE_GRAPH_PRINT_PROC) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* Display duration of execution */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { TRACER_OPT(funcgraph-duration, TRACE_GRAPH_PRINT_DURATION) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* Display absolute time of an entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { TRACER_OPT(funcgraph-abstime, TRACE_GRAPH_PRINT_ABS_TIME) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* Display interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { TRACER_OPT(funcgraph-irqs, TRACE_GRAPH_PRINT_IRQS) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Display function name after trailing } */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { TRACER_OPT(funcgraph-tail, TRACE_GRAPH_PRINT_TAIL) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Include sleep time (scheduled out) between entry and return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { TRACER_OPT(sleep-time, TRACE_GRAPH_SLEEP_TIME) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #ifdef CONFIG_FUNCTION_PROFILER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* Include time within nested functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { TRACER_OPT(graph-time, TRACE_GRAPH_GRAPH_TIME) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { } /* Empty entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static struct tracer_flags tracer_flags = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Don't display overruns, proc, or tail by default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) TRACE_GRAPH_PRINT_DURATION | TRACE_GRAPH_PRINT_IRQS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) TRACE_GRAPH_SLEEP_TIME | TRACE_GRAPH_GRAPH_TIME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .opts = trace_opts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static struct trace_array *graph_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * DURATION column is being also used to display IRQ signs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * following values are used by print_graph_irq and others
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * to fill in space into DURATION column.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) FLAGS_FILL_FULL = 1 << TRACE_GRAPH_PRINT_FILL_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) FLAGS_FILL_START = 2 << TRACE_GRAPH_PRINT_FILL_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) FLAGS_FILL_END = 3 << TRACE_GRAPH_PRINT_FILL_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) print_graph_duration(struct trace_array *tr, unsigned long long duration,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct trace_seq *s, u32 flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int __trace_graph_entry(struct trace_array *tr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct ftrace_graph_ent *trace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned long flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct trace_event_call *call = &event_funcgraph_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct ring_buffer_event *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct trace_buffer *buffer = tr->array_buffer.buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct ftrace_graph_ent_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_ENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) sizeof(*entry), flags, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (!event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) entry = ring_buffer_event_data(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) entry->graph_ent = *trace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!call_filter_check_discard(call, entry, buffer, event))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) trace_buffer_unlock_commit_nostack(buffer, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static inline int ftrace_graph_ignore_irqs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!ftrace_graph_skip_irqs || trace_recursion_test(TRACE_IRQ_BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return in_irq();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int trace_graph_entry(struct ftrace_graph_ent *trace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct trace_array *tr = graph_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct trace_array_cpu *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) long disabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (trace_recursion_test(TRACE_GRAPH_NOTRACE_BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * Do not trace a function if it's filtered by set_graph_notrace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * Make the index of ret stack negative to indicate that it should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * ignore further functions. But it needs its own ret stack entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * to recover the original index in order to continue tracing after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * returning from the function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (ftrace_graph_notrace_addr(trace->func)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) trace_recursion_set(TRACE_GRAPH_NOTRACE_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Need to return 1 to have the return called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * that will clear the NOTRACE bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (!ftrace_trace_task(tr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (ftrace_graph_ignore_func(trace))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (ftrace_graph_ignore_irqs())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * Stop here if tracing_threshold is set. We only write function return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * events to the ring buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (tracing_thresh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) cpu = raw_smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) data = per_cpu_ptr(tr->array_buffer.data, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) disabled = atomic_inc_return(&data->disabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (likely(disabled == 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) pc = preempt_count();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ret = __trace_graph_entry(tr, trace, flags, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) atomic_dec(&data->disabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) __trace_graph_function(struct trace_array *tr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned long ip, unsigned long flags, int pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) u64 time = trace_clock_local();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct ftrace_graph_ent ent = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .func = ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .depth = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct ftrace_graph_ret ret = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .func = ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .depth = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .calltime = time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .rettime = time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) __trace_graph_entry(tr, &ent, flags, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) __trace_graph_return(tr, &ret, flags, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) trace_graph_function(struct trace_array *tr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) unsigned long ip, unsigned long parent_ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) unsigned long flags, int pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) __trace_graph_function(tr, ip, flags, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) void __trace_graph_return(struct trace_array *tr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct ftrace_graph_ret *trace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) unsigned long flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct trace_event_call *call = &event_funcgraph_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct ring_buffer_event *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct trace_buffer *buffer = tr->array_buffer.buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct ftrace_graph_ret_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_RET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) sizeof(*entry), flags, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (!event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) entry = ring_buffer_event_data(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) entry->ret = *trace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (!call_filter_check_discard(call, entry, buffer, event))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) trace_buffer_unlock_commit_nostack(buffer, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) void trace_graph_return(struct ftrace_graph_ret *trace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct trace_array *tr = graph_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct trace_array_cpu *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) long disabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) int pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ftrace_graph_addr_finish(trace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (trace_recursion_test(TRACE_GRAPH_NOTRACE_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) trace_recursion_clear(TRACE_GRAPH_NOTRACE_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) cpu = raw_smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) data = per_cpu_ptr(tr->array_buffer.data, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) disabled = atomic_inc_return(&data->disabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (likely(disabled == 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) pc = preempt_count();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) __trace_graph_return(tr, trace, flags, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) atomic_dec(&data->disabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) void set_graph_array(struct trace_array *tr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) graph_array = tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* Make graph_array visible before we start tracing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) smp_mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ftrace_graph_addr_finish(trace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (trace_recursion_test(TRACE_GRAPH_NOTRACE_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) trace_recursion_clear(TRACE_GRAPH_NOTRACE_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (tracing_thresh &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) (trace->rettime - trace->calltime < tracing_thresh))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) trace_graph_return(trace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static struct fgraph_ops funcgraph_thresh_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .entryfunc = &trace_graph_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .retfunc = &trace_graph_thresh_return,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static struct fgraph_ops funcgraph_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .entryfunc = &trace_graph_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .retfunc = &trace_graph_return,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int graph_trace_init(struct trace_array *tr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) set_graph_array(tr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (tracing_thresh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ret = register_ftrace_graph(&funcgraph_thresh_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ret = register_ftrace_graph(&funcgraph_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) tracing_start_cmdline_record();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static void graph_trace_reset(struct trace_array *tr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) tracing_stop_cmdline_record();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (tracing_thresh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) unregister_ftrace_graph(&funcgraph_thresh_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) unregister_ftrace_graph(&funcgraph_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static int graph_trace_update_thresh(struct trace_array *tr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) graph_trace_reset(tr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return graph_trace_init(tr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static int max_bytes_for_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static void print_graph_cpu(struct trace_seq *s, int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * Start with a space character - to make it stand out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * to the right a bit when trace output is pasted into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * email:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) trace_seq_printf(s, " %*d) ", max_bytes_for_cpu, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) #define TRACE_GRAPH_PROCINFO_LENGTH 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static void print_graph_proc(struct trace_seq *s, pid_t pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) char comm[TASK_COMM_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /* sign + log10(MAX_INT) + '\0' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) char pid_str[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int spaces = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) trace_find_cmdline(pid, comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) comm[7] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) sprintf(pid_str, "%d", pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* 1 stands for the "-" character */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) len = strlen(comm) + strlen(pid_str) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (len < TRACE_GRAPH_PROCINFO_LENGTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) spaces = TRACE_GRAPH_PROCINFO_LENGTH - len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* First spaces to align center */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) for (i = 0; i < spaces / 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) trace_seq_putc(s, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) trace_seq_printf(s, "%s-%s", comm, pid_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* Last spaces to align center */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) for (i = 0; i < spaces - (spaces / 2); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) trace_seq_putc(s, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static void print_graph_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) trace_seq_putc(s, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) trace_print_lat_fmt(s, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) trace_seq_puts(s, " | ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* If the pid changed since the last trace, output this event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) verif_pid(struct trace_seq *s, pid_t pid, int cpu, struct fgraph_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) pid_t prev_pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) pid_t *last_pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) last_pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (*last_pid == pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) prev_pid = *last_pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *last_pid = pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (prev_pid == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * Context-switch trace line:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) | 1) migration/0--1 => sshd-1755
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) trace_seq_puts(s, " ------------------------------------------\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) print_graph_cpu(s, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) print_graph_proc(s, prev_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) trace_seq_puts(s, " => ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) print_graph_proc(s, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) trace_seq_puts(s, "\n ------------------------------------------\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static struct ftrace_graph_ret_entry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) get_return_for_leaf(struct trace_iterator *iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) struct ftrace_graph_ent_entry *curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct ring_buffer_iter *ring_iter = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct ring_buffer_event *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct ftrace_graph_ret_entry *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * If the previous output failed to write to the seq buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * then we just reuse the data from before.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (data && data->failed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) curr = &data->ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) next = &data->ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ring_iter = trace_buffer_iter(iter, iter->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* First peek to compare current entry and the next one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (ring_iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) event = ring_buffer_iter_peek(ring_iter, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * We need to consume the current entry to see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * the next one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ring_buffer_consume(iter->array_buffer->buffer, iter->cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) event = ring_buffer_peek(iter->array_buffer->buffer, iter->cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (!event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) next = ring_buffer_event_data(event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * Save current and next entries for later reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * if the output fails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) data->ent = *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * If the next event is not a return type, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * we only care about what type it is. Otherwise we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * safely copy the entire event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (next->ent.type == TRACE_GRAPH_RET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) data->ret = *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) data->ret.ent.type = next->ent.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (next->ent.type != TRACE_GRAPH_RET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (curr->ent.pid != next->ent.pid ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) curr->graph_ent.func != next->ret.func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* this is a leaf, now advance the iterator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (ring_iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) ring_buffer_iter_advance(ring_iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static void print_graph_abs_time(u64 t, struct trace_seq *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) unsigned long usecs_rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) usecs_rem = do_div(t, NSEC_PER_SEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) usecs_rem /= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) trace_seq_printf(s, "%5lu.%06lu | ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) (unsigned long)t, usecs_rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) print_graph_rel_time(struct trace_iterator *iter, struct trace_seq *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) unsigned long long usecs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) usecs = iter->ts - iter->array_buffer->time_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) do_div(usecs, NSEC_PER_USEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) trace_seq_printf(s, "%9llu us | ", usecs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) print_graph_irq(struct trace_iterator *iter, unsigned long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) enum trace_type type, int cpu, pid_t pid, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct trace_array *tr = iter->tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) struct trace_seq *s = &iter->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct trace_entry *ent = iter->ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (addr < (unsigned long)__irqentry_text_start ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) addr >= (unsigned long)__irqentry_text_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (tr->trace_flags & TRACE_ITER_CONTEXT_INFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* Absolute time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) print_graph_abs_time(iter->ts, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* Relative time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (flags & TRACE_GRAPH_PRINT_REL_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) print_graph_rel_time(iter, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /* Cpu */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (flags & TRACE_GRAPH_PRINT_CPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) print_graph_cpu(s, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* Proc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (flags & TRACE_GRAPH_PRINT_PROC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) print_graph_proc(s, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) trace_seq_puts(s, " | ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /* Latency format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (tr->trace_flags & TRACE_ITER_LATENCY_FMT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) print_graph_lat_fmt(s, ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) /* No overhead */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) print_graph_duration(tr, 0, s, flags | FLAGS_FILL_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (type == TRACE_GRAPH_ENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) trace_seq_puts(s, "==========>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) trace_seq_puts(s, "<==========");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) print_graph_duration(tr, 0, s, flags | FLAGS_FILL_END);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) trace_seq_putc(s, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) trace_print_graph_duration(unsigned long long duration, struct trace_seq *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) unsigned long nsecs_rem = do_div(duration, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* log10(ULONG_MAX) + '\0' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) char usecs_str[21];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) char nsecs_str[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) sprintf(usecs_str, "%lu", (unsigned long) duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) /* Print msecs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) trace_seq_printf(s, "%s", usecs_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) len = strlen(usecs_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* Print nsecs (we don't want to exceed 7 numbers) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (len < 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) size_t slen = min_t(size_t, sizeof(nsecs_str), 8UL - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) snprintf(nsecs_str, slen, "%03lu", nsecs_rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) trace_seq_printf(s, ".%s", nsecs_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) len += strlen(nsecs_str) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) trace_seq_puts(s, " us ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* Print remaining spaces to fit the row's width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) for (i = len; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) trace_seq_putc(s, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) print_graph_duration(struct trace_array *tr, unsigned long long duration,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct trace_seq *s, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (!(flags & TRACE_GRAPH_PRINT_DURATION) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) !(tr->trace_flags & TRACE_ITER_CONTEXT_INFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* No real adata, just filling the column with spaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) switch (flags & TRACE_GRAPH_PRINT_FILL_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) case FLAGS_FILL_FULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) trace_seq_puts(s, " | ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) case FLAGS_FILL_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) trace_seq_puts(s, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) case FLAGS_FILL_END:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) trace_seq_puts(s, " |");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* Signal a overhead of time execution to the output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (flags & TRACE_GRAPH_PRINT_OVERHEAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) trace_seq_printf(s, "%c ", trace_find_mark(duration));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) trace_seq_puts(s, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) trace_print_graph_duration(duration, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) trace_seq_puts(s, "| ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) /* Case of a leaf function on its call entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static enum print_line_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) print_graph_entry_leaf(struct trace_iterator *iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct ftrace_graph_ent_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) struct ftrace_graph_ret_entry *ret_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct trace_seq *s, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct trace_array *tr = iter->tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct ftrace_graph_ret *graph_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct ftrace_graph_ent *call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) unsigned long long duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int cpu = iter->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) graph_ret = &ret_entry->ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) call = &entry->graph_ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) duration = graph_ret->rettime - graph_ret->calltime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct fgraph_cpu_data *cpu_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) cpu_data = per_cpu_ptr(data->cpu_data, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * Comments display at + 1 to depth. Since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * this is a leaf function, keep the comments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * equal to this depth.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) cpu_data->depth = call->depth - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) /* No need to keep this function around for this depth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (call->depth < FTRACE_RETFUNC_DEPTH &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) !WARN_ON_ONCE(call->depth < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) cpu_data->enter_funcs[call->depth] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) /* Overhead and duration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) print_graph_duration(tr, duration, s, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /* Function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) trace_seq_putc(s, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) trace_seq_printf(s, "%ps();\n", (void *)call->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) print_graph_irq(iter, graph_ret->func, TRACE_GRAPH_RET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) cpu, iter->ent->pid, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return trace_handle_return(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static enum print_line_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) print_graph_entry_nested(struct trace_iterator *iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) struct ftrace_graph_ent_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct trace_seq *s, int cpu, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) struct ftrace_graph_ent *call = &entry->graph_ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) struct trace_array *tr = iter->tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) struct fgraph_cpu_data *cpu_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) int cpu = iter->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) cpu_data = per_cpu_ptr(data->cpu_data, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) cpu_data->depth = call->depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /* Save this function pointer to see if the exit matches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (call->depth < FTRACE_RETFUNC_DEPTH &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) !WARN_ON_ONCE(call->depth < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) cpu_data->enter_funcs[call->depth] = call->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /* No time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) print_graph_duration(tr, 0, s, flags | FLAGS_FILL_FULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) /* Function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) trace_seq_putc(s, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) trace_seq_printf(s, "%ps() {\n", (void *)call->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (trace_seq_has_overflowed(s))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return TRACE_TYPE_PARTIAL_LINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * we already consumed the current entry to check the next one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * and see if this is a leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return TRACE_TYPE_NO_CONSUME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) int type, unsigned long addr, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct trace_entry *ent = iter->ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct trace_array *tr = iter->tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int cpu = iter->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* Pid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) verif_pid(s, ent->pid, cpu, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* Interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) print_graph_irq(iter, addr, type, cpu, ent->pid, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (!(tr->trace_flags & TRACE_ITER_CONTEXT_INFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /* Absolute time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) print_graph_abs_time(iter->ts, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* Relative time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (flags & TRACE_GRAPH_PRINT_REL_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) print_graph_rel_time(iter, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /* Cpu */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (flags & TRACE_GRAPH_PRINT_CPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) print_graph_cpu(s, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* Proc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (flags & TRACE_GRAPH_PRINT_PROC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) print_graph_proc(s, ent->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) trace_seq_puts(s, " | ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) /* Latency format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (tr->trace_flags & TRACE_ITER_LATENCY_FMT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) print_graph_lat_fmt(s, ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) * Entry check for irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * returns 1 if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * - we are inside irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * - we just entered irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * retunns 0 if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * - funcgraph-interrupts option is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * - we are not inside irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) check_irq_entry(struct trace_iterator *iter, u32 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) unsigned long addr, int depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) int cpu = iter->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) int *depth_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) * If we are either displaying irqs, or we got called as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * a graph event and private data does not exist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * then we bypass the irq check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if ((flags & TRACE_GRAPH_PRINT_IRQS) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) (!data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * We are inside the irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (*depth_irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if ((addr < (unsigned long)__irqentry_text_start) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) (addr >= (unsigned long)__irqentry_text_end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * We are entering irq code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) *depth_irq = depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * Return check for irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * returns 1 if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * - we are inside irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) * - we just left irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * returns 0 if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * - funcgraph-interrupts option is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * - we are not inside irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) check_irq_return(struct trace_iterator *iter, u32 flags, int depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) int cpu = iter->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) int *depth_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * If we are either displaying irqs, or we got called as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * a graph event and private data does not exist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * then we bypass the irq check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if ((flags & TRACE_GRAPH_PRINT_IRQS) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) (!data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) * We are not inside the irq code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (*depth_irq == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * We are inside the irq code, and this is returning entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * Let's not trace it and clear the entry depth, since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * we are out of irq code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * This condition ensures that we 'leave the irq code' once
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * we are out of the entry depth. Thus protecting us from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * the RETURN entry loss.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (*depth_irq >= depth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) *depth_irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) * We are inside the irq code, and this is not the entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static enum print_line_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct trace_iterator *iter, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) struct ftrace_graph_ent *call = &field->graph_ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) struct ftrace_graph_ret_entry *leaf_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) static enum print_line_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) int cpu = iter->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (check_irq_entry(iter, flags, call->func, call->depth))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return TRACE_TYPE_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) leaf_ret = get_return_for_leaf(iter, field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (leaf_ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) ret = print_graph_entry_leaf(iter, field, leaf_ret, s, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) ret = print_graph_entry_nested(iter, field, s, cpu, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * If we failed to write our output, then we need to make
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * note of it. Because we already consumed our entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (s->full) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) data->failed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) data->cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) data->failed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) static enum print_line_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct trace_entry *ent, struct trace_iterator *iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) unsigned long long duration = trace->rettime - trace->calltime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) struct trace_array *tr = iter->tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) pid_t pid = ent->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) int cpu = iter->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) int func_match = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (check_irq_return(iter, flags, trace->depth))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return TRACE_TYPE_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct fgraph_cpu_data *cpu_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) int cpu = iter->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) cpu_data = per_cpu_ptr(data->cpu_data, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) * Comments display at + 1 to depth. This is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * return from a function, we now want the comments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * to display at the same level of the bracket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) cpu_data->depth = trace->depth - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (trace->depth < FTRACE_RETFUNC_DEPTH &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) !WARN_ON_ONCE(trace->depth < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (cpu_data->enter_funcs[trace->depth] != trace->func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) func_match = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) cpu_data->enter_funcs[trace->depth] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) print_graph_prologue(iter, s, 0, 0, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* Overhead and duration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) print_graph_duration(tr, duration, s, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /* Closing brace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) trace_seq_putc(s, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) * If the return function does not have a matching entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) * then the entry was lost. Instead of just printing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) * the '}' and letting the user guess what function this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) * belongs to, write out the function name. Always do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) * that if the funcgraph-tail option is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (func_match && !(flags & TRACE_GRAPH_PRINT_TAIL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) trace_seq_puts(s, "}\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) trace_seq_printf(s, "} /* %ps */\n", (void *)trace->func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) /* Overrun */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (flags & TRACE_GRAPH_PRINT_OVERRUN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) trace_seq_printf(s, " (Overruns: %lu)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) trace->overrun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) print_graph_irq(iter, trace->func, TRACE_GRAPH_RET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) cpu, pid, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return trace_handle_return(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) static enum print_line_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) struct trace_iterator *iter, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) struct trace_array *tr = iter->tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) unsigned long sym_flags = (tr->trace_flags & TRACE_ITER_SYM_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) struct trace_event *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) int depth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) depth = per_cpu_ptr(data->cpu_data, iter->cpu)->depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) print_graph_prologue(iter, s, 0, 0, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* No time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) print_graph_duration(tr, 0, s, flags | FLAGS_FILL_FULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* Indentation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (depth > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) for (i = 0; i < (depth + 1) * TRACE_GRAPH_INDENT; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) trace_seq_putc(s, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) /* The comment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) trace_seq_puts(s, "/* ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) switch (iter->ent->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) case TRACE_BPUTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ret = trace_print_bputs_msg_only(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (ret != TRACE_TYPE_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) case TRACE_BPRINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) ret = trace_print_bprintk_msg_only(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (ret != TRACE_TYPE_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) case TRACE_PRINT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) ret = trace_print_printk_msg_only(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (ret != TRACE_TYPE_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) event = ftrace_find_event(ent->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (!event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return TRACE_TYPE_UNHANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) ret = event->funcs->trace(iter, sym_flags, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (ret != TRACE_TYPE_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (trace_seq_has_overflowed(s))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) /* Strip ending newline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (s->buffer[s->seq.len - 1] == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) s->buffer[s->seq.len - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) s->seq.len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) trace_seq_puts(s, " */\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) return trace_handle_return(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) enum print_line_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) print_graph_function_flags(struct trace_iterator *iter, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) struct ftrace_graph_ent_entry *field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) struct trace_entry *entry = iter->ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) struct trace_seq *s = &iter->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) int cpu = iter->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (data && per_cpu_ptr(data->cpu_data, cpu)->ignore) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) per_cpu_ptr(data->cpu_data, cpu)->ignore = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return TRACE_TYPE_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) * If the last output failed, there's a possibility we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) * to print out the missing entry which would never go out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (data && data->failed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) field = &data->ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) iter->cpu = data->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) ret = print_graph_entry(field, s, iter, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (ret == TRACE_TYPE_HANDLED && iter->cpu != cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) per_cpu_ptr(data->cpu_data, iter->cpu)->ignore = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) ret = TRACE_TYPE_NO_CONSUME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) iter->cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) switch (entry->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) case TRACE_GRAPH_ENT: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) * print_graph_entry() may consume the current event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) * thus @field may become invalid, so we need to save it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * sizeof(struct ftrace_graph_ent_entry) is very small,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * it can be safely saved at the stack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) struct ftrace_graph_ent_entry saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) trace_assign_type(field, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) saved = *field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return print_graph_entry(&saved, s, iter, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) case TRACE_GRAPH_RET: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) struct ftrace_graph_ret_entry *field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) trace_assign_type(field, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return print_graph_return(&field->ret, s, entry, iter, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) case TRACE_STACK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) case TRACE_FN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /* dont trace stack and functions as comments */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return TRACE_TYPE_UNHANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return print_graph_comment(s, entry, iter, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) return TRACE_TYPE_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) static enum print_line_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) print_graph_function(struct trace_iterator *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return print_graph_function_flags(iter, tracer_flags.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) static enum print_line_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) print_graph_function_event(struct trace_iterator *iter, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct trace_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return print_graph_function(iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) static void print_lat_header(struct seq_file *s, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) static const char spaces[] = " " /* 16 spaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) " " /* 4 spaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) " "; /* 17 spaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) int size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) size += 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (flags & TRACE_GRAPH_PRINT_REL_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) size += 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (flags & TRACE_GRAPH_PRINT_CPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) size += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (flags & TRACE_GRAPH_PRINT_PROC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) size += 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) seq_printf(s, "#%.*s _-----=> irqs-off \n", size, spaces);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) seq_printf(s, "#%.*s / _----=> need-resched \n", size, spaces);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) seq_printf(s, "#%.*s| / _---=> hardirq/softirq \n", size, spaces);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) seq_printf(s, "#%.*s|| / _--=> preempt-depth \n", size, spaces);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) seq_printf(s, "#%.*s||| / \n", size, spaces);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) static void __print_graph_headers_flags(struct trace_array *tr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct seq_file *s, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) int lat = tr->trace_flags & TRACE_ITER_LATENCY_FMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (lat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) print_lat_header(s, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /* 1st line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) seq_putc(s, '#');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) seq_puts(s, " TIME ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (flags & TRACE_GRAPH_PRINT_REL_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) seq_puts(s, " REL TIME ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) if (flags & TRACE_GRAPH_PRINT_CPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) seq_puts(s, " CPU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (flags & TRACE_GRAPH_PRINT_PROC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) seq_puts(s, " TASK/PID ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) if (lat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) seq_puts(s, "|||| ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (flags & TRACE_GRAPH_PRINT_DURATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) seq_puts(s, " DURATION ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) seq_puts(s, " FUNCTION CALLS\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /* 2nd line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) seq_putc(s, '#');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (flags & TRACE_GRAPH_PRINT_ABS_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) seq_puts(s, " | ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (flags & TRACE_GRAPH_PRINT_REL_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) seq_puts(s, " | ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (flags & TRACE_GRAPH_PRINT_CPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) seq_puts(s, " | ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (flags & TRACE_GRAPH_PRINT_PROC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) seq_puts(s, " | | ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (lat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) seq_puts(s, "|||| ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (flags & TRACE_GRAPH_PRINT_DURATION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) seq_puts(s, " | | ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) seq_puts(s, " | | | |\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) static void print_graph_headers(struct seq_file *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) print_graph_headers_flags(s, tracer_flags.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) void print_graph_headers_flags(struct seq_file *s, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) struct trace_iterator *iter = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) struct trace_array *tr = iter->tr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (!(tr->trace_flags & TRACE_ITER_CONTEXT_INFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (tr->trace_flags & TRACE_ITER_LATENCY_FMT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) /* print nothing if the buffers are empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (trace_empty(iter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) print_trace_header(s, iter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) __print_graph_headers_flags(tr, s, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) void graph_trace_open(struct trace_iterator *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) /* pid and depth on the last trace processed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) struct fgraph_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) gfp_t gfpflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) iter->private = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) /* We can be called in atomic context via ftrace_dump() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) gfpflags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) data = kzalloc(sizeof(*data), gfpflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) data->cpu_data = alloc_percpu_gfp(struct fgraph_cpu_data, gfpflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (!data->cpu_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) goto out_err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) for_each_possible_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) pid_t *pid = &(per_cpu_ptr(data->cpu_data, cpu)->last_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) int *depth = &(per_cpu_ptr(data->cpu_data, cpu)->depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) int *ignore = &(per_cpu_ptr(data->cpu_data, cpu)->ignore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) int *depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) *pid = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) *depth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) *ignore = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) *depth_irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) iter->private = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) out_err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) pr_warn("function graph tracer: not enough memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) void graph_trace_close(struct trace_iterator *iter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) struct fgraph_data *data = iter->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if (data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) free_percpu(data->cpu_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) func_graph_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) if (bit == TRACE_GRAPH_PRINT_IRQS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) ftrace_graph_skip_irqs = !set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (bit == TRACE_GRAPH_SLEEP_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) ftrace_graph_sleep_time_control(set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (bit == TRACE_GRAPH_GRAPH_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) ftrace_graph_graph_time_control(set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) static struct trace_event_functions graph_functions = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) .trace = print_graph_function_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) static struct trace_event graph_trace_entry_event = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) .type = TRACE_GRAPH_ENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) .funcs = &graph_functions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) static struct trace_event graph_trace_ret_event = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) .type = TRACE_GRAPH_RET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) .funcs = &graph_functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) static struct tracer graph_trace __tracer_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) .name = "function_graph",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) .update_thresh = graph_trace_update_thresh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) .open = graph_trace_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) .pipe_open = graph_trace_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) .close = graph_trace_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) .pipe_close = graph_trace_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) .init = graph_trace_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) .reset = graph_trace_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) .print_line = print_graph_function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) .print_header = print_graph_headers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) .flags = &tracer_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) .set_flag = func_graph_set_flag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) #ifdef CONFIG_FTRACE_SELFTEST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) .selftest = trace_selftest_startup_function_graph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) graph_depth_write(struct file *filp, const char __user *ubuf, size_t cnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) fgraph_max_depth = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) *ppos += cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) return cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) graph_depth_read(struct file *filp, char __user *ubuf, size_t cnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) char buf[15]; /* More than enough to hold UINT_MAX + "\n"*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) n = sprintf(buf, "%d\n", fgraph_max_depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return simple_read_from_buffer(ubuf, cnt, ppos, buf, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) static const struct file_operations graph_depth_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) .open = tracing_open_generic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) .write = graph_depth_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) .read = graph_depth_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) .llseek = generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) static __init int init_graph_tracefs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) ret = tracing_init_dentry();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) trace_create_file("max_graph_depth", 0644, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) NULL, &graph_depth_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) fs_initcall(init_graph_tracefs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) static __init int init_graph_trace(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) max_bytes_for_cpu = snprintf(NULL, 0, "%u", nr_cpu_ids - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (!register_trace_event(&graph_trace_entry_event)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) pr_warn("Warning: could not register graph trace events\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (!register_trace_event(&graph_trace_ret_event)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) pr_warn("Warning: could not register graph trace events\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) return register_tracer(&graph_trace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) core_initcall(init_graph_trace);