浏览代码

perf script: Add support to display sample misc field

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>
Jiri Olsa 7 年之前
父节点
当前提交
28a0b39877
共有 4 个文件被更改,包括 84 次插入12 次删除
  1. 19 1
      tools/perf/Documentation/perf-script.txt
  2. 63 11
      tools/perf/builtin-script.c
  3. 1 0
      tools/perf/util/event.h
  4. 1 0
      tools/perf/util/evsel.c

+ 19 - 1
tools/perf/Documentation/perf-script.txt

@@ -117,7 +117,7 @@ OPTIONS
         Comma separated list of fields to print. Options are:
         Comma separated list of fields to print. Options are:
         comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
         comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
         srcline, period, iregs, uregs, brstack, brstacksym, flags, bpf-output, brstackinsn,
         srcline, period, iregs, uregs, brstack, brstacksym, flags, bpf-output, brstackinsn,
-	brstackoff, callindent, insn, insnlen, synth, phys_addr, metric.
+        brstackoff, callindent, insn, insnlen, synth, phys_addr, metric, misc.
         Field list can be prepended with the type, trace, sw or hw,
         Field list can be prepended with the type, trace, sw or hw,
         to indicate to which event type the field list applies.
         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
         e.g., -F sw:comm,tid,time,ip,sym  and -F trace:time,cpu,trace
@@ -225,6 +225,24 @@ OPTIONS
 	that the metric computed is averaged over the whole sampling
 	that the metric computed is averaged over the whole sampling
 	period, not just for the sample point.
 	period, not just for the sample point.
 
 
+	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::
 -k::
 --vmlinux=<file>::
 --vmlinux=<file>::
         vmlinux pathname
         vmlinux pathname

+ 63 - 11
tools/perf/builtin-script.c

@@ -93,6 +93,7 @@ enum perf_output_field {
 	PERF_OUTPUT_PHYS_ADDR       = 1U << 26,
 	PERF_OUTPUT_PHYS_ADDR       = 1U << 26,
 	PERF_OUTPUT_UREGS	    = 1U << 27,
 	PERF_OUTPUT_UREGS	    = 1U << 27,
 	PERF_OUTPUT_METRIC	    = 1U << 28,
 	PERF_OUTPUT_METRIC	    = 1U << 28,
+	PERF_OUTPUT_MISC            = 1U << 29,
 };
 };
 
 
 struct output_option {
 struct output_option {
@@ -128,6 +129,7 @@ struct output_option {
 	{.str = "synth", .field = PERF_OUTPUT_SYNTH},
 	{.str = "synth", .field = PERF_OUTPUT_SYNTH},
 	{.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR},
 	{.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR},
 	{.str = "metric", .field = PERF_OUTPUT_METRIC},
 	{.str = "metric", .field = PERF_OUTPUT_METRIC},
+	{.str = "misc", .field = PERF_OUTPUT_MISC},
 };
 };
 
 
 enum {
 enum {
@@ -594,7 +596,8 @@ static int perf_sample__fprintf_uregs(struct perf_sample *sample,
 
 
 static int perf_sample__fprintf_start(struct perf_sample *sample,
 static int perf_sample__fprintf_start(struct perf_sample *sample,
 				      struct thread *thread,
 				      struct thread *thread,
-				      struct perf_evsel *evsel, FILE *fp)
+				      struct perf_evsel *evsel,
+				      u32 type, FILE *fp)
 {
 {
 	struct perf_event_attr *attr = &evsel->attr;
 	struct perf_event_attr *attr = &evsel->attr;
 	unsigned long secs;
 	unsigned long secs;
@@ -624,6 +627,47 @@ static int perf_sample__fprintf_start(struct perf_sample *sample,
 			printed += fprintf(fp, "[%03d] ", sample->cpu);
 			printed += fprintf(fp, "[%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 += fprintf(fp, "K");
+		if (has(USER))
+			ret += fprintf(fp, "U");
+		if (has(HYPERVISOR))
+			ret += fprintf(fp, "H");
+		if (has(GUEST_KERNEL))
+			ret += fprintf(fp, "G");
+		if (has(GUEST_USER))
+			ret += fprintf(fp, "g");
+
+		switch (type) {
+		case PERF_RECORD_MMAP:
+		case PERF_RECORD_MMAP2:
+			if (has(MMAP_DATA))
+				ret += fprintf(fp, "M");
+			break;
+		case PERF_RECORD_COMM:
+			if (has(COMM_EXEC))
+				ret += fprintf(fp, "E");
+			break;
+		case PERF_RECORD_SWITCH:
+		case PERF_RECORD_SWITCH_CPU_WIDE:
+			if (has(SWITCH_OUT))
+				ret += fprintf(fp, "S");
+		default:
+			break;
+		}
+
+		#undef has
+
+		ret += fprintf(fp, "%*s", 6 - ret, " ");
+		printed += ret;
+	}
+
 	if (PRINT_FIELD(TIME)) {
 	if (PRINT_FIELD(TIME)) {
 		nsecs = sample->time;
 		nsecs = sample->time;
 		secs = nsecs / NSEC_PER_SEC;
 		secs = nsecs / NSEC_PER_SEC;
@@ -1502,7 +1546,7 @@ static void script_print_metric(void *ctx, const char *color,
 	if (!fmt)
 	if (!fmt)
 		return;
 		return;
 	perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
 	perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
-				   mctx->fp);
+				   PERF_RECORD_SAMPLE, mctx->fp);
 	fputs("\tmetric: ", mctx->fp);
 	fputs("\tmetric: ", mctx->fp);
 	if (color)
 	if (color)
 		color_fprintf(mctx->fp, color, fmt, val);
 		color_fprintf(mctx->fp, color, fmt, val);
@@ -1516,7 +1560,7 @@ static void script_new_line(void *ctx)
 	struct metric_ctx *mctx = ctx;
 	struct metric_ctx *mctx = ctx;
 
 
 	perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
 	perf_sample__fprintf_start(mctx->sample, mctx->thread, mctx->evsel,
-				   mctx->fp);
+				   PERF_RECORD_SAMPLE, mctx->fp);
 	fputs("\tmetric: ", mctx->fp);
 	fputs("\tmetric: ", mctx->fp);
 }
 }
 
 
@@ -1584,7 +1628,8 @@ static void process_event(struct perf_script *script,
 
 
 	++es->samples;
 	++es->samples;
 
 
-	perf_sample__fprintf_start(sample, thread, evsel, fp);
+	perf_sample__fprintf_start(sample, thread, evsel,
+				   PERF_RECORD_SAMPLE, fp);
 
 
 	if (PRINT_FIELD(PERIOD))
 	if (PRINT_FIELD(PERIOD))
 		fprintf(fp, "%10" PRIu64 " ", sample->period);
 		fprintf(fp, "%10" PRIu64 " ", sample->period);
@@ -1833,7 +1878,8 @@ static int process_comm_event(struct perf_tool *tool,
 		sample->tid = event->comm.tid;
 		sample->tid = event->comm.tid;
 		sample->pid = event->comm.pid;
 		sample->pid = event->comm.pid;
 	}
 	}
-	perf_sample__fprintf_start(sample, thread, evsel, stdout);
+	perf_sample__fprintf_start(sample, thread, evsel,
+				   PERF_RECORD_COMM, stdout);
 	perf_event__fprintf(event, stdout);
 	perf_event__fprintf(event, stdout);
 	ret = 0;
 	ret = 0;
 out:
 out:
@@ -1868,7 +1914,8 @@ static int process_namespaces_event(struct perf_tool *tool,
 		sample->tid = event->namespaces.tid;
 		sample->tid = event->namespaces.tid;
 		sample->pid = event->namespaces.pid;
 		sample->pid = event->namespaces.pid;
 	}
 	}
-	perf_sample__fprintf_start(sample, thread, evsel, stdout);
+	perf_sample__fprintf_start(sample, thread, evsel,
+				   PERF_RECORD_NAMESPACES, stdout);
 	perf_event__fprintf(event, stdout);
 	perf_event__fprintf(event, stdout);
 	ret = 0;
 	ret = 0;
 out:
 out:
@@ -1901,7 +1948,8 @@ static int process_fork_event(struct perf_tool *tool,
 		sample->tid = event->fork.tid;
 		sample->tid = event->fork.tid;
 		sample->pid = event->fork.pid;
 		sample->pid = event->fork.pid;
 	}
 	}
-	perf_sample__fprintf_start(sample, thread, evsel, stdout);
+	perf_sample__fprintf_start(sample, thread, evsel,
+				   PERF_RECORD_FORK, stdout);
 	perf_event__fprintf(event, stdout);
 	perf_event__fprintf(event, stdout);
 	thread__put(thread);
 	thread__put(thread);
 
 
@@ -1930,7 +1978,8 @@ static int process_exit_event(struct perf_tool *tool,
 		sample->tid = event->fork.tid;
 		sample->tid = event->fork.tid;
 		sample->pid = event->fork.pid;
 		sample->pid = event->fork.pid;
 	}
 	}
-	perf_sample__fprintf_start(sample, thread, evsel, stdout);
+	perf_sample__fprintf_start(sample, thread, evsel,
+				   PERF_RECORD_EXIT, stdout);
 	perf_event__fprintf(event, stdout);
 	perf_event__fprintf(event, stdout);
 
 
 	if (perf_event__process_exit(tool, event, sample, machine) < 0)
 	if (perf_event__process_exit(tool, event, sample, machine) < 0)
@@ -1965,7 +2014,8 @@ static int process_mmap_event(struct perf_tool *tool,
 		sample->tid = event->mmap.tid;
 		sample->tid = event->mmap.tid;
 		sample->pid = event->mmap.pid;
 		sample->pid = event->mmap.pid;
 	}
 	}
-	perf_sample__fprintf_start(sample, thread, evsel, stdout);
+	perf_sample__fprintf_start(sample, thread, evsel,
+				   PERF_RECORD_MMAP, stdout);
 	perf_event__fprintf(event, stdout);
 	perf_event__fprintf(event, stdout);
 	thread__put(thread);
 	thread__put(thread);
 	return 0;
 	return 0;
@@ -1996,7 +2046,8 @@ static int process_mmap2_event(struct perf_tool *tool,
 		sample->tid = event->mmap2.tid;
 		sample->tid = event->mmap2.tid;
 		sample->pid = event->mmap2.pid;
 		sample->pid = event->mmap2.pid;
 	}
 	}
-	perf_sample__fprintf_start(sample, thread, evsel, stdout);
+	perf_sample__fprintf_start(sample, thread, evsel,
+				   PERF_RECORD_MMAP2, stdout);
 	perf_event__fprintf(event, stdout);
 	perf_event__fprintf(event, stdout);
 	thread__put(thread);
 	thread__put(thread);
 	return 0;
 	return 0;
@@ -2022,7 +2073,8 @@ static int process_switch_event(struct perf_tool *tool,
 		return -1;
 		return -1;
 	}
 	}
 
 
-	perf_sample__fprintf_start(sample, thread, evsel, stdout);
+	perf_sample__fprintf_start(sample, thread, evsel,
+				   PERF_RECORD_SWITCH, stdout);
 	perf_event__fprintf(event, stdout);
 	perf_event__fprintf(event, stdout);
 	thread__put(thread);
 	thread__put(thread);
 	return 0;
 	return 0;

+ 1 - 0
tools/perf/util/event.h

@@ -205,6 +205,7 @@ struct perf_sample {
 	u32 flags;
 	u32 flags;
 	u16 insn_len;
 	u16 insn_len;
 	u8  cpumode;
 	u8  cpumode;
+	u16 misc;
 	char insn[MAX_INSN];
 	char insn[MAX_INSN];
 	void *raw_data;
 	void *raw_data;
 	struct ip_callchain *callchain;
 	struct ip_callchain *callchain;

+ 1 - 0
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->stream_id = data->id = data->time = -1ULL;
 	data->period = evsel->attr.sample_period;
 	data->period = evsel->attr.sample_period;
 	data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 	data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+	data->misc    = event->header.misc;
 	data->id = -1ULL;
 	data->id = -1ULL;
 	data->data_src = PERF_MEM_DATA_SRC_NONE;
 	data->data_src = PERF_MEM_DATA_SRC_NONE;