aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/pmu.c
diff options
context:
space:
mode:
authorRobert Richter <robert.richter@amd.com>2012-08-16 15:10:24 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-08-22 14:22:55 -0400
commit50a9667c9383982d7ec4e6bbc707f67be0e163d2 (patch)
tree47fa9669f07689f6bb77a9607d94c5b9dc11c685 /tools/perf/util/pmu.c
parent7c2f7afd36cc111dd08eb8eb8ef74fb6564fd131 (diff)
perf tools: Add pmu mappings to header information
With dynamic pmu allocation there are also dynamically assigned pmu ids. These ids are used in event->attr.type to describe the pmu to be used for that event. The information is available in sysfs, e.g: /sys/bus/event_source/devices/breakpoint/type: 5 /sys/bus/event_source/devices/cpu/type: 4 /sys/bus/event_source/devices/ibs_fetch/type: 6 /sys/bus/event_source/devices/ibs_op/type: 7 /sys/bus/event_source/devices/software/type: 1 /sys/bus/event_source/devices/tracepoint/type: 2 These mappings are needed to know which samples belong to which pmu. If a pmu is added dynamically like for ibs_fetch or ibs_op the type value may vary. Now, when decoding samples from perf.data this information in sysfs might be no longer available or may have changed. We need to store it in perf.data. Using the header for this. Now the header information created with perf report contains an additional section looking like this: # pmu mappings: ibs_op = 7, ibs_fetch = 6, cpu = 4, breakpoint = 5, tracepoint = 2, software = 1 Signed-off-by: Robert Richter <robert.richter@amd.com> Acked-by: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1345144224-27280-9-git-send-email-robert.richter@amd.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/pmu.c')
-rw-r--r--tools/perf/util/pmu.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 67715a42cd6d..6631d828db3d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -10,6 +10,8 @@
10#include "pmu.h" 10#include "pmu.h"
11#include "parse-events.h" 11#include "parse-events.h"
12 12
13#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
14
13int perf_pmu_parse(struct list_head *list, char *name); 15int perf_pmu_parse(struct list_head *list, char *name);
14extern FILE *perf_pmu_in; 16extern FILE *perf_pmu_in;
15 17
@@ -69,7 +71,7 @@ static int pmu_format(char *name, struct list_head *format)
69 return -1; 71 return -1;
70 72
71 snprintf(path, PATH_MAX, 73 snprintf(path, PATH_MAX,
72 "%s/bus/event_source/devices/%s/format", sysfs, name); 74 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
73 75
74 if (stat(path, &st) < 0) 76 if (stat(path, &st) < 0)
75 return 0; /* no error if format does not exist */ 77 return 0; /* no error if format does not exist */
@@ -206,7 +208,7 @@ static int pmu_type(char *name, __u32 *type)
206 return -1; 208 return -1;
207 209
208 snprintf(path, PATH_MAX, 210 snprintf(path, PATH_MAX,
209 "%s/bus/event_source/devices/%s/type", sysfs, name); 211 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
210 212
211 if (stat(path, &st) < 0) 213 if (stat(path, &st) < 0)
212 return -1; 214 return -1;
@@ -222,6 +224,35 @@ static int pmu_type(char *name, __u32 *type)
222 return ret; 224 return ret;
223} 225}
224 226
227/* Add all pmus in sysfs to pmu list: */
228static void pmu_read_sysfs(void)
229{
230 char path[PATH_MAX];
231 const char *sysfs;
232 DIR *dir;
233 struct dirent *dent;
234
235 sysfs = sysfs_find_mountpoint();
236 if (!sysfs)
237 return;
238
239 snprintf(path, PATH_MAX,
240 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
241
242 dir = opendir(path);
243 if (!dir)
244 return;
245
246 while ((dent = readdir(dir))) {
247 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
248 continue;
249 /* add to static LIST_HEAD(pmus): */
250 perf_pmu__find(dent->d_name);
251 }
252
253 closedir(dir);
254}
255
225static struct perf_pmu *pmu_lookup(char *name) 256static struct perf_pmu *pmu_lookup(char *name)
226{ 257{
227 struct perf_pmu *pmu; 258 struct perf_pmu *pmu;
@@ -267,6 +298,21 @@ static struct perf_pmu *pmu_find(char *name)
267 return NULL; 298 return NULL;
268} 299}
269 300
301struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
302{
303 /*
304 * pmu iterator: If pmu is NULL, we start at the begin,
305 * otherwise return the next pmu. Returns NULL on end.
306 */
307 if (!pmu) {
308 pmu_read_sysfs();
309 pmu = list_prepare_entry(pmu, &pmus, list);
310 }
311 list_for_each_entry_continue(pmu, &pmus, list)
312 return pmu;
313 return NULL;
314}
315
270struct perf_pmu *perf_pmu__find(char *name) 316struct perf_pmu *perf_pmu__find(char *name)
271{ 317{
272 struct perf_pmu *pmu; 318 struct perf_pmu *pmu;