Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c410431c authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo
Browse files

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 895d9766
Loading
Loading
Loading
Loading
+90 −0
Original line number Diff line number Diff line
@@ -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)
{
+3 −0
Original line number Diff line number Diff line
@@ -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);
+11 −16
Original line number Diff line number Diff line
@@ -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;