From: Jiri Olsa <jolsa@kernel.org>
Date: Sun, 7 Jan 2018 17:03:52 +0100
Subject: perf script: Add support to display sample misc field
Git-commit: 28a0b39877f5ed64ae9fadf95dddb90999309dee
Patch-mainline: v4.16-rc1
References: FATE#326324 (dependent patch)
X-Info: Major changes for context. Missing multiple options in perf-script.txt
X-Info: Missing a1a587073ccd (perf_sample__fprintf_*)

Adding support to display sample misc field in form
of letter for each bit:

  # perf script -F +misc ...
   sched-messaging  1414 K     28690.636582:       4590 cycles ...
   sched-messaging  1407 U     28690.636600:     325620 cycles ...
   sched-messaging  1414 K     28690.636608:      19473 cycles ...
  misc field  __________/

The misc bits are assigned to following letters:

  PERF_RECORD_MISC_KERNEL        K
  PERF_RECORD_MISC_USER          U
  PERF_RECORD_MISC_HYPERVISOR    H
  PERF_RECORD_MISC_GUEST_KERNEL  G
  PERF_RECORD_MISC_GUEST_USER    g
  PERF_RECORD_MISC_MMAP_DATA*    M
  PERF_RECORD_MISC_COMM_EXEC     E
  PERF_RECORD_MISC_SWITCH_OUT    S

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180107160356.28203-9-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Tony Jones <tonyj@suse.de>
---
 tools/perf/Documentation/perf-script.txt | 20 ++++++++-
 tools/perf/builtin-script.c              | 74 +++++++++++++++++++++++++++-----
 tools/perf/util/event.h                  |  1 +
 tools/perf/util/evsel.c                  |  1 +
 4 files changed, 84 insertions(+), 12 deletions(-)

diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 7b622a812a72..93ae8d60e3d3 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -116,8 +116,9 @@
 --fields::
         Comma separated list of fields to print. Options are:
         comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
-        srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn,
-        callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw,
+        srcline, period, iregs, brstack, brstacksym, flags, bpf-output,
+        brstackinsn, callindent, insn, insnlen, misc. 
+        Field list can be prepended with the type, trace, sw or hw,
         to indicate to which event type the field list applies.
         e.g., -F sw:comm,tid,time,ip,sym  and -F trace:time,cpu,trace
 
@@ -203,6 +203,24 @@ OPTIONS
	is printed. This is the full execution path leading to the sample. This is only supported when the
	sample was recorded with perf record -b or -j any.

+	For sample events it's possible to display misc field with -F +misc option,
+	following letters are displayed for each bit:
+
+	  PERF_RECORD_MISC_KERNEL        K
+	  PERF_RECORD_MISC_USER          U
+	  PERF_RECORD_MISC_HYPERVISOR    H
+	  PERF_RECORD_MISC_GUEST_KERNEL  G
+	  PERF_RECORD_MISC_GUEST_USER    g
+	  PERF_RECORD_MISC_MMAP_DATA*    M
+	  PERF_RECORD_MISC_COMM_EXEC     E
+	  PERF_RECORD_MISC_SWITCH_OUT    S
+
+	  $ perf script -F +misc ...
+	   sched-messaging  1414 K     28690.636582:       4590 cycles ...
+	   sched-messaging  1407 U     28690.636600:     325620 cycles ...
+	   sched-messaging  1414 K     28690.636608:      19473 cycles ...
+	  misc field ___________/
+
 -k::
 --vmlinux=<file>::
         vmlinux pathname
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 330dcd9b9b8f..bb603495cf4a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -93,6 +93,7 @@ enum perf_output_field {
	PERF_OUTPUT_INSN	    = 1U << 21,
	PERF_OUTPUT_INSNLEN	    = 1U << 22,
	PERF_OUTPUT_BRSTACKINSN	    = 1U << 23,
+	PERF_OUTPUT_MISC            = 1U << 29,
 };
 
 struct output_option {
@@ -120,6 +120,7 @@ struct output_option {
	{.str = "insn", .field = PERF_OUTPUT_INSN},
	{.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
	{.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
+	{.str = "misc", .field = PERF_OUTPUT_MISC},
 };
 
 /* default set to maintain compatibility with current format */
@@ -463,7 +463,8 @@
 
 static void print_sample_start(struct perf_sample *sample,
 			       struct thread *thread,
-			       struct perf_evsel *evsel)
+			       struct perf_evsel *evsel,
+			       u32 type)
 {
 	struct perf_event_attr *attr = &evsel->attr;
 	unsigned long secs;
@@ -492,6 +493,47 @@
 			printf("[%03d] ", sample->cpu);
 	}
 
+	if (PRINT_FIELD(MISC)) {
+		int ret = 0;
+
+		#define has(m) \
+			(sample->misc & PERF_RECORD_MISC_##m) == PERF_RECORD_MISC_##m
+
+		if (has(KERNEL))
+			ret += printf("K");
+		if (has(USER))
+			ret += printf("U");
+		if (has(HYPERVISOR))
+			ret += printf("H");
+		if (has(GUEST_KERNEL))
+			ret += printf("G");
+		if (has(GUEST_USER))
+			ret += printf("g");
+
+		switch (type) {
+		case PERF_RECORD_MMAP:
+		case PERF_RECORD_MMAP2:
+			if (has(MMAP_DATA))
+				ret += printf("M");
+			break;
+		case PERF_RECORD_COMM:
+			if (has(COMM_EXEC))
+				ret += printf("E");
+			break;
+		case PERF_RECORD_SWITCH:
+		case PERF_RECORD_SWITCH_CPU_WIDE:
+			if (has(SWITCH_OUT))
+				ret += printf("S");
+		default:
+			break;
+		}
+
+		#undef has
+
+		printf("%*s", 6 - ret, " ");
+	}
+
+
 	if (PRINT_FIELD(TIME)) {
 		nsecs = sample->time;
 		secs = nsecs / NSEC_PER_SEC;
@@ -1138,7 +1181,7 @@
 	if (output[attr->type].fields == 0)
 		return;
 
-	print_sample_start(sample, thread, evsel);
+	print_sample_start(sample, thread, evsel, PERF_RECORD_SAMPLE);
 
 	if (PRINT_FIELD(PERIOD))
 		printf("%10" PRIu64 " ", sample->period);
@@ -1369,7 +1412,7 @@
 		sample->tid = event->comm.tid;
 		sample->pid = event->comm.pid;
 	}
-	print_sample_start(sample, thread, evsel);
+	print_sample_start(sample, thread, evsel, PERF_RECORD_COMM);
 	perf_event__fprintf(event, stdout);
 	ret = 0;
 out:
@@ -1404,7 +1447,7 @@
 		sample->tid = event->namespaces.tid;
 		sample->pid = event->namespaces.pid;
 	}
-	print_sample_start(sample, thread, evsel);
+	print_sample_start(sample, thread, evsel, PERF_RECORD_NAMESPACES);
 	perf_event__fprintf(event, stdout);
 	ret = 0;
 out:
@@ -1437,7 +1480,7 @@
 		sample->tid = event->fork.tid;
 		sample->pid = event->fork.pid;
 	}
-	print_sample_start(sample, thread, evsel);
+	print_sample_start(sample, thread, evsel, PERF_RECORD_FORK);
 	perf_event__fprintf(event, stdout);
 	thread__put(thread);
 
@@ -1466,7 +1509,7 @@
 		sample->tid = event->fork.tid;
 		sample->pid = event->fork.pid;
 	}
-	print_sample_start(sample, thread, evsel);
+	print_sample_start(sample, thread, evsel, PERF_RECORD_EXIT);
 	perf_event__fprintf(event, stdout);
 
 	if (perf_event__process_exit(tool, event, sample, machine) < 0)
@@ -1501,7 +1544,7 @@
 		sample->tid = event->mmap.tid;
 		sample->pid = event->mmap.pid;
 	}
-	print_sample_start(sample, thread, evsel);
+	print_sample_start(sample, thread, evsel, PERF_RECORD_MMAP);
 	perf_event__fprintf(event, stdout);
 	thread__put(thread);
 	return 0;
@@ -1532,7 +1575,7 @@
 		sample->tid = event->mmap2.tid;
 		sample->pid = event->mmap2.pid;
 	}
-	print_sample_start(sample, thread, evsel);
+	print_sample_start(sample, thread, evsel, PERF_RECORD_MMAP2);
 	perf_event__fprintf(event, stdout);
 	thread__put(thread);
 	return 0;
@@ -1558,7 +1601,7 @@
 		return -1;
 	}
 
-	print_sample_start(sample, thread, evsel);
+	print_sample_start(sample, thread, evsel, PERF_RECORD_SWITCH);
 	perf_event__fprintf(event, stdout);
 	thread__put(thread);
 	return 0;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1ae95efbfb95..e5fbd6dd1b01 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -205,6 +205,7 @@ struct perf_sample {
 	u32 flags;
 	u16 insn_len;
 	u8  cpumode;
+	u16 misc;
 	char insn[MAX_INSN];
 	void *raw_data;
 	struct ip_callchain *callchain;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index c435b2444153..d934f04e3110 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2042,6 +2042,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
 	data->stream_id = data->id = data->time = -1ULL;
 	data->period = evsel->attr.sample_period;
 	data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+	data->misc    = event->header.misc;

	if (event->header.type != PERF_RECORD_SAMPLE) {
		if (!evsel->attr.sample_id_all)
