]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
perf tool: Parse general/raw events from sysfs
authorLin Ming <ming.m.lin@intel.com>
Fri, 15 Jul 2011 14:35:03 +0000 (10:35 -0400)
committerRobert Richter <robert.richter@amd.com>
Thu, 15 Dec 2011 14:17:43 +0000 (15:17 +0100)
PMU can export general events to sysfs, for example,

/sys/bus/event_source/devices/uncore/events
└── cycle

Then specify the event as <pmu>:<event>,

$ sudo perf stat -a -C 0 -e uncore:cycle
^C
 Performance counter stats for 'CPU 0':

        56,547,314 uncore:cycle

Raw event can be specified as <pmu>:rXXXX

$ sudo perf stat -a -C 0 -e uncore:r0101
^C
 Performance counter stats for 'CPU 0':

             8,504 uncore:r0101

Signed-off-by: Lin Ming <ming.m.lin@intel.com>
tools/perf/util/parse-events.c

index 586ab3fe60f87e16acb34426a52177964e0704f0..4ce94043168bcdb34bb504349d24006c5ddebc97 100644 (file)
@@ -685,7 +685,7 @@ parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
 }
 
 static enum event_result
-parse_raw_event(const char **strp, struct perf_event_attr *attr)
+parse_raw_config(const char **strp, struct perf_event_attr *attr)
 {
        const char *str = *strp;
        u64 config;
@@ -700,13 +700,89 @@ parse_raw_event(const char **strp, struct perf_event_attr *attr)
                        return EVT_FAILED;
 
                *strp = end;
-               attr->type = PERF_TYPE_RAW;
                attr->config = config;
                return EVT_HANDLED;
        }
        return EVT_FAILED;
 }
 
+static enum event_result
+parse_raw_event(const char **strp, struct perf_event_attr *attr)
+{
+       if (parse_raw_config(strp, attr) != EVT_HANDLED)
+               return EVT_FAILED;
+
+       attr->type = PERF_TYPE_RAW;
+       return EVT_HANDLED;
+}
+
+#define EVENT_SOURCE_DIR "/sys/bus/event_source/devices"
+
+static u64 read_sysfs_entry(const char *path)
+{
+       char buf[19];
+       int fd;
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return -1;
+
+       if (read(fd, buf, sizeof(buf)) < 0) {
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+       return atoll(buf);
+}
+
+static u64 get_pmu_type(const char *pmu_name)
+{
+       char evt_path[MAXPATHLEN];
+
+       snprintf(evt_path, MAXPATHLEN, "%s/%s/type", EVENT_SOURCE_DIR,
+                pmu_name);
+
+       return read_sysfs_entry(evt_path);
+}
+
+static u64 get_pmu_event_config(const char *pmu_name, const char *evt_name)
+{
+       char evt_path[MAXPATHLEN];
+
+       snprintf(evt_path, MAXPATHLEN, "%s/%s/events/%s", EVENT_SOURCE_DIR,
+                pmu_name, evt_name);
+
+       return read_sysfs_entry(evt_path);
+}
+
+static enum event_result
+parse_sysfs_event(const char **strp, struct perf_event_attr *attr)
+{
+       char *pmu_name, *evt_name;
+       u64 type, config;
+
+       pmu_name = strchr(*strp, ':');
+       if (!pmu_name)
+               return EVT_FAILED;
+       pmu_name = strndup(*strp, pmu_name - *strp);
+       type = get_pmu_type(pmu_name);
+       if ((int)type < 0)
+               return EVT_FAILED;
+       attr->type = type;
+
+       evt_name = strchr(*strp, ':') + 1;
+       config = get_pmu_event_config(pmu_name, evt_name);
+       *strp += strlen(pmu_name) + 1; /* + 1 for the ':' */
+
+       if ((int)config < 0)
+               return parse_raw_config(strp, attr);
+
+       attr->config = config;
+       *strp += strlen(evt_name);
+       return EVT_HANDLED;
+}
+
 static enum event_result
 parse_numeric_event(const char **strp, struct perf_event_attr *attr)
 {
@@ -788,6 +864,10 @@ parse_event_symbols(struct perf_evlist *evlist, const char **str,
 {
        enum event_result ret;
 
+       ret = parse_sysfs_event(str, attr);
+       if (ret != EVT_FAILED)
+               goto modifier;
+
        ret = parse_tracepoint_event(evlist, str, attr);
        if (ret != EVT_FAILED)
                goto modifier;