LCOV - code coverage report
Current view: top level - kernel/trace - trace_functions_graph.c (source / functions) Hit Total Coverage
Test: Real Lines: 10 481 2.1 %
Date: 2020-10-17 15:46:16 Functions: 0 41 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

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

Generated by: LCOV version 1.14