diff options
| author | Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> | 2013-01-23 01:24:54 -0500 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-01-31 11:07:50 -0500 |
| commit | 1c53a270724df91276d28d66f8e5a302fc6a5d74 (patch) | |
| tree | 73351ee19f0c8fe04815e4f3603329cecbe0b2c8 | |
| parent | 2663960c159f23cbfb8e196c96e9fc9f3b5f1a8d (diff) | |
perf/POWER7: Make generic event translations available in sysfs
Make the generic perf events in POWER7 available via sysfs.
$ ls /sys/bus/event_source/devices/cpu/events
branch-instructions
branch-misses
cache-misses
cache-references
cpu-cycles
instructions
stalled-cycles-backend
stalled-cycles-frontend
$ cat /sys/bus/event_source/devices/cpu/events/cache-misses
event=0x400f0
This patch is based on commits that implement this functionality on x86.
Eg:
commit a47473939db20e3961b200eb00acf5fcf084d755
Author: Jiri Olsa <jolsa@redhat.com>
Date: Wed Oct 10 14:53:11 2012 +0200
perf/x86: Make hardware event translations available in sysfs
Changelog:[v2]
[Jiri Osla] Drop EVENT_ID() macro since it is only used once.
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Anton Blanchard <anton@au1.ibm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Robert Richter <robert.richter@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: linuxppc-dev@ozlabs.org
Link: http://lkml.kernel.org/r/20130123062454.GD13720@us.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | Documentation/ABI/stable/sysfs-devices-cpu-events | 0 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/perf_event_server.h | 23 | ||||
| -rw-r--r-- | arch/powerpc/perf/core-book3s.c | 12 | ||||
| -rw-r--r-- | arch/powerpc/perf/power7-pmu.c | 34 |
4 files changed, 69 insertions, 0 deletions
diff --git a/Documentation/ABI/stable/sysfs-devices-cpu-events b/Documentation/ABI/stable/sysfs-devices-cpu-events new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-devices-cpu-events | |||
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index 9710be3a2d17..b9b6c557bd0c 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 13 | #include <asm/hw_irq.h> | 13 | #include <asm/hw_irq.h> |
| 14 | #include <linux/device.h> | ||
| 14 | 15 | ||
| 15 | #define MAX_HWEVENTS 8 | 16 | #define MAX_HWEVENTS 8 |
| 16 | #define MAX_EVENT_ALTERNATIVES 8 | 17 | #define MAX_EVENT_ALTERNATIVES 8 |
| @@ -35,6 +36,7 @@ struct power_pmu { | |||
| 35 | void (*disable_pmc)(unsigned int pmc, unsigned long mmcr[]); | 36 | void (*disable_pmc)(unsigned int pmc, unsigned long mmcr[]); |
| 36 | int (*limited_pmc_event)(u64 event_id); | 37 | int (*limited_pmc_event)(u64 event_id); |
| 37 | u32 flags; | 38 | u32 flags; |
| 39 | const struct attribute_group **attr_groups; | ||
| 38 | int n_generic; | 40 | int n_generic; |
| 39 | int *generic_events; | 41 | int *generic_events; |
| 40 | int (*cache_events)[PERF_COUNT_HW_CACHE_MAX] | 42 | int (*cache_events)[PERF_COUNT_HW_CACHE_MAX] |
| @@ -109,3 +111,24 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs); | |||
| 109 | * If an event_id is not subject to the constraint expressed by a particular | 111 | * If an event_id is not subject to the constraint expressed by a particular |
| 110 | * field, then it will have 0 in both the mask and value for that field. | 112 | * field, then it will have 0 in both the mask and value for that field. |
| 111 | */ | 113 | */ |
| 114 | |||
| 115 | extern ssize_t power_events_sysfs_show(struct device *dev, | ||
| 116 | struct device_attribute *attr, char *page); | ||
| 117 | |||
| 118 | /* | ||
| 119 | * EVENT_VAR() is same as PMU_EVENT_VAR with a suffix. | ||
| 120 | * | ||
| 121 | * Having a suffix allows us to have aliases in sysfs - eg: the generic | ||
| 122 | * event 'cpu-cycles' can have two entries in sysfs: 'cpu-cycles' and | ||
| 123 | * 'PM_CYC' where the latter is the name by which the event is known in | ||
| 124 | * POWER CPU specification. | ||
| 125 | */ | ||
| 126 | #define EVENT_VAR(_id, _suffix) event_attr_##_id##_suffix | ||
| 127 | #define EVENT_PTR(_id, _suffix) &EVENT_VAR(_id, _suffix) | ||
| 128 | |||
| 129 | #define EVENT_ATTR(_name, _id, _suffix) \ | ||
| 130 | PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), PME_PM_##_id, \ | ||
| 131 | power_events_sysfs_show) | ||
| 132 | |||
| 133 | #define GENERIC_EVENT_ATTR(_name, _id) EVENT_ATTR(_name, _id, _g) | ||
| 134 | #define GENERIC_EVENT_PTR(_id) EVENT_PTR(_id, _g) | ||
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index aa2465e21f1a..fa476d50791f 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c | |||
| @@ -1305,6 +1305,16 @@ static int power_pmu_event_idx(struct perf_event *event) | |||
| 1305 | return event->hw.idx; | 1305 | return event->hw.idx; |
| 1306 | } | 1306 | } |
| 1307 | 1307 | ||
| 1308 | ssize_t power_events_sysfs_show(struct device *dev, | ||
| 1309 | struct device_attribute *attr, char *page) | ||
| 1310 | { | ||
| 1311 | struct perf_pmu_events_attr *pmu_attr; | ||
| 1312 | |||
| 1313 | pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); | ||
| 1314 | |||
| 1315 | return sprintf(page, "event=0x%02llx\n", pmu_attr->id); | ||
| 1316 | } | ||
| 1317 | |||
| 1308 | struct pmu power_pmu = { | 1318 | struct pmu power_pmu = { |
| 1309 | .pmu_enable = power_pmu_enable, | 1319 | .pmu_enable = power_pmu_enable, |
| 1310 | .pmu_disable = power_pmu_disable, | 1320 | .pmu_disable = power_pmu_disable, |
| @@ -1537,6 +1547,8 @@ int __cpuinit register_power_pmu(struct power_pmu *pmu) | |||
| 1537 | pr_info("%s performance monitor hardware support registered\n", | 1547 | pr_info("%s performance monitor hardware support registered\n", |
| 1538 | pmu->name); | 1548 | pmu->name); |
| 1539 | 1549 | ||
| 1550 | power_pmu.attr_groups = ppmu->attr_groups; | ||
| 1551 | |||
| 1540 | #ifdef MSR_HV | 1552 | #ifdef MSR_HV |
| 1541 | /* | 1553 | /* |
| 1542 | * Use FCHV to ignore kernel events if MSR.HV is set. | 1554 | * Use FCHV to ignore kernel events if MSR.HV is set. |
diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c index eebb36de429f..269bf2464a36 100644 --- a/arch/powerpc/perf/power7-pmu.c +++ b/arch/powerpc/perf/power7-pmu.c | |||
| @@ -374,6 +374,39 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
| 374 | }, | 374 | }, |
| 375 | }; | 375 | }; |
| 376 | 376 | ||
| 377 | |||
| 378 | GENERIC_EVENT_ATTR(cpu-cycles, CYC); | ||
| 379 | GENERIC_EVENT_ATTR(stalled-cycles-frontend, GCT_NOSLOT_CYC); | ||
| 380 | GENERIC_EVENT_ATTR(stalled-cycles-backend, CMPLU_STALL); | ||
| 381 | GENERIC_EVENT_ATTR(instructions, INST_CMPL); | ||
| 382 | GENERIC_EVENT_ATTR(cache-references, LD_REF_L1); | ||
| 383 | GENERIC_EVENT_ATTR(cache-misses, LD_MISS_L1); | ||
| 384 | GENERIC_EVENT_ATTR(branch-instructions, BRU_FIN); | ||
| 385 | GENERIC_EVENT_ATTR(branch-misses, BRU_MPRED); | ||
| 386 | |||
| 387 | static struct attribute *power7_events_attr[] = { | ||
| 388 | GENERIC_EVENT_PTR(CYC), | ||
| 389 | GENERIC_EVENT_PTR(GCT_NOSLOT_CYC), | ||
| 390 | GENERIC_EVENT_PTR(CMPLU_STALL), | ||
| 391 | GENERIC_EVENT_PTR(INST_CMPL), | ||
| 392 | GENERIC_EVENT_PTR(LD_REF_L1), | ||
| 393 | GENERIC_EVENT_PTR(LD_MISS_L1), | ||
| 394 | GENERIC_EVENT_PTR(BRU_FIN), | ||
| 395 | GENERIC_EVENT_PTR(BRU_MPRED), | ||
| 396 | NULL | ||
| 397 | }; | ||
| 398 | |||
| 399 | |||
| 400 | static struct attribute_group power7_pmu_events_group = { | ||
| 401 | .name = "events", | ||
| 402 | .attrs = power7_events_attr, | ||
| 403 | }; | ||
| 404 | |||
| 405 | static const struct attribute_group *power7_pmu_attr_groups[] = { | ||
| 406 | &power7_pmu_events_group, | ||
| 407 | NULL, | ||
| 408 | }; | ||
| 409 | |||
| 377 | static struct power_pmu power7_pmu = { | 410 | static struct power_pmu power7_pmu = { |
| 378 | .name = "POWER7", | 411 | .name = "POWER7", |
| 379 | .n_counter = 6, | 412 | .n_counter = 6, |
| @@ -385,6 +418,7 @@ static struct power_pmu power7_pmu = { | |||
| 385 | .get_alternatives = power7_get_alternatives, | 418 | .get_alternatives = power7_get_alternatives, |
| 386 | .disable_pmc = power7_disable_pmc, | 419 | .disable_pmc = power7_disable_pmc, |
| 387 | .flags = PPMU_ALT_SIPR, | 420 | .flags = PPMU_ALT_SIPR, |
| 421 | .attr_groups = power7_pmu_attr_groups, | ||
| 388 | .n_generic = ARRAY_SIZE(power7_generic_events), | 422 | .n_generic = ARRAY_SIZE(power7_generic_events), |
| 389 | .generic_events = power7_generic_events, | 423 | .generic_events = power7_generic_events, |
| 390 | .cache_events = &power7_cache_events, | 424 | .cache_events = &power7_cache_events, |
