2012-10-10 12:54:06

by Jiri Olsa

[permalink] [raw]
Subject: [PATCHv4 0/8] perf, tool: Allow to use hw events in PMU syntax

hi,
here's the change to make following syntax available:
perf stat -e cpu/event=instructions/u ls
perf stat -e cpu/cycles/u ls

this is identical to:
perf stat -e instructions:u ls
perf stat -e cycles:u ls

v4 changes:
- kernel change is now structured differently allowing
to pick up cpu differences
- added support for intel/p6/amd PMUs - intel and amd tested,
did not get p6 server, but should be ok.. feel free to omit

Attached patches:
1/8 perf x86: Making hardware events translations available in sysfs
2/8 perf x86: Filter out undefined events from sysfs events attribute
3/8 perf x86: Adding hardware events translations for intel cpus
4/8 perf x86: Adding hardware events translations for amd cpus
5/8 perf x86: Adding hardware events translations for p6 cpus
6/8 perf tools: Fix pmu object alias initialization
7/8 perf tools: Add support to specify hw event as pmu event term
8/8 perf test: Add automated tests for pmu sysfs translated events

jirka

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
---
arch/x86/kernel/cpu/perf_event.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/cpu/perf_event.h | 2 ++
arch/x86/kernel/cpu/perf_event_amd.c | 9 +++++++
arch/x86/kernel/cpu/perf_event_intel.c | 9 +++++++
arch/x86/kernel/cpu/perf_event_p6.c | 2 ++
include/linux/perf_event.h | 3 +++
tools/perf/util/parse-events-test.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/parse-events.c | 18 ++++++++++++++
tools/perf/util/parse-events.h | 2 ++
tools/perf/util/parse-events.y | 18 ++++++++++++++
tools/perf/util/pmu.c | 7 +++---
11 files changed, 256 insertions(+), 3 deletions(-)


2012-10-10 12:54:25

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 7/8] perf tools: Add support to specify hw event as pmu event term

Adding a way to specify hw event as pmu event term like:
'cpu/event=cpu-cycles/u'
'cpu/event=instructions,.../u'
'cpu/cycles,.../u'

The 'event=cpu-cycles' term is replaced/translated by the hw events
term translation, which is exposed by sysfs 'events' group attribute.

Adding parser bits, the rest is already handled by the pmu alias code.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
---
tools/perf/util/parse-events.c | 18 ++++++++++++++++++
tools/perf/util/parse-events.h | 2 ++
tools/perf/util/parse-events.y | 18 ++++++++++++++++++
3 files changed, 38 insertions(+)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index aed38e4..5ce6f8c 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1139,6 +1139,24 @@ int parse_events__term_str(struct parse_events__term **term,
config, str, 0);
}

+int parse_events__term_sym_hw(struct parse_events__term **term,
+ char *config, unsigned idx)
+{
+ struct event_symbol *sym;
+
+ BUG_ON(idx >= PERF_COUNT_HW_MAX);
+ sym = &event_symbols_hw[idx];
+
+ if (config)
+ return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
+ PARSE_EVENTS__TERM_TYPE_USER, config,
+ (char *) sym->symbol, 0);
+ else
+ return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
+ PARSE_EVENTS__TERM_TYPE_USER,
+ (char *) "event", (char *) sym->symbol, 0);
+}
+
int parse_events__term_clone(struct parse_events__term **new,
struct parse_events__term *term)
{
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index c356e44..6b1e841 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -76,6 +76,8 @@ int parse_events__term_num(struct parse_events__term **_term,
int type_term, char *config, u64 num);
int parse_events__term_str(struct parse_events__term **_term,
int type_term, char *config, char *str);
+int parse_events__term_sym_hw(struct parse_events__term **term,
+ char *config, unsigned idx);
int parse_events__term_clone(struct parse_events__term **new,
struct parse_events__term *term);
void parse_events__free_terms(struct list_head *terms);
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index cd88209..0f9914a 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -352,6 +352,15 @@ PE_NAME '=' PE_VALUE
$$ = term;
}
|
+PE_NAME '=' PE_VALUE_SYM_HW
+{
+ struct parse_events__term *term;
+ int config = $3 & 255;
+
+ ABORT_ON(parse_events__term_sym_hw(&term, $1, config));
+ $$ = term;
+}
+|
PE_NAME
{
struct parse_events__term *term;
@@ -361,6 +370,15 @@ PE_NAME
$$ = term;
}
|
+PE_VALUE_SYM_HW
+{
+ struct parse_events__term *term;
+ int config = $1 & 255;
+
+ ABORT_ON(parse_events__term_sym_hw(&term, NULL, config));
+ $$ = term;
+}
+|
PE_TERM '=' PE_NAME
{
struct parse_events__term *term;
--
1.7.11.4

2012-10-10 12:54:20

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 6/8] perf tools: Fix pmu object alias initialization

The pmu_lookup should return pmus that do not expose the 'events'
group attribute in sysfs. Also it should fail when any other error
during 'events' lookup is hit (pmu_aliases fails).

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
---
tools/perf/util/pmu.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 8a2229d..18e8480 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -164,7 +164,7 @@ static int pmu_aliases(char *name, struct list_head *head)
"%s/bus/event_source/devices/%s/events", sysfs, name);

if (stat(path, &st) < 0)
- return -1;
+ return 0; /* no error if 'events' does not exist */

if (pmu_aliases_parse(path, head))
return -1;
@@ -296,6 +296,9 @@ static struct perf_pmu *pmu_lookup(char *name)
if (pmu_format(name, &format))
return NULL;

+ if (pmu_aliases(name, &aliases))
+ return NULL;
+
if (pmu_type(name, &type))
return NULL;

@@ -305,8 +308,6 @@ static struct perf_pmu *pmu_lookup(char *name)

pmu->cpus = pmu_cpumask(name);

- pmu_aliases(name, &aliases);
-
INIT_LIST_HEAD(&pmu->format);
INIT_LIST_HEAD(&pmu->aliases);
list_splice(&format, &pmu->format);
--
1.7.11.4

2012-10-10 12:54:41

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 8/8] perf test: Add automated tests for pmu sysfs translated events

Adding automated tests for all events found under PMU/events
directory. Tested events are in 'cpu/event=xxx/u' format,
where 'xxx' is substituted by every event found.

The 'event=xxx' term is translated to the cpu specific term.
We only check that the event is created (not the real config
numbers) and that modifier is properly set.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
---
tools/perf/util/parse-events-test.c | 68 +++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)

diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index d7244e5..c9354b6 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -443,6 +443,23 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
return 0;
}

+static int test__checkevent_pmu_events(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+
+ evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong exclude_user",
+ !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel",
+ evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+ return 0;
+}
+
static int test__checkterms_simple(struct list_head *terms)
{
struct parse_events__term *term;
@@ -1020,6 +1037,51 @@ static int test_pmu(void)
return !ret;
}

+static int test_pmu_events(void)
+{
+ struct stat st;
+ char path[PATH_MAX];
+ struct dirent *ent;
+ DIR *dir;
+ int ret;
+
+ snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/events/",
+ sysfs_find_mountpoint());
+
+ ret = stat(path, &st);
+ if (ret) {
+ pr_debug("ommiting PMU cpu events tests\n");
+ return 0;
+ }
+
+ dir = opendir(path);
+ if (!dir) {
+ pr_debug("can't open pmu event dir");
+ return -1;
+ }
+
+ while (!ret && (ent = readdir(dir))) {
+#define MAX_NAME 100
+ struct test__event_st e;
+ char name[MAX_NAME];
+
+ if (!strcmp(ent->d_name, ".") ||
+ !strcmp(ent->d_name, ".."))
+ continue;
+
+ snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name);
+
+ e.name = name;
+ e.check = test__checkevent_pmu_events;
+
+ ret = test_event(&e);
+#undef MAX_NAME
+ }
+
+ closedir(dir);
+ return ret;
+}
+
int parse_events__test(void)
{
int ret1, ret2 = 0;
@@ -1036,6 +1098,12 @@ do { \
if (test_pmu())
TEST_EVENTS(test__events_pmu);

+ if (test_pmu()) {
+ int ret = test_pmu_events();
+ if (ret)
+ return ret;
+ }
+
ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
if (!ret2)
ret2 = ret1;
--
1.7.11.4

2012-10-10 12:58:58

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 1/8] perf x86: Making hardware events translations available in sysfs

Adding support to display hardware events translations available
through the sysfs. Adding 'events' group attribute under the sysfs
x86 PMU record with attribute/file for each hardware event.

This patch adds only backbone for PMUs to display config under
'events' directory. The specific PMU support itself will come
in next patches, however this is how the sysfs group will look
like:

# ls /sys/devices/cpu/events/
branch-instructions
branch-misses
bus-cycles
cache-misses
cache-references
cpu-cycles
instructions
ref-cycles
stalled-cycles-backend
stalled-cycles-frontend

The file - hw event ID mappings is:

file hw event ID
---------------------------------------------------------------
cpu-cycles PERF_COUNT_HW_CPU_CYCLES
instructions PERF_COUNT_HW_INSTRUCTIONS
cache-references PERF_COUNT_HW_CACHE_REFERENCES
cache-misses PERF_COUNT_HW_CACHE_MISSES
branch-instructions PERF_COUNT_HW_BRANCH_INSTRUCTIONS
branch-misses PERF_COUNT_HW_BRANCH_MISSES
bus-cycles PERF_COUNT_HW_BUS_CYCLES
stalled-cycles-frontend PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
stalled-cycles-backend PERF_COUNT_HW_STALLED_CYCLES_BACKEND
ref-cycles PERF_COUNT_HW_REF_CPU_CYCLES

Each file in 'events' directory contains term translation for
the symbolic hw event for the currently running cpu model.

# cat /sys/devices/cpu/events/stalled-cycles-backend
event=0xb1,umask=0x01,inv,cmask=0x01

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
---
arch/x86/kernel/cpu/perf_event.c | 60 ++++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/cpu/perf_event.h | 2 ++
2 files changed, 62 insertions(+)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 915b876..bff2eaa 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1308,6 +1308,62 @@ static struct attribute_group x86_pmu_format_group = {
.attrs = NULL,
};

+struct perf_pmu_events_attr {
+ struct device_attribute attr;
+ u64 id;
+};
+
+ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
+ char *page)
+{
+ struct perf_pmu_events_attr *pmu_attr = \
+ container_of(attr, struct perf_pmu_events_attr, attr);
+
+ u64 config = x86_pmu.event_map(pmu_attr->id);
+ return x86_pmu.events_sysfs_show(page, config);
+}
+
+#define EVENT_VAR(_id) event_attr_##_id
+#define EVENT_PTR(_id) &event_attr_##_id.attr.attr
+
+#define EVENT_ATTR(_name, _id) \
+static struct perf_pmu_events_attr EVENT_VAR(_id) = { \
+ .attr = __ATTR(_name, 0444, events_sysfs_show, NULL), \
+ .id = PERF_COUNT_HW_##_id, \
+};
+
+EVENT_ATTR(cpu-cycles, CPU_CYCLES );
+EVENT_ATTR(instructions, INSTRUCTIONS );
+EVENT_ATTR(cache-references, CACHE_REFERENCES );
+EVENT_ATTR(cache-misses, CACHE_MISSES );
+EVENT_ATTR(branch-instructions, BRANCH_INSTRUCTIONS );
+EVENT_ATTR(branch-misses, BRANCH_MISSES );
+EVENT_ATTR(bus-cycles, BUS_CYCLES );
+EVENT_ATTR(stalled-cycles-frontend, STALLED_CYCLES_FRONTEND );
+EVENT_ATTR(stalled-cycles-backend, STALLED_CYCLES_BACKEND );
+EVENT_ATTR(ref-cycles, REF_CPU_CYCLES );
+
+static struct attribute *empty_attrs;
+
+struct attribute *events_attr[] = {
+ EVENT_PTR(CPU_CYCLES),
+ EVENT_PTR(INSTRUCTIONS),
+ EVENT_PTR(CACHE_REFERENCES),
+ EVENT_PTR(CACHE_MISSES),
+ EVENT_PTR(BRANCH_INSTRUCTIONS),
+ EVENT_PTR(BRANCH_MISSES),
+ EVENT_PTR(BUS_CYCLES),
+ EVENT_PTR(STALLED_CYCLES_FRONTEND),
+ EVENT_PTR(STALLED_CYCLES_BACKEND),
+ EVENT_PTR(REF_CPU_CYCLES),
+ NULL,
+};
+
+static struct attribute_group x86_pmu_events_group = {
+ .name = "events",
+ .attrs = events_attr,
+};
+
static int __init init_hw_perf_events(void)
{
struct x86_pmu_quirk *quirk;
@@ -1354,6 +1410,9 @@ static int __init init_hw_perf_events(void)
x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
x86_pmu_format_group.attrs = x86_pmu.format_attrs;

+ if (!x86_pmu.events_sysfs_show)
+ x86_pmu_events_group.attrs = &empty_attrs;
+
pr_info("... version: %d\n", x86_pmu.version);
pr_info("... bit width: %d\n", x86_pmu.cntval_bits);
pr_info("... generic registers: %d\n", x86_pmu.num_counters);
@@ -1643,6 +1702,7 @@ static struct attribute_group x86_pmu_attr_group = {
static const struct attribute_group *x86_pmu_attr_groups[] = {
&x86_pmu_attr_group,
&x86_pmu_format_group,
+ &x86_pmu_events_group,
NULL,
};

diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 6605a81..63e223b 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -354,6 +354,8 @@ struct x86_pmu {
int attr_rdpmc;
struct attribute **format_attrs;

+ ssize_t (*events_sysfs_show)(char *page, u64 config);
+
/*
* CPU Hotplug hooks
*/
--
1.7.11.4

2012-10-10 12:55:08

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 5/8] perf x86: Adding hardware events translations for p6 cpus

Adding support for p6 processors to display 'events' sysfs
directory (/sys/devices/cpu/events/) with hw event translations.

# ls /sys/devices/cpu/events/
branch-instructions
branch-misses
bus-cycles
cache-misses
cache-references
cpu-cycles
instructions
ref-cycles
stalled-cycles-backend
stalled-cycles-frontend

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
---
arch/x86/kernel/cpu/perf_event_p6.c | 2 ++
include/linux/perf_event.h | 1 +
2 files changed, 3 insertions(+)

diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
index e4dd0f7..900b76b 100644
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -134,6 +134,8 @@ static __initconst const struct x86_pmu p6_pmu = {
.event_constraints = p6_event_constraints,

.format_attrs = intel_p6_formats_attr,
+ .events_sysfs_show = intel_event_sysfs_show,
+
};

__init int p6_pmu_init(void)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 827c374..6e48be0 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1419,6 +1419,7 @@ _name##_show(struct device *dev, \
static struct device_attribute format_attr_##_name = __ATTR_RO(_name)

ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event);
+ssize_t intel_event_sysfs_show(char *page, u64 config);

#endif /* __KERNEL__ */
#endif /* _LINUX_PERF_EVENT_H */
--
1.7.11.4

2012-10-10 14:12:08

by Peter Zijlstra

[permalink] [raw]
Subject: Re: [PATCH 4/8] perf x86: Adding hardware events translations for amd cpus

On Wed, 2012-10-10 at 14:53 +0200, Jiri Olsa wrote:
> +static ssize_t amd_event_sysfs_show(char *page, u64 config)
> +{
> + u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
> + (config & AMD64_EVENTSEL_EVENT) >> 24;
> +
> + return x86_event_sysfs_show(page, config, event);
> +}

You'll need to filter out 0xF<<32 bits before passing them on in
@config, Intel has a different meaning for them.

2012-10-10 14:25:48

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 4/8] perf x86: Adding hardware events translations for amd cpus

On Wed, Oct 10, 2012 at 04:11:42PM +0200, Peter Zijlstra wrote:
> On Wed, 2012-10-10 at 14:53 +0200, Jiri Olsa wrote:
> > +static ssize_t amd_event_sysfs_show(char *page, u64 config)
> > +{
> > + u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
> > + (config & AMD64_EVENTSEL_EVENT) >> 24;
> > +
> > + return x86_event_sysfs_show(page, config, event);
> > +}
>
> You'll need to filter out 0xF<<32 bits before passing them on in
> @config, Intel has a different meaning for them.

Right, that would be those 'intx and intx_cp' bits we discussed, right?

My thinking was to customize this once those bits are introduced and
part of the format stuff. Until that time the x86_event_sysfs_show
function shows proper data for both amd and intel. Or is it already
on its way in?

jirka

2012-10-10 12:59:10

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 2/8] perf x86: Filter out undefined events from sysfs events attribute

The sysfs events group attribute currently shows all hw events,
including also undefined ones.

This patch filters out all undefined events out of the sysfs events
group attribute, so they don't even show up.

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
---
arch/x86/kernel/cpu/perf_event.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index bff2eaa..9b6f83c 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1313,6 +1313,26 @@ struct perf_pmu_events_attr {
u64 id;
};

+/*
+ * Remove all undefined events (x86_pmu.event_map(id) == 0)
+ * out of events_attr attributes.
+ */
+static void __init filter_events(struct attribute **attrs)
+{
+ int i, j;
+
+ for (i = 0; attrs[i]; i++) {
+ if (x86_pmu.event_map(i))
+ continue;
+
+ for (j = i; attrs[j]; j++)
+ attrs[j] = attrs[j + 1];
+
+ /* Check the shifted attr. */
+ i--;
+ }
+}
+
ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
char *page)
{
@@ -1412,6 +1432,8 @@ static int __init init_hw_perf_events(void)

if (!x86_pmu.events_sysfs_show)
x86_pmu_events_group.attrs = &empty_attrs;
+ else
+ filter_events(x86_pmu_events_group.attrs);

pr_info("... version: %d\n", x86_pmu.version);
pr_info("... bit width: %d\n", x86_pmu.cntval_bits);
--
1.7.11.4

2012-10-10 13:34:56

by Stephane Eranian

[permalink] [raw]
Subject: Re: [PATCHv4 0/8] perf, tool: Allow to use hw events in PMU syntax

On Wed, Oct 10, 2012 at 2:53 PM, Jiri Olsa <[email protected]> wrote:
> hi,
> here's the change to make following syntax available:
> perf stat -e cpu/event=instructions/u ls
> perf stat -e cpu/cycles/u ls
>
Unless, I am mistaken but I did not see in your patch where you adjust the list
of generic Hw events (and encodings) you expose via sysfs based on CPU model
number. Some generic HW PMU may not have actual physical mappings. Look
at IvyBridge, for instance.


> this is identical to:
> perf stat -e instructions:u ls
> perf stat -e cycles:u ls
>
> v4 changes:
> - kernel change is now structured differently allowing
> to pick up cpu differences
> - added support for intel/p6/amd PMUs - intel and amd tested,
> did not get p6 server, but should be ok.. feel free to omit
>
> Attached patches:
> 1/8 perf x86: Making hardware events translations available in sysfs
> 2/8 perf x86: Filter out undefined events from sysfs events attribute
> 3/8 perf x86: Adding hardware events translations for intel cpus
> 4/8 perf x86: Adding hardware events translations for amd cpus
> 5/8 perf x86: Adding hardware events translations for p6 cpus
> 6/8 perf tools: Fix pmu object alias initialization
> 7/8 perf tools: Add support to specify hw event as pmu event term
> 8/8 perf test: Add automated tests for pmu sysfs translated events
>
> jirka
>
> Suggested-by: Peter Zijlstra <[email protected]>
> Signed-off-by: Jiri Olsa <[email protected]>
> Cc: Arnaldo Carvalho de Melo <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Corey Ashford <[email protected]>
> Cc: Frederic Weisbecker <[email protected]>
> Cc: Stephane Eranian <[email protected]>
> ---
> arch/x86/kernel/cpu/perf_event.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> arch/x86/kernel/cpu/perf_event.h | 2 ++
> arch/x86/kernel/cpu/perf_event_amd.c | 9 +++++++
> arch/x86/kernel/cpu/perf_event_intel.c | 9 +++++++
> arch/x86/kernel/cpu/perf_event_p6.c | 2 ++
> include/linux/perf_event.h | 3 +++
> tools/perf/util/parse-events-test.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
> tools/perf/util/parse-events.c | 18 ++++++++++++++
> tools/perf/util/parse-events.h | 2 ++
> tools/perf/util/parse-events.y | 18 ++++++++++++++
> tools/perf/util/pmu.c | 7 +++---
> 11 files changed, 256 insertions(+), 3 deletions(-)

2012-10-10 13:41:20

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCHv4 0/8] perf, tool: Allow to use hw events in PMU syntax

On Wed, Oct 10, 2012 at 03:34:53PM +0200, Stephane Eranian wrote:
> On Wed, Oct 10, 2012 at 2:53 PM, Jiri Olsa <[email protected]> wrote:
> > hi,
> > here's the change to make following syntax available:
> > perf stat -e cpu/event=instructions/u ls
> > perf stat -e cpu/cycles/u ls
> >
> Unless, I am mistaken but I did not see in your patch where you adjust the list
> of generic Hw events (and encodings) you expose via sysfs based on CPU model
> number. Some generic HW PMU may not have actual physical mappings. Look
> at IvyBridge, for instance.

hm, path 2 remove any attribute that is not defined via x86_pmu.event_map,
if that's what you mean..

jirka

2012-10-10 13:44:12

by Stephane Eranian

[permalink] [raw]
Subject: Re: [PATCHv4 0/8] perf, tool: Allow to use hw events in PMU syntax

On Wed, Oct 10, 2012 at 3:40 PM, Jiri Olsa <[email protected]> wrote:
> On Wed, Oct 10, 2012 at 03:34:53PM +0200, Stephane Eranian wrote:
>> On Wed, Oct 10, 2012 at 2:53 PM, Jiri Olsa <[email protected]> wrote:
>> > hi,
>> > here's the change to make following syntax available:
>> > perf stat -e cpu/event=instructions/u ls
>> > perf stat -e cpu/cycles/u ls
>> >
>> Unless, I am mistaken but I did not see in your patch where you adjust the list
>> of generic Hw events (and encodings) you expose via sysfs based on CPU model
>> number. Some generic HW PMU may not have actual physical mappings. Look
>> at IvyBridge, for instance.
>
> hm, path 2 remove any attribute that is not defined via x86_pmu.event_map,
> if that's what you mean..
>
Ok, you're right, so this should be okay then.
Thanks.

> jirka

2012-10-10 12:55:28

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 3/8] perf x86: Adding hardware events translations for intel cpus

Adding support for intel processors to display 'events' sysfs
directory (/sys/devices/cpu/events/) with hw event translations.

# ls /sys/devices/cpu/events/
branch-instructions
branch-misses
bus-cycles
cache-misses
cache-references
cpu-cycles
instructions
ref-cycles
stalled-cycles-backend
stalled-cycles-frontend

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
---
arch/x86/kernel/cpu/perf_event.c | 40 ++++++++++++++++++++++++++++++++++
arch/x86/kernel/cpu/perf_event_intel.c | 2 ++
include/linux/perf_event.h | 2 ++
3 files changed, 44 insertions(+)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 9b6f83c..1fbf319 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1384,6 +1384,46 @@ static struct attribute_group x86_pmu_events_group = {
.attrs = events_attr,
};

+ssize_t x86_event_sysfs_show(char *page, u64 config)
+{
+ u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT);
+ u64 umask = (config & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
+ u64 cmask = (config & ARCH_PERFMON_EVENTSEL_CMASK) >> 24;
+ bool edge = (config & ARCH_PERFMON_EVENTSEL_EDGE);
+ bool pc = (config & ARCH_PERFMON_EVENTSEL_PIN_CONTROL);
+ bool any = (config & ARCH_PERFMON_EVENTSEL_ANY);
+ bool inv = (config & ARCH_PERFMON_EVENTSEL_INV);
+ ssize_t ret;
+
+ /*
+ * We have whole page size to spend and just little data
+ * to write, so we can safely use sprintf.
+ */
+ ret = sprintf(page, "event=0x%02llx", event);
+
+ if (umask)
+ ret += sprintf(page + ret, ",umask=0x%02llx", umask);
+
+ if (edge)
+ ret += sprintf(page + ret, ",edge");
+
+ if (pc)
+ ret += sprintf(page + ret, ",pc");
+
+ if (any)
+ ret += sprintf(page + ret, ",any");
+
+ if (inv)
+ ret += sprintf(page + ret, ",inv");
+
+ if (cmask)
+ ret += sprintf(page + ret, ",cmask=0x%02llx", cmask);
+
+ ret += sprintf(page + ret, "\n");
+
+ return ret;
+}
+
static int __init init_hw_perf_events(void)
{
struct x86_pmu_quirk *quirk;
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 7f2739e..f711ca2 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1628,6 +1628,7 @@ static __initconst const struct x86_pmu core_pmu = {
.event_constraints = intel_core_event_constraints,
.guest_get_msrs = core_guest_get_msrs,
.format_attrs = intel_arch_formats_attr,
+ .events_sysfs_show = x86_event_sysfs_show,
};

struct intel_shared_regs *allocate_shared_regs(int cpu)
@@ -1766,6 +1767,7 @@ static __initconst const struct x86_pmu intel_pmu = {
.pebs_aliases = intel_pebs_aliases_core2,

.format_attrs = intel_arch3_formats_attr,
+ .events_sysfs_show = x86_event_sysfs_show,

.cpu_prepare = intel_pmu_cpu_prepare,
.cpu_starting = intel_pmu_cpu_starting,
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 28f9cee..ee9c9d0 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1418,5 +1418,7 @@ _name##_show(struct device *dev, \
\
static struct device_attribute format_attr_##_name = __ATTR_RO(_name)

+ssize_t x86_event_sysfs_show(char *page, u64 config);
+
#endif /* __KERNEL__ */
#endif /* _LINUX_PERF_EVENT_H */
--
1.7.11.4

2012-10-10 12:54:13

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 4/8] perf x86: Adding hardware events translations for amd cpus

Adding support for amd processors to display 'events' sysfs
directory (/sys/devices/cpu/events/) with hw event translations.

# ls /sys/devices/cpu/events/
branch-instructions
branch-misses
bus-cycles
cache-misses
cache-references
cpu-cycles
instructions
ref-cycles
stalled-cycles-backend
stalled-cycles-frontend

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
---
arch/x86/kernel/cpu/perf_event.c | 3 +--
arch/x86/kernel/cpu/perf_event_amd.c | 9 +++++++++
arch/x86/kernel/cpu/perf_event_intel.c | 11 +++++++++--
include/linux/perf_event.h | 2 +-
4 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 1fbf319..476dab0 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1384,9 +1384,8 @@ static struct attribute_group x86_pmu_events_group = {
.attrs = events_attr,
};

-ssize_t x86_event_sysfs_show(char *page, u64 config)
+ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event)
{
- u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT);
u64 umask = (config & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
u64 cmask = (config & ARCH_PERFMON_EVENTSEL_CMASK) >> 24;
bool edge = (config & ARCH_PERFMON_EVENTSEL_EDGE);
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index 4528ae7..c93bc4e 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -568,6 +568,14 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
}
}

+static ssize_t amd_event_sysfs_show(char *page, u64 config)
+{
+ u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
+ (config & AMD64_EVENTSEL_EVENT) >> 24;
+
+ return x86_event_sysfs_show(page, config, event);
+}
+
static __initconst const struct x86_pmu amd_pmu = {
.name = "AMD",
.handle_irq = x86_pmu_handle_irq,
@@ -591,6 +599,7 @@ static __initconst const struct x86_pmu amd_pmu = {
.put_event_constraints = amd_put_event_constraints,

.format_attrs = amd_format_attr,
+ .events_sysfs_show = amd_event_sysfs_show,

.cpu_prepare = amd_pmu_cpu_prepare,
.cpu_starting = amd_pmu_cpu_starting,
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index f711ca2..fe50274 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1603,6 +1603,13 @@ static struct attribute *intel_arch_formats_attr[] = {
NULL,
};

+ssize_t intel_event_sysfs_show(char *page, u64 config)
+{
+ u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT);
+
+ return x86_event_sysfs_show(page, config, event);
+}
+
static __initconst const struct x86_pmu core_pmu = {
.name = "core",
.handle_irq = x86_pmu_handle_irq,
@@ -1628,7 +1635,7 @@ static __initconst const struct x86_pmu core_pmu = {
.event_constraints = intel_core_event_constraints,
.guest_get_msrs = core_guest_get_msrs,
.format_attrs = intel_arch_formats_attr,
- .events_sysfs_show = x86_event_sysfs_show,
+ .events_sysfs_show = intel_event_sysfs_show,
};

struct intel_shared_regs *allocate_shared_regs(int cpu)
@@ -1767,7 +1774,7 @@ static __initconst const struct x86_pmu intel_pmu = {
.pebs_aliases = intel_pebs_aliases_core2,

.format_attrs = intel_arch3_formats_attr,
- .events_sysfs_show = x86_event_sysfs_show,
+ .events_sysfs_show = intel_event_sysfs_show,

.cpu_prepare = intel_pmu_cpu_prepare,
.cpu_starting = intel_pmu_cpu_starting,
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index ee9c9d0..827c374 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1418,7 +1418,7 @@ _name##_show(struct device *dev, \
\
static struct device_attribute format_attr_##_name = __ATTR_RO(_name)

-ssize_t x86_event_sysfs_show(char *page, u64 config);
+ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event);

#endif /* __KERNEL__ */
#endif /* _LINUX_PERF_EVENT_H */
--
1.7.11.4

2012-10-10 14:38:55

by Peter Zijlstra

[permalink] [raw]
Subject: Re: [PATCH 4/8] perf x86: Adding hardware events translations for amd cpus

On Wed, 2012-10-10 at 16:25 +0200, Jiri Olsa wrote:
> On Wed, Oct 10, 2012 at 04:11:42PM +0200, Peter Zijlstra wrote:
> > On Wed, 2012-10-10 at 14:53 +0200, Jiri Olsa wrote:
> > > +static ssize_t amd_event_sysfs_show(char *page, u64 config)
> > > +{
> > > + u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
> > > + (config & AMD64_EVENTSEL_EVENT) >> 24;
> > > +
> > > + return x86_event_sysfs_show(page, config, event);
> > > +}
> >
> > You'll need to filter out 0xF<<32 bits before passing them on in
> > @config, Intel has a different meaning for them.
>
> Right, that would be those 'intx and intx_cp' bits we discussed, right?

Right.

> My thinking was to customize this once those bits are introduced and
> part of the format stuff. Until that time the x86_event_sysfs_show
> function shows proper data for both amd and intel. Or is it already
> on its way in?

No thats fine, just something we shouldn't forget about. They're in Andi
Kleen's HSW patches, I need to go over the v2 of that.

2012-10-23 15:06:01

by Peter Zijlstra

[permalink] [raw]
Subject: Re: [PATCHv4 0/8] perf, tool: Allow to use hw events in PMU syntax

On Wed, 2012-10-10 at 14:53 +0200, Jiri Olsa wrote:
> arch/x86/kernel/cpu/perf_event.c | 121
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> arch/x86/kernel/cpu/perf_event.h | 2 ++
> arch/x86/kernel/cpu/perf_event_amd.c | 9 +++++++
> arch/x86/kernel/cpu/perf_event_intel.c | 9 +++++++
> arch/x86/kernel/cpu/perf_event_p6.c | 2 ++
> include/linux/perf_event.h | 3 +++

These bits look like they want to live in
arch/x86/kernel/cpu/perf_event.h, they're rather x86 specific. I moved
them over.

> tools/perf/util/parse-events-test.c | 68
> ++++++++++++++++++++++++++++++++++++++++++++++++++
> tools/perf/util/parse-events.c | 18 ++++++++++++++
> tools/perf/util/parse-events.h | 2 ++
> tools/perf/util/parse-events.y | 18 ++++++++++++++
> tools/perf/util/pmu.c | 7 +++---
> 11 files changed, 256 insertions(+), 3 deletions(-)

Acme, you ok with these bits?

2012-10-24 10:04:15

by Jiri Olsa

[permalink] [raw]
Subject: [tip:perf/core] perf/x86: Make hardware event translations available in sysfs

Commit-ID: a47473939db20e3961b200eb00acf5fcf084d755
Gitweb: http://git.kernel.org/tip/a47473939db20e3961b200eb00acf5fcf084d755
Author: Jiri Olsa <[email protected]>
AuthorDate: Wed, 10 Oct 2012 14:53:11 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Oct 2012 10:41:23 +0200

perf/x86: Make hardware event translations available in sysfs

Add support to display hardware events translations available
through the sysfs. Add 'events' group attribute under the sysfs
x86 PMU record with attribute/file for each hardware event.

This patch adds only backbone for PMUs to display config under
'events' directory. The specific PMU support itself will come
in next patches, however this is how the sysfs group will look
like:

# ls /sys/devices/cpu/events/
branch-instructions
branch-misses
bus-cycles
cache-misses
cache-references
cpu-cycles
instructions
ref-cycles
stalled-cycles-backend
stalled-cycles-frontend

The file - hw event ID mapping is:

file hw event ID
---------------------------------------------------------------
cpu-cycles PERF_COUNT_HW_CPU_CYCLES
instructions PERF_COUNT_HW_INSTRUCTIONS
cache-references PERF_COUNT_HW_CACHE_REFERENCES
cache-misses PERF_COUNT_HW_CACHE_MISSES
branch-instructions PERF_COUNT_HW_BRANCH_INSTRUCTIONS
branch-misses PERF_COUNT_HW_BRANCH_MISSES
bus-cycles PERF_COUNT_HW_BUS_CYCLES
stalled-cycles-frontend PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
stalled-cycles-backend PERF_COUNT_HW_STALLED_CYCLES_BACKEND
ref-cycles PERF_COUNT_HW_REF_CPU_CYCLES

Each file in the 'events' directory contains the term translation
for the symbolic hw event for the currently running cpu model.

# cat /sys/devices/cpu/events/stalled-cycles-backend
event=0xb1,umask=0x01,inv,cmask=0x01

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Signed-off-by: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/cpu/perf_event.c | 60 ++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/cpu/perf_event.h | 2 +
2 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 4a3374e..9fa4c45 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1316,6 +1316,62 @@ static struct attribute_group x86_pmu_format_group = {
.attrs = NULL,
};

+struct perf_pmu_events_attr {
+ struct device_attribute attr;
+ u64 id;
+};
+
+ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
+ char *page)
+{
+ struct perf_pmu_events_attr *pmu_attr = \
+ container_of(attr, struct perf_pmu_events_attr, attr);
+
+ u64 config = x86_pmu.event_map(pmu_attr->id);
+ return x86_pmu.events_sysfs_show(page, config);
+}
+
+#define EVENT_VAR(_id) event_attr_##_id
+#define EVENT_PTR(_id) &event_attr_##_id.attr.attr
+
+#define EVENT_ATTR(_name, _id) \
+static struct perf_pmu_events_attr EVENT_VAR(_id) = { \
+ .attr = __ATTR(_name, 0444, events_sysfs_show, NULL), \
+ .id = PERF_COUNT_HW_##_id, \
+};
+
+EVENT_ATTR(cpu-cycles, CPU_CYCLES );
+EVENT_ATTR(instructions, INSTRUCTIONS );
+EVENT_ATTR(cache-references, CACHE_REFERENCES );
+EVENT_ATTR(cache-misses, CACHE_MISSES );
+EVENT_ATTR(branch-instructions, BRANCH_INSTRUCTIONS );
+EVENT_ATTR(branch-misses, BRANCH_MISSES );
+EVENT_ATTR(bus-cycles, BUS_CYCLES );
+EVENT_ATTR(stalled-cycles-frontend, STALLED_CYCLES_FRONTEND );
+EVENT_ATTR(stalled-cycles-backend, STALLED_CYCLES_BACKEND );
+EVENT_ATTR(ref-cycles, REF_CPU_CYCLES );
+
+static struct attribute *empty_attrs;
+
+struct attribute *events_attr[] = {
+ EVENT_PTR(CPU_CYCLES),
+ EVENT_PTR(INSTRUCTIONS),
+ EVENT_PTR(CACHE_REFERENCES),
+ EVENT_PTR(CACHE_MISSES),
+ EVENT_PTR(BRANCH_INSTRUCTIONS),
+ EVENT_PTR(BRANCH_MISSES),
+ EVENT_PTR(BUS_CYCLES),
+ EVENT_PTR(STALLED_CYCLES_FRONTEND),
+ EVENT_PTR(STALLED_CYCLES_BACKEND),
+ EVENT_PTR(REF_CPU_CYCLES),
+ NULL,
+};
+
+static struct attribute_group x86_pmu_events_group = {
+ .name = "events",
+ .attrs = events_attr,
+};
+
static int __init init_hw_perf_events(void)
{
struct x86_pmu_quirk *quirk;
@@ -1362,6 +1418,9 @@ static int __init init_hw_perf_events(void)
x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
x86_pmu_format_group.attrs = x86_pmu.format_attrs;

+ if (!x86_pmu.events_sysfs_show)
+ x86_pmu_events_group.attrs = &empty_attrs;
+
pr_info("... version: %d\n", x86_pmu.version);
pr_info("... bit width: %d\n", x86_pmu.cntval_bits);
pr_info("... generic registers: %d\n", x86_pmu.num_counters);
@@ -1651,6 +1710,7 @@ static struct attribute_group x86_pmu_attr_group = {
static const struct attribute_group *x86_pmu_attr_groups[] = {
&x86_pmu_attr_group,
&x86_pmu_format_group,
+ &x86_pmu_events_group,
NULL,
};

diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 271d257..6f75b6a 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -354,6 +354,8 @@ struct x86_pmu {
int attr_rdpmc;
struct attribute **format_attrs;

+ ssize_t (*events_sysfs_show)(char *page, u64 config);
+
/*
* CPU Hotplug hooks
*/

2012-10-24 10:04:56

by Jiri Olsa

[permalink] [raw]
Subject: [tip:perf/core] perf/x86: Filter out undefined events from sysfs events attribute

Commit-ID: 8300daa26755c9a194776778bd822acf1fa2dbf6
Gitweb: http://git.kernel.org/tip/8300daa26755c9a194776778bd822acf1fa2dbf6
Author: Jiri Olsa <[email protected]>
AuthorDate: Wed, 10 Oct 2012 14:53:12 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Oct 2012 10:41:24 +0200

perf/x86: Filter out undefined events from sysfs events attribute

The sysfs events group attribute currently shows all hw events,
including also undefined ones.

This patch filters out all undefined events out of the sysfs events
group attribute, so they don't even show up.

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
Signed-off-by: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/cpu/perf_event.c | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 9fa4c45..39737a6 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1321,6 +1321,26 @@ struct perf_pmu_events_attr {
u64 id;
};

+/*
+ * Remove all undefined events (x86_pmu.event_map(id) == 0)
+ * out of events_attr attributes.
+ */
+static void __init filter_events(struct attribute **attrs)
+{
+ int i, j;
+
+ for (i = 0; attrs[i]; i++) {
+ if (x86_pmu.event_map(i))
+ continue;
+
+ for (j = i; attrs[j]; j++)
+ attrs[j] = attrs[j + 1];
+
+ /* Check the shifted attr. */
+ i--;
+ }
+}
+
ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
char *page)
{
@@ -1420,6 +1440,8 @@ static int __init init_hw_perf_events(void)

if (!x86_pmu.events_sysfs_show)
x86_pmu_events_group.attrs = &empty_attrs;
+ else
+ filter_events(x86_pmu_events_group.attrs);

pr_info("... version: %d\n", x86_pmu.version);
pr_info("... bit width: %d\n", x86_pmu.cntval_bits);

2012-10-24 10:07:03

by Jiri Olsa

[permalink] [raw]
Subject: [tip:perf/core] perf/x86: Add hardware events translations for AMD cpus

Commit-ID: 0bf79d44133de42af01a70a1700b8bb4b6d3fb92
Gitweb: http://git.kernel.org/tip/0bf79d44133de42af01a70a1700b8bb4b6d3fb92
Author: Jiri Olsa <[email protected]>
AuthorDate: Wed, 10 Oct 2012 14:53:14 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Oct 2012 10:41:25 +0200

perf/x86: Add hardware events translations for AMD cpus

Add support for AMD processors to display 'events' sysfs
directory (/sys/devices/cpu/events/) with hw event translations:

# ls /sys/devices/cpu/events/
branch-instructions
branch-misses
bus-cycles
cache-misses
cache-references
cpu-cycles
instructions
ref-cycles
stalled-cycles-backend
stalled-cycles-frontend

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Signed-off-by: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/cpu/perf_event.c | 3 +--
arch/x86/kernel/cpu/perf_event.h | 2 +-
arch/x86/kernel/cpu/perf_event_amd.c | 9 +++++++++
arch/x86/kernel/cpu/perf_event_intel.c | 11 +++++++++--
4 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 8a1fa23..0a55ab2 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1392,9 +1392,8 @@ static struct attribute_group x86_pmu_events_group = {
.attrs = events_attr,
};

-ssize_t x86_event_sysfs_show(char *page, u64 config)
+ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event)
{
- u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT);
u64 umask = (config & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
u64 cmask = (config & ARCH_PERFMON_EVENTSEL_CMASK) >> 24;
bool edge = (config & ARCH_PERFMON_EVENTSEL_EDGE);
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index f8aa2f6..21419b9 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -538,7 +538,7 @@ static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip)
regs->ip = ip;
}

-ssize_t x86_event_sysfs_show(char *page, u64 config);
+ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event);

#ifdef CONFIG_CPU_SUP_AMD

diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index 4528ae7..c93bc4e 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -568,6 +568,14 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
}
}

+static ssize_t amd_event_sysfs_show(char *page, u64 config)
+{
+ u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
+ (config & AMD64_EVENTSEL_EVENT) >> 24;
+
+ return x86_event_sysfs_show(page, config, event);
+}
+
static __initconst const struct x86_pmu amd_pmu = {
.name = "AMD",
.handle_irq = x86_pmu_handle_irq,
@@ -591,6 +599,7 @@ static __initconst const struct x86_pmu amd_pmu = {
.put_event_constraints = amd_put_event_constraints,

.format_attrs = amd_format_attr,
+ .events_sysfs_show = amd_event_sysfs_show,

.cpu_prepare = amd_pmu_cpu_prepare,
.cpu_starting = amd_pmu_cpu_starting,
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 6106d3b..93b9e11 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1603,6 +1603,13 @@ static struct attribute *intel_arch_formats_attr[] = {
NULL,
};

+ssize_t intel_event_sysfs_show(char *page, u64 config)
+{
+ u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT);
+
+ return x86_event_sysfs_show(page, config, event);
+}
+
static __initconst const struct x86_pmu core_pmu = {
.name = "core",
.handle_irq = x86_pmu_handle_irq,
@@ -1628,7 +1635,7 @@ static __initconst const struct x86_pmu core_pmu = {
.event_constraints = intel_core_event_constraints,
.guest_get_msrs = core_guest_get_msrs,
.format_attrs = intel_arch_formats_attr,
- .events_sysfs_show = x86_event_sysfs_show,
+ .events_sysfs_show = intel_event_sysfs_show,
};

struct intel_shared_regs *allocate_shared_regs(int cpu)
@@ -1767,7 +1774,7 @@ static __initconst const struct x86_pmu intel_pmu = {
.pebs_aliases = intel_pebs_aliases_core2,

.format_attrs = intel_arch3_formats_attr,
- .events_sysfs_show = x86_event_sysfs_show,
+ .events_sysfs_show = intel_event_sysfs_show,

.cpu_prepare = intel_pmu_cpu_prepare,
.cpu_starting = intel_pmu_cpu_starting,

2012-10-24 10:07:39

by Jiri Olsa

[permalink] [raw]
Subject: [tip:perf/core] perf/x86: Add hardware events translations for Intel cpus

Commit-ID: 43c032febde48aabcf6d59f47cdcb7b5debbdc63
Gitweb: http://git.kernel.org/tip/43c032febde48aabcf6d59f47cdcb7b5debbdc63
Author: Jiri Olsa <[email protected]>
AuthorDate: Wed, 10 Oct 2012 14:53:13 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Oct 2012 10:41:24 +0200

perf/x86: Add hardware events translations for Intel cpus

Add support for Intel processors to display 'events' sysfs
directory (/sys/devices/cpu/events/) with hw event translations:

# ls /sys/devices/cpu/events/
branch-instructions
branch-misses
bus-cycles
cache-misses
cache-references
cpu-cycles
instructions
ref-cycles
stalled-cycles-backend
stalled-cycles-frontend

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Signed-off-by: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/cpu/perf_event.c | 40 ++++++++++++++++++++++++++++++++
arch/x86/kernel/cpu/perf_event.h | 2 +
arch/x86/kernel/cpu/perf_event_intel.c | 2 +
3 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 39737a6..8a1fa23 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1392,6 +1392,46 @@ static struct attribute_group x86_pmu_events_group = {
.attrs = events_attr,
};

+ssize_t x86_event_sysfs_show(char *page, u64 config)
+{
+ u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT);
+ u64 umask = (config & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
+ u64 cmask = (config & ARCH_PERFMON_EVENTSEL_CMASK) >> 24;
+ bool edge = (config & ARCH_PERFMON_EVENTSEL_EDGE);
+ bool pc = (config & ARCH_PERFMON_EVENTSEL_PIN_CONTROL);
+ bool any = (config & ARCH_PERFMON_EVENTSEL_ANY);
+ bool inv = (config & ARCH_PERFMON_EVENTSEL_INV);
+ ssize_t ret;
+
+ /*
+ * We have whole page size to spend and just little data
+ * to write, so we can safely use sprintf.
+ */
+ ret = sprintf(page, "event=0x%02llx", event);
+
+ if (umask)
+ ret += sprintf(page + ret, ",umask=0x%02llx", umask);
+
+ if (edge)
+ ret += sprintf(page + ret, ",edge");
+
+ if (pc)
+ ret += sprintf(page + ret, ",pc");
+
+ if (any)
+ ret += sprintf(page + ret, ",any");
+
+ if (inv)
+ ret += sprintf(page + ret, ",inv");
+
+ if (cmask)
+ ret += sprintf(page + ret, ",cmask=0x%02llx", cmask);
+
+ ret += sprintf(page + ret, "\n");
+
+ return ret;
+}
+
static int __init init_hw_perf_events(void)
{
struct x86_pmu_quirk *quirk;
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 6f75b6a..f8aa2f6 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -538,6 +538,8 @@ static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip)
regs->ip = ip;
}

+ssize_t x86_event_sysfs_show(char *page, u64 config);
+
#ifdef CONFIG_CPU_SUP_AMD

int amd_pmu_init(void);
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 324bb52..6106d3b 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1628,6 +1628,7 @@ static __initconst const struct x86_pmu core_pmu = {
.event_constraints = intel_core_event_constraints,
.guest_get_msrs = core_guest_get_msrs,
.format_attrs = intel_arch_formats_attr,
+ .events_sysfs_show = x86_event_sysfs_show,
};

struct intel_shared_regs *allocate_shared_regs(int cpu)
@@ -1766,6 +1767,7 @@ static __initconst const struct x86_pmu intel_pmu = {
.pebs_aliases = intel_pebs_aliases_core2,

.format_attrs = intel_arch3_formats_attr,
+ .events_sysfs_show = x86_event_sysfs_show,

.cpu_prepare = intel_pmu_cpu_prepare,
.cpu_starting = intel_pmu_cpu_starting,

2012-10-24 10:08:06

by Jiri Olsa

[permalink] [raw]
Subject: [tip:perf/core] perf/x86: Add hardware events translations for Intel P6 cpus

Commit-ID: 20550a434583c78f8ff9a2819639e2bacbe58574
Gitweb: http://git.kernel.org/tip/20550a434583c78f8ff9a2819639e2bacbe58574
Author: Jiri Olsa <[email protected]>
AuthorDate: Wed, 10 Oct 2012 14:53:15 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Oct 2012 10:41:25 +0200

perf/x86: Add hardware events translations for Intel P6 cpus

Add support for Intel P6 processors to display 'events' sysfs
directory (/sys/devices/cpu/events/) with hw event translations:

# ls /sys/devices/cpu/events/
branch-instructions
branch-misses
bus-cycles
cache-misses
cache-references
cpu-cycles
instructions
ref-cycles
stalled-cycles-backend
stalled-cycles-frontend

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Jiri Olsa <[email protected]>
Cc: Vince Weaver <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
Signed-off-by: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/cpu/perf_event.h | 1 +
arch/x86/kernel/cpu/perf_event_p6.c | 2 ++
2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 21419b9..115c1ea 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -539,6 +539,7 @@ static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip)
}

ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event);
+ssize_t intel_event_sysfs_show(char *page, u64 config);

#ifdef CONFIG_CPU_SUP_AMD

diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
index e4dd0f7..900b76b 100644
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -134,6 +134,8 @@ static __initconst const struct x86_pmu p6_pmu = {
.event_constraints = p6_event_constraints,

.format_attrs = intel_p6_formats_attr,
+ .events_sysfs_show = intel_event_sysfs_show,
+
};

__init int p6_pmu_init(void)

2012-10-24 10:08:56

by Jiri Olsa

[permalink] [raw]
Subject: [tip:perf/core] perf tools: Fix PMU object alias initialization

Commit-ID: 3fded963cdae12ff891a55efc866437506c3f912
Gitweb: http://git.kernel.org/tip/3fded963cdae12ff891a55efc866437506c3f912
Author: Jiri Olsa <[email protected]>
AuthorDate: Wed, 10 Oct 2012 14:53:16 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Oct 2012 10:41:26 +0200

perf tools: Fix PMU object alias initialization

The pmu_lookup should return pmus that do not expose the 'events'
group attribute in sysfs. Also it should fail when any other error
during 'events' lookup is hit (pmu_aliases fails).

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
Signed-off-by: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/util/pmu.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 8a2229d..18e8480 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -164,7 +164,7 @@ static int pmu_aliases(char *name, struct list_head *head)
"%s/bus/event_source/devices/%s/events", sysfs, name);

if (stat(path, &st) < 0)
- return -1;
+ return 0; /* no error if 'events' does not exist */

if (pmu_aliases_parse(path, head))
return -1;
@@ -296,6 +296,9 @@ static struct perf_pmu *pmu_lookup(char *name)
if (pmu_format(name, &format))
return NULL;

+ if (pmu_aliases(name, &aliases))
+ return NULL;
+
if (pmu_type(name, &type))
return NULL;

@@ -305,8 +308,6 @@ static struct perf_pmu *pmu_lookup(char *name)

pmu->cpus = pmu_cpumask(name);

- pmu_aliases(name, &aliases);
-
INIT_LIST_HEAD(&pmu->format);
INIT_LIST_HEAD(&pmu->aliases);
list_splice(&format, &pmu->format);

2012-10-24 10:11:00

by Jiri Olsa

[permalink] [raw]
Subject: [tip:perf/core] perf test: Add automated tests for pmu sysfs translated events

Commit-ID: 3f3a20648797c3ff49c6ebfe10747ef0acd37c50
Gitweb: http://git.kernel.org/tip/3f3a20648797c3ff49c6ebfe10747ef0acd37c50
Author: Jiri Olsa <[email protected]>
AuthorDate: Wed, 10 Oct 2012 14:53:18 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Oct 2012 10:41:27 +0200

perf test: Add automated tests for pmu sysfs translated events

Add automated tests for all events found under PMU/events
directory. Tested events are in the 'cpu/event=xxx/u' format,
where 'xxx' is substituted by every event found.

The 'event=xxx' term is translated to the cpu specific term.
We only check that the event is created (not the real config
numbers) and that the modifier is properly set.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Signed-off-by: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/util/parse-events-test.c | 68 +++++++++++++++++++++++++++++++++++
1 files changed, 68 insertions(+), 0 deletions(-)

diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 516ecd9..b49c2ee 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -443,6 +443,23 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
return 0;
}

+static int test__checkevent_pmu_events(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+
+ evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
+ TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+ TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
+ TEST_ASSERT_VAL("wrong exclude_user",
+ !evsel->attr.exclude_user);
+ TEST_ASSERT_VAL("wrong exclude_kernel",
+ evsel->attr.exclude_kernel);
+ TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+ TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+
+ return 0;
+}
+
static int test__checkterms_simple(struct list_head *terms)
{
struct parse_events__term *term;
@@ -1024,6 +1041,51 @@ static int test_pmu(void)
return !ret;
}

+static int test_pmu_events(void)
+{
+ struct stat st;
+ char path[PATH_MAX];
+ struct dirent *ent;
+ DIR *dir;
+ int ret;
+
+ snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/events/",
+ sysfs_find_mountpoint());
+
+ ret = stat(path, &st);
+ if (ret) {
+ pr_debug("ommiting PMU cpu events tests\n");
+ return 0;
+ }
+
+ dir = opendir(path);
+ if (!dir) {
+ pr_debug("can't open pmu event dir");
+ return -1;
+ }
+
+ while (!ret && (ent = readdir(dir))) {
+#define MAX_NAME 100
+ struct test__event_st e;
+ char name[MAX_NAME];
+
+ if (!strcmp(ent->d_name, ".") ||
+ !strcmp(ent->d_name, ".."))
+ continue;
+
+ snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name);
+
+ e.name = name;
+ e.check = test__checkevent_pmu_events;
+
+ ret = test_event(&e);
+#undef MAX_NAME
+ }
+
+ closedir(dir);
+ return ret;
+}
+
int parse_events__test(void)
{
int ret1, ret2 = 0;
@@ -1040,6 +1102,12 @@ do { \
if (test_pmu())
TEST_EVENTS(test__events_pmu);

+ if (test_pmu()) {
+ int ret = test_pmu_events();
+ if (ret)
+ return ret;
+ }
+
ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
if (!ret2)
ret2 = ret1;

2012-10-24 10:11:58

by Jiri Olsa

[permalink] [raw]
Subject: [tip:perf/core] perf tools: Add support to specify hw event as PMU event term

Commit-ID: 1d33d6dce11e2c900daeca8110d56b95f1174188
Gitweb: http://git.kernel.org/tip/1d33d6dce11e2c900daeca8110d56b95f1174188
Author: Jiri Olsa <[email protected]>
AuthorDate: Wed, 10 Oct 2012 14:53:17 +0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Oct 2012 10:41:27 +0200

perf tools: Add support to specify hw event as PMU event term

Add a way to specify hw event as PMU event term like:

'cpu/event=cpu-cycles/u'
'cpu/event=instructions,.../u'
'cpu/cycles,.../u'

The 'event=cpu-cycles' term is replaced/translated by the hw events
term translation, which is exposed by sysfs 'events' group attribute.

Add parser bits, the rest is already handled by the PMU alias code.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Stephane Eranian <[email protected]>
Signed-off-by: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/util/parse-events.c | 18 ++++++++++++++++++
tools/perf/util/parse-events.h | 2 ++
tools/perf/util/parse-events.y | 18 ++++++++++++++++++
3 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 75c7b0f..2fe1587 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1142,6 +1142,24 @@ int parse_events__term_str(struct parse_events__term **term,
config, str, 0);
}

+int parse_events__term_sym_hw(struct parse_events__term **term,
+ char *config, unsigned idx)
+{
+ struct event_symbol *sym;
+
+ BUG_ON(idx >= PERF_COUNT_HW_MAX);
+ sym = &event_symbols_hw[idx];
+
+ if (config)
+ return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
+ PARSE_EVENTS__TERM_TYPE_USER, config,
+ (char *) sym->symbol, 0);
+ else
+ return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
+ PARSE_EVENTS__TERM_TYPE_USER,
+ (char *) "event", (char *) sym->symbol, 0);
+}
+
int parse_events__term_clone(struct parse_events__term **new,
struct parse_events__term *term)
{
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 839230c..ac9a6aa 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -76,6 +76,8 @@ int parse_events__term_num(struct parse_events__term **_term,
int type_term, char *config, u64 num);
int parse_events__term_str(struct parse_events__term **_term,
int type_term, char *config, char *str);
+int parse_events__term_sym_hw(struct parse_events__term **term,
+ char *config, unsigned idx);
int parse_events__term_clone(struct parse_events__term **new,
struct parse_events__term *term);
void parse_events__free_terms(struct list_head *terms);
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index cd88209..0f9914a 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -352,6 +352,15 @@ PE_NAME '=' PE_VALUE
$$ = term;
}
|
+PE_NAME '=' PE_VALUE_SYM_HW
+{
+ struct parse_events__term *term;
+ int config = $3 & 255;
+
+ ABORT_ON(parse_events__term_sym_hw(&term, $1, config));
+ $$ = term;
+}
+|
PE_NAME
{
struct parse_events__term *term;
@@ -361,6 +370,15 @@ PE_NAME
$$ = term;
}
|
+PE_VALUE_SYM_HW
+{
+ struct parse_events__term *term;
+ int config = $1 & 255;
+
+ ABORT_ON(parse_events__term_sym_hw(&term, NULL, config));
+ $$ = term;
+}
+|
PE_TERM '=' PE_NAME
{
struct parse_events__term *term;