tracing: Record and show NMI state
authorPeter Zijlstra <peterz@infradead.org>
Fri, 18 Mar 2016 15:28:04 +0000 (16:28 +0100)
committerSteven Rostedt <rostedt@goodmis.org>
Tue, 22 Mar 2016 22:04:10 +0000 (18:04 -0400)
The latency tracer format has a nice column to indicate IRQ state, but
this is not able to tell us about NMI state.

When tracing perf interrupt handlers (which often run in NMI context)
it is very useful to see how the events nest.

Link: http://lkml.kernel.org/r/20160318153022.105068893@infradead.org
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_output.c

index cb2b708..7bdf8ba 100644 (file)
@@ -1664,6 +1664,7 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
 #else
                TRACE_FLAG_IRQS_NOSUPPORT |
 #endif
+               ((pc & NMI_MASK    ) ? TRACE_FLAG_NMI     : 0) |
                ((pc & HARDIRQ_MASK) ? TRACE_FLAG_HARDIRQ : 0) |
                ((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) |
                (tif_need_resched() ? TRACE_FLAG_NEED_RESCHED : 0) |
index 39588c2..3fff4ad 100644 (file)
@@ -125,6 +125,7 @@ enum trace_flag_type {
        TRACE_FLAG_HARDIRQ              = 0x08,
        TRACE_FLAG_SOFTIRQ              = 0x10,
        TRACE_FLAG_PREEMPT_RESCHED      = 0x20,
+       TRACE_FLAG_NMI                  = 0x40,
 };
 
 #define TRACE_BUF_SIZE         1024
index 2829821..0bb9cf2 100644 (file)
@@ -389,7 +389,9 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
        char irqs_off;
        int hardirq;
        int softirq;
+       int nmi;
 
+       nmi = entry->flags & TRACE_FLAG_NMI;
        hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
        softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
 
@@ -415,10 +417,12 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
        }
 
        hardsoft_irq =
+               (nmi && hardirq)     ? 'Z' :
+               nmi                  ? 'z' :
                (hardirq && softirq) ? 'H' :
-               hardirq ? 'h' :
-               softirq ? 's' :
-               '.';
+               hardirq              ? 'h' :
+               softirq              ? 's' :
+                                      '.' ;
 
        trace_seq_printf(s, "%c%c%c",
                         irqs_off, need_resched, hardsoft_irq);