perf tools: Reconstruct event with modifiers from perf_event_attr
The modifiers: k kernel space u user space h hypervisor G guest H host p, pp, ppp precision level (PEBS) that can be suffixed to an event were lost when tools used event_name() to reconstruct them from the perf_event_attr entries in a perf.data file. Fix it by following the defaults used for these modifiers in the current codebase, so: $ perf record -e instructions:u usleep 1 2> /dev/null $ perf evlist instructions:u $ perf record -e cycles:k usleep 1 2> /dev/null $ perf evlist cycles:k $ perf record -e cycles:kh usleep 1 2> /dev/null $ perf evlist cycles:kh $ perf record -e cache-misses:G usleep 1 2> /dev/null $ perf evlist cache-misses:G $ perf record -e cycles:ppk usleep 1 2> /dev/null $ perf evlist cycles:kpp $ Also works with 'top', 'report', etc. More work needed to cover tracepoints and software events while not dragging lots of baggage to the python binding, this is a minimal fix for v3.5. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-4hl5glle0hxlklw4usva1mkt@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
895d97663c
commit
c410431cef
|
@ -15,6 +15,7 @@
|
||||||
#include "cpumap.h"
|
#include "cpumap.h"
|
||||||
#include "thread_map.h"
|
#include "thread_map.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
#include "../../include/linux/perf_event.h"
|
||||||
|
|
||||||
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
||||||
#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
|
#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
|
||||||
|
@ -64,6 +65,95 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
|
||||||
return evsel;
|
return evsel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
|
||||||
|
"cycles",
|
||||||
|
"instructions",
|
||||||
|
"cache-references",
|
||||||
|
"cache-misses",
|
||||||
|
"branches",
|
||||||
|
"branch-misses",
|
||||||
|
"bus-cycles",
|
||||||
|
"stalled-cycles-frontend",
|
||||||
|
"stalled-cycles-backend",
|
||||||
|
"ref-cycles",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *__perf_evsel__hw_name(u64 config)
|
||||||
|
{
|
||||||
|
if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
|
||||||
|
return perf_evsel__hw_names[config];
|
||||||
|
|
||||||
|
return "unknown-hardware";
|
||||||
|
}
|
||||||
|
|
||||||
|
static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
|
||||||
|
{
|
||||||
|
int colon = 0;
|
||||||
|
struct perf_event_attr *attr = &evsel->attr;
|
||||||
|
int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(attr->config));
|
||||||
|
bool exclude_guest_default = false;
|
||||||
|
|
||||||
|
#define MOD_PRINT(context, mod) do { \
|
||||||
|
if (!attr->exclude_##context) { \
|
||||||
|
if (!colon) colon = r++; \
|
||||||
|
r += scnprintf(bf + r, size - r, "%c", mod); \
|
||||||
|
} } while(0)
|
||||||
|
|
||||||
|
if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv) {
|
||||||
|
MOD_PRINT(kernel, 'k');
|
||||||
|
MOD_PRINT(user, 'u');
|
||||||
|
MOD_PRINT(hv, 'h');
|
||||||
|
exclude_guest_default = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr->precise_ip) {
|
||||||
|
if (!colon)
|
||||||
|
colon = r++;
|
||||||
|
r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
|
||||||
|
exclude_guest_default = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) {
|
||||||
|
MOD_PRINT(host, 'H');
|
||||||
|
MOD_PRINT(guest, 'G');
|
||||||
|
}
|
||||||
|
#undef MOD_PRINT
|
||||||
|
if (colon)
|
||||||
|
bf[colon] = ':';
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
switch (evsel->attr.type) {
|
||||||
|
case PERF_TYPE_RAW:
|
||||||
|
ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PERF_TYPE_HARDWARE:
|
||||||
|
ret = perf_evsel__hw_name(evsel, bf, size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* FIXME
|
||||||
|
*
|
||||||
|
* This is the minimal perf_evsel__name so that we can
|
||||||
|
* reconstruct event names taking into account event modifiers.
|
||||||
|
*
|
||||||
|
* The old event_name uses it now for raw anr hw events, so that
|
||||||
|
* we don't drag all the parsing stuff into the python binding.
|
||||||
|
*
|
||||||
|
* On the next devel cycle the rest of the event naming will be
|
||||||
|
* brought here.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
|
void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
|
||||||
struct perf_evsel *first)
|
struct perf_evsel *first)
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,6 +83,9 @@ void perf_evsel__config(struct perf_evsel *evsel,
|
||||||
struct perf_record_opts *opts,
|
struct perf_record_opts *opts,
|
||||||
struct perf_evsel *first);
|
struct perf_evsel *first);
|
||||||
|
|
||||||
|
const char* __perf_evsel__hw_name(u64 config);
|
||||||
|
int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size);
|
||||||
|
|
||||||
int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
|
int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
|
||||||
int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
|
int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
|
||||||
int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
|
int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
|
||||||
|
|
|
@ -62,19 +62,6 @@ static struct event_symbol event_symbols[] = {
|
||||||
#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
|
#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
|
||||||
#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
|
#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
|
||||||
|
|
||||||
static const char *hw_event_names[PERF_COUNT_HW_MAX] = {
|
|
||||||
"cycles",
|
|
||||||
"instructions",
|
|
||||||
"cache-references",
|
|
||||||
"cache-misses",
|
|
||||||
"branches",
|
|
||||||
"branch-misses",
|
|
||||||
"bus-cycles",
|
|
||||||
"stalled-cycles-frontend",
|
|
||||||
"stalled-cycles-backend",
|
|
||||||
"ref-cycles",
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
|
static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
|
||||||
"cpu-clock",
|
"cpu-clock",
|
||||||
"task-clock",
|
"task-clock",
|
||||||
|
@ -300,6 +287,16 @@ const char *event_name(struct perf_evsel *evsel)
|
||||||
u64 config = evsel->attr.config;
|
u64 config = evsel->attr.config;
|
||||||
int type = evsel->attr.type;
|
int type = evsel->attr.type;
|
||||||
|
|
||||||
|
if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) {
|
||||||
|
/*
|
||||||
|
* XXX minimal fix, see comment on perf_evsen__name, this static buffer
|
||||||
|
* will go away together with event_name in the next devel cycle.
|
||||||
|
*/
|
||||||
|
static char bf[128];
|
||||||
|
perf_evsel__name(evsel, bf, sizeof(bf));
|
||||||
|
return bf;
|
||||||
|
}
|
||||||
|
|
||||||
if (evsel->name)
|
if (evsel->name)
|
||||||
return evsel->name;
|
return evsel->name;
|
||||||
|
|
||||||
|
@ -317,9 +314,7 @@ const char *__event_name(int type, u64 config)
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PERF_TYPE_HARDWARE:
|
case PERF_TYPE_HARDWARE:
|
||||||
if (config < PERF_COUNT_HW_MAX && hw_event_names[config])
|
return __perf_evsel__hw_name(config);
|
||||||
return hw_event_names[config];
|
|
||||||
return "unknown-hardware";
|
|
||||||
|
|
||||||
case PERF_TYPE_HW_CACHE: {
|
case PERF_TYPE_HW_CACHE: {
|
||||||
u8 cache_type, cache_op, cache_result;
|
u8 cache_type, cache_op, cache_result;
|
||||||
|
|
Loading…
Reference in New Issue