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
3 changed files with 104 additions and 16 deletions
|
@ -15,6 +15,7 @@
|
|||
#include "cpumap.h"
|
||||
#include "thread_map.h"
|
||||
#include "target.h"
|
||||
#include "../../include/linux/perf_event.h"
|
||||
|
||||
#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))
|
||||
|
@ -64,6 +65,95 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
|
|||
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,
|
||||
struct perf_evsel *first)
|
||||
{
|
||||
|
|
|
@ -83,6 +83,9 @@ void perf_evsel__config(struct perf_evsel *evsel,
|
|||
struct perf_record_opts *opts,
|
||||
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_id(struct perf_evsel *evsel, int ncpus, int nthreads);
|
||||
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_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] = {
|
||||
"cpu-clock",
|
||||
"task-clock",
|
||||
|
@ -300,6 +287,16 @@ const char *event_name(struct perf_evsel *evsel)
|
|||
u64 config = evsel->attr.config;
|
||||
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)
|
||||
return evsel->name;
|
||||
|
||||
|
@ -317,9 +314,7 @@ const char *__event_name(int type, u64 config)
|
|||
|
||||
switch (type) {
|
||||
case PERF_TYPE_HARDWARE:
|
||||
if (config < PERF_COUNT_HW_MAX && hw_event_names[config])
|
||||
return hw_event_names[config];
|
||||
return "unknown-hardware";
|
||||
return __perf_evsel__hw_name(config);
|
||||
|
||||
case PERF_TYPE_HW_CACHE: {
|
||||
u8 cache_type, cache_op, cache_result;
|
||||
|
|
Loading…
Reference in a new issue