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>
This commit is contained in:
Jiri Olsa
2018-01-07 17:03:52 +01:00
committed by Arnaldo Carvalho de Melo
parent 972c148847
commit 28a0b39877
4 changed files with 84 additions and 12 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;