Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCHv2 0/5] perf tools: Enhance parsing events tracepoint error output

391 views
Skip to first unread message

Jiri Olsa

unread,
Sep 7, 2015, 4:38:19 AM9/7/15
to Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
hi,
enhancing parsing events tracepoint error output. Adding
more verbose output when the tracepoint is not found or
the tracing event path cannot be access.

$ sudo perf record -e sched:sched_krava ls
event syntax error: 'sched:sched_krava'
\___ unknown tracepoint

Error: File /sys/kernel/debug/tracing//tracing/events/sched/sched_krava not found.
Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.

Run 'perf list' for a list of valid events
...

$ perf record -e sched:sched_krava ls
event syntax error: 'sched:sched_krava'
\___ can't access trace events

Error: No permissions to read /sys/kernel/debug/tracing//tracing/events/sched/sched_krava
Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'

Run 'perf list' for a list of valid events
...

v2 changes:
- debugfs/tracefs changes went already in through separate patchset
- more commentary on err.h interface
- fixed callers of err.h enhanced functions
- added extra tags/cscope fix

Also available in:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/tp


thanks,
jirka


---
Jiri Olsa (5):
tools: Add err.h with ERR_PTR PTR_ERR interface
perf tools: Add tools/include into tags directories
perf tools: Propagate error info for the tracepoint parsing
perf tools: Propagate error info from tp_format
perf tools: Enhance parsing events tracepoint error output

tools/include/linux/err.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
tools/perf/Makefile.perf | 2 +-
tools/perf/builtin-trace.c | 19 +++++++++++--------
tools/perf/tests/evsel-tp-sched.c | 10 ++++++++--
tools/perf/tests/openat-syscall-all-cpus.c | 3 ++-
tools/perf/tests/openat-syscall-tp-fields.c | 3 ++-
tools/perf/tests/openat-syscall.c | 3 ++-
tools/perf/util/evlist.c | 3 ++-
tools/perf/util/evsel.c | 11 +++++++++--
tools/perf/util/evsel.h | 3 +++
tools/perf/util/parse-events.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++----------------
tools/perf/util/parse-events.h | 3 ++-
tools/perf/util/parse-events.y | 16 +++++++++-------
tools/perf/util/trace-event.c | 13 +++++++++++--
14 files changed, 161 insertions(+), 43 deletions(-)
create mode 100644 tools/include/linux/err.h
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Jiri Olsa

unread,
Sep 7, 2015, 4:38:24 AM9/7/15
to Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Adding part of the kernel's <linux/err.h> interface:
inline void * __must_check ERR_PTR(long error);
inline long __must_check PTR_ERR(__force const void *ptr);
inline bool __must_check IS_ERR(__force const void *ptr);

it will be used to propagate error through pointers
in following patches.

Link: http://lkml.kernel.org/n/tip-ufgnyf683u...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
tools/include/linux/err.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
create mode 100644 tools/include/linux/err.h

diff --git a/tools/include/linux/err.h b/tools/include/linux/err.h
new file mode 100644
index 000000000000..c9ada48f5156
--- /dev/null
+++ b/tools/include/linux/err.h
@@ -0,0 +1,49 @@
+#ifndef __TOOLS_LINUX_ERR_H
+#define __TOOLS_LINUX_ERR_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#include <asm/errno.h>
+
+/*
+ * Original kernel header comment:
+ *
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a normal
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ *
+ * Userspace note:
+ * The same principle works for userspace, because 'error' pointers
+ * fall down to the unused hole far from user space, as described
+ * in Documentation/x86/x86_64/mm.txt for x86_64 arch:
+ *
+ * 0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm hole caused by [48:63] sign extension
+ * ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole
+ *
+ * It should be the same case for other architectures, because
+ * this code is used in generic kernel code.
+ */
+#define MAX_ERRNO 4095
+
+#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
+
+static inline void * __must_check ERR_PTR(long error)
+{
+ return (void *) error;
+}
+
+static inline long __must_check PTR_ERR(__force const void *ptr)
+{
+ return (long) ptr;
+}
+
+static inline bool __must_check IS_ERR(__force const void *ptr)
+{
+ return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+#endif /* _LINUX_ERR_H */
--
2.4.3

Jiri Olsa

unread,
Sep 7, 2015, 4:38:28 AM9/7/15
to Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Pass 'struct parse_events_error *error' to the parse-event.c
tracepoint adding path. It will be filled with error data
in following patches.

Link: http://lkml.kernel.org/n/tip-las1hm5zf5...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
tools/perf/util/parse-events.c | 27 ++++++++++++++++-----------
tools/perf/util/parse-events.h | 3 ++-
tools/perf/util/parse-events.y | 4 ++--
3 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 3840176642f8..1b284b8ad243 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -387,7 +387,8 @@ int parse_events_add_cache(struct list_head *list, int *idx,
}

static int add_tracepoint(struct list_head *list, int *idx,
- char *sys_name, char *evt_name)
+ char *sys_name, char *evt_name,
+ struct parse_events_error *error __maybe_unused)
{
struct perf_evsel *evsel;

@@ -401,7 +402,8 @@ static int add_tracepoint(struct list_head *list, int *idx,
}

static int add_tracepoint_multi_event(struct list_head *list, int *idx,
- char *sys_name, char *evt_name)
+ char *sys_name, char *evt_name,
+ struct parse_events_error *error)
{
char evt_path[MAXPATHLEN];
struct dirent *evt_ent;
@@ -425,7 +427,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
if (!strglobmatch(evt_ent->d_name, evt_name))
continue;

- ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name);
+ ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, error);
}

closedir(evt_dir);
@@ -433,15 +435,17 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
}

static int add_tracepoint_event(struct list_head *list, int *idx,
- char *sys_name, char *evt_name)
+ char *sys_name, char *evt_name,
+ struct parse_events_error *error)
{
return strpbrk(evt_name, "*?") ?
- add_tracepoint_multi_event(list, idx, sys_name, evt_name) :
- add_tracepoint(list, idx, sys_name, evt_name);
+ add_tracepoint_multi_event(list, idx, sys_name, evt_name, error) :
+ add_tracepoint(list, idx, sys_name, evt_name, error);
}

static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
- char *sys_name, char *evt_name)
+ char *sys_name, char *evt_name,
+ struct parse_events_error *error)
{
struct dirent *events_ent;
DIR *events_dir;
@@ -465,7 +469,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
continue;

ret = add_tracepoint_event(list, idx, events_ent->d_name,
- evt_name);
+ evt_name, error);
}

closedir(events_dir);
@@ -473,12 +477,13 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
}

int parse_events_add_tracepoint(struct list_head *list, int *idx,
- char *sys, char *event)
+ char *sys, char *event,
+ struct parse_events_error *error)
{
if (strpbrk(sys, "*?"))
- return add_tracepoint_multi_sys(list, idx, sys, event);
+ return add_tracepoint_multi_sys(list, idx, sys, event, error);
else
- return add_tracepoint_event(list, idx, sys, event);
+ return add_tracepoint_event(list, idx, sys, event, error);
}

static int
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index a09b0e210997..ffee7ece75a6 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -118,7 +118,8 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add);
int parse_events__modifier_group(struct list_head *list, char *event_mod);
int parse_events_name(struct list_head *list, char *name);
int parse_events_add_tracepoint(struct list_head *list, int *idx,
- char *sys, char *event);
+ char *sys, char *event,
+ struct parse_events_error *error);
int parse_events_add_numeric(struct parse_events_evlist *data,
struct list_head *list,
u32 type, u64 config,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 9cd70819c795..54a3004a8192 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -376,7 +376,7 @@ PE_NAME '-' PE_NAME ':' PE_NAME
snprintf(&sys_name, 128, "%s-%s", $1, $3);

ALLOC_LIST(list);
- ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5));
+ ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, data->error));
$$ = list;
}
|
@@ -386,7 +386,7 @@ PE_NAME ':' PE_NAME
struct list_head *list;

ALLOC_LIST(list);
- if (parse_events_add_tracepoint(list, &data->idx, $1, $3)) {
+ if (parse_events_add_tracepoint(list, &data->idx, $1, $3, data->error)) {
struct parse_events_error *error = data->error;

if (error) {
--
2.4.3

Jiri Olsa

unread,
Sep 7, 2015, 4:38:30 AM9/7/15
to Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Enhancing parsing events tracepoint error output. Adding
more verbose output when the tracepoint is not found or
the tracing event path cannot be access.

$ sudo perf record -e sched:sched_krava ls
event syntax error: 'sched:sched_krava'
\___ unknown tracepoint

Error: File /sys/kernel/debug/tracing//tracing/events/sched/sched_krava not found.
Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.

Run 'perf list' for a list of valid events
...

$ perf record -e sched:sched_krava ls
event syntax error: 'sched:sched_krava'
\___ can't access trace events

Error: No permissions to read /sys/kernel/debug/tracing//tracing/events/sched/sched_krava
Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'

Run 'perf list' for a list of valid events
...

Link: http://lkml.kernel.org/n/tip-l0lu26995r...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
tools/perf/util/parse-events.c | 35 ++++++++++++++++++++++++++++++++---
tools/perf/util/parse-events.y | 16 +++++++++-------
2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index c47831c47220..d3fb90be6216 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -387,6 +387,33 @@ int parse_events_add_cache(struct list_head *list, int *idx,
return add_event(list, idx, &attr, name, NULL);
}

+static void tracepoint_error(struct parse_events_error *error, int err,
+ char *sys, char *name)
+{
+ char help[BUFSIZ];
+
+ /*
+ * We get error directly from syscall errno ( > 0),
+ * or from encoded pointer's error ( < 0).
+ */
+ err = abs(err);
+
+ switch (err) {
+ case EACCES:
+ error->str = strdup("can't access trace events");
+ break;
+ case ENOENT:
+ error->str = strdup("unknown tracepoint");
+ break;
+ default:
+ error->str = strdup("failed to add tracepoint");
+ break;
+ }
+
+ tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name);
+ error->help = strdup(help);
+}
+
static int add_tracepoint(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
struct parse_events_error *error __maybe_unused)
@@ -394,8 +421,10 @@ static int add_tracepoint(struct list_head *list, int *idx,
struct perf_evsel *evsel;

evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
- if (IS_ERR(evsel))
+ if (IS_ERR(evsel)) {
+ tracepoint_error(error, PTR_ERR(evsel), sys_name, evt_name);
return PTR_ERR(evsel);
+ }

list_add_tail(&evsel->node, list);
return 0;
@@ -413,7 +442,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
evt_dir = opendir(evt_path);
if (!evt_dir) {
- perror("Can't open event dir");
+ tracepoint_error(error, errno, sys_name, evt_name);
return -1;
}

@@ -453,7 +482,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,

events_dir = opendir(tracing_events_path);
if (!events_dir) {
- perror("Can't open event dir");
+ tracepoint_error(error, errno, sys_name, evt_name);
return -1;
}

diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 54a3004a8192..8bcc45868457 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -371,28 +371,30 @@ event_legacy_tracepoint:
PE_NAME '-' PE_NAME ':' PE_NAME
{
struct parse_events_evlist *data = _data;
+ struct parse_events_error *error = data->error;
struct list_head *list;
char sys_name[128];
snprintf(&sys_name, 128, "%s-%s", $1, $3);

ALLOC_LIST(list);
- ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, data->error));
+ if (parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, error)) {
+ if (error)
+ error->idx = @1.first_column;
+ return -1;
+ }
$$ = list;
}
|
PE_NAME ':' PE_NAME
{
struct parse_events_evlist *data = _data;
+ struct parse_events_error *error = data->error;
struct list_head *list;

ALLOC_LIST(list);
- if (parse_events_add_tracepoint(list, &data->idx, $1, $3, data->error)) {
- struct parse_events_error *error = data->error;
-
- if (error) {
+ if (parse_events_add_tracepoint(list, &data->idx, $1, $3, error)) {
+ if (error)
error->idx = @1.first_column;
- error->str = strdup("unknown tracepoint");
- }
return -1;
}
$$ = list;
--
2.4.3

Jiri Olsa

unread,
Sep 7, 2015, 4:38:52 AM9/7/15
to Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Propagate error info from tp_format via ERR_PTR to get
it all the way down to the parse-event.c tracepoint adding
routines. Following functions now return pointer with
encoded error:
- tp_format
- trace_event__tp_format
- perf_evsel__newtp_idx
- perf_evsel__newtp

This affects several other places in perf, that cannot use
pointer check anymore, but must utilize the err.h interface,
when getting error information from above functions list.

Link: http://lkml.kernel.org/n/tip-bzdckgv1zf...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
tools/perf/builtin-trace.c | 19 +++++++++++--------
tools/perf/tests/evsel-tp-sched.c | 10 ++++++++--
tools/perf/tests/openat-syscall-all-cpus.c | 3 ++-
tools/perf/tests/openat-syscall-tp-fields.c | 3 ++-
tools/perf/tests/openat-syscall.c | 3 ++-
tools/perf/util/evlist.c | 3 ++-
tools/perf/util/evsel.c | 11 +++++++++--
tools/perf/util/evsel.h | 3 +++
tools/perf/util/parse-events.c | 6 +++---
tools/perf/util/trace-event.c | 13 +++++++++++--
10 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 215653274102..93b80f12f35e 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -38,6 +38,7 @@
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/futex.h>
+#include <linux/err.h>

/* For older distros: */
#ifndef MAP_STACK
@@ -245,13 +246,14 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);

/* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
- if (evsel == NULL)
+ if (IS_ERR(evsel))
evsel = perf_evsel__newtp("syscalls", direction);

- if (evsel) {
- if (perf_evsel__init_syscall_tp(evsel, handler))
- goto out_delete;
- }
+ if (IS_ERR(evsel))
+ return NULL;
+
+ if (perf_evsel__init_syscall_tp(evsel, handler))
+ goto out_delete;

return evsel;

@@ -1705,12 +1707,12 @@ static int trace__read_syscall_info(struct trace *trace, int id)
snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
sc->tp_format = trace_event__tp_format("syscalls", tp_name);

- if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
+ if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
sc->tp_format = trace_event__tp_format("syscalls", tp_name);
}

- if (sc->tp_format == NULL)
+ if (IS_ERR(sc->tp_format))
return -1;

sc->args = sc->tp_format->format.fields;
@@ -2390,7 +2392,8 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
{
struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
- if (evsel == NULL)
+
+ if (IS_ERR(evsel))
return false;

if (perf_evsel__field(evsel, "pathname") == NULL) {
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index 52162425c969..790e413d9a1f 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -1,3 +1,4 @@
+#include <linux/err.h>
#include <traceevent/event-parse.h>
#include "evsel.h"
#include "tests.h"
@@ -36,8 +37,8 @@ int test__perf_evsel__tp_sched_test(void)
struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch");
int ret = 0;

- if (evsel == NULL) {
- pr_debug("perf_evsel__new\n");
+ if (IS_ERR(evsel)) {
+ pr_debug("perf_evsel__newtp failed with %ld\n", PTR_ERR(evsel));
return -1;
}

@@ -66,6 +67,11 @@ int test__perf_evsel__tp_sched_test(void)

evsel = perf_evsel__newtp("sched", "sched_wakeup");

+ if (IS_ERR(evsel)) {
+ pr_debug("perf_evsel__newtp failed with %ld\n", PTR_ERR(evsel));
+ return -1;
+ }
+
if (perf_evsel__test_field(evsel, "comm", 16, true))
ret = -1;

diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 495d8126b722..9e104a2e973d 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -1,4 +1,5 @@
#include <api/fs/fs.h>
+#include <linux/err.h>
#include "evsel.h"
#include "tests.h"
#include "thread_map.h"
@@ -31,7 +32,7 @@ int test__openat_syscall_event_on_all_cpus(void)
CPU_ZERO(&cpu_set);

evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
- if (evsel == NULL) {
+ if (IS_ERR(evsel)) {
tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
pr_err("%s\n", errbuf);
goto out_thread_map_delete;
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 01a19626c846..473d3869727e 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -1,3 +1,4 @@
+#include <linux/err.h>
#include "perf.h"
#include "evlist.h"
#include "evsel.h"
@@ -30,7 +31,7 @@ int test__syscall_openat_tp_fields(void)
}

evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
- if (evsel == NULL) {
+ if (IS_ERR(evsel)) {
pr_debug("%s: perf_evsel__newtp\n", __func__);
goto out_delete_evlist;
}
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index 08ac9d94a050..7b1db8306098 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -1,4 +1,5 @@
#include <api/fs/tracing_path.h>
+#include <linux/err.h>
#include "thread_map.h"
#include "evsel.h"
#include "debug.h"
@@ -19,7 +20,7 @@ int test__openat_syscall_event(void)
}

evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
- if (evsel == NULL) {
+ if (IS_ERR(evsel)) {
tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
pr_err("%s\n", errbuf);
goto out_thread_map_delete;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d51a5200c8af..3cb2bf9bd4bd 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -25,6 +25,7 @@
#include <linux/bitops.h>
#include <linux/hash.h>
#include <linux/log2.h>
+#include <linux/err.h>

static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
@@ -265,7 +266,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
{
struct perf_evsel *evsel = perf_evsel__newtp(sys, name);

- if (evsel == NULL)
+ if (IS_ERR(evsel))
return -1;

evsel->handler = handler;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 771ade4d5966..08c20ee4e27d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -13,6 +13,7 @@
#include <traceevent/event-parse.h>
#include <linux/hw_breakpoint.h>
#include <linux/perf_event.h>
+#include <linux/err.h>
#include <sys/resource.h>
#include "asm/bug.h"
#include "callchain.h"
@@ -225,9 +226,13 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
return evsel;
}

+/*
+ * Returns pointer with encoded error via <linux/err.h> interface.
+ */
struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
{
struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
+ int err = -ENOMEM;

if (evsel != NULL) {
struct perf_event_attr attr = {
@@ -240,8 +245,10 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
goto out_free;

evsel->tp_format = trace_event__tp_format(sys, name);
- if (evsel->tp_format == NULL)
+ if (IS_ERR(evsel->tp_format)) {
+ err = PTR_ERR(evsel->tp_format);
goto out_free;
+ }

event_attr_init(&attr);
attr.config = evsel->tp_format->id;
@@ -254,7 +261,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
out_free:
zfree(&evsel->name);
free(evsel);
- return NULL;
+ return ERR_PTR(err);
}

const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 298e6bbca200..b6e8ff876f17 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -161,6 +161,9 @@ static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)

struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx);

+/*
+ * Returns pointer with encoded error via <linux/err.h> interface.
+ */
static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name)
{
return perf_evsel__newtp_idx(sys, name, 0);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1b284b8ad243..c47831c47220 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,4 +1,5 @@
#include <linux/hw_breakpoint.h>
+#include <linux/err.h>
#include "util.h"
#include "../perf.h"
#include "evlist.h"
@@ -393,11 +394,10 @@ static int add_tracepoint(struct list_head *list, int *idx,
struct perf_evsel *evsel;

evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
- if (!evsel)
- return -ENOMEM;
+ if (IS_ERR(evsel))
+ return PTR_ERR(evsel);

list_add_tail(&evsel->node, list);
-
return 0;
}

diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index 2f4996ab313d..8e3a60e3e15f 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -7,6 +7,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/kernel.h>
+#include <linux/err.h>
#include <traceevent/event-parse.h>
#include <api/fs/tracing_path.h>
#include "trace-event.h"
@@ -66,6 +67,9 @@ void trace_event__cleanup(struct trace_event *t)
pevent_free(t->pevent);
}

+/*
+ * Returns pointer with encoded error via <linux/err.h> interface.
+ */
static struct event_format*
tp_format(const char *sys, const char *name)
{
@@ -74,12 +78,14 @@ tp_format(const char *sys, const char *name)
char path[PATH_MAX];
size_t size;
char *data;
+ int err;

scnprintf(path, PATH_MAX, "%s/%s/%s/format",
tracing_events_path, sys, name);

- if (filename__read_str(path, &data, &size))
- return NULL;
+ err = filename__read_str(path, &data, &size);
+ if (err)
+ return ERR_PTR(err);

pevent_parse_format(pevent, &event, data, size, sys);

@@ -87,6 +93,9 @@ tp_format(const char *sys, const char *name)
return event;
}

+/*
+ * Returns pointer with encoded error via <linux/err.h> interface.
+ */
struct event_format*
trace_event__tp_format(const char *sys, const char *name)
{
--
2.4.3

Jiri Olsa

unread,
Sep 7, 2015, 4:39:09 AM9/7/15
to Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Adding tools/include into tags directories, to have include
definitions reachable via tags/cscope.

Link: http://lkml.kernel.org/n/tip-jihvx6xbdo...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
tools/perf/Makefile.perf | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d9863cb96f59..6c5c699002cb 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -459,7 +459,7 @@ INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
$(DOC_TARGETS):
$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)

-TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol
+TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../include
TAG_FILES= ../../include/uapi/linux/perf_event.h

TAGS:
--
2.4.3

Raphaël Beamonte

unread,
Sep 8, 2015, 4:23:09 PM9/8/15
to Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
Perhaps a dumb question, but it seems the code is exactly the same as
in linux/err.h besides the part of the comment you added. Why not
using that file directly in the other patches then?

Raphaël Beamonte

unread,
Sep 8, 2015, 4:24:31 PM9/8/15
to Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
2015-09-08 16:22 GMT-04:00 Raphaël Beamonte <raphael....@gmail.com>:
> Perhaps a dumb question, but it seems the code is exactly the same as
> in linux/err.h besides the part of the comment you added. Why not
> using that file directly in the other patches then?

I meant include/linux/err.h, from git root

Arnaldo Carvalho de Melo

unread,
Sep 8, 2015, 5:07:08 PM9/8/15
to Raphaël Beamonte, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
We can't do that.

Read:

commit 3f735377bfd6567d80815a6242c147211963680a
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
Date: Sun Jul 5 22:48:21 2015 -0300

tools: Copy lib/rbtree.c to tools/lib/

So that we can remove kernel specific stuff we've been stubbing out via
a tools/include/linux/export.h that gets removed in this patch and to
avoid breakages in the future like the one fixed recently where
rcupdate.h started being used in rbtree.h.


--------------------------

There are more copies like that, but the explanation above should be
enough, no?


- Arnaldo

Raphaël Beamonte

unread,
Sep 8, 2015, 5:29:31 PM9/8/15
to Arnaldo Carvalho de Melo, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
Yes, I understand now! Thanks!

Raphaël Beamonte

unread,
Sep 8, 2015, 5:30:15 PM9/8/15
to Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
2015-09-07 4:38 GMT-04:00 Jiri Olsa <jo...@kernel.org>:
> Adding part of the kernel's <linux/err.h> interface:
> inline void * __must_check ERR_PTR(long error);
> inline long __must_check PTR_ERR(__force const void *ptr);
> inline bool __must_check IS_ERR(__force const void *ptr);
>
> it will be used to propagate error through pointers
> in following patches.
>
> Link: http://lkml.kernel.org/n/tip-ufgnyf683u...@git.kernel.org
> Signed-off-by: Jiri Olsa <jo...@kernel.org>
> ---
> tools/include/linux/err.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 49 insertions(+)
> create mode 100644 tools/include/linux/err.h

Reviewed-by: Raphaël Beamonte <raphael....@gmail.com>

Raphaël Beamonte

unread,
Sep 8, 2015, 5:42:54 PM9/8/15
to Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
2015-09-07 4:38 GMT-04:00 Jiri Olsa <jo...@kernel.org>:
Works for me.
Reviewed-by: Raphaël Beamonte <raphael....@gmail.com>

I also made sure I could compile and run perf with that patch applied
on top of the current linux master. Should I also propose my
Tested-by: tag? I didn't do thorough tests though.

Jiri Olsa

unread,
Sep 9, 2015, 3:51:12 AM9/9/15
to Raphaël Beamonte, Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
On Tue, Sep 08, 2015 at 05:42:25PM -0400, Raphaël Beamonte wrote:

SNIP

> > @@ -386,7 +386,7 @@ PE_NAME ':' PE_NAME
> > struct list_head *list;
> >
> > ALLOC_LIST(list);
> > - if (parse_events_add_tracepoint(list, &data->idx, $1, $3)) {
> > + if (parse_events_add_tracepoint(list, &data->idx, $1, $3, data->error)) {
> > struct parse_events_error *error = data->error;
> >
> > if (error) {
> > --
> > 2.4.3
> >
>
> Works for me.
> Reviewed-by: Raphaël Beamonte <raphael....@gmail.com>
>
> I also made sure I could compile and run perf with that patch applied
> on top of the current linux master. Should I also propose my
> Tested-by: tag? I didn't do thorough tests though.

I always base my changes over Arnaldo's perf/core,
which gets eventually merged to Ingo's tip tree and
then the Linus'es tree.. it should be enough to test
it over my branch

thanks,
jirka

Arnaldo Carvalho de Melo

unread,
Sep 9, 2015, 4:58:29 PM9/9/15
to Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Em Mon, Sep 07, 2015 at 10:38:06AM +0200, Jiri Olsa escreveu:
> Propagate error info from tp_format via ERR_PTR to get
> it all the way down to the parse-event.c tracepoint adding
> routines. Following functions now return pointer with
> encoded error:
> - tp_format
> - trace_event__tp_format
> - perf_evsel__newtp_idx
> - perf_evsel__newtp
>
> This affects several other places in perf, that cannot use
> pointer check anymore, but must utilize the err.h interface,
> when getting error information from above functions list.

Right, so this is tricky and we must be careful, see below...
This kind of stuff is ok, as evsel is a local variable and you kept the
interface for perf_evsel__syscall_newtp(), i.e. it returns NULL if a new
evsel can't be instantiated.

Ok, but that is a different interface than the one used by
perf_evsel__newtp(), that also instantiates a new evsel.

So when one thinks about "foo__new()" we now need to check which one of
the two interfaces it uses, if err.h or if the old NULL based failure
reporting one.

Double tricky if it is foo__new() and foo__new_variant(), as
perf_evsel__syscall_newtp() and perf_evsel__newtp(), i.e. both will
return a "struct perf_evsel" instance, but one using err.h, the other
use NULL.

Ok, you marked the ones using a comment, wonder if we couldn't use
'sparse' somehow here, is it used to check IS_ERR() usage in the kernel?

Ah, but what about this in trace__event_handler() in builtin-trace.c?

if (evsel->tp_format) {
event_format__fprintf(evsel->tp_format, sample->cpu,
sample->raw_data, sample->raw_size,
trace->output);
}


Don't we have to use IS_ERR() here? Ok, no, because if setting up
evsel->tp_format fails, then that evsel will be destroyed and
perf_evsel__newtp() will return ERR_PTR(), so it is ok not no use
ERR_PTR(evsel->tp_format) because it will only be != NULL when it was
successfully set up.

But then, in perf_evsel__newtp_idx if zalloc() fails we will not return
ERR_PTR(), but instead NULL, a-ha, this one seems to be a real bug, no?

/*
* Returns pointer with encoded error via <linux/err.h> interface.
*/
struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
{
struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
int err = -ENOMEM;

if (evsel != NULL) {
struct perf_event_attr attr = {
.type = PERF_TYPE_TRACEPOINT,
.sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
};

if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
goto out_free;

evsel->tp_format = trace_event__tp_format(sys, name);
if (IS_ERR(evsel->tp_format)) {
err = PTR_ERR(evsel->tp_format);
goto out_free;
}

event_attr_init(&attr);
attr.config = evsel->tp_format->id;
attr.sample_period = 1;
perf_evsel__init(evsel, &attr, idx);
}

return evsel;

out_free:
zfree(&evsel->name);
free(evsel);
return ERR_PTR(err);

Namhyung Kim

unread,
Sep 10, 2015, 3:04:24 AM9/10/15
to Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
On Mon, Sep 07, 2015 at 10:38:07AM +0200, Jiri Olsa wrote:
> Enhancing parsing events tracepoint error output. Adding
> more verbose output when the tracepoint is not found or
> the tracing event path cannot be access.
>
> $ sudo perf record -e sched:sched_krava ls
> event syntax error: 'sched:sched_krava'
> \___ unknown tracepoint
>
> Error: File /sys/kernel/debug/tracing//tracing/events/sched/sched_krava not found.
> Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
>
> Run 'perf list' for a list of valid events
> ...
>
> $ perf record -e sched:sched_krava ls
> event syntax error: 'sched:sched_krava'
> \___ can't access trace events
>
> Error: No permissions to read /sys/kernel/debug/tracing//tracing/events/sched/sched_krava
> Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'

What about tracefs? On my system, tracefs is mounted on
/sys/kernel/debug/tracing thus I cannot access trace events after
remounting debugfs with mode=755.

Also, IIRC tracepoint events adds PERF_SAMPLE_RAW bit automatically,
and it requires perf_event_paranoid being -1 for non-root user, right?

Thanks,
Namhyung

Jiri Olsa

unread,
Sep 10, 2015, 4:05:53 AM9/10/15
to Namhyung Kim, Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
On Thu, Sep 10, 2015 at 04:00:30PM +0900, Namhyung Kim wrote:
> On Mon, Sep 07, 2015 at 10:38:07AM +0200, Jiri Olsa wrote:
> > Enhancing parsing events tracepoint error output. Adding
> > more verbose output when the tracepoint is not found or
> > the tracing event path cannot be access.
> >
> > $ sudo perf record -e sched:sched_krava ls
> > event syntax error: 'sched:sched_krava'
> > \___ unknown tracepoint
> >
> > Error: File /sys/kernel/debug/tracing//tracing/events/sched/sched_krava not found.
> > Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
> >
> > Run 'perf list' for a list of valid events
> > ...
> >
> > $ perf record -e sched:sched_krava ls
> > event syntax error: 'sched:sched_krava'
> > \___ can't access trace events
> >
> > Error: No permissions to read /sys/kernel/debug/tracing//tracing/events/sched/sched_krava
> > Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'
>
> What about tracefs? On my system, tracefs is mounted on
> /sys/kernel/debug/tracing thus I cannot access trace events after
> remounting debugfs with mode=755.

right, patch below keeps the actual mount and
display proper info.. could you please try?

>
> Also, IIRC tracepoint events adds PERF_SAMPLE_RAW bit automatically,
> and it requires perf_event_paranoid being -1 for non-root user, right?

there's related error message when you try to open the
tracepoint, the whole session is like:


[jolsa@krava perf]$ ./perf record -e sched:sched_switch ls
event syntax error: 'sched:sched_switch'
\___ can't access trace events

Error: No permissions to read /sys/kernel/debug/tracing/events/sched/sched_switch
Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'

Run 'perf list' for a list of valid events

usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]

-e, --event <event> event selector. use 'perf list' to list available events
[jolsa@krava perf]$ sudo mount -o remount,mode=755 /sys/kernel/debug/tracing
[jolsa@krava perf]$ ./perf record -e sched:sched_switch ls
Error:
You may not have permission to collect stats.
Consider tweaking /proc/sys/kernel/perf_event_paranoid:
-1 - Not paranoid at all
0 - Disallow raw tracepoint access for unpriv
1 - Disallow cpu events for unpriv
2 - Disallow kernel profiling for unpriv



thanks,
jirka


---
diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
index 38aca2dd1946..0406a7d5c891 100644
--- a/tools/lib/api/fs/tracing_path.c
+++ b/tools/lib/api/fs/tracing_path.c
@@ -12,12 +12,14 @@
#include "tracing_path.h"


+char tracing_mnt[PATH_MAX + 1] = "/sys/kernel/debug";
char tracing_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing";
char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";


static void __tracing_path_set(const char *tracing, const char *mountpoint)
{
+ snprintf(tracing_mnt, sizeof(tracing_mnt), "%s", mountpoint);
snprintf(tracing_path, sizeof(tracing_path), "%s/%s",
mountpoint, tracing);
snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
@@ -109,19 +111,10 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
"Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
break;
case EACCES: {
- const char *mountpoint = debugfs__mountpoint();
-
- if (!access(mountpoint, R_OK) && strncmp(filename, "tracing/", 8) == 0) {
- const char *tracefs_mntpoint = tracefs__mountpoint();
-
- if (tracefs_mntpoint)
- mountpoint = tracefs__mountpoint();
- }
-
snprintf(buf, size,
"Error:\tNo permissions to read %s/%s\n"
"Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
- tracing_events_path, filename, mountpoint);
+ tracing_events_path, filename, tracing_mnt);
}
break;
default:

Jiri Olsa

unread,
Sep 10, 2015, 4:25:05 AM9/10/15
to Arnaldo Carvalho de Melo, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
On Wed, Sep 09, 2015 at 05:58:13PM -0300, Arnaldo Carvalho de Melo wrote:

SNIP

> This kind of stuff is ok, as evsel is a local variable and you kept the
> interface for perf_evsel__syscall_newtp(), i.e. it returns NULL if a new
> evsel can't be instantiated.
>
> Ok, but that is a different interface than the one used by
> perf_evsel__newtp(), that also instantiates a new evsel.
>
> So when one thinks about "foo__new()" we now need to check which one of
> the two interfaces it uses, if err.h or if the old NULL based failure
> reporting one.
>
> Double tricky if it is foo__new() and foo__new_variant(), as
> perf_evsel__syscall_newtp() and perf_evsel__newtp(), i.e. both will
> return a "struct perf_evsel" instance, but one using err.h, the other
> use NULL.
>
> Ok, you marked the ones using a comment, wonder if we couldn't use
> 'sparse' somehow here, is it used to check IS_ERR() usage in the kernel?

hum, not sure.. will check ;-)

at least we could mark related functions with __must_check
to force the return value check

>
> Ah, but what about this in trace__event_handler() in builtin-trace.c?
>
> if (evsel->tp_format) {
> event_format__fprintf(evsel->tp_format, sample->cpu,
> sample->raw_data, sample->raw_size,
> trace->output);
> }
>
>
> Don't we have to use IS_ERR() here? Ok, no, because if setting up
> evsel->tp_format fails, then that evsel will be destroyed and
> perf_evsel__newtp() will return ERR_PTR(), so it is ok not no use
> ERR_PTR(evsel->tp_format) because it will only be != NULL when it was
> successfully set up.
>
> But then, in perf_evsel__newtp_idx if zalloc() fails we will not return
> ERR_PTR(), but instead NULL, a-ha, this one seems to be a real bug, no?

hate those allocations in declarations.. never do any good ;-)

yep, NULL is not an error, so it's real bug, attached patch should fix it

thanks,
jirka


---
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 08c20ee4e27d..162973bec713 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -256,7 +256,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
perf_evsel__init(evsel, &attr, idx);
}

- return evsel;
+ return evsel ?: ERR_PTR(err);

out_free:
zfree(&evsel->name);

Arnaldo Carvalho de Melo

unread,
Sep 10, 2015, 10:16:46 AM9/10/15
to Jiri Olsa, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Em Thu, Sep 10, 2015 at 10:24:52AM +0200, Jiri Olsa escreveu:
> On Wed, Sep 09, 2015 at 05:58:13PM -0300, Arnaldo Carvalho de Melo wrote:
>
> SNIP
>
> > This kind of stuff is ok, as evsel is a local variable and you kept the
> > interface for perf_evsel__syscall_newtp(), i.e. it returns NULL if a new
> > evsel can't be instantiated.
> >
> > Ok, but that is a different interface than the one used by
> > perf_evsel__newtp(), that also instantiates a new evsel.
> >
> > So when one thinks about "foo__new()" we now need to check which one of
> > the two interfaces it uses, if err.h or if the old NULL based failure
> > reporting one.
> >
> > Double tricky if it is foo__new() and foo__new_variant(), as
> > perf_evsel__syscall_newtp() and perf_evsel__newtp(), i.e. both will
> > return a "struct perf_evsel" instance, but one using err.h, the other
> > use NULL.
> >
> > Ok, you marked the ones using a comment, wonder if we couldn't use
> > 'sparse' somehow here, is it used to check IS_ERR() usage in the kernel?
>
> hum, not sure.. will check ;-)
>
> at least we could mark related functions with __must_check
> to force the return value check

Right, that helps a bit, but not when the test _is already there_,
against NULL.

That is why I thought about sparse, if it was used in the kernel somehow
to check for this, guess either it would notice ERR_PTR using routines
and then auto-mark them for checking if they are being tested using
IS_ERR() or plain NULL, will check, later...

- Arnaldo

Namhyung Kim

unread,
Sep 11, 2015, 12:12:59 PM9/11/15
to Jiri Olsa, Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Hi Jiri,

On Thu, Sep 10, 2015 at 10:05:37AM +0200, Jiri Olsa wrote:
> On Thu, Sep 10, 2015 at 04:00:30PM +0900, Namhyung Kim wrote:
> > On Mon, Sep 07, 2015 at 10:38:07AM +0200, Jiri Olsa wrote:
> > > Enhancing parsing events tracepoint error output. Adding
> > > more verbose output when the tracepoint is not found or
> > > the tracing event path cannot be access.
> > >
> > > $ sudo perf record -e sched:sched_krava ls
> > > event syntax error: 'sched:sched_krava'
> > > \___ unknown tracepoint
> > >
> > > Error: File /sys/kernel/debug/tracing//tracing/events/sched/sched_krava not found.
> > > Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
> > >
> > > Run 'perf list' for a list of valid events
> > > ...
> > >
> > > $ perf record -e sched:sched_krava ls
> > > event syntax error: 'sched:sched_krava'
> > > \___ can't access trace events
> > >
> > > Error: No permissions to read /sys/kernel/debug/tracing//tracing/events/sched/sched_krava
> > > Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'
> >
> > What about tracefs? On my system, tracefs is mounted on
> > /sys/kernel/debug/tracing thus I cannot access trace events after
> > remounting debugfs with mode=755.
>
> right, patch below keeps the actual mount and
> display proper info.. could you please try?

Sure, this patch displays the proper tracefs mountpoint. But it also
has a problem - if tracefs is mounted under debugfs, the access mode
of debugfs also affects, so in this case I had to change it both for
debugfs and tracefs..


>
> >
> > Also, IIRC tracepoint events adds PERF_SAMPLE_RAW bit automatically,
> > and it requires perf_event_paranoid being -1 for non-root user, right?
>
> there's related error message when you try to open the
> tracepoint, the whole session is like:

Ah, great. :)

Thanks,
Namhyung

Jiri Olsa

unread,
Sep 11, 2015, 12:16:59 PM9/11/15
to Namhyung Kim, Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
thanks

> has a problem - if tracefs is mounted under debugfs, the access mode
> of debugfs also affects, so in this case I had to change it both for
> debugfs and tracefs..


hum, I wonder the error message needs to be that smart..

jirka

Raphaël Beamonte

unread,
Sep 11, 2015, 1:50:51 PM9/11/15
to Jiri Olsa, Namhyung Kim, Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Peter Zijlstra, Matt Fleming
2015-09-11 12:16 GMT-04:00 Jiri Olsa <jo...@redhat.com>:
> On Sat, Sep 12, 2015 at 01:09:31AM +0900, Namhyung Kim wrote:
<SNIP>
>> has a problem - if tracefs is mounted under debugfs, the access mode
>> of debugfs also affects, so in this case I had to change it both for
>> debugfs and tracefs..
>
>
> hum, I wonder the error message needs to be that smart..
>
> jirka

Hmm... If tracefs is mounted under debugfs, wouldn't remounting
debugfs do the trick, as it was done before?
If so, why couldn't we just check the paths with a basic strcmp to
verify if tracefs starts by debugfs, and in that case offer to remount
debugfs, else offer to remount tracefs?

Arnaldo Carvalho de Melo

unread,
Sep 11, 2015, 2:55:56 PM9/11/15
to Raphaël Beamonte, Jiri Olsa, Namhyung Kim, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Peter Zijlstra, Matt Fleming
Em Fri, Sep 11, 2015 at 01:50:02PM -0400, Raphaël Beamonte escreveu:
> 2015-09-11 12:16 GMT-04:00 Jiri Olsa <jo...@redhat.com>:
> > On Sat, Sep 12, 2015 at 01:09:31AM +0900, Namhyung Kim wrote:
> <SNIP>
> >> has a problem - if tracefs is mounted under debugfs, the access mode
> >> of debugfs also affects, so in this case I had to change it both for
> >> debugfs and tracefs..

> > hum, I wonder the error message needs to be that smart..
>
> Hmm... If tracefs is mounted under debugfs, wouldn't remounting
> debugfs do the trick, as it was done before?

Not necessarily, we may be able to access /a/ but not /a/b/, so, before
we get to /a/b/ we need to solve access to /a/ to then realize that
/a/b/ also need permission change so that we can access it.

> If so, why couldn't we just check the paths with a basic strcmp to
> verify if tracefs starts by debugfs, and in that case offer to remount
> debugfs, else offer to remount tracefs?

say it is how it was before tracefs:

/sys/kernel/debug/tracing/

If we can't access "/sys/kernel/debug/tracing/" because we can't access
"/sys/kernel/debug/" we need first to change (remount, chmod/grp/own,
whatever is best in each hypotetical use case) /sys/kernel/debug/ to
then do the same for /sys/kernel/debug/tracing/, no?

We could of course say something like "Something is wrong with tracefs
and/or debugfs, figure it out and try again", but we can do better,
right? 8-P

- Arnaldo

Raphaël Beamonte

unread,
Sep 11, 2015, 3:57:15 PM9/11/15
to Arnaldo Carvalho de Melo, Jiri Olsa, Namhyung Kim, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Peter Zijlstra, Matt Fleming
2015-09-11 14:55 GMT-04:00 Arnaldo Carvalho de Melo <arnald...@gmail.com>:
> Em Fri, Sep 11, 2015 at 01:50:02PM -0400, Raphaël Beamonte escreveu:
>> 2015-09-11 12:16 GMT-04:00 Jiri Olsa <jo...@redhat.com>:
>> > On Sat, Sep 12, 2015 at 01:09:31AM +0900, Namhyung Kim wrote:
>> <SNIP>
>> >> has a problem - if tracefs is mounted under debugfs, the access mode
>> >> of debugfs also affects, so in this case I had to change it both for
>> >> debugfs and tracefs..
>
>> > hum, I wonder the error message needs to be that smart..
>>
>> Hmm... If tracefs is mounted under debugfs, wouldn't remounting
>> debugfs do the trick, as it was done before?
>
> Not necessarily, we may be able to access /a/ but not /a/b/, so, before
> we get to /a/b/ we need to solve access to /a/ to then realize that
> /a/b/ also need permission change so that we can access it.

Well, I kind of had in mind that if we can access /a/, it's that /a/
is not the problem, so why would we remount it? Remounting /a/b/
should do the trick, and there's no reason we couldn't do it if we can
access /a/. Or perhaps I'm missing something?

>> If so, why couldn't we just check the paths with a basic strcmp to
>> verify if tracefs starts by debugfs, and in that case offer to remount
>> debugfs, else offer to remount tracefs?
>
> say it is how it was before tracefs:
>
> /sys/kernel/debug/tracing/
>
> If we can't access "/sys/kernel/debug/tracing/" because we can't access
> "/sys/kernel/debug/" we need first to change (remount, chmod/grp/own,
> whatever is best in each hypotetical use case) /sys/kernel/debug/ to
> then do the same for /sys/kernel/debug/tracing/, no?

In that case, I'm following: if we can't access /sys/kernel/debug, we
have to remount it anyway, and there's no guarantee that
/sys/kernel/debug/tracing will have the right permissions. In that
case, ok, we perhaps need to remount both. Perhaps because: can
we be sure that if /sys/kernel/debug is inaccessible, it will be the
same for /sys/kernel/debug/tracing ?

> We could of course say something like "Something is wrong with tracefs
> and/or debugfs, figure it out and try again", but we can do better,
> right? 8-P
>
> - Arnaldo

I agree! We were talking in a previous conversation about making perf
the user-friendliest possible. But I don't know if providing two
different remount to the user at the same time is the best thing to do
(even in that second case).
Why not checking first access to debugfs: if it doesn't work, give the
remount line for debugfs then exit. The user will do it then run perf
again. If it works, check tracefs: if it doesn't work, give the
remount line for tracefs. That gives at most two fail-runs of perf
before using it without any problem. It also allows not to give the
user two different remount lines directly when we can't be sure the
second one is useful (perhaps tracefs will be accessible directly?)
Another possibility would be to have another perf command, sort of a
"perf remountfs", to run with sudo and that would make itself both
checks and remount accordingly the two fs.

Thoughts?

Arnaldo Carvalho de Melo

unread,
Sep 11, 2015, 4:22:37 PM9/11/15
to Raphaël Beamonte, Jiri Olsa, Namhyung Kim, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Peter Zijlstra, Matt Fleming
Em Fri, Sep 11, 2015 at 03:56:44PM -0400, Raphaël Beamonte escreveu:
> Another possibility would be to have another perf command, sort of a
> "perf remountfs", to run with sudo and that would make itself both
> checks and remount accordingly the two fs.

This part maybe more interesting, so I'll focus on it, yeah, having a:
'perf fixperms' command (have a better name? :) ) may make sense, would
need context tho, i.e. something like:

perf fixperms trace

Or:

perf fixperms top

But then, perhaps in that case:

$ trace ls
Error: No permissions to read
/sys/kernel/debug/tracing/events/raw_syscalls/sys_(enter|exit)
Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'

We could just add some more text saying that please check as well that
the other parts of the path we're trying to access are available once
the suggestion is followed.

- Arnaldo

Raphaël Beamonte

unread,
Sep 11, 2015, 6:02:18 PM9/11/15
to Arnaldo Carvalho de Melo, Jiri Olsa, Namhyung Kim, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Peter Zijlstra, Matt Fleming
2015-09-11 16:22 GMT-04:00 Arnaldo Carvalho de Melo <arnald...@gmail.com>:
> Em Fri, Sep 11, 2015 at 03:56:44PM -0400, Raphaël Beamonte escreveu:
>> Another possibility would be to have another perf command, sort of a
>> "perf remountfs", to run with sudo and that would make itself both
>> checks and remount accordingly the two fs.
>
> This part maybe more interesting, so I'll focus on it, yeah, having a:
> 'perf fixperms' command (have a better name? :) ) may make sense, would
> need context tho, i.e. something like:
>
> perf fixperms trace
>
> Or:
>
> perf fixperms top
>
> But then, perhaps in that case:
>
> $ trace ls
> Error: No permissions to read
> /sys/kernel/debug/tracing/events/raw_syscalls/sys_(enter|exit)
> Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'
>
> We could just add some more text saying that please check as well that
> the other parts of the path we're trying to access are available once
> the suggestion is followed.

Wouldn't it be almost the same as your "Something is wrong with
tracefs and/or debugfs, figure it out and try again" ? ;o)
I think that if the 'fixperms' need a context, we could as well give
the 'perf fixperms' command to type directly in the Hint, such as:

$ trace ls
Error: No permissions to read
/sys/kernel/debug/tracing/events/raw_syscalls/sys_(enter|exit)
Hint: Try 'sudo perf fixperms trace'

It would be the same as the current copy/paste, but one command that
would fix the situation directly, instead of having to check the
permissions of each level in the path. A little bit user-friendlier!

Matt Fleming

unread,
Sep 12, 2015, 6:55:31 AM9/12/15
to Jiri Olsa, Arnaldo Carvalho de Melo, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Raphaël Beamonte
On Mon, 07 Sep, at 10:38:05AM, Jiri Olsa wrote:
> Pass 'struct parse_events_error *error' to the parse-event.c
> tracepoint adding path. It will be filled with error data
> in following patches.
>
> Link: http://lkml.kernel.org/n/tip-las1hm5zf5...@git.kernel.org
> Signed-off-by: Jiri Olsa <jo...@kernel.org>
> ---
> tools/perf/util/parse-events.c | 27 ++++++++++++++++-----------
> tools/perf/util/parse-events.h | 3 ++-
> tools/perf/util/parse-events.y | 4 ++--
> 3 files changed, 20 insertions(+), 14 deletions(-)

Reviewed-by: Matt Fleming <matt.f...@intel.com>

--
Matt Fleming, Intel Open Source Technology Center

Arnaldo Carvalho de Melo

unread,
Sep 14, 2015, 4:53:14 PM9/14/15
to Jiri Olsa, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Em Thu, Sep 10, 2015 at 10:24:52AM +0200, Jiri Olsa escreveu:
Ok continuing, found two more problems in this patch, fixed as follows,
merging.

- Arnaldo

diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 666b67a4df9d..4bb0c5d2059d 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -65,7 +65,7 @@ int test__basic_mmap(void)

snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
evsels[i] = perf_evsel__newtp("syscalls", name);
- if (evsels[i] == NULL) {
+ if (IS_ERR(evsels[i]) == NULL) {
pr_debug("perf_evsel__new\n");
goto out_delete_evlist;
}
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 08c20ee4e27d..6b5d1b509148 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -234,7 +234,9 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
int err = -ENOMEM;

- if (evsel != NULL) {
+ if (evsel == NULL) {
+ goto out_err;
+ } else {
struct perf_event_attr attr = {
.type = PERF_TYPE_TRACEPOINT,
.sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
@@ -261,6 +263,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
out_free:
zfree(&evsel->name);
free(evsel);
+out_err:
return ERR_PTR(err);
}

diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index 8e3a60e3e15f..802bb868d446 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -100,7 +100,7 @@ struct event_format*
trace_event__tp_format(const char *sys, const char *name)
{
if (!tevent_initialized && trace_event__init2())
- return NULL;
+ return ERR_PTR(-ENOMEM);

return tp_format(sys, name);

Arnaldo Carvalho de Melo

unread,
Sep 14, 2015, 4:59:41 PM9/14/15
to Jiri Olsa, Namhyung Kim, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Em Thu, Sep 10, 2015 at 10:05:37AM +0200, Jiri Olsa escreveu:
> On Thu, Sep 10, 2015 at 04:00:30PM +0900, Namhyung Kim wrote:
> > On Mon, Sep 07, 2015 at 10:38:07AM +0200, Jiri Olsa wrote:
> > > Enhancing parsing events tracepoint error output. Adding
> > > more verbose output when the tracepoint is not found or
> > > the tracing event path cannot be access.
> > >
> > > $ sudo perf record -e sched:sched_krava ls
> > > event syntax error: 'sched:sched_krava'
> > > \___ unknown tracepoint
> > >
> > > Error: File /sys/kernel/debug/tracing//tracing/events/sched/sched_krava not found.
> > > Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
> > >
> > > Run 'perf list' for a list of valid events
> > > ...
> > >
> > > $ perf record -e sched:sched_krava ls
> > > event syntax error: 'sched:sched_krava'
> > > \___ can't access trace events
> > >
> > > Error: No permissions to read /sys/kernel/debug/tracing//tracing/events/sched/sched_krava
> > > Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'
> >
> > What about tracefs? On my system, tracefs is mounted on
> > /sys/kernel/debug/tracing thus I cannot access trace events after
> > remounting debugfs with mode=755.
>
> right, patch below keeps the actual mount and
> display proper info.. could you please try?

I'll apply up to 5/5, will wait for this one to be resubmitted with
S-o-B, ok?

- Arnaldo

Raphaël Beamonte

unread,
Sep 14, 2015, 5:00:11 PM9/14/15
to Arnaldo Carvalho de Melo, Jiri Olsa, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
Is the else really necessary after a goto?

Arnaldo Carvalho de Melo

unread,
Sep 14, 2015, 5:02:51 PM9/14/15
to Jiri Olsa, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming, Raphaël Beamonte
Em Mon, Sep 14, 2015 at 05:53:03PM -0300, Arnaldo Carvalho de Melo escreveu:
> Ok continuing, found two more problems in this patch, fixed as follows,
> merging.

> - Arnaldo

> +++ b/tools/perf/tests/mmap-basic.c
> @@ -65,7 +65,7 @@ int test__basic_mmap(void)
>
> snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
> evsels[i] = perf_evsel__newtp("syscalls", name);
> - if (evsels[i] == NULL) {
> + if (IS_ERR(evsels[i]) == NULL) {

modulo the == NULL ;-)

> pr_debug("perf_evsel__new\n");
> goto out_delete_evlist;
> }

Arnaldo Carvalho de Melo

unread,
Sep 14, 2015, 5:36:41 PM9/14/15
to Raphaël Beamonte, Jiri Olsa, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
Em Mon, Sep 14, 2015 at 04:59:41PM -0400, Raphaël Beamonte escreveu:
> 2015-09-14 16:53 GMT-04:00 Arnaldo Carvalho de Melo <arnald...@gmail.com>:
> > +++ b/tools/perf/util/evsel.c
> > @@ -234,7 +234,9 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
> > struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
> > int err = -ENOMEM;
> >
> > - if (evsel != NULL) {
> > + if (evsel == NULL) {
> > + goto out_err;
> > + } else {
>
> Is the else really necessary after a goto?

Not really, we can remove it and all would be equivalent (the code
with/without should be the same), its just that I wanted to avoid
touching the identation to reduce patch size and since we need o open a
brace to declare that attr variable...

- Arnaldo

Raphaël Beamonte

unread,
Sep 14, 2015, 6:06:07 PM9/14/15
to Arnaldo Carvalho de Melo, Jiri Olsa, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
2015-09-14 17:36 GMT-04:00 Arnaldo Carvalho de Melo <arnald...@gmail.com>:
> Em Mon, Sep 14, 2015 at 04:59:41PM -0400, Raphaël Beamonte escreveu:
>> 2015-09-14 16:53 GMT-04:00 Arnaldo Carvalho de Melo <arnald...@gmail.com>:
>> > +++ b/tools/perf/util/evsel.c
>> > @@ -234,7 +234,9 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
>> > struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
>> > int err = -ENOMEM;
>> >
>> > - if (evsel != NULL) {
>> > + if (evsel == NULL) {
>> > + goto out_err;
>> > + } else {
>>
>> Is the else really necessary after a goto?
>
> Not really, we can remove it and all would be equivalent (the code
> with/without should be the same), its just that I wanted to avoid
> touching the identation to reduce patch size and since we need o open a
> brace to declare that attr variable...
>
> - Arnaldo

Ok. Though, given the content of that function, we could probably
declare attr in the first lines of the function and assign it its
value after the if. But I understand the patch size argument! :o)
On another subject, but on the same lines, shouldn't we use if
(!evsel) instead of if (evsel == NULL)? (kernel code style if I'm not
mistaken) Or is there something that prevents from using it here?

Arnaldo Carvalho de Melo

unread,
Sep 14, 2015, 10:37:14 PM9/14/15
to Raphaël Beamonte, Jiri Olsa, Jiri Olsa, lkml, David Ahern, Ingo Molnar, Namhyung Kim, Peter Zijlstra, Matt Fleming
Em Mon, Sep 14, 2015 at 06:05:38PM -0400, Raphaël Beamonte escreveu:
> 2015-09-14 17:36 GMT-04:00 Arnaldo Carvalho de Melo <arnald...@gmail.com>:
> > Em Mon, Sep 14, 2015 at 04:59:41PM -0400, Raphaël Beamonte escreveu:
> >> 2015-09-14 16:53 GMT-04:00 Arnaldo Carvalho de Melo <arnald...@gmail.com>:
> >> > +++ b/tools/perf/util/evsel.c
> >> > @@ -234,7 +234,9 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
> >> > struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
> >> > int err = -ENOMEM;
> >> >
> >> > - if (evsel != NULL) {
> >> > + if (evsel == NULL) {
> >> > + goto out_err;
> >> > + } else {
> >>
> >> Is the else really necessary after a goto?
> >
> > Not really, we can remove it and all would be equivalent (the code
> > with/without should be the same), its just that I wanted to avoid
> > touching the identation to reduce patch size and since we need o open a
> > brace to declare that attr variable...
>
> Ok. Though, given the content of that function, we could probably
> declare attr in the first lines of the function and assign it its
> value after the if. But I understand the patch size argument! :o)

Yeah, in other times I would have cleaned it all up, having that else is
ugly, but review time is more expensive, I think, so we need to reduce
its cost.

Cleaning it up makes it easier to read, but we get the info about when
that particular code was written buried a bit below the reindentation
cset.

Would be nice to have a 'git blame' that would just unwind things like
that :-)

> On another subject, but on the same lines, shouldn't we use if
> (!evsel) instead of if (evsel == NULL)? (kernel code style if I'm not
> mistaken) Or is there something that prevents from using it here?

I'd say both are ok. (evsel) is shorter than (evsel != NULL), but the
later is more expressive, at a glance you know it is a pointer, etc.

- Arnaldo

tip-bot for Jiri Olsa

unread,
Sep 15, 2015, 3:03:20 AM9/15/15
to linux-ti...@vger.kernel.org, jo...@kernel.org, linux-...@vger.kernel.org, namh...@kernel.org, a.p.zi...@chello.nl, h...@zytor.com, ac...@redhat.com, ma...@codeblueprint.co.uk, tg...@linutronix.de, raphael....@gmail.com, mi...@kernel.org, dsa...@gmail.com
Commit-ID: b60114067c656be572f0ca4030c3a2c560e7255c
Gitweb: http://git.kernel.org/tip/b60114067c656be572f0ca4030c3a2c560e7255c
Author: Jiri Olsa <jo...@kernel.org>
AuthorDate: Mon, 7 Sep 2015 10:38:04 +0200
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Mon, 14 Sep 2015 12:50:23 -0300

perf tools: Add tools/include into tags directories

Adding tools/include into tags directories, to have include definitions
reachable via tags/cscope.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Raphael Beamonte <raphael....@gmail.com>
Link: http://lkml.kernel.org/r/1441615087-13886-3-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile.perf | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d9863cb..6c5c699 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -459,7 +459,7 @@ INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
$(DOC_TARGETS):
$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)

-TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol
+TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../include
TAG_FILES= ../../include/uapi/linux/perf_event.h

TAGS:

Arnaldo Carvalho de Melo

unread,
Sep 15, 2015, 11:29:02 AM9/15/15
to Ingo Molnar, linux-...@vger.kernel.org, Jiri Olsa, Raphael Beamonte, David Ahern, Matt Fleming, Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Jiri Olsa <jo...@kernel.org>

Enhancing parsing events tracepoint error output. Adding
more verbose output when the tracepoint is not found or
the tracing event path cannot be access.

$ sudo perf record -e sched:sched_krava ls
event syntax error: 'sched:sched_krava'
\___ unknown tracepoint

Error: File /sys/kernel/debug/tracing//tracing/events/sched/sched_krava not found.
Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.

Run 'perf list' for a list of valid events
...

$ perf record -e sched:sched_krava ls
event syntax error: 'sched:sched_krava'
\___ can't access trace events

Error: No permissions to read /sys/kernel/debug/tracing//tracing/events/sched/sched_krava
Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'

Run 'perf list' for a list of valid events
...

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
Cc: Raphael Beamonte <raphael....@gmail.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1441615087-13886-6-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/parse-events.c | 35 ++++++++++++++++++++++++++++++++---
tools/perf/util/parse-events.y | 16 +++++++++-------
2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index c47831c47220..d3fb90be6216 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -387,6 +387,33 @@ int parse_events_add_cache(struct list_head *list, int *idx,
return add_event(list, idx, &attr, name, NULL);
}

+static void tracepoint_error(struct parse_events_error *error, int err,
+ char *sys, char *name)
+{
+ char help[BUFSIZ];
+
+ /*
+ * We get error directly from syscall errno ( > 0),
+ * or from encoded pointer's error ( < 0).
+ */
+ err = abs(err);
+
+ switch (err) {
+ case EACCES:
+ error->str = strdup("can't access trace events");
+ break;
+ case ENOENT:
+ error->str = strdup("unknown tracepoint");
+ break;
+ default:
+ error->str = strdup("failed to add tracepoint");
+ break;
+ }
+
+ tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name);
+ error->help = strdup(help);
+}
+
static int add_tracepoint(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
struct parse_events_error *error __maybe_unused)
@@ -394,8 +421,10 @@ static int add_tracepoint(struct list_head *list, int *idx,
struct perf_evsel *evsel;

evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
- if (IS_ERR(evsel))
+ if (IS_ERR(evsel)) {
+ tracepoint_error(error, PTR_ERR(evsel), sys_name, evt_name);
return PTR_ERR(evsel);
+ }

list_add_tail(&evsel->node, list);
return 0;
@@ -413,7 +442,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
evt_dir = opendir(evt_path);
if (!evt_dir) {
- perror("Can't open event dir");
+ tracepoint_error(error, errno, sys_name, evt_name);
return -1;
}

@@ -453,7 +482,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,

events_dir = opendir(tracing_events_path);
if (!events_dir) {
- perror("Can't open event dir");
+ tracepoint_error(error, errno, sys_name, evt_name);
return -1;
}

diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 54a3004a8192..8bcc45868457 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -371,28 +371,30 @@ event_legacy_tracepoint:
PE_NAME '-' PE_NAME ':' PE_NAME
{
struct parse_events_evlist *data = _data;
+ struct parse_events_error *error = data->error;
struct list_head *list;
char sys_name[128];
snprintf(&sys_name, 128, "%s-%s", $1, $3);

ALLOC_LIST(list);
- ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, data->error));
+ if (parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, error)) {
+ if (error)
+ error->idx = @1.first_column;
+ return -1;
+ }
$$ = list;
}
|
PE_NAME ':' PE_NAME
{
struct parse_events_evlist *data = _data;
+ struct parse_events_error *error = data->error;
struct list_head *list;

ALLOC_LIST(list);
- if (parse_events_add_tracepoint(list, &data->idx, $1, $3, data->error)) {
- struct parse_events_error *error = data->error;
-
- if (error) {
+ if (parse_events_add_tracepoint(list, &data->idx, $1, $3, error)) {
+ if (error)
error->idx = @1.first_column;
- error->str = strdup("unknown tracepoint");
- }
return -1;
}
$$ = list;
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 15, 2015, 11:29:04 AM9/15/15
to Ingo Molnar, linux-...@vger.kernel.org, Jiri Olsa, David Ahern, Matt Fleming, Namhyung Kim, Peter Zijlstra, Raphael Beamonte, Arnaldo Carvalho de Melo
From: Jiri Olsa <jo...@kernel.org>

Propagate error info from tp_format via ERR_PTR to get it all the way
down to the parse-event.c tracepoint adding routines. Following
functions now return pointer with encoded error:

- tp_format
- trace_event__tp_format
- perf_evsel__newtp_idx
- perf_evsel__newtp

This affects several other places in perf, that cannot use pointer check
anymore, but must utilize the err.h interface, when getting error
information from above functions list.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Raphael Beamonte <raphael....@gmail.com>
Link: http://lkml.kernel.org/r/1441615087-13886-5-...@kernel.org
[ Add two missing ERR_PTR() and one IS_ERR() ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 19 +++++++++++--------
tools/perf/tests/evsel-tp-sched.c | 10 ++++++++--
tools/perf/tests/mmap-basic.c | 3 ++-
tools/perf/tests/openat-syscall-all-cpus.c | 3 ++-
tools/perf/tests/openat-syscall-tp-fields.c | 3 ++-
tools/perf/tests/openat-syscall.c | 3 ++-
tools/perf/util/evlist.c | 3 ++-
tools/perf/util/evsel.c | 16 +++++++++++++---
tools/perf/util/evsel.h | 3 +++
tools/perf/util/parse-events.c | 6 +++---
tools/perf/util/trace-event.c | 15 ++++++++++++---
11 files changed, 60 insertions(+), 24 deletions(-)
return evsel;

@@ -1705,12 +1707,12 @@ static int trace__read_syscall_info(struct trace *trace, int id)
snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
sc->tp_format = trace_event__tp_format("syscalls", tp_name);

- if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
+ if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
sc->tp_format = trace_event__tp_format("syscalls", tp_name);
}

- if (sc->tp_format == NULL)
+ if (IS_ERR(sc->tp_format))
return -1;

sc->args = sc->tp_format->format.fields;
@@ -2390,7 +2392,8 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
{
struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
- if (evsel == NULL)
+
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 666b67a4df9d..4495493c9431 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -3,6 +3,7 @@
#include "thread_map.h"
#include "cpumap.h"
#include "tests.h"
+#include <linux/err.h>

/*
* This test will generate random numbers of calls to some getpid syscalls,
@@ -65,7 +66,7 @@ int test__basic_mmap(void)

snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
evsels[i] = perf_evsel__newtp("syscalls", name);
- if (evsels[i] == NULL) {
+ if (IS_ERR(evsels[i])) {
pr_debug("perf_evsel__new\n");
goto out_delete_evlist;
}
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 771ade4d5966..6b5d1b509148 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -13,6 +13,7 @@
#include <traceevent/event-parse.h>
#include <linux/hw_breakpoint.h>
#include <linux/perf_event.h>
+#include <linux/err.h>
#include <sys/resource.h>
#include "asm/bug.h"
#include "callchain.h"
@@ -225,11 +226,17 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
return evsel;
}

+/*
+ * Returns pointer with encoded error via <linux/err.h> interface.
+ */
struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
{
struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
+ int err = -ENOMEM;

- if (evsel != NULL) {
+ if (evsel == NULL) {
+ goto out_err;
+ } else {
struct perf_event_attr attr = {
.type = PERF_TYPE_TRACEPOINT,
.sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
@@ -240,8 +247,10 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
goto out_free;

evsel->tp_format = trace_event__tp_format(sys, name);
- if (evsel->tp_format == NULL)
+ if (IS_ERR(evsel->tp_format)) {
+ err = PTR_ERR(evsel->tp_format);
goto out_free;
+ }

event_attr_init(&attr);
attr.config = evsel->tp_format->id;
@@ -254,7 +263,8 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
out_free:
zfree(&evsel->name);
free(evsel);
- return NULL;
+out_err:
+ return ERR_PTR(err);
}

const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index f164a149da82..62ab307b7306 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -160,6 +160,9 @@ static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)

struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx);

+/*
+ * Returns pointer with encoded error via <linux/err.h> interface.
+ */
static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name)
{
return perf_evsel__newtp_idx(sys, name, 0);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1b284b8ad243..c47831c47220 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,4 +1,5 @@
#include <linux/hw_breakpoint.h>
+#include <linux/err.h>
#include "util.h"
#include "../perf.h"
#include "evlist.h"
@@ -393,11 +394,10 @@ static int add_tracepoint(struct list_head *list, int *idx,
struct perf_evsel *evsel;

evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
- if (!evsel)
- return -ENOMEM;
+ if (IS_ERR(evsel))
+ return PTR_ERR(evsel);

list_add_tail(&evsel->node, list);
-
return 0;
}

diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index 2f4996ab313d..802bb868d446 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -7,6 +7,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/kernel.h>
+#include <linux/err.h>
#include <traceevent/event-parse.h>
#include <api/fs/tracing_path.h>
#include "trace-event.h"
@@ -66,6 +67,9 @@ void trace_event__cleanup(struct trace_event *t)
pevent_free(t->pevent);
}

+/*
+ * Returns pointer with encoded error via <linux/err.h> interface.
+ */
static struct event_format*
tp_format(const char *sys, const char *name)
{
@@ -74,12 +78,14 @@ tp_format(const char *sys, const char *name)
char path[PATH_MAX];
size_t size;
char *data;
+ int err;

scnprintf(path, PATH_MAX, "%s/%s/%s/format",
tracing_events_path, sys, name);

- if (filename__read_str(path, &data, &size))
- return NULL;
+ err = filename__read_str(path, &data, &size);
+ if (err)
+ return ERR_PTR(err);

pevent_parse_format(pevent, &event, data, size, sys);

@@ -87,11 +93,14 @@ tp_format(const char *sys, const char *name)
return event;
}

+/*
+ * Returns pointer with encoded error via <linux/err.h> interface.
+ */
struct event_format*
trace_event__tp_format(const char *sys, const char *name)
{
if (!tevent_initialized && trace_event__init2())
- return NULL;
+ return ERR_PTR(-ENOMEM);

return tp_format(sys, name);
}

Arnaldo Carvalho de Melo

unread,
Sep 15, 2015, 11:29:13 AM9/15/15
to Ingo Molnar, linux-...@vger.kernel.org, Wang Nan, Alexei Starovoitov, Brendan Gregg, Daniel Borkmann, David Ahern, Jiri Olsa, Kaixu Xia, Namhyung Kim, Paul Mackerras, Peter Zijlstra, Zefan Li, pi3o...@163.com, He Kuang, Arnaldo Carvalho de Melo
From: Wang Nan <wang...@huawei.com>

regs_query_register_offset() is a helper function which converts
register name like "%rax" to offset of a register in 'struct pt_regs',
which is required by BPF prologue generator.

PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET indicates an architecture
supports converting name of a register to its offset in 'struct
pt_regs'.

HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET is introduced as the corresponding
CFLAGS of PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET.

Signed-off-by: Wang Nan <wang...@huawei.com>
Acked-by: Masami Hiramatsu <masami.hi...@hitachi.com>
Cc: Alexei Starovoitov <a...@plumgrid.com>
Cc: Brendan Gregg <brendan...@gmail.com>
Cc: Daniel Borkmann <dan...@iogearbox.net>
Cc: David Ahern <dsa...@gmail.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Kaixu Xia <xiak...@huawei.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Zefan Li <liz...@huawei.com>
Cc: pi3o...@163.com
Link: http://lkml.kernel.org/r/1441523623-152703-19-g...@huawei.com
Signed-off-by: He Kuang <hek...@huawei.com>
[ Extracted from eBPF patches ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/config/Makefile | 4 ++++
tools/perf/util/include/dwarf-regs.h | 8 ++++++++
2 files changed, 12 insertions(+)

diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 827557fc7511..0435ac41cea9 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -109,6 +109,10 @@ endif
# include ARCH specific config
-include $(src-perf)/arch/$(ARCH)/Makefile

+ifdef PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
+ CFLAGS += -DHAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
+endif
+
include $(src-perf)/config/utilities.mak

ifeq ($(call get-executable,$(FLEX)),)
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index 8f149655f497..07c644ed64c4 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -5,4 +5,12 @@
const char *get_arch_regstr(unsigned int n);
#endif

+#ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
+/*
+ * Arch should support fetching the offset of a register in pt_regs
+ * by its name. See kernel's regs_query_register_offset in
+ * arch/xxx/kernel/ptrace.c.
+ */
+int regs_query_register_offset(const char *name);
+#endif
#endif

Arnaldo Carvalho de Melo

unread,
Sep 15, 2015, 11:30:00 AM9/15/15
to Ingo Molnar, linux-...@vger.kernel.org, Wang Nan, He Kuang, Alexei Starovoitov, Brendan Gregg, Daniel Borkmann, David Ahern, Jiri Olsa, Kaixu Xia, Namhyung Kim, Paul Mackerras, Peter Zijlstra, Zefan Li, pi3o...@163.com, Arnaldo Carvalho de Melo
From: Wang Nan <wang...@huawei.com>

regs_query_register_offset() is a helper function which converts
register name like "%rax" to offset of a register in 'struct pt_regs',
which is required by BPF prologue generator. Since the function is
identical, try to reuse the code in arch/x86/kernel/ptrace.c.

Comment inside dwarf-regs.c list the differences between this
implementation and kernel code.

get_arch_regstr() switches to regoffset_table and the old string table
is dropped.

Signed-off-by: He Kuang <hek...@huawei.com>
Acked-by: Masami Hiramatsu <masami.hi...@hitachi.com>
Cc: Alexei Starovoitov <a...@plumgrid.com>
Cc: Brendan Gregg <brendan...@gmail.com>
Cc: Daniel Borkmann <dan...@iogearbox.net>
Cc: David Ahern <dsa...@gmail.com>
Cc: He Kuang <hek...@huawei.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Kaixu Xia <xiak...@huawei.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Zefan Li <liz...@huawei.com>
Cc: pi3o...@163.com
Link: http://lkml.kernel.org/r/1441523623-152703-20-g...@huawei.com
Signed-off-by: Wang Nan <wang...@huawei.com>
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/arch/x86/Makefile | 1 +
tools/perf/arch/x86/util/dwarf-regs.c | 122 ++++++++++++++++++++++++----------
2 files changed, 89 insertions(+), 34 deletions(-)

diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 21322e0385b8..09ba923debe8 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -2,3 +2,4 @@ ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1
endif
HAVE_KVM_STAT_SUPPORT := 1
+PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c
index a08de0a35b83..9223c164e545 100644
--- a/tools/perf/arch/x86/util/dwarf-regs.c
+++ b/tools/perf/arch/x86/util/dwarf-regs.c
@@ -21,55 +21,109 @@
*/

#include <stddef.h>
+#include <errno.h> /* for EINVAL */
+#include <string.h> /* for strcmp */
+#include <linux/ptrace.h> /* for struct pt_regs */
+#include <linux/kernel.h> /* for offsetof */
#include <dwarf-regs.h>

/*
- * Generic dwarf analysis helpers
+ * See arch/x86/kernel/ptrace.c.
+ * Different from it:
+ *
+ * - Since struct pt_regs is defined differently for user and kernel,
+ * but we want to use 'ax, bx' instead of 'rax, rbx' (which is struct
+ * field name of user's pt_regs), we make REG_OFFSET_NAME to accept
+ * both string name and reg field name.
+ *
+ * - Since accessing x86_32's pt_regs from x86_64 building is difficult
+ * and vise versa, we simply fill offset with -1, so
+ * get_arch_regstr() still works but regs_query_register_offset()
+ * returns error.
+ * The only inconvenience caused by it now is that we are not allowed
+ * to generate BPF prologue for a x86_64 kernel if perf is built for
+ * x86_32. This is really a rare usecase.
+ *
+ * - Order is different from kernel's ptrace.c for get_arch_regstr(). Use
+ * the order defined by dwarf.
*/

-#define X86_32_MAX_REGS 8
-const char *x86_32_regs_table[X86_32_MAX_REGS] = {
- "%ax",
- "%cx",
- "%dx",
- "%bx",
- "$stack", /* Stack address instead of %sp */
- "%bp",
- "%si",
- "%di",
+struct pt_regs_offset {
+ const char *name;
+ int offset;
+};
+
+#define REG_OFFSET_END {.name = NULL, .offset = 0}
+
+#ifdef __x86_64__
+# define REG_OFFSET_NAME_64(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)}
+# define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = -1}
+#else
+# define REG_OFFSET_NAME_64(n, r) {.name = n, .offset = -1}
+# define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)}
+#endif
+
+static const struct pt_regs_offset x86_32_regoffset_table[] = {
+ REG_OFFSET_NAME_32("%ax", eax),
+ REG_OFFSET_NAME_32("%cx", ecx),
+ REG_OFFSET_NAME_32("%dx", edx),
+ REG_OFFSET_NAME_32("%bx", ebx),
+ REG_OFFSET_NAME_32("$stack", esp), /* Stack address instead of %sp */
+ REG_OFFSET_NAME_32("%bp", ebp),
+ REG_OFFSET_NAME_32("%si", esi),
+ REG_OFFSET_NAME_32("%di", edi),
+ REG_OFFSET_END,
};

-#define X86_64_MAX_REGS 16
-const char *x86_64_regs_table[X86_64_MAX_REGS] = {
- "%ax",
- "%dx",
- "%cx",
- "%bx",
- "%si",
- "%di",
- "%bp",
- "%sp",
- "%r8",
- "%r9",
- "%r10",
- "%r11",
- "%r12",
- "%r13",
- "%r14",
- "%r15",
+static const struct pt_regs_offset x86_64_regoffset_table[] = {
+ REG_OFFSET_NAME_64("%ax", rax),
+ REG_OFFSET_NAME_64("%dx", rdx),
+ REG_OFFSET_NAME_64("%cx", rcx),
+ REG_OFFSET_NAME_64("%bx", rbx),
+ REG_OFFSET_NAME_64("%si", rsi),
+ REG_OFFSET_NAME_64("%di", rdi),
+ REG_OFFSET_NAME_64("%bp", rbp),
+ REG_OFFSET_NAME_64("%sp", rsp),
+ REG_OFFSET_NAME_64("%r8", r8),
+ REG_OFFSET_NAME_64("%r9", r9),
+ REG_OFFSET_NAME_64("%r10", r10),
+ REG_OFFSET_NAME_64("%r11", r11),
+ REG_OFFSET_NAME_64("%r12", r12),
+ REG_OFFSET_NAME_64("%r13", r13),
+ REG_OFFSET_NAME_64("%r14", r14),
+ REG_OFFSET_NAME_64("%r15", r15),
+ REG_OFFSET_END,
};

/* TODO: switching by dwarf address size */
#ifdef __x86_64__
-#define ARCH_MAX_REGS X86_64_MAX_REGS
-#define arch_regs_table x86_64_regs_table
+#define regoffset_table x86_64_regoffset_table
#else
-#define ARCH_MAX_REGS X86_32_MAX_REGS
-#define arch_regs_table x86_32_regs_table
+#define regoffset_table x86_32_regoffset_table
#endif

+/* Minus 1 for the ending REG_OFFSET_END */
+#define ARCH_MAX_REGS ((sizeof(regoffset_table) / sizeof(regoffset_table[0])) - 1)
+
/* Return architecture dependent register string (for kprobe-tracer) */
const char *get_arch_regstr(unsigned int n)
{
- return (n < ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
+ return (n < ARCH_MAX_REGS) ? regoffset_table[n].name : NULL;
+}
+
+/* Reuse code from arch/x86/kernel/ptrace.c */
+/**
+ * regs_query_register_offset() - query register offset from its name
+ * @name: the name of a register
+ *
+ * regs_query_register_offset() returns the offset of a register in struct
+ * pt_regs from its name. If the name is invalid, this returns -EINVAL;
+ */
+int regs_query_register_offset(const char *name)
+{
+ const struct pt_regs_offset *roff;
+ for (roff = regoffset_table; roff->name != NULL; roff++)
+ if (!strcmp(roff->name, name))
+ return roff->offset;
+ return -EINVAL;

Arnaldo Carvalho de Melo

unread,
Sep 15, 2015, 11:32:11 AM9/15/15
to Ingo Molnar, linux-...@vger.kernel.org, Namhyung Kim, Jiri Olsa, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Namhyung Kim <namh...@kernel.org>

The cleanup_perf_probe_events() frees all resources related to a perf
probe event. However it only freed resources in trace probe events, not
perf probe events. So call clear_perf_probe_event() too.

Reported-by: Wang Nan <wang...@huawei.com>
Signed-off-by: Namhyung Kim <namh...@kernel.org>
Acked-by: Masami Hiramatsu <masami.hi...@hitachi.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1441852026-28974-1-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/probe-event.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 5964eccbe94d..3d7d60cc6f16 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2792,6 +2792,7 @@ void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs)
clear_probe_trace_event(&pevs[i].tevs[j]);
zfree(&pevs[i].tevs);
pevs[i].ntevs = 0;
+ clear_perf_probe_event(&pevs[i]);
}

exit_symbol_maps();

Arnaldo Carvalho de Melo

unread,
Sep 15, 2015, 11:33:02 AM9/15/15
to Ingo Molnar, linux-...@vger.kernel.org, Jiri Olsa, David Ahern, Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Jiri Olsa <jo...@kernel.org>

Pass 'struct parse_events_error *error' to the parse-event.c tracepoint
adding path. It will be filled with error data in following patches.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Reviewed-by: Raphael Beamonte <raphael....@gmail.com>
Reviewed-by: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1441615087-13886-4-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/parse-events.c | 27 ++++++++++++++++-----------
tools/perf/util/parse-events.h | 3 ++-
tools/perf/util/parse-events.y | 4 ++--
3 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 3840176642f8..1b284b8ad243 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -387,7 +387,8 @@ int parse_events_add_cache(struct list_head *list, int *idx,
}

static int add_tracepoint(struct list_head *list, int *idx,
- char *sys_name, char *evt_name)
+ char *sys_name, char *evt_name,
+ struct parse_events_error *error __maybe_unused)
{
struct perf_evsel *evsel;

@@ -401,7 +402,8 @@ static int add_tracepoint(struct list_head *list, int *idx,
}

static int add_tracepoint_multi_event(struct list_head *list, int *idx,
- char *sys_name, char *evt_name)
+ char *sys_name, char *evt_name,
+ struct parse_events_error *error)
{
char evt_path[MAXPATHLEN];
struct dirent *evt_ent;
@@ -425,7 +427,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
if (!strglobmatch(evt_ent->d_name, evt_name))
continue;

- ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name);
+ ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, error);
}

closedir(evt_dir);
@@ -433,15 +435,17 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
}

static int add_tracepoint_event(struct list_head *list, int *idx,
- char *sys_name, char *evt_name)
+ char *sys_name, char *evt_name,
+ struct parse_events_error *error)
{
return strpbrk(evt_name, "*?") ?
- add_tracepoint_multi_event(list, idx, sys_name, evt_name) :
- add_tracepoint(list, idx, sys_name, evt_name);
+ add_tracepoint_multi_event(list, idx, sys_name, evt_name, error) :
+ add_tracepoint(list, idx, sys_name, evt_name, error);
}

static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
- char *sys_name, char *evt_name)
+ char *sys_name, char *evt_name,
+ struct parse_events_error *error)
{
struct dirent *events_ent;
DIR *events_dir;
@@ -465,7 +469,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
continue;

ret = add_tracepoint_event(list, idx, events_ent->d_name,
- evt_name);
+ evt_name, error);
}

closedir(events_dir);
@@ -473,12 +477,13 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
}

int parse_events_add_tracepoint(struct list_head *list, int *idx,
- char *sys, char *event)
+ char *sys, char *event,
+ struct parse_events_error *error)
{
if (strpbrk(sys, "*?"))
- return add_tracepoint_multi_sys(list, idx, sys, event);
+ return add_tracepoint_multi_sys(list, idx, sys, event, error);
else
- return add_tracepoint_event(list, idx, sys, event);
+ return add_tracepoint_event(list, idx, sys, event, error);
}

static int
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index a09b0e210997..ffee7ece75a6 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -118,7 +118,8 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add);
int parse_events__modifier_group(struct list_head *list, char *event_mod);
int parse_events_name(struct list_head *list, char *name);
int parse_events_add_tracepoint(struct list_head *list, int *idx,
- char *sys, char *event);
+ char *sys, char *event,
+ struct parse_events_error *error);
int parse_events_add_numeric(struct parse_events_evlist *data,
struct list_head *list,
u32 type, u64 config,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 9cd70819c795..54a3004a8192 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -376,7 +376,7 @@ PE_NAME '-' PE_NAME ':' PE_NAME
snprintf(&sys_name, 128, "%s-%s", $1, $3);

ALLOC_LIST(list);
- ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5));
+ ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, data->error));
$$ = list;
}
|
@@ -386,7 +386,7 @@ PE_NAME ':' PE_NAME
struct list_head *list;

ALLOC_LIST(list);
- if (parse_events_add_tracepoint(list, &data->idx, $1, $3)) {
+ if (parse_events_add_tracepoint(list, &data->idx, $1, $3, data->error)) {
struct parse_events_error *error = data->error;

if (error) {

Arnaldo Carvalho de Melo

unread,
Sep 15, 2015, 11:33:22 AM9/15/15
to Ingo Molnar, linux-...@vger.kernel.org, Jiri Olsa, David Ahern, Matt Fleming, Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Jiri Olsa <jo...@kernel.org>

Adding part of the kernel's <linux/err.h> interface:

inline void * __must_check ERR_PTR(long error);
inline long __must_check PTR_ERR(__force const void *ptr);
inline bool __must_check IS_ERR(__force const void *ptr);

It will be used to propagate error through pointers in following
patches.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Reviewed-by: Raphael Beamonte <raphael....@gmail.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1441615087-13886-2-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/include/linux/err.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
create mode 100644 tools/include/linux/err.h

diff --git a/tools/include/linux/err.h b/tools/include/linux/err.h
new file mode 100644
index 000000000000..c9ada48f5156
--- /dev/null
+++ b/tools/include/linux/err.h
@@ -0,0 +1,49 @@
+#ifndef __TOOLS_LINUX_ERR_H
+#define __TOOLS_LINUX_ERR_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#include <asm/errno.h>
+
+/*
+ * Original kernel header comment:
+ *
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a normal
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ *
+ * Userspace note:
+ * The same principle works for userspace, because 'error' pointers
+ * fall down to the unused hole far from user space, as described
+ * in Documentation/x86/x86_64/mm.txt for x86_64 arch:
+ *
+ * 0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm hole caused by [48:63] sign extension
+ * ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole
+ *
+ * It should be the same case for other architectures, because
+ * this code is used in generic kernel code.
+ */
+#define MAX_ERRNO 4095
+
+#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
+
+static inline void * __must_check ERR_PTR(long error)
+{
+ return (void *) error;
+}
+
+static inline long __must_check PTR_ERR(__force const void *ptr)
+{
+ return (long) ptr;
+}
+
+static inline bool __must_check IS_ERR(__force const void *ptr)
+{
+ return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+#endif /* _LINUX_ERR_H */

Arnaldo Carvalho de Melo

unread,
Sep 15, 2015, 11:33:36 AM9/15/15
to Ingo Molnar, linux-...@vger.kernel.org, Namhyung Kim, Jiri Olsa, Peter Zijlstra, Wang Nan, Arnaldo Carvalho de Melo
From: Namhyung Kim <namh...@kernel.org>

The init/exit_symbols_maps() functions are to setup and cleanup
necessary info for probe events. But they need to be called from out of
the probe code now, so this patch exports them.

However the names are too generic, so change them to have 'probe'. :)

Signed-off-by: Namhyung Kim <namh...@kernel.org>
Acked-by: Masami Hiramatsu <masami.hi...@hitachi.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/1441852026-28974-2-gi...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-probe.c | 5 +++++
tools/perf/util/probe-event.c | 31 +++++++++++++++----------------
tools/perf/util/probe-event.h | 2 ++
3 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 2bec9c1ef2a3..94385ee89dc8 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -317,6 +317,10 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
int i, k;
const char *event = NULL, *group = NULL;

+ ret = init_probe_symbol_maps(pevs->uprobes);
+ if (ret < 0)
+ return ret;
+
ret = convert_perf_probe_events(pevs, npevs);
if (ret < 0)
goto out_cleanup;
@@ -354,6 +358,7 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)

out_cleanup:
cleanup_perf_probe_events(pevs, npevs);
+ exit_probe_symbol_maps();
return ret;
}

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3d7d60cc6f16..2b78e8f19b45 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -71,7 +71,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
static struct machine *host_machine;

/* Initialize symbol maps and path of vmlinux/modules */
-static int init_symbol_maps(bool user_only)
+int init_probe_symbol_maps(bool user_only)
{
int ret;

@@ -101,7 +101,7 @@ out:
return ret;
}

-static void exit_symbol_maps(void)
+void exit_probe_symbol_maps(void)
{
if (host_machine) {
machine__delete(host_machine);
@@ -859,11 +859,11 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
{
int ret;

- ret = init_symbol_maps(user);
+ ret = init_probe_symbol_maps(user);
if (ret < 0)
return ret;
ret = __show_line_range(lr, module, user);
- exit_symbol_maps();
+ exit_probe_symbol_maps();

return ret;
}
@@ -941,7 +941,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
int i, ret = 0;
struct debuginfo *dinfo;

- ret = init_symbol_maps(pevs->uprobes);
+ ret = init_probe_symbol_maps(pevs->uprobes);
if (ret < 0)
return ret;

@@ -958,7 +958,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,

debuginfo__delete(dinfo);
out:
- exit_symbol_maps();
+ exit_probe_symbol_maps();
return ret;
}

@@ -2262,7 +2262,7 @@ int show_perf_probe_events(struct strfilter *filter)

setup_pager();

- ret = init_symbol_maps(false);
+ ret = init_probe_symbol_maps(false);
if (ret < 0)
return ret;

@@ -2278,7 +2278,7 @@ int show_perf_probe_events(struct strfilter *filter)
close(kp_fd);
if (up_fd > 0)
close(up_fd);
- exit_symbol_maps();
+ exit_probe_symbol_maps();

return ret;
}
@@ -2746,10 +2746,6 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)
{
int i, ret;

- ret = init_symbol_maps(pevs->uprobes);
- if (ret < 0)
- return ret;
-
/* Loop 1: convert all events */
for (i = 0; i < npevs; i++) {
/* Init kprobe blacklist if needed */
@@ -2794,20 +2790,23 @@ void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs)
pevs[i].ntevs = 0;
clear_perf_probe_event(&pevs[i]);
}
-
- exit_symbol_maps();
}

int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)
{
int ret;

+ ret = init_probe_symbol_maps(pevs->uprobes);
+ if (ret < 0)
+ return ret;
+
ret = convert_perf_probe_events(pevs, npevs);
if (ret == 0)
ret = apply_perf_probe_events(pevs, npevs);

cleanup_perf_probe_events(pevs, npevs);

+ exit_probe_symbol_maps();
return ret;
}

@@ -2867,7 +2866,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
struct map *map;
int ret;

- ret = init_symbol_maps(user);
+ ret = init_probe_symbol_maps(user);
if (ret < 0)
return ret;

@@ -2897,7 +2896,7 @@ end:
if (user) {
map__put(map);
}
- exit_symbol_maps();
+ exit_probe_symbol_maps();

return ret;
}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 9bcea36359f2..ba926c30f8cd 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -110,6 +110,8 @@ struct variable_list {
};

struct map;
+int init_probe_symbol_maps(bool user_only);
+void exit_probe_symbol_maps(void);

/* Command string to events */
extern int parse_perf_probe_command(const char *cmd,

Ingo Molnar

unread,
Sep 16, 2015, 3:25:56 AM9/16/15
to Arnaldo Carvalho de Melo, linux-...@vger.kernel.org, Alexei Starovoitov, Brendan Gregg, Daniel Borkmann, David Ahern, He Kuang, Jiri Olsa, Kaixu Xia, Masami Hiramatsu, Matt Fleming, Namhyung Kim, Paul Mackerras, Peter Zijlstra, pi3o...@163.com, Raphael Beamonte, Wang Nan, Zefan Li, Arnaldo Carvalho de Melo

* Arnaldo Carvalho de Melo <ac...@kernel.org> wrote:

> Hi Ingo,
>
> Please consider pulling,
>
> - Arnaldo
>
> The following changes since commit 9059b284caecb628fac826c2c5cc8ee85708eec1:
>
> Merge tag 'perf-core-for-mingo-2' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2015-09-15 08:50:59 +0200)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo

So your perf/urgent bits now conflict with the latest perf/core, in
tools/perf/ui/browsers/hists.c. I have merged perf/urgent into perf/core - please
double check my resolution (d71b0ad8d309).

>
> for you to fetch changes up to bbbe6bf6037d77816c4a19aaf35f4cecf662b49a:
>
> perf tools: Introduce regs_query_register_offset() for x86 (2015-09-15 09:48:33 -0300)
>
> ----------------------------------------------------------------
> perf/core improvements and fixes:
>
> User visible:
>
> - Enhance the error reporting of tracepoint event parsing, e.g.:
>
> $ oldperf record -e sched:sched_switc usleep 1
> event syntax error: 'sched:sched_switc'
> \___ unknown tracepoint
> Run 'perf list' for a list of valid events
>
> Now we get the much nicer:
>
> $ perf record -e sched:sched_switc ls
> event syntax error: 'sched:sched_switc'
> \___ can't access trace events
>
> Error: No permissions to read /sys/kernel/debug/tracing/events/sched/sched_switc
> Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'
>
> And after we have those mount point permissions fixed:
>
> $ perf record -e sched:sched_switc ls
> event syntax error: 'sched:sched_switc'
> \___ unknown tracepoint
>
> Error: File /sys/kernel/debug/tracing/events/sched/sched_switc not found.
> Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
>
> Now its just a matter of using what git uses to suggest alternatives when we
> make a typo, i.e. that it is just an 'h' missing :-)

Nice changes!

Btw., wouldn't it be even better to allow partial matches? Not allowing
'sched:sched_switc' is unnecessarily pedantic IMHO.

For example 'perf list' allows partial matches as well. As long as the resulting
event is unique, we should allow partial matches. If it's not unique, we should
print the first 3 matching entries or so.

There's a real UI advantage as well: I could abbreviate the command line with:

-e sched_sw

instead of always being forced to type out the full tracepoint name.

(Programmatic tracepoint usage and portable scripts should naturally always spell
out the full event, to make sure new tracepoints don't cause overlaps - but ad-hoc
usage can do abbreviations just fine.)


> I.e. basically now the event parsing routing uses the strerror_open()
> routines introduced by and used in 'perf trace' work. (Jiri Olsa)
>
> Infrastructure:
>
> - Export init/exit_probe_symbol_maps() from 'perf probe' for use in eBPF
> (Namhyung Kim)
>
> - Free perf_probe_event in cleanup_perf_probe_events() (Namhyung Kim)
>
> - regs_query_register_offset() infrastructure + implementation for x86.
> First user will be the perf/eBPF code (Wang Nan)
>
> Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
>
> ----------------------------------------------------------------
> Jiri Olsa (4):
> tools: Add err.h with ERR_PTR PTR_ERR interface
> perf tools: Propagate error info for the tracepoint parsing
> perf evsel: Propagate error info from tp_format
> perf tools: Enhance parsing events tracepoint error output
>
> Namhyung Kim (2):
> perf probe: Free perf_probe_event in cleanup_perf_probe_events()
> perf probe: Export init/exit_probe_symbol_maps()
>
> Wang Nan (2):
> perf tools: regs_query_register_offset() infrastructure
> perf tools: Introduce regs_query_register_offset() for x86
>
> tools/include/linux/err.h | 49 +++++++++++
> tools/perf/arch/x86/Makefile | 1 +
> tools/perf/arch/x86/util/dwarf-regs.c | 122 ++++++++++++++++++++--------
> tools/perf/builtin-probe.c | 5 ++
> tools/perf/builtin-trace.c | 19 +++--
> tools/perf/config/Makefile | 4 +
> tools/perf/tests/evsel-tp-sched.c | 10 ++-
> tools/perf/tests/mmap-basic.c | 3 +-
> tools/perf/tests/openat-syscall-all-cpus.c | 3 +-
> tools/perf/tests/openat-syscall-tp-fields.c | 3 +-
> tools/perf/tests/openat-syscall.c | 3 +-
> tools/perf/util/evlist.c | 3 +-
> tools/perf/util/evsel.c | 16 +++-
> tools/perf/util/evsel.h | 3 +
> tools/perf/util/include/dwarf-regs.h | 8 ++
> tools/perf/util/parse-events.c | 66 +++++++++++----
> tools/perf/util/parse-events.h | 3 +-
> tools/perf/util/parse-events.y | 16 ++--
> tools/perf/util/probe-event.c | 32 ++++----
> tools/perf/util/probe-event.h | 2 +
> tools/perf/util/trace-event.c | 15 +++-
> 21 files changed, 291 insertions(+), 95 deletions(-)
> create mode 100644 tools/include/linux/err.h

Pulled, thanks a lot Arnaldo!

Ingo

tip-bot for Jiri Olsa

unread,
Sep 16, 2015, 3:29:18 AM9/16/15
to linux-ti...@vger.kernel.org, linux-...@vger.kernel.org, h...@zytor.com, tg...@linutronix.de, namh...@kernel.org, dsa...@gmail.com, jo...@kernel.org, mi...@kernel.org, ma...@codeblueprint.co.uk, ac...@redhat.com, a.p.zi...@chello.nl, raphael....@gmail.com
Commit-ID: 01ca9fd41d6f2ad796a6b109b5253e06b6ae6dc7
Gitweb: http://git.kernel.org/tip/01ca9fd41d6f2ad796a6b109b5253e06b6ae6dc7
Author: Jiri Olsa <jo...@kernel.org>
AuthorDate: Mon, 7 Sep 2015 10:38:03 +0200
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 15 Sep 2015 09:48:32 -0300

tools: Add err.h with ERR_PTR PTR_ERR interface

Adding part of the kernel's <linux/err.h> interface:

inline void * __must_check ERR_PTR(long error);
inline long __must_check PTR_ERR(__force const void *ptr);
inline bool __must_check IS_ERR(__force const void *ptr);

It will be used to propagate error through pointers in following
patches.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Reviewed-by: Raphael Beamonte <raphael....@gmail.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1441615087-13886-2-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/include/linux/err.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)

diff --git a/tools/include/linux/err.h b/tools/include/linux/err.h
new file mode 100644
index 0000000..c9ada48

tip-bot for Jiri Olsa

unread,
Sep 16, 2015, 3:29:35 AM9/16/15
to linux-ti...@vger.kernel.org, a.p.zi...@chello.nl, jo...@kernel.org, raphael....@gmail.com, mi...@kernel.org, dsa...@gmail.com, ac...@redhat.com, tg...@linutronix.de, linux-...@vger.kernel.org, h...@zytor.com, namh...@kernel.org, ma...@codeblueprint.co.uk
Commit-ID: e2f9f8ea6a54e252e3a94a5c2321f673b5b97360
Gitweb: http://git.kernel.org/tip/e2f9f8ea6a54e252e3a94a5c2321f673b5b97360
Author: Jiri Olsa <jo...@kernel.org>
AuthorDate: Mon, 7 Sep 2015 10:38:05 +0200
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 15 Sep 2015 09:48:32 -0300

perf tools: Propagate error info for the tracepoint parsing

Pass 'struct parse_events_error *error' to the parse-event.c tracepoint
adding path. It will be filled with error data in following patches.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Reviewed-by: Raphael Beamonte <raphael....@gmail.com>
Reviewed-by: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1441615087-13886-4-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/parse-events.c | 27 ++++++++++++++++-----------
tools/perf/util/parse-events.h | 3 ++-
tools/perf/util/parse-events.y | 4 ++--
3 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 3840176..1b284b8 100644
index a09b0e2..ffee7ec 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -118,7 +118,8 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add);
int parse_events__modifier_group(struct list_head *list, char *event_mod);
int parse_events_name(struct list_head *list, char *name);
int parse_events_add_tracepoint(struct list_head *list, int *idx,
- char *sys, char *event);
+ char *sys, char *event,
+ struct parse_events_error *error);
int parse_events_add_numeric(struct parse_events_evlist *data,
struct list_head *list,
u32 type, u64 config,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 9cd7081..54a3004 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -376,7 +376,7 @@ PE_NAME '-' PE_NAME ':' PE_NAME
snprintf(&sys_name, 128, "%s-%s", $1, $3);

ALLOC_LIST(list);
- ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5));
+ ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, data->error));
$$ = list;
}
|
@@ -386,7 +386,7 @@ PE_NAME ':' PE_NAME
struct list_head *list;

ALLOC_LIST(list);
- if (parse_events_add_tracepoint(list, &data->idx, $1, $3)) {
+ if (parse_events_add_tracepoint(list, &data->idx, $1, $3, data->error)) {
struct parse_events_error *error = data->error;

if (error) {

tip-bot for Jiri Olsa

unread,
Sep 16, 2015, 3:30:05 AM9/16/15
to linux-ti...@vger.kernel.org, h...@zytor.com, namh...@kernel.org, linux-...@vger.kernel.org, tg...@linutronix.de, dsa...@gmail.com, jo...@kernel.org, mi...@kernel.org, ac...@redhat.com, a.p.zi...@chello.nl, ma...@codeblueprint.co.uk, raphael....@gmail.com
Commit-ID: 8dd2a1317eba2c207632dcb19adb7cb746861652
Gitweb: http://git.kernel.org/tip/8dd2a1317eba2c207632dcb19adb7cb746861652
Author: Jiri Olsa <jo...@kernel.org>
AuthorDate: Mon, 7 Sep 2015 10:38:06 +0200
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 15 Sep 2015 09:48:33 -0300

perf evsel: Propagate error info from tp_format

Propagate error info from tp_format via ERR_PTR to get it all the way
down to the parse-event.c tracepoint adding routines. Following
functions now return pointer with encoded error:

- tp_format
- trace_event__tp_format
- perf_evsel__newtp_idx
- perf_evsel__newtp

This affects several other places in perf, that cannot use pointer check
anymore, but must utilize the err.h interface, when getting error
information from above functions list.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Raphael Beamonte <raphael....@gmail.com>
Link: http://lkml.kernel.org/r/1441615087-13886-5-...@kernel.org
[ Add two missing ERR_PTR() and one IS_ERR() ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-trace.c | 19 +++++++++++--------
tools/perf/tests/evsel-tp-sched.c | 10 ++++++++--
tools/perf/tests/mmap-basic.c | 3 ++-
tools/perf/tests/openat-syscall-all-cpus.c | 3 ++-
tools/perf/tests/openat-syscall-tp-fields.c | 3 ++-
tools/perf/tests/openat-syscall.c | 3 ++-
tools/perf/util/evlist.c | 3 ++-
tools/perf/util/evsel.c | 16 +++++++++++++---
tools/perf/util/evsel.h | 3 +++
tools/perf/util/parse-events.c | 6 +++---
tools/perf/util/trace-event.c | 15 ++++++++++++---
11 files changed, 60 insertions(+), 24 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 2156532..93b80f1 100644
index 5216242..790e413 100644
index 666b67a..4495493 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -3,6 +3,7 @@
#include "thread_map.h"
#include "cpumap.h"
#include "tests.h"
+#include <linux/err.h>

/*
* This test will generate random numbers of calls to some getpid syscalls,
@@ -65,7 +66,7 @@ int test__basic_mmap(void)

snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
evsels[i] = perf_evsel__newtp("syscalls", name);
- if (evsels[i] == NULL) {
+ if (IS_ERR(evsels[i])) {
pr_debug("perf_evsel__new\n");
goto out_delete_evlist;
}
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 495d812..9e104a2 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -1,4 +1,5 @@
#include <api/fs/fs.h>
+#include <linux/err.h>
#include "evsel.h"
#include "tests.h"
#include "thread_map.h"
@@ -31,7 +32,7 @@ int test__openat_syscall_event_on_all_cpus(void)
CPU_ZERO(&cpu_set);

evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
- if (evsel == NULL) {
+ if (IS_ERR(evsel)) {
tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
pr_err("%s\n", errbuf);
goto out_thread_map_delete;
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 01a1962..473d386 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -1,3 +1,4 @@
+#include <linux/err.h>
#include "perf.h"
#include "evlist.h"
#include "evsel.h"
@@ -30,7 +31,7 @@ int test__syscall_openat_tp_fields(void)
}

evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
- if (evsel == NULL) {
+ if (IS_ERR(evsel)) {
pr_debug("%s: perf_evsel__newtp\n", __func__);
goto out_delete_evlist;
}
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index 08ac9d9..7b1db83 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -1,4 +1,5 @@
#include <api/fs/tracing_path.h>
+#include <linux/err.h>
#include "thread_map.h"
#include "evsel.h"
#include "debug.h"
@@ -19,7 +20,7 @@ int test__openat_syscall_event(void)
}

evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
- if (evsel == NULL) {
+ if (IS_ERR(evsel)) {
tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
pr_err("%s\n", errbuf);
goto out_thread_map_delete;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d51a520..3cb2bf9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -25,6 +25,7 @@
#include <linux/bitops.h>
#include <linux/hash.h>
#include <linux/log2.h>
+#include <linux/err.h>

static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
@@ -265,7 +266,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
{
struct perf_evsel *evsel = perf_evsel__newtp(sys, name);

- if (evsel == NULL)
+ if (IS_ERR(evsel))
return -1;

evsel->handler = handler;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 771ade4..6b5d1b5 100644
index f164a14..62ab307 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -160,6 +160,9 @@ static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)

struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx);

+/*
+ * Returns pointer with encoded error via <linux/err.h> interface.
+ */
static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name)
{
return perf_evsel__newtp_idx(sys, name, 0);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1b284b8..c47831c 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,4 +1,5 @@
#include <linux/hw_breakpoint.h>
+#include <linux/err.h>
#include "util.h"
#include "../perf.h"
#include "evlist.h"
@@ -393,11 +394,10 @@ static int add_tracepoint(struct list_head *list, int *idx,
struct perf_evsel *evsel;

evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
- if (!evsel)
- return -ENOMEM;
+ if (IS_ERR(evsel))
+ return PTR_ERR(evsel);

list_add_tail(&evsel->node, list);
-
return 0;
}

diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index 2f4996a..802bb86 100644

tip-bot for Jiri Olsa

unread,
Sep 16, 2015, 3:30:29 AM9/16/15
to linux-ti...@vger.kernel.org, namh...@kernel.org, mi...@kernel.org, ma...@codeblueprint.co.uk, jo...@kernel.org, linux-...@vger.kernel.org, a.p.zi...@chello.nl, tg...@linutronix.de, ac...@redhat.com, dsa...@gmail.com, h...@zytor.com, raphael....@gmail.com
Commit-ID: 196581717d85f59365dc9303685cd5b1cdf106a3
Gitweb: http://git.kernel.org/tip/196581717d85f59365dc9303685cd5b1cdf106a3
Author: Jiri Olsa <jo...@kernel.org>
AuthorDate: Mon, 7 Sep 2015 10:38:07 +0200
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Tue, 15 Sep 2015 09:48:33 -0300

perf tools: Enhance parsing events tracepoint error output

Enhancing parsing events tracepoint error output. Adding
more verbose output when the tracepoint is not found or
the tracing event path cannot be access.

$ sudo perf record -e sched:sched_krava ls
event syntax error: 'sched:sched_krava'
\___ unknown tracepoint

Error: File /sys/kernel/debug/tracing//tracing/events/sched/sched_krava not found.
Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.

Run 'perf list' for a list of valid events
...

$ perf record -e sched:sched_krava ls
event syntax error: 'sched:sched_krava'
\___ can't access trace events

Error: No permissions to read /sys/kernel/debug/tracing//tracing/events/sched/sched_krava
Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'

Run 'perf list' for a list of valid events
...

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
Cc: Raphael Beamonte <raphael....@gmail.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1441615087-13886-6-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/parse-events.c | 35 ++++++++++++++++++++++++++++++++---
tools/perf/util/parse-events.y | 16 +++++++++-------
2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index c47831c..d3fb90b 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
static int add_tracepoint(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
struct parse_events_error *error __maybe_unused)
@@ -394,8 +421,10 @@ static int add_tracepoint(struct list_head *list, int *idx,
struct perf_evsel *evsel;

evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
- if (IS_ERR(evsel))
+ if (IS_ERR(evsel)) {
+ tracepoint_error(error, PTR_ERR(evsel), sys_name, evt_name);
return PTR_ERR(evsel);
+ }

list_add_tail(&evsel->node, list);
return 0;
@@ -413,7 +442,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
evt_dir = opendir(evt_path);
if (!evt_dir) {
- perror("Can't open event dir");
+ tracepoint_error(error, errno, sys_name, evt_name);
return -1;
}

@@ -453,7 +482,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,

events_dir = opendir(tracing_events_path);
if (!events_dir) {
- perror("Can't open event dir");
+ tracepoint_error(error, errno, sys_name, evt_name);
return -1;
}

diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 54a3004..8bcc458 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -371,28 +371,30 @@ event_legacy_tracepoint:
PE_NAME '-' PE_NAME ':' PE_NAME
{
struct parse_events_evlist *data = _data;
+ struct parse_events_error *error = data->error;
struct list_head *list;
char sys_name[128];
snprintf(&sys_name, 128, "%s-%s", $1, $3);

ALLOC_LIST(list);
- ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, data->error));
+ if (parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, error)) {
+ if (error)
+ error->idx = @1.first_column;
+ return -1;
+ }
$$ = list;
}
|
PE_NAME ':' PE_NAME
{
struct parse_events_evlist *data = _data;
+ struct parse_events_error *error = data->error;
struct list_head *list;

ALLOC_LIST(list);
- if (parse_events_add_tracepoint(list, &data->idx, $1, $3, data->error)) {
- struct parse_events_error *error = data->error;
-
- if (error) {
+ if (parse_events_add_tracepoint(list, &data->idx, $1, $3, error)) {
+ if (error)
error->idx = @1.first_column;
- error->str = strdup("unknown tracepoint");
- }
return -1;
}
$$ = list;

Arnaldo Carvalho de Melo

unread,
Sep 16, 2015, 9:51:05 AM9/16/15
to Ingo Molnar, linux-...@vger.kernel.org, Alexei Starovoitov, Brendan Gregg, Daniel Borkmann, David Ahern, He Kuang, Jiri Olsa, Kaixu Xia, Masami Hiramatsu, Matt Fleming, Namhyung Kim, Paul Mackerras, Peter Zijlstra, pi3o...@163.com, Raphael Beamonte, Wang Nan, Zefan Li
Em Wed, Sep 16, 2015 at 09:25:44AM +0200, Ingo Molnar escreveu:
>
> * Arnaldo Carvalho de Melo <ac...@kernel.org> wrote:
>
> > Hi Ingo,
> >
> > Please consider pulling,
> >
> > - Arnaldo
> >
> > The following changes since commit 9059b284caecb628fac826c2c5cc8ee85708eec1:
> >
> > Merge tag 'perf-core-for-mingo-2' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2015-09-15 08:50:59 +0200)
> >
> > are available in the git repository at:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo
>
> So your perf/urgent bits now conflict with the latest perf/core, in
> tools/perf/ui/browsers/hists.c. I have merged perf/urgent into perf/core - please
> double check my resolution (d71b0ad8d309).

Looks fine, tested it even, thanks!

- Arnaldo

Vinson Lee

unread,
Sep 21, 2015, 7:42:05 PM9/21/15
to LKML, H. Peter Anvin, Thomas Gleixner, Namhyung Kim, David Ahern, Jiri Olsa, Ingo Molnar, Peter Zijlstra, raphael....@gmail.com, ma...@codeblueprint.co.uk, Arnaldo Carvalho de Melo, linux-ti...@vger.kernel.org
On Wed, Sep 16, 2015 at 12:28 AM, tip-bot for Jiri Olsa
<tip...@zytor.com> wrote:
> Commit-ID: 01ca9fd41d6f2ad796a6b109b5253e06b6ae6dc7
> Gitweb: http://git.kernel.org/tip/01ca9fd41d6f2ad796a6b109b5253e06b6ae6dc7
> Author: Jiri Olsa <jo...@kernel.org>
> AuthorDate: Mon, 7 Sep 2015 10:38:03 +0200
> Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
> CommitDate: Tue, 15 Sep 2015 09:48:32 -0300
>
> tools: Add err.h with ERR_PTR PTR_ERR interface
>
> Adding part of the kernel's <linux/err.h> interface:
>
> inline void * __must_check ERR_PTR(long error);
> inline long __must_check PTR_ERR(__force const void *ptr);
> inline bool __must_check IS_ERR(__force const void *ptr);
>
> It will be used to propagate error through pointers in following
> patches.
>
> Signed-off-by: Jiri Olsa <jo...@kernel.org>
> Reviewed-by: Raphael Beamonte <raphael....@gmail.com>
> Cc: David Ahern <dsa...@gmail.com>
> Cc: Matt Fleming <ma...@codeblueprint.co.uk>
> Cc: Namhyung Kim <namh...@kernel.org>
> Cc: Peter Zijlstra <a.p.zi...@chello.nl>
> Link: http://lkml.kernel.org/r/1441615087-13886-2-...@kernel.org
> Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>


Hi.

This patch appears to have introduced a build error on CentOS 6.7 with GCC 4.4.

This build error occurs on next-20150921.

CC util/evlist.o
cc1: warnings being treated as errors
In file included from util/evlist.c:28:
tools/include/linux/err.h: In function ‘ERR_PTR’:
tools/include/linux/err.h:34: error: declaration of ‘error’ shadows a
global declaration
util/util.h:135: error: shadowed declaration is here

$ gcc --version
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Cheers,
Vinson

Arnaldo Carvalho de Melo

unread,
Sep 22, 2015, 10:12:54 PM9/22/15
to Ingo Molnar
Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit 96f3eda67fcf2598e9d2794398e0e7ab35138ea6:

perf/x86/intel: Fix static checker warning in lbr enable (2015-09-18 09:24:57 +0200)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo

for you to fetch changes up to e803cf97a4f90d31bcc2c9a1ea20fe9cdc12b2f9:

perf record: Synthesize COMM event for a command line workload (2015-09-22 22:43:12 -0300)

----------------------------------------------------------------
perf/core improvements and fixes:

User visible:

- Fix a segfault in 'perf probe' when removing uprobe events (Masami Hiramatsu)

- Synthesize COMM event for workloads started from the command line in 'perf
record' so that we can have the pid->comm mapping before we get the real
PERF_RECORD_COMM switching from perf to the workload (Namhyung Kim)

- Fix build tools/vm/ due to removal of tools/lib/api/fs/debugfs.h
(Arnaldo Carvalho de Melo)

Developer stuff:

- Fix the make tarball targets by including the recently added err.h header in
the perf MANIFEST file (Jiri Olsa)

- Don't assume that the event parser returns a non empty evlist (Wang Nan)

- Add way to disambiguate feature detection state files, needed to use
tools/build feature detection for multiple components in a single O= output
dir, which will be the case with tools/perf/ and tools/lib/bpf/
(Arnaldo Carvalho de Melo)

- Fixup FEATURE_{TESTS,DISPLAY} inversion in tools/lib/bpf/ (Arnaldo Carvalho de Melo)

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

----------------------------------------------------------------
Arnaldo Carvalho de Melo (5):
tools build: Fixup feature detection display function name
tools lib bpf: Fix up FEATURE_{TESTS,DISPLAY} usage
tools build: Allow setting the feature detection user
tools lib bpf: Use FEATURE_USER to allow building in the same dir as perf
tools vm: Fix build due to removal of tools/lib/api/fs/debugfs.h

Jiri Olsa (1):
perf tools: Add include/err.h into MANIFEST

Masami Hiramatsu (1):
perf probe: Fix a segfault when removing uprobe events

Namhyung Kim (1):
perf record: Synthesize COMM event for a command line workload

Wang Nan (1):
perf tools: Don't assume that the parser returns non empty evsel list

tools/build/Makefile.feature | 9 +++++----
tools/lib/bpf/Makefile | 5 +++--
tools/perf/MANIFEST | 1 +
tools/perf/builtin-probe.c | 7 +++++--
tools/perf/builtin-record.c | 15 ++++++++++++++-
tools/perf/util/event.c | 2 +-
tools/perf/util/event.h | 5 +++++
tools/perf/util/parse-events.c | 16 ++++++++++++++++
tools/vm/page-types.c | 6 +++---
9 files changed, 53 insertions(+), 13 deletions(-)

Ingo Molnar

unread,
Sep 23, 2015, 3:45:36 AM9/23/15
to Arnaldo Carvalho de Melo

* Arnaldo Carvalho de Melo <ac...@kernel.org> wrote:

Pulled, thanks a lot Arnaldo!

Ingo

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:09:27 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Arnaldo Carvalho de Melo, Adrian Hunter, Borislav Petkov, David Ahern, Frederic Weisbecker, He Kuang, Jiri Olsa, Kai Germaschewski, Kan Liang, Matt Fleming, Namhyung Kim, Peter Zijlstra, pi3o...@163.com, Raphael Beamonte, Stephane Eranian, Wang Nan, Arnaldo Carvalho de Melo
Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit 18ab2cd3ee9d52dc64c5ae984146a261a328c4e8:

perf/core, perf/x86: Change needlessly global functions and a variable to static (2015-09-28 08:09:52 +0200)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo

for you to fetch changes up to e637d17757a10732fa5d573c18f20b3cd4d31245:

perf tools: Enable event_config terms to tracepoint events (2015-09-28 17:30:07 -0300)

----------------------------------------------------------------
perf/core improvements and fixes:

- Accept a zero --itrace period, meaning "as often as possible". In the case
of Intel PT that is the same as a period of 1 and a unit of 'instructions'
(i.e. --itrace=i1i). (Adrian Hunter)

- Harmonise itrace's synthesized callchains with the existing --max-stack
tool option (Adrian Hunter)

- Allow time to be displayed in nanoseconds in 'perf script' (Adrian Hunter)

- Fix potential loop forever when handling Intel PT timestamps (Adrian Hunter)

- Slighly improve Intel PT debug logging (Adrian Hunter)

- Warn when AUX data has been lost, just like when processing PERF_RECORD_LOST
(Adrian Hunter)

- Further document export-to-postgresql.py script (Adrian Hunter)

- Add option to synthesize branch stack from auxtrace data (Adrian Hunter)

- Use equivalent logic to avoid using dso->kernel (Arnaldo Carvalho de Melo)

- Show proper error messages when parsing bad terms for hw/sw events (He Kuang)

- Tracepoint event parsing improvements (He Kuang)

- Store tracing mountpoint for better error message (Jiri Olsa)

- Add fixdep to tools/build, bringing it closer to the kernel counterpart, from
where it is being lifted (Jiri Olsa)

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

----------------------------------------------------------------
Adrian Hunter (24):
perf auxtrace: Fix 'instructions' period of zero
perf report: Fix sample type validation for synthesized callchains
perf intel-pt: Fix potential loop forever
perf intel-pt: Make logging slightly more efficient
perf script: Allow time to be displayed in nanoseconds
perf session: Warn when AUX data has been lost
perf tools: Add more documentation to export-to-postgresql.py script
perf auxtrace: Add option to synthesize branch stacks on samples
perf report: Adjust sample type validation for synthesized branch stacks
perf report: Also do default setup for synthesized branch stacks
perf report: Skip events with null branch stacks
perf inject: Set branch stack feature flag when synthesizing branch stacks
perf intel-pt: Move branch filter logic
perf intel-pt: Support generating branch stack
perf report: Make max_stack value allow for synthesized callchains
perf hists: Allow for max_stack greater than PERF_MAX_STACK_DEPTH
perf script: Add a setting for maximum stack depth
perf scripting python: Allow for max_stack greater than PERF_MAX_STACK_DEPTH
perf script: Make scripting_max_stack value allow for synthesized callchains
perf evlist: Add perf_evlist__id2evsel_strict()
perf evlist: Add perf_evlist__remove()
perf inject: Remove more aux-related stuff when processing instruction traces
perf inject: Add --strip option to strip out non-synthesized events
perf intel-pt: Add mispred-all config option to aid use with autofdo

Arnaldo Carvalho de Melo (3):
perf top: Filter symbols based on __map__is_kernel(map)
perf hists browser: Use the map to determine if a DSO is being used as a kernel
perf tools: Use __map__is_kernel() when synthesizing kernel module mmap records

He Kuang (4):
perf tools: Adds the config_term callback for different type events
perf tools: Show proper error message for wrong terms of hw/sw events
perf tools: Adds the tracepoint name parsing support
perf tools: Enable event_config terms to tracepoint events

Jiri Olsa (8):
tools lib api fs: Store tracing mountpoint for better error message
tools build: Add Makefile.include
tools build: Add test for missing include
tools build: Add fixdep dependency helper
tools build: Move dependency copy into function
tools build: Make the fixdep helper part of the build process
perf tools: Rename the 'single_dep' target to 'prepare'
tools build: Build fixdep helper from perf and basic libs

tools/build/Build | 1 +
tools/build/Build.include | 17 +-
tools/build/Documentation/Build.txt | 52 +++--
tools/build/Makefile | 43 ++++
tools/build/Makefile.build | 7 +
tools/build/Makefile.include | 6 +
tools/build/fixdep.c | 168 ++++++++++++++++
tools/build/tests/ex/Build | 1 +
tools/build/tests/ex/Makefile | 13 +-
tools/build/tests/ex/ex.c | 2 +
tools/build/tests/ex/inc.c | 8 +
tools/build/tests/run.sh | 27 +++
tools/lib/api/Makefile | 6 +-
tools/lib/api/fs/tracing_path.c | 13 +-
tools/lib/bpf/Makefile | 6 +-
tools/lib/lockdep/Makefile | 6 +-
tools/perf/Documentation/intel-pt.txt | 44 ++++
tools/perf/Documentation/itrace.txt | 4 +
tools/perf/Documentation/perf-inject.txt | 3 +
tools/perf/Documentation/perf-script.txt | 3 +
tools/perf/Makefile.perf | 32 +--
tools/perf/builtin-inject.c | 127 +++++++++++-
tools/perf/builtin-report.c | 31 ++-
tools/perf/builtin-script.c | 18 +-
tools/perf/builtin-top.c | 2 +-
tools/perf/scripts/python/export-to-postgresql.py | 221 +++++++++++++++++++++
tools/perf/ui/browsers/hists.c | 24 ++-
tools/perf/util/auxtrace.c | 24 ++-
tools/perf/util/auxtrace.h | 4 +
tools/perf/util/event.c | 2 +-
tools/perf/util/event.h | 1 +
tools/perf/util/evlist.c | 22 ++
tools/perf/util/evlist.h | 3 +
tools/perf/util/hist.c | 6 +-
tools/perf/util/hist.h | 1 +
.../perf/util/intel-pt-decoder/intel-pt-decoder.c | 4 +-
tools/perf/util/intel-pt-decoder/intel-pt-log.c | 21 +-
tools/perf/util/intel-pt-decoder/intel-pt-log.h | 38 +++-
tools/perf/util/intel-pt.c | 135 ++++++++++++-
tools/perf/util/parse-events.c | 151 +++++++++++---
tools/perf/util/parse-events.h | 4 +-
tools/perf/util/parse-events.l | 2 +-
tools/perf/util/parse-events.y | 51 +++--
tools/perf/util/pmu.c | 37 ++--
.../util/scripting-engines/trace-event-python.c | 2 +-
tools/perf/util/session.c | 12 +-
tools/perf/util/trace-event.h | 2 +
47 files changed, 1240 insertions(+), 167 deletions(-)
create mode 100644 tools/build/Build
create mode 100644 tools/build/Makefile
create mode 100644 tools/build/Makefile.include
create mode 100644 tools/build/fixdep.c
create mode 100644 tools/build/tests/ex/inc.c

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:09:34 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, He Kuang, Adrian Hunter, Kan Liang, Peter Zijlstra, Wang Nan, pi3o...@163.com, Arnaldo Carvalho de Melo
From: He Kuang <hek...@huawei.com>

This patch enables config terms for tracepoint perf events. Valid terms
for tracepoint events are 'call-graph' and 'stack-size', so we can use
different callgraph settings for each event and eliminate unnecessary
overhead.

Here is an example for using different call-graph config for each
tracepoint.

$ perf record -e syscalls:sys_enter_write/call-graph=fp/
-e syscalls:sys_exit_write/call-graph=no/
dd if=/dev/zero of=test bs=4k count=10

$ perf report --stdio

#
# Total Lost Samples: 0
#
# Samples: 13 of event 'syscalls:sys_enter_write'
# Event count (approx.): 13
#
# Children Self Command Shared Object Symbol
# ........ ........ ....... .................. ......................
#
76.92% 76.92% dd libpthread-2.20.so [.] __write_nocancel
|
---__write_nocancel

23.08% 23.08% dd libc-2.20.so [.] write
|
---write
|
|--33.33%-- 0x2031342820736574
|
|--33.33%-- 0xa6e69207364726f
|
--33.33%-- 0x34202c7320393039
...

# Samples: 13 of event 'syscalls:sys_exit_write'
# Event count (approx.): 13
#
# Children Self Command Shared Object Symbol
# ........ ........ ....... .................. ......................
#
76.92% 76.92% dd libpthread-2.20.so [.] __write_nocancel
23.08% 23.08% dd libc-2.20.so [.] write
7.69% 0.00% dd [unknown] [.] 0x0a6e69207364726f
7.69% 0.00% dd [unknown] [.] 0x2031342820736574
7.69% 0.00% dd [unknown] [.] 0x34202c7320393039

Signed-off-by: He Kuang <hek...@huawei.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Adrian Hunter <adrian...@intel.com>
Cc: Kan Liang <kan....@intel.com>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Wang Nan <wang...@huawei.com>
Cc: pi3o...@163.com
Link: http://lkml.kernel.org/r/1443412336-120050-4-g...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/parse-events.c | 84 +++++++++++++++++++++++++++++++++---------
tools/perf/util/parse-events.h | 3 +-
tools/perf/util/parse-events.y | 26 +++++++++++--
3 files changed, 90 insertions(+), 23 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index ea64ec0720ca..5ffb356cbcc6 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -27,6 +27,8 @@
extern int parse_events_debug;
#endif
int parse_events_parse(void *data, void *scanner);
+static int get_config_terms(struct list_head *head_config,
+ struct list_head *head_terms __maybe_unused);

static struct perf_pmu_event_symbol *perf_pmu_events_list;
/*
@@ -416,7 +418,8 @@ static void tracepoint_error(struct parse_events_error *error, int err,

static int add_tracepoint(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error __maybe_unused)
+ struct parse_events_error *error __maybe_unused,
+ struct list_head *head_config)
{
struct perf_evsel *evsel;

@@ -426,13 +429,22 @@ static int add_tracepoint(struct list_head *list, int *idx,
return PTR_ERR(evsel);
}

+ if (head_config) {
+ LIST_HEAD(config_terms);
+
+ if (get_config_terms(head_config, &config_terms))
+ return -ENOMEM;
+ list_splice(&config_terms, &evsel->config_terms);
+ }
+
list_add_tail(&evsel->node, list);
return 0;
}

static int add_tracepoint_multi_event(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error)
+ struct parse_events_error *error,
+ struct list_head *head_config)
{
char evt_path[MAXPATHLEN];
struct dirent *evt_ent;
@@ -456,7 +468,8 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
if (!strglobmatch(evt_ent->d_name, evt_name))
continue;

- ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, error);
+ ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name,
+ error, head_config);
}

closedir(evt_dir);
@@ -465,16 +478,20 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,

static int add_tracepoint_event(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error)
+ struct parse_events_error *error,
+ struct list_head *head_config)
{
return strpbrk(evt_name, "*?") ?
- add_tracepoint_multi_event(list, idx, sys_name, evt_name, error) :
- add_tracepoint(list, idx, sys_name, evt_name, error);
+ add_tracepoint_multi_event(list, idx, sys_name, evt_name,
+ error, head_config) :
+ add_tracepoint(list, idx, sys_name, evt_name,
+ error, head_config);
}

static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error)
+ struct parse_events_error *error,
+ struct list_head *head_config)
{
struct dirent *events_ent;
DIR *events_dir;
@@ -498,23 +515,13 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
continue;

ret = add_tracepoint_event(list, idx, events_ent->d_name,
- evt_name, error);
+ evt_name, error, head_config);
}

closedir(events_dir);
return ret;
}

-int parse_events_add_tracepoint(struct list_head *list, int *idx,
- char *sys, char *event,
- struct parse_events_error *error)
-{
- if (strpbrk(sys, "*?"))
- return add_tracepoint_multi_sys(list, idx, sys, event, error);
- else
- return add_tracepoint_event(list, idx, sys, event, error);
-}
-
static int
parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
{
@@ -680,6 +687,26 @@ static int config_term_pmu(struct perf_event_attr *attr,
return config_term_common(attr, term, err);
}

+static int config_term_tracepoint(struct perf_event_attr *attr,
+ struct parse_events_term *term,
+ struct parse_events_error *err)
+{
+ switch (term->type_term) {
+ case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
+ case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
+ return config_term_common(attr, term, err);
+ default:
+ if (err) {
+ err->idx = term->err_term;
+ err->str = strdup("unknown term");
+ err->help = strdup("valid terms: call-graph,stack-size\n");
+ }
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int config_attr(struct perf_event_attr *attr,
struct list_head *head,
struct parse_events_error *err,
@@ -738,6 +765,27 @@ do { \
return 0;
}

+int parse_events_add_tracepoint(struct list_head *list, int *idx,
+ char *sys, char *event,
+ struct parse_events_error *error,
+ struct list_head *head_config)
+{
+ if (head_config) {
+ struct perf_event_attr attr;
+
+ if (config_attr(&attr, head_config, error,
+ config_term_tracepoint))
+ return -EINVAL;
+ }
+
+ if (strpbrk(sys, "*?"))
+ return add_tracepoint_multi_sys(list, idx, sys, event,
+ error, head_config);
+ else
+ return add_tracepoint_event(list, idx, sys, event,
+ error, head_config);
+}
+
int parse_events_add_numeric(struct parse_events_evlist *data,
struct list_head *list,
u32 type, u64 config,
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index c7b904a49189..f13d3ccda444 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -119,7 +119,8 @@ int parse_events__modifier_group(struct list_head *list, char *event_mod);
int parse_events_name(struct list_head *list, char *name);
int parse_events_add_tracepoint(struct list_head *list, int *idx,
char *sys, char *event,
- struct parse_events_error *error);
+ struct parse_events_error *error,
+ struct list_head *head_config);
int parse_events_add_numeric(struct parse_events_evlist *data,
struct list_head *list,
u32 type, u64 config,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 1c598c2f8dfc..ae6af269f9c9 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -380,12 +380,30 @@ tracepoint_name
struct list_head *list;

ALLOC_LIST(list);
+ if (error)
+ error->idx = @1.first_column;
+
if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
- error)) {
- if (error)
- error->idx = @1.first_column;
+ error, NULL))
return -1;
- }
+
+ $$ = list;
+}
+|
+tracepoint_name '/' event_config '/'
+{
+ struct parse_events_evlist *data = _data;
+ struct parse_events_error *error = data->error;
+ struct list_head *list;
+
+ ALLOC_LIST(list);
+ if (error)
+ error->idx = @1.first_column;
+
+ if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
+ error, $3))
+ return -1;
+
$$ = list;
}

--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:09:51 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

perf report looks at event sample types to determine if branch stacks
have been sampled. Adjust the validation to know about instruction
tracing options.

This change allows the use of the -b option which otherwise would
complain with an error like:

Error:
Selected -b but no branch data. Did you call perf record without -b?
# To display the perf.data header info,
# please use --header/--header-only options.
#

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-10-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-report.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 0d53b485a87b..7af35af5a5e5 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -220,6 +220,9 @@ static int report__setup_sample_type(struct report *rep)
!session->itrace_synth_opts->set))
sample_type |= PERF_SAMPLE_CALLCHAIN;

+ if (session->itrace_synth_opts->last_branch)
+ sample_type |= PERF_SAMPLE_BRANCH_STACK;
+
if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
if (sort__has_parent) {
ui__error("Selected --sort parent, but no "
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:09:57 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, He Kuang, Adrian Hunter, Kan Liang, Peter Zijlstra, Wang Nan, pi3o...@163.com, Arnaldo Carvalho de Melo
From: He Kuang <hek...@huawei.com>

Adds rules for parsing tracepoint names. Change rules of tracepoint which
derives from PE_NAMEs into tracepoint names directly, so adding more rules
based on tracepoint names will be easier.

Changes v2-v3:
- Change __event_legacy_tracepoint label in bison file to tracepoint_name
- Fix formats error.

Signed-off-by: He Kuang <hek...@huawei.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Adrian Hunter <adrian...@intel.com>
Cc: Kan Liang <kan....@intel.com>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Wang Nan <wang...@huawei.com>
Cc: pi3o...@163.com
Link: http://lkml.kernel.org/r/1443412336-120050-3-g...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/parse-events.y | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 8bcc45868457..1c598c2f8dfc 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -67,6 +67,7 @@ static inc_group_count(struct list_head *list,
%type <head> event_legacy_cache
%type <head> event_legacy_mem
%type <head> event_legacy_tracepoint
+%type <tracepoint_name> tracepoint_name
%type <head> event_legacy_numeric
%type <head> event_legacy_raw
%type <head> event_def
@@ -84,6 +85,10 @@ static inc_group_count(struct list_head *list,
u64 num;
struct list_head *head;
struct parse_events_term *term;
+ struct tracepoint_name {
+ char *sys;
+ char *event;
+ } tracepoint_name;
}
%%

@@ -368,36 +373,40 @@ PE_PREFIX_MEM PE_VALUE sep_dc
}

event_legacy_tracepoint:
-PE_NAME '-' PE_NAME ':' PE_NAME
+tracepoint_name
{
struct parse_events_evlist *data = _data;
struct parse_events_error *error = data->error;
struct list_head *list;
- char sys_name[128];
- snprintf(&sys_name, 128, "%s-%s", $1, $3);

ALLOC_LIST(list);
- if (parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, error)) {
+ if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
+ error)) {
if (error)
error->idx = @1.first_column;
return -1;
}
$$ = list;
}
+
+tracepoint_name:
+PE_NAME '-' PE_NAME ':' PE_NAME
+{
+ char sys_name[128];
+ struct tracepoint_name tracepoint;
+
+ snprintf(&sys_name, 128, "%s-%s", $1, $3);
+ tracepoint.sys = &sys_name;
+ tracepoint.event = $5;
+
+ $$ = tracepoint;
+}
|
PE_NAME ':' PE_NAME
{
- struct parse_events_evlist *data = _data;
- struct parse_events_error *error = data->error;
- struct list_head *list;
+ struct tracepoint_name tracepoint = {$1, $3};

- ALLOC_LIST(list);
- if (parse_events_add_tracepoint(list, &data->idx, $1, $3, error)) {
- if (error)
- error->idx = @1.first_column;
- return -1;
- }
- $$ = list;
+ $$ = tracepoint;
}

event_legacy_numeric:
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:12:08 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

TSC packets contain only 7 bytes of TSC. The 8th byte is assumed to
change so infrequently that its value can be inferred. However the
logic must cater for a 7 byte wraparound, which it does by adding 1 to
the top byte.

The existing code was doing that with a while loop even though the
addition should only need to be done once. That logic won't work (will
loop forever) if TSC wraps around at the 8th byte. Theoretically that
would take at least 10 years, unless something else went wrong.

And what else could go wrong. Well, if the chunks of trace data are
processed out of order, it will make it look like the 7-byte TSC has
gone backwards (i.e. wrapped). If that happens 256 times then stuck in
the while loop it will be.

Fix that by getting rid of the unnecessary while loop.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-4-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 22ba50224319..9409d014b46c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -650,7 +650,7 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
if (data->from_mtc && timestamp < data->timestamp &&
data->timestamp - timestamp < decoder->tsc_slip)
return 1;
- while (timestamp < data->timestamp)
+ if (timestamp < data->timestamp)
timestamp += (1ULL << 56);
if (pkt_info->last_packet_type != INTEL_PT_CYC) {
if (data->from_mtc)
@@ -1191,7 +1191,7 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder)
timestamp);
timestamp = decoder->timestamp;
}
- while (timestamp < decoder->timestamp) {
+ if (timestamp < decoder->timestamp) {
intel_pt_log_to("Wraparound timestamp", timestamp);
timestamp += (1ULL << 56);
decoder->tsc_timestamp = timestamp;
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:12:13 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

perf report has an option (--max-stack) to set the maximum stack depth
when processing callchains. The option defaults to the hard-coded
maximum definition PERF_MAX_STACK_DEPTH which is 127. The intention of
the option is to allow the user to reduce the processing time by
reducing the amount of the callchain that is processed.

It is also possible, when processing instruction traces, to synthesize
callchains. Synthesized callchains do not have the kernel size
limitation and are whatever size the user requests, although validation
presently prevents the user requested a value greater that 1024. The
default value is 16.

To allow for synthesized callchains, make the max_stack value at least
the same size as the synthesized callchain size.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-16-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-report.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index e94e5c7155af..37c9f5125887 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -809,6 +809,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
if (report.inverted_callchain)
callchain_param.order = ORDER_CALLER;

+ if (itrace_synth_opts.callchain &&
+ (int)itrace_synth_opts.callchain_sz > report.max_stack)
+ report.max_stack = itrace_synth_opts.callchain_sz;
+
if (!input_name || !strlen(input_name)) {
if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
input_name = "-";
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:12:40 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Arnaldo Carvalho de Melo, Adrian Hunter, Borislav Petkov, David Ahern, Frederic Weisbecker, Jiri Olsa, Namhyung Kim, Stephane Eranian, Wang Nan
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Equivalent and removes one more case of using dso->kernel.

# perf record -a usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.768 MB perf.data (30 samples) ]

Before:

[root@zoo ~]# perf script --show-task --show-mmap | head -3
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffff81000000(0x1f000000) @ 0xffffffff81000000]: x [kernel.kallsyms]_text
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffffa0000000(0xa000) @ 0]: x /lib/modules/4.3.0-rc1+/kernel/drivers/acpi/video.ko
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffffa000a000(0x5000) @ 0]: x /lib/modules/4.3.0-rc1+/kernel/drivers/i2c/algos/i2c-algo-bit.ko
#

# perf script --show-task --show-mmap | head -3
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffff81000000(0x1f000000) @ 0xffffffff81000000]: x [kernel.kallsyms]_text
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffffa0000000(0xa000) @ 0]: x /lib/modules/4.3.0-rc1+/kernel/drivers/acpi/video.ko
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffffa000a000(0x5000) @ 0]: x /lib/modules/4.3.0-rc1+/kernel/drivers/i2c/algos/i2c-algo-bit.ko
#

Cc: Adrian Hunter <adrian...@intel.com>
Cc: Borislav Petkov <b...@suse.de>
Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-b65xe578dw...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/event.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 6214ad47d554..b1bb348ec3b6 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -378,7 +378,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
for (pos = maps__first(maps); pos; pos = map__next(pos)) {
size_t size;

- if (pos->dso->kernel)
+ if (__map__is_kernel(pos))
continue;

size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:12:59 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, He Kuang, Adrian Hunter, Kan Liang, Peter Zijlstra, Wang Nan, pi3o...@163.com, Arnaldo Carvalho de Melo
From: He Kuang <hek...@huawei.com>

Show proper error message and show valid terms when wrong config terms
is specified for hw/sw type perf events.

This patch makes the original error format function formats_error_string()
more generic, which only outputs the static config terms for hw/sw perf
events, and prepends pmu formats for pmu events.

Before this patch:

$ perf record -e 'cpu-clock/freqx=200/' -a sleep 1
invalid or unsupported event: 'cpu-clock/freqx=200/'
Run 'perf list' for a list of valid events

usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]

-e, --event <event> event selector. use 'perf list' to list available events

After this patch:

$ perf record -e 'cpu-clock/freqx=200/' -a sleep 1
event syntax error: 'cpu-clock/freqx=200/'
\___ unknown term

valid terms: config,config1,config2,name,period,freq,branch_type,time,call-graph,stack-size

Run 'perf list' for a list of valid events

usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]

-e, --event <event> event selector. use 'perf list' to list available events

Signed-off-by: He Kuang <hek...@huawei.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Adrian Hunter <adrian...@intel.com>
Cc: Kan Liang <kan....@intel.com>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Wang Nan <wang...@huawei.com>
Cc: pi3o...@163.com
Link: http://lkml.kernel.org/r/1443412336-120050-2-g...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/parse-events.c | 29 +++++++++++++++++++++++++++++
tools/perf/util/parse-events.h | 1 +
tools/perf/util/parse-events.l | 2 +-
tools/perf/util/pmu.c | 37 ++++++++++++++-----------------------
4 files changed, 45 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 9dc3fb6ee81e..ea64ec0720ca 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -656,6 +656,9 @@ do { \
CHECK_TYPE_VAL(STR);
break;
default:
+ err->str = strdup("unknown term");
+ err->idx = term->err_term;
+ err->help = parse_events_formats_error_string(NULL);
return -EINVAL;
}

@@ -1875,3 +1878,29 @@ void parse_events_evlist_error(struct parse_events_evlist *data,
err->str = strdup(str);
WARN_ONCE(!err->str, "WARNING: failed to allocate error string");
}
+
+/*
+ * Return string contains valid config terms of an event.
+ * @additional_terms: For terms such as PMU sysfs terms.
+ */
+char *parse_events_formats_error_string(char *additional_terms)
+{
+ char *str;
+ static const char *static_terms = "config,config1,config2,name,"
+ "period,freq,branch_type,time,"
+ "call-graph,stack-size\n";
+
+ /* valid terms */
+ if (additional_terms) {
+ if (!asprintf(&str, "valid terms: %s,%s",
+ additional_terms, static_terms))
+ goto fail;
+ } else {
+ if (!asprintf(&str, "valid terms: %s", static_terms))
+ goto fail;
+ }
+ return str;
+
+fail:
+ return NULL;
+}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ffee7ece75a6..c7b904a49189 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -156,5 +156,6 @@ int print_hwcache_events(const char *event_glob, bool name_only);
extern int is_valid_tracepoint(const char *event_string);

int valid_event_mount(const char *eventfs);
+char *parse_events_formats_error_string(char *additional_terms);

#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 936d566f48d8..c29832bce496 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -174,7 +174,7 @@ modifier_bp [rwx]{1,3}

<config>{
/*
- * Please update formats_error_string any time
+ * Please update parse_events_formats_error_string any time
* new static term is added.
*/
config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 89c91a1a67e7..ac42c97be9e4 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -626,38 +626,26 @@ static int pmu_resolve_param_term(struct parse_events_term *term,
return -1;
}

-static char *formats_error_string(struct list_head *formats)
+static char *pmu_formats_string(struct list_head *formats)
{
struct perf_pmu_format *format;
- char *err, *str;
- static const char *static_terms = "config,config1,config2,name,"
- "period,freq,branch_type,time,"
- "call-graph,stack-size\n";
+ char *str;
+ struct strbuf buf;
unsigned i = 0;

- if (!asprintf(&str, "valid terms:"))
+ if (!formats)
return NULL;

+ strbuf_init(&buf, 0);
/* sysfs exported terms */
- list_for_each_entry(format, formats, list) {
- char c = i++ ? ',' : ' ';
-
- err = str;
- if (!asprintf(&str, "%s%c%s", err, c, format->name))
- goto fail;
- free(err);
- }
+ list_for_each_entry(format, formats, list)
+ strbuf_addf(&buf, i++ ? ",%s" : "%s",
+ format->name);

- /* static terms */
- err = str;
- if (!asprintf(&str, "%s,%s", err, static_terms))
- goto fail;
+ str = strbuf_detach(&buf, NULL);
+ strbuf_release(&buf);

- free(err);
return str;
-fail:
- free(err);
- return NULL;
}

/*
@@ -693,9 +681,12 @@ static int pmu_config_term(struct list_head *formats,
if (verbose)
printf("Invalid event/parameter '%s'\n", term->config);
if (err) {
+ char *pmu_term = pmu_formats_string(formats);
+
err->idx = term->err_term;
err->str = strdup("unknown term");
- err->help = formats_error_string(formats);
+ err->help = parse_events_formats_error_string(pmu_term);
+ free(pmu_term);
}
return -EINVAL;
}
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:14:02 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

Add a new option --strip which is used with --itrace to strip out
non-synthesized events. This results in a perf.data file that is
simpler for external tools to parse. In particular, this can be used to
prepare a perf.data file for consumption by autofdo.

A subsequent patch makes a change to Intel PT also to enable use with
autofdo and gives an example of that use.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-25-git-...@intel.com
[ Made it use perf_evlist__remove() + perf_evsel__delete() ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/perf-inject.txt | 3 ++
tools/perf/builtin-inject.c | 92 ++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+)

diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt
index 0c721c3e37e1..0b1cedeef895 100644
--- a/tools/perf/Documentation/perf-inject.txt
+++ b/tools/perf/Documentation/perf-inject.txt
@@ -50,6 +50,9 @@ OPTIONS

include::itrace.txt[]

+--strip::
+ Use with --itrace to strip out non-synthesized events.
+
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 9b6119f134b4..0a945d2e8ca5 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -28,6 +28,7 @@ struct perf_inject {
bool build_ids;
bool sched_stat;
bool have_auxtrace;
+ bool strip;
const char *input_name;
struct perf_data_file output;
u64 bytes_written;
@@ -177,6 +178,14 @@ static int perf_event__repipe(struct perf_tool *tool,
return perf_event__repipe_synth(tool, event);
}

+static int perf_event__drop(struct perf_tool *tool __maybe_unused,
+ union perf_event *event __maybe_unused,
+ struct perf_sample *sample __maybe_unused,
+ struct machine *machine __maybe_unused)
+{
+ return 0;
+}
+
static int perf_event__drop_aux(struct perf_tool *tool,
union perf_event *event __maybe_unused,
struct perf_sample *sample,
@@ -480,6 +489,78 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
return 0;
}

+static int drop_sample(struct perf_tool *tool __maybe_unused,
+ union perf_event *event __maybe_unused,
+ struct perf_sample *sample __maybe_unused,
+ struct perf_evsel *evsel __maybe_unused,
+ struct machine *machine __maybe_unused)
+{
+ return 0;
+}
+
+static void strip_init(struct perf_inject *inject)
+{
+ struct perf_evlist *evlist = inject->session->evlist;
+ struct perf_evsel *evsel;
+
+ inject->tool.context_switch = perf_event__drop;
+
+ evlist__for_each(evlist, evsel)
+ evsel->handler = drop_sample;
+}
+
+static bool has_tracking(struct perf_evsel *evsel)
+{
+ return evsel->attr.mmap || evsel->attr.mmap2 || evsel->attr.comm ||
+ evsel->attr.task;
+}
+
+#define COMPAT_MASK (PERF_SAMPLE_ID | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | \
+ PERF_SAMPLE_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER)
+
+/*
+ * In order that the perf.data file is parsable, tracking events like MMAP need
+ * their selected event to exist, except if there is only 1 selected event left
+ * and it has a compatible sample type.
+ */
+static bool ok_to_remove(struct perf_evlist *evlist,
+ struct perf_evsel *evsel_to_remove)
+{
+ struct perf_evsel *evsel;
+ int cnt = 0;
+ bool ok = false;
+
+ if (!has_tracking(evsel_to_remove))
+ return true;
+
+ evlist__for_each(evlist, evsel) {
+ if (evsel->handler != drop_sample) {
+ cnt += 1;
+ if ((evsel->attr.sample_type & COMPAT_MASK) ==
+ (evsel_to_remove->attr.sample_type & COMPAT_MASK))
+ ok = true;
+ }
+ }
+
+ return ok && cnt == 1;
+}
+
+static void strip_fini(struct perf_inject *inject)
+{
+ struct perf_evlist *evlist = inject->session->evlist;
+ struct perf_evsel *evsel, *tmp;
+
+ /* Remove non-synthesized evsels if possible */
+ evlist__for_each_safe(evlist, tmp, evsel) {
+ if (evsel->handler == drop_sample &&
+ ok_to_remove(evlist, evsel)) {
+ pr_debug("Deleting %s\n", perf_evsel__name(evsel));
+ perf_evlist__remove(evlist, evsel);
+ perf_evsel__delete(evsel);
+ }
+ }
+}
+
static int __cmd_inject(struct perf_inject *inject)
{
int ret = -EINVAL;
@@ -532,6 +613,8 @@ static int __cmd_inject(struct perf_inject *inject)
inject->tool.ordering_requires_timestamps = true;
/* Allow space in the header for new attributes */
output_data_offset = 4096;
+ if (inject->strip)
+ strip_init(inject);
}

if (!inject->itrace_synth_opts.set)
@@ -570,6 +653,8 @@ static int __cmd_inject(struct perf_inject *inject)
perf_evlist__remove(session->evlist, evsel);
perf_evsel__delete(evsel);
}
+ if (inject->strip)
+ strip_fini(inject);
}
session->header.data_offset = output_data_offset;
session->header.data_size = inject->bytes_written;
@@ -635,6 +720,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
NULL, "opts", "Instruction Tracing options",
itrace_parse_synth_opts),
+ OPT_BOOLEAN(0, "strip", &inject.strip,
+ "strip non-synthesized events (use with --itrace)"),
OPT_END()
};
const char * const inject_usage[] = {
@@ -650,6 +737,11 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
if (argc)
usage_with_options(inject_usage, options);

+ if (inject.strip && !inject.itrace_synth_opts.set) {
+ pr_err("--strip option requires --itrace option\n");
+ return -1;
+ }
+
if (perf_data_file__open(&inject.output)) {
perror("failed to create output file");
return -1;
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:14:05 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

Use the scripting_max_stack value to allow for values greater than
PERF_MAX_STACK_DEPTH.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-20-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-script.c | 2 +-
tools/perf/util/scripting-engines/trace-event-python.c | 2 +-
tools/perf/util/trace-event.h | 2 ++
3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index a65b498df097..5c3c02d5af53 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -33,7 +33,7 @@ static bool nanosecs;
static const char *cpu_list;
static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);

-static unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
+unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;

enum perf_output_field {
PERF_OUTPUT_COMM = 1U << 0,
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index aa9e1257c1ee..a8e825fca42a 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -319,7 +319,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample,

if (thread__resolve_callchain(al->thread, evsel,
sample, NULL, NULL,
- PERF_MAX_STACK_DEPTH) != 0) {
+ scripting_max_stack) != 0) {
pr_err("Failed to resolve callchain. Skipping\n");
goto exit;
}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index da6cc4cc2a4f..b85ee55cca0c 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -78,6 +78,8 @@ struct scripting_ops {
int (*generate_script) (struct pevent *pevent, const char *outfile);
};

+extern unsigned int scripting_max_stack;
+
int script_spec_register(const char *spec, struct scripting_ops *ops);

void setup_perl_scripting(void);
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:14:24 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

perf script has a setting to set the maximum stack depth when processing
callchains. The setting defaults to the hard-coded maximum definition
PERF_MAX_STACK_DEPTH which is 127.

It is possible, when processing instruction traces, to synthesize
callchains. Synthesized callchains do not have the kernel size
limitation and are whatever size the user requests, although validation
presently prevents the user requested a value greater that 1024. The
default value is 16.

To allow for synthesized callchains, make the scripting_max_stack value
at least the same size as the synthesized callchain size.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-21-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-script.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 5c3c02d5af53..8ce1c6bbfa45 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1748,6 +1748,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
}
}

+ if (itrace_synth_opts.callchain &&
+ itrace_synth_opts.callchain_sz > scripting_max_stack)
+ scripting_max_stack = itrace_synth_opts.callchain_sz;
+
/* make sure PERF_EXEC_PATH is set for scripts */
perf_set_argv_exec_path(perf_exec_path());

--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:15:21 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

Logging is only used for debugging. Use macros to save calling into the
functions only to return immediately when logging is not enabled.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-5-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/intel-pt-decoder/intel-pt-log.c | 21 +++++++-------
tools/perf/util/intel-pt-decoder/intel-pt-log.h | 38 +++++++++++++++++++++----
2 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
index d09c7d9f9050..319bef33a64b 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
@@ -29,18 +29,18 @@

static FILE *f;
static char log_name[MAX_LOG_NAME];
-static bool enable_logging;
+bool intel_pt_enable_logging;

void intel_pt_log_enable(void)
{
- enable_logging = true;
+ intel_pt_enable_logging = true;
}

void intel_pt_log_disable(void)
{
if (f)
fflush(f);
- enable_logging = false;
+ intel_pt_enable_logging = false;
}

void intel_pt_log_set_name(const char *name)
@@ -80,7 +80,7 @@ static void intel_pt_print_no_data(uint64_t pos, int indent)

static int intel_pt_log_open(void)
{
- if (!enable_logging)
+ if (!intel_pt_enable_logging)
return -1;

if (f)
@@ -91,15 +91,15 @@ static int intel_pt_log_open(void)

f = fopen(log_name, "w+");
if (!f) {
- enable_logging = false;
+ intel_pt_enable_logging = false;
return -1;
}

return 0;
}

-void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
- uint64_t pos, const unsigned char *buf)
+void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
+ uint64_t pos, const unsigned char *buf)
{
char desc[INTEL_PT_PKT_DESC_MAX];

@@ -111,7 +111,7 @@ void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
fprintf(f, "%s\n", desc);
}

-void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
+void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
{
char desc[INTEL_PT_INSN_DESC_MAX];
size_t len = intel_pt_insn->length;
@@ -128,7 +128,8 @@ void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
fprintf(f, "Bad instruction!\n");
}

-void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
+void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
+ uint64_t ip)
{
char desc[INTEL_PT_INSN_DESC_MAX];

@@ -142,7 +143,7 @@ void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
fprintf(f, "Bad instruction!\n");
}

-void intel_pt_log(const char *fmt, ...)
+void __intel_pt_log(const char *fmt, ...)
{
va_list args;

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.h b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
index db3942f83677..debe751dc3d6 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
@@ -25,20 +25,46 @@ void intel_pt_log_enable(void);
void intel_pt_log_disable(void);
void intel_pt_log_set_name(const char *name);

-void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
- uint64_t pos, const unsigned char *buf);
+void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
+ uint64_t pos, const unsigned char *buf);

struct intel_pt_insn;

-void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip);
-void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
- uint64_t ip);
+void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip);
+void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
+ uint64_t ip);

__attribute__((format(printf, 1, 2)))
-void intel_pt_log(const char *fmt, ...);
+void __intel_pt_log(const char *fmt, ...);
+
+#define intel_pt_log(fmt, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log(fmt, ##__VA_ARGS__); \
+ } while (0)
+
+#define intel_pt_log_packet(arg, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log_packet(arg, ##__VA_ARGS__); \
+ } while (0)
+
+#define intel_pt_log_insn(arg, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log_insn(arg, ##__VA_ARGS__); \
+ } while (0)
+
+#define intel_pt_log_insn_no_data(arg, ...) \
+ do { \
+ if (intel_pt_enable_logging) \
+ __intel_pt_log_insn_no_data(arg, ##__VA_ARGS__); \
+ } while (0)

#define x64_fmt "0x%" PRIx64

+extern bool intel_pt_enable_logging;
+
static inline void intel_pt_log_at(const char *msg, uint64_t u)
{
intel_pt_log("%s at " x64_fmt "\n", msg, u);
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:17:28 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Jiri Olsa, David Ahern, Kai Germaschewski, Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Jiri Olsa <jo...@kernel.org>

For dependency tracking we currently use targets that fall out of the
gcc -MD command. We store this info in the .cmd file and include as
makefile during the build.

This format put object as target and all the c and header files as
dependencies, like:

util/abspath.o: util/abspath.c /usr/include/stdc-predef.h util/cache.h \
/usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
...

If any of those dependency header files (krava.h below) is removed the
build fails on:

make[1]: *** No rule to make target 'krava.h', needed by 'inc.o'. Stop.

This patch adds fixdep helper, that is used by kbuild to alter the shape
of the object dependencies like:

source_util/abspath.o := util/abspath.c

deps_util/abspath.o := \
/usr/include/stdc-predef.h \
util/cache.h \
...

util/abspath.o: $(deps_util/abspath.o)

$(deps_util/abspath.o):

With this format the header removal won't make the build fail, because
it'll be picked up by the last empty target defined for each header.

As previously mentioned the fixdep tool is taken from kbuild. It's not
complete backport, only the part that alters the standard dependency
info was taken, the part that adds the CONFIG_* dependency logic will be
probably taken later on.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Kai Germaschewski <kai.germ...@gmx.de>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1443004442-32660-4-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/build/Build | 1 +
tools/build/Makefile | 43 +++++++++++++
tools/build/fixdep.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 212 insertions(+)
create mode 100644 tools/build/Build
create mode 100644 tools/build/Makefile
create mode 100644 tools/build/fixdep.c

diff --git a/tools/build/Build b/tools/build/Build
new file mode 100644
index 000000000000..63a6c34c0c88
--- /dev/null
+++ b/tools/build/Build
@@ -0,0 +1 @@
+fixdep-y := fixdep.o
diff --git a/tools/build/Makefile b/tools/build/Makefile
new file mode 100644
index 000000000000..a93036272d43
--- /dev/null
+++ b/tools/build/Makefile
@@ -0,0 +1,43 @@
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+endif
+
+include $(srctree)/tools//scripts/Makefile.include
+
+define allow-override
+ $(if $(or $(findstring environment,$(origin $(1))),\
+ $(findstring command line,$(origin $(1)))),,\
+ $(eval $(1) = $(2)))
+endef
+
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
+
+ifeq ($(V),1)
+ Q =
+else
+ Q = @
+endif
+
+export Q srctree CC LD
+
+MAKEFLAGS := --no-print-directory
+build := -f $(srctree)/tools/build/Makefile.build dir=. obj
+
+all: fixdep
+
+clean:
+ $(call QUIET_CLEAN, fixdep)
+ $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
+ $(Q)rm -f fixdep
+
+$(OUTPUT)fixdep-in.o: FORCE
+ $(Q)$(MAKE) $(build)=fixdep
+
+$(OUTPUT)fixdep: $(OUTPUT)fixdep-in.o
+ $(QUIET_LINK)$(CC) $(LDFLAGS) -o $@ $<
+
+FORCE:
+
+.PHONY: FORCE
diff --git a/tools/build/fixdep.c b/tools/build/fixdep.c
new file mode 100644
index 000000000000..1521d36cef0d
--- /dev/null
+++ b/tools/build/fixdep.c
@@ -0,0 +1,168 @@
+/*
+ * "Optimize" a list of dependencies as spit out by gcc -MD
+ * for the build framework.
+ *
+ * Original author:
+ * Copyright 2002 by Kai Germaschewski <kai.germ...@gmx.de>
+ *
+ * This code has been borrowed from kbuild's fixdep (scripts/basic/fixdep.c),
+ * Please check it for detailed explanation. This fixdep borow only the
+ * base transformation of dependecies without the CONFIG mangle.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
+char *target;
+char *depfile;
+char *cmdline;
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
+ exit(1);
+}
+
+/*
+ * Print out the commandline prefixed with cmd_<target filename> :=
+ */
+static void print_cmdline(void)
+{
+ printf("cmd_%s := %s\n\n", target, cmdline);
+}
+
+/*
+ * Important: The below generated source_foo.o and deps_foo.o variable
+ * assignments are parsed not only by make, but also by the rather simple
+ * parser in scripts/mod/sumversion.c.
+ */
+static void parse_dep_file(void *map, size_t len)
+{
+ char *m = map;
+ char *end = m + len;
+ char *p;
+ char s[PATH_MAX];
+ int is_target;
+ int saw_any_target = 0;
+ int is_first_dep = 0;
+
+ while (m < end) {
+ /* Skip any "white space" */
+ while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
+ m++;
+ /* Find next "white space" */
+ p = m;
+ while (p < end && *p != ' ' && *p != '\\' && *p != '\n')
+ p++;
+ /* Is the token we found a target name? */
+ is_target = (*(p-1) == ':');
+ /* Don't write any target names into the dependency file */
+ if (is_target) {
+ /* The /next/ file is the first dependency */
+ is_first_dep = 1;
+ } else {
+ /* Save this token/filename */
+ memcpy(s, m, p-m);
+ s[p - m] = 0;
+
+ /*
+ * Do not list the source file as dependency,
+ * so that kbuild is not confused if a .c file
+ * is rewritten into .S or vice versa. Storing
+ * it in source_* is needed for modpost to
+ * compute srcversions.
+ */
+ if (is_first_dep) {
+ /*
+ * If processing the concatenation of
+ * multiple dependency files, only
+ * process the first target name, which
+ * will be the original source name,
+ * and ignore any other target names,
+ * which will be intermediate temporary
+ * files.
+ */
+ if (!saw_any_target) {
+ saw_any_target = 1;
+ printf("source_%s := %s\n\n",
+ target, s);
+ printf("deps_%s := \\\n",
+ target);
+ }
+ is_first_dep = 0;
+ } else
+ printf(" %s \\\n", s);
+ }
+ /*
+ * Start searching for next token immediately after the first
+ * "whitespace" character that follows this token.
+ */
+ m = p + 1;
+ }
+
+ if (!saw_any_target) {
+ fprintf(stderr, "fixdep: parse error; no targets found\n");
+ exit(1);
+ }
+
+ printf("\n%s: $(deps_%s)\n\n", target, target);
+ printf("$(deps_%s):\n", target);
+}
+
+static void print_deps(void)
+{
+ struct stat st;
+ int fd;
+ void *map;
+
+ fd = open(depfile, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "fixdep: error opening depfile: ");
+ perror(depfile);
+ exit(2);
+ }
+ if (fstat(fd, &st) < 0) {
+ fprintf(stderr, "fixdep: error fstat'ing depfile: ");
+ perror(depfile);
+ exit(2);
+ }
+ if (st.st_size == 0) {
+ fprintf(stderr, "fixdep: %s is empty\n", depfile);
+ close(fd);
+ return;
+ }
+ map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if ((long) map == -1) {
+ perror("fixdep: mmap");
+ close(fd);
+ return;
+ }
+
+ parse_dep_file(map, st.st_size);
+
+ munmap(map, st.st_size);
+
+ close(fd);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 4)
+ usage();
+
+ depfile = argv[1];
+ target = argv[2];
+ cmdline = argv[3];
+
+ print_cmdline();
+ print_deps();
+
+ return 0;
+}
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:17:41 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Jiri Olsa, David Ahern, Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Jiri Olsa <jo...@kernel.org>

Adding the fixdep target into the Makefile.include to ease up building of
fixdep helper, that needs to be built before we dive in to the build itself.
The user can invoke the fixdep target to build the helper.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1443004442-32660-8-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/build/Documentation/Build.txt | 7 +++++++
tools/build/Makefile.include | 5 +++++
tools/build/tests/ex/Makefile | 8 +++++---
tools/lib/api/Makefile | 4 +++-
tools/lib/bpf/Makefile | 4 +++-
tools/lib/lockdep/Makefile | 4 +++-
tools/perf/Makefile.perf | 12 ++++++------
7 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt
index 88824359d595..a47bffbae159 100644
--- a/tools/build/Documentation/Build.txt
+++ b/tools/build/Documentation/Build.txt
@@ -113,6 +113,13 @@ It defines following interface:
make $(build)=ex


+Fixdep
+------
+It is necessary to build the fixdep helper before invoking the build.
+The Makefile.include file adds the fixdep target, that could be
+invoked by the user.
+
+
Rules
-----

diff --git a/tools/build/Makefile.include b/tools/build/Makefile.include
index 91bc60616de5..6572bb023543 100644
--- a/tools/build/Makefile.include
+++ b/tools/build/Makefile.include
@@ -1 +1,6 @@
build := -f $(srctree)/tools/build/Makefile.build dir=. obj
+
+fixdep:
+ $(Q)$(MAKE) -C $(srctree)/tools/build fixdep
+
+.PHONY: fixdep
diff --git a/tools/build/tests/ex/Makefile b/tools/build/tests/ex/Makefile
index f279b84cb859..c50d5782ad5a 100644
--- a/tools/build/tests/ex/Makefile
+++ b/tools/build/tests/ex/Makefile
@@ -3,18 +3,20 @@ export CC := gcc
export LD := ld
export AR := ar

+ex:
+
include $(srctree)/tools/build/Makefile.include

ex: ex-in.o libex-in.o
gcc -o $@ $^

-ex.%: FORCE
+ex.%: fixdep FORCE
make -f $(srctree)/tools/build/Makefile.build dir=. $@

-ex-in.o: FORCE
+ex-in.o: fixdep FORCE
make $(build)=ex

-libex-in.o: FORCE
+libex-in.o: fixdep FORCE
make $(build)=libex

clean:
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index 8806ea7c2f99..d85904dc9b38 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -23,10 +23,12 @@ RM = rm -f

API_IN := $(OUTPUT)libapi-in.o

+all:
+
export srctree OUTPUT CC LD CFLAGS V
include $(srctree)/tools/build/Makefile.include

-all: $(LIBFILE)
+all: fixdep $(LIBFILE)

$(API_IN): FORCE
@$(MAKE) $(build)=libapi
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index c66ade68d4a1..fc9af57b666e 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -123,6 +123,8 @@ endif
# the same command line setup.
MAKEOVERRIDES=

+all:
+
export srctree OUTPUT CC LD CFLAGS V
include $(srctree)/tools/build/Makefile.include

@@ -133,7 +135,7 @@ CMD_TARGETS = $(LIB_FILE)

TARGETS = $(CMD_TARGETS)

-all: $(VERSION_FILES) all_cmd
+all: fixdep $(VERSION_FILES) all_cmd

all_cmd: $(CMD_TARGETS)

diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index d12081da383b..7e319afac78a 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -93,6 +93,8 @@ else
print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
endif

+all:
+
export srctree OUTPUT CC LD CFLAGS V
include $(srctree)/tools/build/Makefile.include

@@ -109,7 +111,7 @@ CMD_TARGETS = $(LIB_FILE)
TARGETS = $(CMD_TARGETS)


-all: all_cmd
+all: fixdep all_cmd

all_cmd: $(CMD_TARGETS)

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 25c1753ffbeb..56517d304772 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -306,7 +306,7 @@ $(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \
$(PERF_IN) $(LIBS) -o $@

-$(GTK_IN): FORCE
+$(GTK_IN): fixdep FORCE
$(Q)$(MAKE) $(build)=gtk

$(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS)
@@ -349,7 +349,7 @@ endif
__build-dir = $(subst $(OUTPUT),,$(dir $@))
build-dir = $(if $(__build-dir),$(__build-dir),.)

-prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
+prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep

$(OUTPUT)%.o: %.c prepare FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -389,7 +389,7 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)

LIBPERF_IN := $(OUTPUT)libperf-in.o

-$(LIBPERF_IN): FORCE
+$(LIBPERF_IN): fixdep FORCE
$(Q)$(MAKE) $(build)=libperf

$(LIB_FILE): $(LIBPERF_IN)
@@ -397,10 +397,10 @@ $(LIB_FILE): $(LIBPERF_IN)

LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)

-$(LIBTRACEEVENT): FORCE
+$(LIBTRACEEVENT): fixdep FORCE
$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a

-libtraceevent_plugins: FORCE
+libtraceevent_plugins: fixdep FORCE
$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins

$(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins
@@ -413,7 +413,7 @@ $(LIBTRACEEVENT)-clean:
install-traceevent-plugins: $(LIBTRACEEVENT)
$(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins

-$(LIBAPI): FORCE
+$(LIBAPI): fixdep FORCE
$(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a

$(LIBAPI)-clean:
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:17:55 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Jiri Olsa, David Ahern, Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Jiri Olsa <jo...@kernel.org>

And use the new 'prepare' target for the $(PERF_IN) target.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1443004442-32660-7-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Makefile.perf | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 6dec86665acc..25c1753ffbeb 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -299,7 +299,7 @@ PERF_IN := $(OUTPUT)perf-in.o
export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
include $(srctree)/tools/build/Makefile.include

-$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE
+$(PERF_IN): prepare FORCE
$(Q)$(MAKE) $(build)=perf

$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
@@ -349,27 +349,27 @@ endif
__build-dir = $(subst $(OUTPUT),,$(dir $@))
build-dir = $(if $(__build-dir),$(__build-dir),.)

-single_dep: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
+prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h

-$(OUTPUT)%.o: %.c single_dep FORCE
+$(OUTPUT)%.o: %.c prepare FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@

-$(OUTPUT)%.i: %.c single_dep FORCE
+$(OUTPUT)%.i: %.c prepare FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@

-$(OUTPUT)%.s: %.c single_dep FORCE
+$(OUTPUT)%.s: %.c prepare FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@

-$(OUTPUT)%-bison.o: %.c single_dep FORCE
+$(OUTPUT)%-bison.o: %.c prepare FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@

-$(OUTPUT)%-flex.o: %.c single_dep FORCE
+$(OUTPUT)%-flex.o: %.c prepare FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@

-$(OUTPUT)%.o: %.S single_dep FORCE
+$(OUTPUT)%.o: %.S prepare FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@

-$(OUTPUT)%.i: %.S single_dep FORCE
+$(OUTPUT)%.i: %.S prepare FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@

$(OUTPUT)perf-%: %.o $(PERFLIBS)
@@ -591,6 +591,6 @@ FORCE:

.PHONY: all install clean config-clean strip install-gtk
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
-.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE single_dep
+.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare
.PHONY: libtraceevent_plugins

--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:18:23 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

Processing instruction tracing data (e.g. Intel PT) can synthesize
callchains e.g.

$ perf record -e intel_pt//u uname
$ perf report --stdio --itrace=ige

However perf report's callgraph option gets extra validation, so:

$ perf report --stdio --itrace=ige -gflat
Error:
Selected -g or --branch-history but no callchain data. Did
you call 'perf record' without -g?
# To display the perf.data header info,
# please use --header/--header-only options.
#

Fix the validation to know about instruction tracing options so
above command works.

A side-effect of the change is that the default option to
accumulate the callchain of child functions comes into force.
To get the previous behaviour the --no-children option can be
used e.g.

$ perf report --stdio --itrace=ige -gflat --no-children

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-3-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-report.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index e4e3f1432622..0d53b485a87b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -214,6 +214,12 @@ static int report__setup_sample_type(struct report *rep)
u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
bool is_pipe = perf_data_file__is_pipe(session->file);

+ if (session->itrace_synth_opts->callchain ||
+ (!is_pipe &&
+ perf_header__has_feat(&session->header, HEADER_AUXTRACE) &&
+ !session->itrace_synth_opts->set))
+ sample_type |= PERF_SAMPLE_CALLCHAIN;
+
if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
if (sort__has_parent) {
ui__error("Selected --sort parent, but no "
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:18:38 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Jiri Olsa, David Ahern, Matt Fleming, Namhyung Kim, Peter Zijlstra, Raphael Beamonte, Arnaldo Carvalho de Melo
From: Jiri Olsa <jo...@kernel.org>

Storing the actual tracing path mountpoint to display correct
error message hint ('Hint:' line). The error hint rediscovers
mountpoints, but it could be different from what we actually
used in tracing path.

Before we'd display debugfs mount even though tracefs was used:
$ perf record -e sched:sched_krava ls
event syntax error: 'sched:sched_krava'
\___ can't access trace events

Error: No permissions to read /sys/kernel/debug/tracing/events/sched/sched_krava
Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug'
...

After this change, correct mountpoint is displayed:
$ perf record -e sched:sched_krava ls
event syntax error: 'sched:sched_krava'
\___ can't access trace events

Error: No permissions to read /sys/kernel/debug/tracing/events/sched/sched_krava
Hint: Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'
...

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Raphael Beamonte <raphael....@gmail.com>
Link: http://lkml.kernel.org/r/1442674027-19427-1-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/lib/api/fs/tracing_path.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
index 38aca2dd1946..0406a7d5c891 100644
--- a/tools/lib/api/fs/tracing_path.c
+++ b/tools/lib/api/fs/tracing_path.c
@@ -12,12 +12,14 @@
#include "tracing_path.h"


+char tracing_mnt[PATH_MAX + 1] = "/sys/kernel/debug";
char tracing_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing";
char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";


static void __tracing_path_set(const char *tracing, const char *mountpoint)
{
+ snprintf(tracing_mnt, sizeof(tracing_mnt), "%s", mountpoint);
snprintf(tracing_path, sizeof(tracing_path), "%s/%s",
mountpoint, tracing);
snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
@@ -109,19 +111,10 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
"Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
break;
case EACCES: {
- const char *mountpoint = debugfs__mountpoint();
-
- if (!access(mountpoint, R_OK) && strncmp(filename, "tracing/", 8) == 0) {
- const char *tracefs_mntpoint = tracefs__mountpoint();
-
- if (tracefs_mntpoint)
- mountpoint = tracefs__mountpoint();
- }
-
snprintf(buf, size,
"Error:\tNo permissions to read %s/%s\n"
"Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
- tracing_events_path, filename, mountpoint);
+ tracing_events_path, filename, tracing_mnt);
}
break;
default:
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:19:04 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Arnaldo Carvalho de Melo, Adrian Hunter, Borislav Petkov, David Ahern, Frederic Weisbecker, Jiri Olsa, Namhyung Kim, Stephane Eranian, Wang Nan
From: Arnaldo Carvalho de Melo <ac...@redhat.com>

Instead of using dso->kernel, this is equivalent at the moment,
and helps in reducing the accesses to dso->kernel.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: Borislav Petkov <b...@suse.de>
Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-1pc2v63iph...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-top.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index bdaf44f24d5d..38d4d6cac823 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -655,7 +655,7 @@ static int symbol_filter(struct map *map, struct symbol *sym)
{
const char *name = sym->name;

- if (!map->dso->kernel)
+ if (!__map__is_kernel(map))
return 0;
/*
* ppc64 uses function descriptors and appends a '.' to the
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:19:08 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

autofdo incorrectly expects branch flags to include either mispred or
predicted. In fact mispred = predicted = 0 is valid and means the flags
are not supported, which they aren't by Intel PT.

To make autofdo work, add a config option which will cause Intel PT
decoder to set the mispred flag on all branches.

Below is an example of using Intel PT with autofdo. The example is
also added to the Intel PT documentation. It requires autofdo
(https://github.com/google/autofdo) and gcc version 5. The bubble
sort example is from the AutoFDO tutorial (https://gcc.gnu.org/wiki/AutoFDO/Tutorial)
amended to take the number of elements as a parameter.

$ gcc-5 -O3 sort.c -o sort_optimized
$ ./sort_optimized 30000
Bubble sorting array of 30000 elements
2254 ms

$ cat ~/.perfconfig
[intel-pt]
mispred-all

$ perf record -e intel_pt//u ./sort 3000
Bubble sorting array of 3000 elements
58 ms
[ perf record: Woken up 2 times to write data ]
[ perf record: Captured and wrote 3.939 MB perf.data ]
$ perf inject -i perf.data -o inj --itrace=i100usle --strip
$ ./create_gcov --binary=./sort --profile=inj --gcov=sort.gcov -gcov_version=1
$ gcc-5 -O3 -fauto-profile=sort.gcov sort.c -o sort_autofdo
$ ./sort_autofdo 30000
Bubble sorting array of 30000 elements
2155 ms

Note there is currently no advantage to using Intel PT instead of LBR,
but that may change in the future if greater use is made of the data.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-26-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/intel-pt.txt | 29 +++++++++++++++++++++++++++++
tools/perf/util/intel-pt.c | 14 ++++++++++++++
2 files changed, 43 insertions(+)

diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index a0fbb5d71f7d..be764f9ec769 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -764,3 +764,32 @@ perf inject also accepts the --itrace option in which case tracing data is
removed and replaced with the synthesized events. e.g.

perf inject --itrace -i perf.data -o perf.data.new
+
+Below is an example of using Intel PT with autofdo. It requires autofdo
+(https://github.com/google/autofdo) and gcc version 5. The bubble
+sort example is from the AutoFDO tutorial (https://gcc.gnu.org/wiki/AutoFDO/Tutorial)
+amended to take the number of elements as a parameter.
+
+ $ gcc-5 -O3 sort.c -o sort_optimized
+ $ ./sort_optimized 30000
+ Bubble sorting array of 30000 elements
+ 2254 ms
+
+ $ cat ~/.perfconfig
+ [intel-pt]
+ mispred-all
+
+ $ perf record -e intel_pt//u ./sort 3000
+ Bubble sorting array of 3000 elements
+ 58 ms
+ [ perf record: Woken up 2 times to write data ]
+ [ perf record: Captured and wrote 3.939 MB perf.data ]
+ $ perf inject -i perf.data -o inj --itrace=i100usle --strip
+ $ ./create_gcov --binary=./sort --profile=inj --gcov=sort.gcov -gcov_version=1
+ $ gcc-5 -O3 -fauto-profile=sort.gcov sort.c -o sort_autofdo
+ $ ./sort_autofdo 30000
+ Bubble sorting array of 30000 elements
+ 2155 ms
+
+Note there is currently no advantage to using Intel PT instead of LBR, but
+that may change in the future if greater use is made of the data.
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 05e8fcc5188b..03ff072b5993 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -64,6 +64,7 @@ struct intel_pt {
bool data_queued;
bool est_tsc;
bool sync_switch;
+ bool mispred_all;
int have_sched_switch;
u32 pmu_type;
u64 kernel_start;
@@ -943,6 +944,7 @@ static void intel_pt_update_last_branch_rb(struct intel_pt_queue *ptq)
be->flags.abort = !!(state->flags & INTEL_PT_ABORT_TX);
be->flags.in_tx = !!(state->flags & INTEL_PT_IN_TX);
/* No support for mispredict */
+ be->flags.mispred = ptq->pt->mispred_all;

if (bs->nr < ptq->pt->synth_opts.last_branch_sz)
bs->nr += 1;
@@ -1967,6 +1969,16 @@ static bool intel_pt_find_switch(struct perf_evlist *evlist)
return false;
}

+static int intel_pt_perf_config(const char *var, const char *value, void *data)
+{
+ struct intel_pt *pt = data;
+
+ if (!strcmp(var, "intel-pt.mispred-all"))
+ pt->mispred_all = perf_config_bool(var, value);
+
+ return 0;
+}
+
static const char * const intel_pt_info_fmts[] = {
[INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n",
[INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n",
@@ -2011,6 +2023,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
if (!pt)
return -ENOMEM;

+ perf_config(intel_pt_perf_config, pt);
+
err = auxtrace_queues__init(&pt->queues);
if (err)
goto err_free;
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:19:35 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

Add a counterpart to perf_evlist__add() that does the opposite and
deletes the evsel.

This will be used by perf inject to remove unwanted evsels.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-23-git-...@intel.com
[ Renamed it from perf_evlist__del() to perf_evlist__remove() and removed the perf_evsel__delete() call ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/evlist.c | 7 +++++++
tools/perf/util/evlist.h | 1 +
2 files changed, 8 insertions(+)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e6760380d731..89546228b8ed 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -165,6 +165,13 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
__perf_evlist__propagate_maps(evlist, entry);
}

+void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel)
+{
+ evsel->evlist = NULL;
+ list_del_init(&evsel->node);
+ evlist->nr_entries -= 1;
+}
+
void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
struct list_head *list)
{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 0edf0d4f4efa..66bc9d4c0869 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -73,6 +73,7 @@ void perf_evlist__exit(struct perf_evlist *evlist);
void perf_evlist__delete(struct perf_evlist *evlist);

void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
+void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel);
int perf_evlist__add_default(struct perf_evlist *evlist);
int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
struct perf_event_attr *attrs, size_t nr_attrs);
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:19:42 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

Use the max_stack value instead of PERF_MAX_STACK_DEPTH so that
arbitrary-sized callchains can be supported.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-17-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/hist.c | 6 ++++--
tools/perf/util/hist.h | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index b3567a25f0c4..0cad9e07c5b4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -695,7 +695,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter,
}

static int
-iter_prepare_cumulative_entry(struct hist_entry_iter *iter __maybe_unused,
+iter_prepare_cumulative_entry(struct hist_entry_iter *iter,
struct addr_location *al __maybe_unused)
{
struct hist_entry **he_cache;
@@ -707,7 +707,7 @@ iter_prepare_cumulative_entry(struct hist_entry_iter *iter __maybe_unused,
* cumulated only one time to prevent entries more than 100%
* overhead.
*/
- he_cache = malloc(sizeof(*he_cache) * (PERF_MAX_STACK_DEPTH + 1));
+ he_cache = malloc(sizeof(*he_cache) * (iter->max_stack + 1));
if (he_cache == NULL)
return -ENOMEM;

@@ -868,6 +868,8 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
if (err)
return err;

+ iter->max_stack = max_stack_depth;
+
err = iter->ops->prepare_entry(iter, al);
if (err)
goto out;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 4d6aa1dbdaee..8c20a8f6b214 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -90,6 +90,7 @@ struct hist_entry_iter {
int curr;

bool hide_unresolved;
+ int max_stack;

struct perf_evsel *evsel;
struct perf_sample *sample;
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:19:56 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

perf_evlist__id2evsel_strict() is the same as perf_evlist__id2evsel()
except that it ensures that the id must match.

This will be used by perf inject to find a specific evsel that is to be
deleted, hence the need to match exactly.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-22-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/evlist.c | 15 +++++++++++++++
tools/perf/util/evlist.h | 2 ++
2 files changed, 17 insertions(+)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a8643735dcea..e6760380d731 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -617,6 +617,21 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
return NULL;
}

+struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
+ u64 id)
+{
+ struct perf_sample_id *sid;
+
+ if (!id)
+ return NULL;
+
+ sid = perf_evlist__id2sid(evlist, id);
+ if (sid)
+ return sid->evsel;
+
+ return NULL;
+}
+
static int perf_evlist__event2id(struct perf_evlist *evlist,
union perf_event *event, u64 *id)
{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 115d8b53c601..0edf0d4f4efa 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -104,6 +104,8 @@ int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mas
int perf_evlist__poll(struct perf_evlist *evlist, int timeout);

struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
+struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
+ u64 id);

struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);

--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:20:40 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

Add a setting for maximum stack depth in preparation for allowing for
synthesized callchains.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-19-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-script.c | 6 ++++--
tools/perf/util/session.c | 2 +-
2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 092843968791..a65b498df097 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -33,6 +33,8 @@ static bool nanosecs;
static const char *cpu_list;
static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);

+static unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
+
enum perf_output_field {
PERF_OUTPUT_COMM = 1U << 0,
PERF_OUTPUT_TID = 1U << 1,
@@ -475,7 +477,7 @@ static void print_sample_bts(union perf_event *event,
}
}
perf_evsel__print_ip(evsel, sample, al, print_opts,
- PERF_MAX_STACK_DEPTH);
+ scripting_max_stack);
}

/* print branch_to information */
@@ -552,7 +554,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,

perf_evsel__print_ip(evsel, sample, al,
output[attr->type].print_ip_opts,
- PERF_MAX_STACK_DEPTH);
+ scripting_max_stack);
}

if (PRINT_FIELD(IREGS))
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 15c84cad213a..84a02eae4394 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1800,7 +1800,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,

if (thread__resolve_callchain(al->thread, evsel,
sample, NULL, NULL,
- PERF_MAX_STACK_DEPTH) != 0) {
+ stack_depth) != 0) {
if (verbose)
error("Failed to resolve callchain. Skipping\n");
return;
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:21:08 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

perf inject can process instruction traces (using the --itrace option)
which removes aux-related events and replaces them with the requested
synthesized events.

However there are still some leftovers, namely PERF_RECORD_ITRACE_START
events and the original evsel (selected event) e.g. intel_pt//

For the sake of completeness, remove them too.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-24-git-...@intel.com
[ Made it use perf_evlist__remove() + perf_evsel__delete() ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-inject.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 8638fad8a085..9b6119f134b4 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -31,6 +31,7 @@ struct perf_inject {
const char *input_name;
struct perf_data_file output;
u64 bytes_written;
+ u64 aux_id;
struct list_head samples;
struct itrace_synth_opts itrace_synth_opts;
};
@@ -176,6 +177,19 @@ static int perf_event__repipe(struct perf_tool *tool,
return perf_event__repipe_synth(tool, event);
}

+static int perf_event__drop_aux(struct perf_tool *tool,
+ union perf_event *event __maybe_unused,
+ struct perf_sample *sample,
+ struct machine *machine __maybe_unused)
+{
+ struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
+
+ if (!inject->aux_id)
+ inject->aux_id = sample->id;
+
+ return 0;
+}
+
typedef int (*inject_handler)(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
@@ -512,6 +526,8 @@ static int __cmd_inject(struct perf_inject *inject)
inject->tool.id_index = perf_event__repipe_id_index;
inject->tool.auxtrace_info = perf_event__process_auxtrace_info;
inject->tool.auxtrace = perf_event__process_auxtrace;
+ inject->tool.aux = perf_event__drop_aux;
+ inject->tool.itrace_start = perf_event__drop_aux,
inject->tool.ordered_events = true;
inject->tool.ordering_requires_timestamps = true;
/* Allow space in the header for new attributes */
@@ -535,14 +551,25 @@ static int __cmd_inject(struct perf_inject *inject)
}
/*
* The AUX areas have been removed and replaced with
- * synthesized hardware events, so clear the feature flag.
+ * synthesized hardware events, so clear the feature flag and
+ * remove the evsel.
*/
if (inject->itrace_synth_opts.set) {
+ struct perf_evsel *evsel;
+
perf_header__clear_feat(&session->header,
HEADER_AUXTRACE);
if (inject->itrace_synth_opts.last_branch)
perf_header__set_feat(&session->header,
HEADER_BRANCH_STACK);
+ evsel = perf_evlist__id2evsel_strict(session->evlist,
+ inject->aux_id);
+ if (evsel) {
+ pr_debug("Deleting %s\n",
+ perf_evsel__name(evsel));
+ perf_evlist__remove(session->evlist, evsel);
+ perf_evsel__delete(evsel);
+ }
}
session->header.data_offset = output_data_offset;
session->header.data_size = inject->bytes_written;
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:21:43 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

A non-synthesized event might not have a branch stack if branch stacks
have been synthesized (using itrace options).

An example of that is when Intel PT records sched_switch events for
decoding purposes. Those sched_switch events do not have branch stacks
even though the Intel PT decoder may be synthesizing other events that
do due to the itrace options.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-12-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-report.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 92f7c5a75208..e94e5c7155af 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -163,14 +163,21 @@ static int process_sample_event(struct perf_tool *tool,
if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
goto out_put;

- if (sort__mode == SORT_MODE__BRANCH)
+ if (sort__mode == SORT_MODE__BRANCH) {
+ /*
+ * A non-synthesized event might not have a branch stack if
+ * branch stacks have been synthesized (using itrace options).
+ */
+ if (!sample->branch_stack)
+ goto out_put;
iter.ops = &hist_iter_branch;
- else if (rep->mem_mode)
+ } else if (rep->mem_mode) {
iter.ops = &hist_iter_mem;
- else if (symbol_conf.cumulate_callchain)
+ } else if (symbol_conf.cumulate_callchain) {
iter.ops = &hist_iter_cumulative;
- else
+ } else {
iter.ops = &hist_iter_normal;
+ }

if (al.map != NULL)
al.map->dso->hit = 1;
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:21:57 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

Add support for generating branch stack context for PT samples. The
decoder reports a configurable number of branches as branch context for
each sample. Internally it keeps track of them by using a simple sliding
window. We also flush the last branch buffer on each sample to avoid
overlapping intervals.

This is useful for:

- Reporting accurate basic block edge frequencies through the perf
report branch view
- Using with --branch-history to get the wider context of samples
- Other users of LBRs

Also the Documentation is updated.

Examples:

Record with Intel PT:

perf record -e intel_pt//u ls

Branch stacks are used by default if synthesized so:

perf report --itrace=ile

is the same as:

perf report --itrace=ile -b

Branch history can be requested also:

perf report --itrace=igle --branch-history

Based-on-patch-by: Andi Kleen <a...@linux.intel.com>
Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-15-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/intel-pt.txt | 10 +++
tools/perf/util/intel-pt.c | 115 ++++++++++++++++++++++++++++++++++
2 files changed, 125 insertions(+)

diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index 886612b50961..a0fbb5d71f7d 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -671,6 +671,7 @@ The letters are:
e synthesize tracing error events
d create a debug log
g synthesize a call chain (use with i or x)
+ l synthesize last branch entries (use with i or x)

"Instructions" events look like they were recorded by "perf record -e
instructions".
@@ -718,6 +719,15 @@ transactions events can be specified. e.g.
--itrace=ig32
--itrace=xg32

+Also the number of last branch entries (default 64, max. 1024) for instructions or
+transactions events can be specified. e.g.
+
+ --itrace=il10
+ --itrace=xl10
+
+Note that last branch entries are cleared for each sample, so there is no overlap
+from one sample to the next.
+
To disable trace decoding entirely, use the option --no-itrace.


diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 2c01e723826a..05e8fcc5188b 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -22,6 +22,7 @@
#include "../perf.h"
#include "session.h"
#include "machine.h"
+#include "sort.h"
#include "tool.h"
#include "event.h"
#include "evlist.h"
@@ -115,6 +116,9 @@ struct intel_pt_queue {
void *decoder;
const struct intel_pt_state *state;
struct ip_callchain *chain;
+ struct branch_stack *last_branch;
+ struct branch_stack *last_branch_rb;
+ size_t last_branch_pos;
union perf_event *event_buf;
bool on_heap;
bool stop;
@@ -675,6 +679,19 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
goto out_free;
}

+ if (pt->synth_opts.last_branch) {
+ size_t sz = sizeof(struct branch_stack);
+
+ sz += pt->synth_opts.last_branch_sz *
+ sizeof(struct branch_entry);
+ ptq->last_branch = zalloc(sz);
+ if (!ptq->last_branch)
+ goto out_free;
+ ptq->last_branch_rb = zalloc(sz);
+ if (!ptq->last_branch_rb)
+ goto out_free;
+ }
+
ptq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
if (!ptq->event_buf)
goto out_free;
@@ -732,6 +749,8 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,

out_free:
zfree(&ptq->event_buf);
+ zfree(&ptq->last_branch);
+ zfree(&ptq->last_branch_rb);
zfree(&ptq->chain);
free(ptq);
return NULL;
@@ -746,6 +765,8 @@ static void intel_pt_free_queue(void *priv)
thread__zput(ptq->thread);
intel_pt_decoder_free(ptq->decoder);
zfree(&ptq->event_buf);
+ zfree(&ptq->last_branch);
+ zfree(&ptq->last_branch_rb);
zfree(&ptq->chain);
free(ptq);
}
@@ -876,6 +897,57 @@ static int intel_pt_setup_queues(struct intel_pt *pt)
return 0;
}

+static inline void intel_pt_copy_last_branch_rb(struct intel_pt_queue *ptq)
+{
+ struct branch_stack *bs_src = ptq->last_branch_rb;
+ struct branch_stack *bs_dst = ptq->last_branch;
+ size_t nr = 0;
+
+ bs_dst->nr = bs_src->nr;
+
+ if (!bs_src->nr)
+ return;
+
+ nr = ptq->pt->synth_opts.last_branch_sz - ptq->last_branch_pos;
+ memcpy(&bs_dst->entries[0],
+ &bs_src->entries[ptq->last_branch_pos],
+ sizeof(struct branch_entry) * nr);
+
+ if (bs_src->nr >= ptq->pt->synth_opts.last_branch_sz) {
+ memcpy(&bs_dst->entries[nr],
+ &bs_src->entries[0],
+ sizeof(struct branch_entry) * ptq->last_branch_pos);
+ }
+}
+
+static inline void intel_pt_reset_last_branch_rb(struct intel_pt_queue *ptq)
+{
+ ptq->last_branch_pos = 0;
+ ptq->last_branch_rb->nr = 0;
+}
+
+static void intel_pt_update_last_branch_rb(struct intel_pt_queue *ptq)
+{
+ const struct intel_pt_state *state = ptq->state;
+ struct branch_stack *bs = ptq->last_branch_rb;
+ struct branch_entry *be;
+
+ if (!ptq->last_branch_pos)
+ ptq->last_branch_pos = ptq->pt->synth_opts.last_branch_sz;
+
+ ptq->last_branch_pos -= 1;
+
+ be = &bs->entries[ptq->last_branch_pos];
+ be->from = state->from_ip;
+ be->to = state->to_ip;
+ be->flags.abort = !!(state->flags & INTEL_PT_ABORT_TX);
+ be->flags.in_tx = !!(state->flags & INTEL_PT_IN_TX);
+ /* No support for mispredict */
+
+ if (bs->nr < ptq->pt->synth_opts.last_branch_sz)
+ bs->nr += 1;
+}
+
static int intel_pt_inject_event(union perf_event *event,
struct perf_sample *sample, u64 type,
bool swapped)
@@ -890,6 +962,10 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
struct intel_pt *pt = ptq->pt;
union perf_event *event = ptq->event_buf;
struct perf_sample sample = { .ip = 0, };
+ struct dummy_branch_stack {
+ u64 nr;
+ struct branch_entry entries;
+ } dummy_bs;

if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
return 0;
@@ -912,6 +988,21 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
sample.flags = ptq->flags;
sample.insn_len = ptq->insn_len;

+ /*
+ * perf report cannot handle events without a branch stack when using
+ * SORT_MODE__BRANCH so make a dummy one.
+ */
+ if (pt->synth_opts.last_branch && sort__mode == SORT_MODE__BRANCH) {
+ dummy_bs = (struct dummy_branch_stack){
+ .nr = 1,
+ .entries = {
+ .from = sample.ip,
+ .to = sample.addr,
+ },
+ };
+ sample.branch_stack = (struct branch_stack *)&dummy_bs;
+ }
+
if (pt->synth_opts.inject) {
ret = intel_pt_inject_event(event, &sample,
pt->branches_sample_type,
@@ -961,6 +1052,11 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
sample.callchain = ptq->chain;
}

+ if (pt->synth_opts.last_branch) {
+ intel_pt_copy_last_branch_rb(ptq);
+ sample.branch_stack = ptq->last_branch;
+ }
+
if (pt->synth_opts.inject) {
ret = intel_pt_inject_event(event, &sample,
pt->instructions_sample_type,
@@ -974,6 +1070,9 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n",
ret);

+ if (pt->synth_opts.last_branch)
+ intel_pt_reset_last_branch_rb(ptq);
+
return ret;
}

@@ -1008,6 +1107,11 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
sample.callchain = ptq->chain;
}

+ if (pt->synth_opts.last_branch) {
+ intel_pt_copy_last_branch_rb(ptq);
+ sample.branch_stack = ptq->last_branch;
+ }
+
if (pt->synth_opts.inject) {
ret = intel_pt_inject_event(event, &sample,
pt->transactions_sample_type,
@@ -1021,6 +1125,9 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n",
ret);

+ if (pt->synth_opts.callchain)
+ intel_pt_reset_last_branch_rb(ptq);
+
return ret;
}

@@ -1116,6 +1223,9 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
return err;
}

+ if (pt->synth_opts.last_branch)
+ intel_pt_update_last_branch_rb(ptq);
+
if (!pt->sync_switch)
return 0;

@@ -1763,6 +1873,8 @@ static int intel_pt_synth_events(struct intel_pt *pt,
pt->instructions_sample_period = attr.sample_period;
if (pt->synth_opts.callchain)
attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
+ if (pt->synth_opts.last_branch)
+ attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
id, (u64)attr.sample_type);
err = intel_pt_synth_event(session, &attr, id);
@@ -1782,6 +1894,8 @@ static int intel_pt_synth_events(struct intel_pt *pt,
attr.sample_period = 1;
if (pt->synth_opts.callchain)
attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
+ if (pt->synth_opts.last_branch)
+ attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
id, (u64)attr.sample_type);
err = intel_pt_synth_event(session, &attr, id);
@@ -1808,6 +1922,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
attr.sample_period = 1;
attr.sample_type |= PERF_SAMPLE_ADDR;
attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN;
+ attr.sample_type &= ~(u64)PERF_SAMPLE_BRANCH_STACK;
pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
id, (u64)attr.sample_type);
err = intel_pt_synth_event(session, &attr, id);
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:22:12 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

The 'perf report' tool will default to displaying branch stacks (-b
option) if they are present. Make that also happen for synthesized
branch stacks.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-11-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-report.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 7af35af5a5e5..92f7c5a75208 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -829,6 +829,9 @@ repeat:
has_br_stack = perf_header__has_feat(&session->header,
HEADER_BRANCH_STACK);

+ if (itrace_synth_opts.last_branch)
+ has_br_stack = true;
+
/*
* Branch mode is a tristate:
* -1 means default, so decide based on the file having branch data.

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:23:57 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

intel_pt_synth_branch_sample() skips synthesizing if the branch does not
match the branch filter. That logic was sitting in the middle of the
function but is more efficiently placed at the start of the function, so
move it.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-14-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/intel-pt.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index c8bb5ca6a157..2c01e723826a 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -891,6 +891,9 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
union perf_event *event = ptq->event_buf;
struct perf_sample sample = { .ip = 0, };

+ if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
+ return 0;
+
event->sample.header.type = PERF_RECORD_SAMPLE;
event->sample.header.misc = PERF_RECORD_MISC_USER;
event->sample.header.size = sizeof(struct perf_event_header);
@@ -909,9 +912,6 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
sample.flags = ptq->flags;
sample.insn_len = ptq->insn_len;

- if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
- return 0;
-
if (pt->synth_opts.inject) {
ret = intel_pt_inject_event(event, &sample,
pt->branches_sample_type,

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:24:16 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

The branch stack feature flag is set by 'perf record' when recording
data that contains branch stacks. Consequently, when 'perf inject'
synthesizes branch stacks, the feature flag should be set also.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-13-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-inject.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index f62c49b35be0..8638fad8a085 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -537,9 +537,13 @@ static int __cmd_inject(struct perf_inject *inject)
* The AUX areas have been removed and replaced with
* synthesized hardware events, so clear the feature flag.
*/
- if (inject->itrace_synth_opts.set)
+ if (inject->itrace_synth_opts.set) {
perf_header__clear_feat(&session->header,
HEADER_AUXTRACE);
+ if (inject->itrace_synth_opts.last_branch)
+ perf_header__set_feat(&session->header,
+ HEADER_BRANCH_STACK);
+ }
session->header.data_offset = output_data_offset;
session->header.data_size = inject->bytes_written;
perf_session__write_header(session, session->evlist, fd, true);

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:24:49 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

Add option --ns to display time to 9 decimal places. That is useful in
some cases, for example when using Intel PT cycle accurate mode.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-6-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/Documentation/perf-script.txt | 3 +++
tools/perf/builtin-script.c | 8 +++++++-
2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index dc3ec783b7bd..b3b42f9285df 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -249,6 +249,9 @@ include::itrace.txt[]
--full-source-path::
Show the full path for source files for srcline output.

+--ns::
+ Use 9 decimal places when displaying time (i.e. show the nanoseconds)
+
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 284a76e04628..092843968791 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -29,6 +29,7 @@ static bool no_callchain;
static bool latency_format;
static bool system_wide;
static bool print_flags;
+static bool nanosecs;
static const char *cpu_list;
static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);

@@ -415,7 +416,10 @@ static void print_sample_start(struct perf_sample *sample,
secs = nsecs / NSECS_PER_SEC;
nsecs -= secs * NSECS_PER_SEC;
usecs = nsecs / NSECS_PER_USEC;
- printf("%5lu.%06lu: ", secs, usecs);
+ if (nanosecs)
+ printf("%5lu.%09llu: ", secs, nsecs);
+ else
+ printf("%5lu.%06lu: ", secs, usecs);
}
}

@@ -1695,6 +1699,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
"Show context switch events (if recorded)"),
OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
+ OPT_BOOLEAN(0, "ns", &nanosecs,
+ "Use 9 decimal places when displaying time"),
OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
"Instruction Tracing options",
itrace_parse_synth_opts),

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:25:00 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

By default 'perf record' will postprocess the perf.data file to
determine build-ids. When that happens, the number of lost perf events
is displayed.

Make that also happen for AUX events.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-7-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/event.h | 1 +
tools/perf/util/session.c | 10 ++++++++++
2 files changed, 11 insertions(+)

diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index be5cbc7be889..a0dbcbd4f6d8 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -257,6 +257,7 @@ struct events_stats {
u64 total_non_filtered_period;
u64 total_lost;
u64 total_lost_samples;
+ u64 total_aux_lost;
u64 total_invalid_chains;
u32 nr_events[PERF_RECORD_HEADER_MAX];
u32 nr_non_filtered_samples;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f5e000030a5e..15c84cad213a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1101,6 +1101,9 @@ static int machines__deliver_event(struct machines *machines,
case PERF_RECORD_UNTHROTTLE:
return tool->unthrottle(tool, event, sample, machine);
case PERF_RECORD_AUX:
+ if (tool->aux == perf_event__process_aux &&
+ (event->aux.flags & PERF_AUX_FLAG_TRUNCATED))
+ evlist->stats.total_aux_lost += 1;
return tool->aux(tool, event, sample, machine);
case PERF_RECORD_ITRACE_START:
return tool->itrace_start(tool, event, sample, machine);
@@ -1346,6 +1349,13 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
}
}

+ if (session->tool->aux == perf_event__process_aux &&
+ stats->total_aux_lost != 0) {
+ ui__warning("AUX data lost %" PRIu64 " times out of %u!\n\n",
+ stats->total_aux_lost,
+ stats->nr_events[PERF_RECORD_AUX]);
+ }
+
if (stats->nr_unknown_events != 0) {
ui__warning("Found %u unknown events!\n\n"
"Is this an older tool processing a perf.data "

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:25:18 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Adrian Hunter, Jiri Olsa, Arnaldo Carvalho de Melo
From: Adrian Hunter <adrian...@intel.com>

Add some comments to the script and some 'views' to the created database
that better illustrate the database structure and how it can be used.

Signed-off-by: Adrian Hunter <adrian...@intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Link: http://lkml.kernel.org/r/1443186956-18718-8-git-...@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/scripts/python/export-to-postgresql.py | 221 ++++++++++++++++++++++
1 file changed, 221 insertions(+)

diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 84a32037a80f..1b02cdc0cab6 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -61,6 +61,142 @@ import datetime
#
# An example of using the database is provided by the script
# call-graph-from-postgresql.py. Refer to that script for details.
+#
+# Tables:
+#
+# The tables largely correspond to perf tools' data structures. They are largely self-explanatory.
+#
+# samples
+#
+# 'samples' is the main table. It represents what instruction was executing at a point in time
+# when something (a selected event) happened. The memory address is the instruction pointer or 'ip'.
+#
+# calls
+#
+# 'calls' represents function calls and is related to 'samples' by 'call_id' and 'return_id'.
+# 'calls' is only created when the 'calls' option to this script is specified.
+#
+# call_paths
+#
+# 'call_paths' represents all the call stacks. Each 'call' has an associated record in 'call_paths'.
+# 'calls_paths' is only created when the 'calls' option to this script is specified.
+#
+# branch_types
+#
+# 'branch_types' provides descriptions for each type of branch.
+#
+# comm_threads
+#
+# 'comm_threads' shows how 'comms' relates to 'threads'.
+#
+# comms
+#
+# 'comms' contains a record for each 'comm' - the name given to the executable that is running.
+#
+# dsos
+#
+# 'dsos' contains a record for each executable file or library.
+#
+# machines
+#
+# 'machines' can be used to distinguish virtual machines if virtualization is supported.
+#
+# selected_events
+#
+# 'selected_events' contains a record for each kind of event that has been sampled.
+#
+# symbols
+#
+# 'symbols' contains a record for each symbol. Only symbols that have samples are present.
+#
+# threads
+#
+# 'threads' contains a record for each thread.
+#
+# Views:
+#
+# Most of the tables have views for more friendly display. The views are:
+#
+# calls_view
+# call_paths_view
+# comm_threads_view
+# dsos_view
+# machines_view
+# samples_view
+# symbols_view
+# threads_view
+#
+# More examples of browsing the database with psql:
+# Note that some of the examples are not the most optimal SQL query.
+# Note that call information is only available if the script's 'calls' option has been used.
+#
+# Top 10 function calls (not aggregated by symbol):
+#
+# SELECT * FROM calls_view ORDER BY elapsed_time DESC LIMIT 10;
+#
+# Top 10 function calls (aggregated by symbol):
+#
+# SELECT symbol_id,(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,
+# SUM(elapsed_time) AS tot_elapsed_time,SUM(branch_count) AS tot_branch_count
+# FROM calls_view GROUP BY symbol_id ORDER BY tot_elapsed_time DESC LIMIT 10;
+#
+# Note that the branch count gives a rough estimation of cpu usage, so functions
+# that took a long time but have a relatively low branch count must have spent time
+# waiting.
+#
+# Find symbols by pattern matching on part of the name (e.g. names containing 'alloc'):
+#
+# SELECT * FROM symbols_view WHERE name LIKE '%alloc%';
+#
+# Top 10 function calls for a specific symbol (e.g. whose symbol_id is 187):
+#
+# SELECT * FROM calls_view WHERE symbol_id = 187 ORDER BY elapsed_time DESC LIMIT 10;
+#
+# Show function calls made by function in the same context (i.e. same call path) (e.g. one with call_path_id 254):
+#
+# SELECT * FROM calls_view WHERE parent_call_path_id = 254;
+#
+# Show branches made during a function call (e.g. where call_id is 29357 and return_id is 29370 and tid is 29670)
+#
+# SELECT * FROM samples_view WHERE id >= 29357 AND id <= 29370 AND tid = 29670 AND event LIKE 'branches%';
+#
+# Show transactions:
+#
+# SELECT * FROM samples_view WHERE event = 'transactions';
+#
+# Note transaction start has 'in_tx' true whereas, transaction end has 'in_tx' false.
+# Transaction aborts have branch_type_name 'transaction abort'
+#
+# Show transaction aborts:
+#
+# SELECT * FROM samples_view WHERE event = 'transactions' AND branch_type_name = 'transaction abort';
+#
+# To print a call stack requires walking the call_paths table. For example this python script:
+# #!/usr/bin/python2
+#
+# import sys
+# from PySide.QtSql import *
+#
+# if __name__ == '__main__':
+# if (len(sys.argv) < 3):
+# print >> sys.stderr, "Usage is: printcallstack.py <database name> <call_path_id>"
+# raise Exception("Too few arguments")
+# dbname = sys.argv[1]
+# call_path_id = sys.argv[2]
+# db = QSqlDatabase.addDatabase('QPSQL')
+# db.setDatabaseName(dbname)
+# if not db.open():
+# raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
+# query = QSqlQuery(db)
+# print " id ip symbol_id symbol dso_id dso_short_name"
+# while call_path_id != 0 and call_path_id != 1:
+# ret = query.exec_('SELECT * FROM call_paths_view WHERE id = ' + str(call_path_id))
+# if not ret:
+# raise Exception("Query failed: " + query.lastError().text())
+# if not query.next():
+# raise Exception("Query failed")
+# print "{0:>6} {1:>10} {2:>9} {3:<30} {4:>6} {5:<30}".format(query.value(0), query.value(1), query.value(2), query.value(3), query.value(4), query.value(5))
+# call_path_id = query.value(6)

from PySide.QtSql import *

@@ -244,6 +380,91 @@ if perf_db_export_calls:
'parent_call_path_id bigint,'
'flags integer)')

+do_query(query, 'CREATE VIEW machines_view AS '
+ 'SELECT '
+ 'id,'
+ 'pid,'
+ 'root_dir,'
+ 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
+ ' FROM machines')
+
+do_query(query, 'CREATE VIEW dsos_view AS '
+ 'SELECT '
+ 'id,'
+ 'machine_id,'
+ '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
+ 'short_name,'
+ 'long_name,'
+ 'build_id'
+ ' FROM dsos')
+
+do_query(query, 'CREATE VIEW symbols_view AS '
+ 'SELECT '
+ 'id,'
+ 'name,'
+ '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
+ 'dso_id,'
+ 'sym_start,'
+ 'sym_end,'
+ 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
+ ' FROM symbols')
+
+do_query(query, 'CREATE VIEW threads_view AS '
+ 'SELECT '
+ 'id,'
+ 'machine_id,'
+ '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
+ 'process_id,'
+ 'pid,'
+ 'tid'
+ ' FROM threads')
+
+do_query(query, 'CREATE VIEW comm_threads_view AS '
+ 'SELECT '
+ 'comm_id,'
+ '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
+ 'thread_id,'
+ '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
+ '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
+ ' FROM comm_threads')
+
+if perf_db_export_calls:
+ do_query(query, 'CREATE VIEW call_paths_view AS '
+ 'SELECT '
+ 'c.id,'
+ 'to_hex(c.ip) AS ip,'
+ 'c.symbol_id,'
+ '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
+ '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
+ '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,'
+ 'c.parent_id,'
+ 'to_hex(p.ip) AS parent_ip,'
+ 'p.symbol_id AS parent_symbol_id,'
+ '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
+ '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
+ '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
+ ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
+ do_query(query, 'CREATE VIEW calls_view AS '
+ 'SELECT '
+ 'calls.id,'
+ 'thread_id,'
+ '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
+ '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
+ '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
+ 'call_path_id,'
+ 'to_hex(ip) AS ip,'
+ 'symbol_id,'
+ '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
+ 'call_time,'
+ 'return_time,'
+ 'return_time - call_time AS elapsed_time,'
+ 'branch_count,'
+ 'call_id,'
+ 'return_id,'
+ 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,'
+ 'parent_call_path_id'
+ ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
+
do_query(query, 'CREATE VIEW samples_view AS '
'SELECT '
'id,'

Arnaldo Carvalho de Melo

unread,
Sep 28, 2015, 5:25:39 PM9/28/15
to Ingo Molnar, linux-...@vger.kernel.org, Jiri Olsa, David Ahern, Namhyung Kim, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Jiri Olsa <jo...@kernel.org>

To ease up build framework code setup for users.

More shared code will be added in the following patches.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
Cc: David Ahern <dsa...@gmail.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Link: http://lkml.kernel.org/r/1443004442-32660-2-...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/build/Documentation/Build.txt | 45 ++++++++++++++++++++++++++-----------
tools/build/Makefile.include | 1 +
tools/build/tests/ex/Makefile | 3 ++-
tools/lib/api/Makefile | 2 +-
tools/lib/bpf/Makefile | 2 +-
tools/lib/lockdep/Makefile | 2 +-
tools/perf/Makefile.perf | 2 +-
7 files changed, 39 insertions(+), 18 deletions(-)
create mode 100644 tools/build/Makefile.include

diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt
index aa5e092c4352..88824359d595 100644
--- a/tools/build/Documentation/Build.txt
+++ b/tools/build/Documentation/Build.txt
@@ -11,8 +11,9 @@ Unlike the kernel we don't have a single build object 'obj-y' list that where
we setup source objects, but we support more. This allows one 'Build' file to
carry a sources list for multiple build objects.

-a) Build framework makefiles
-----------------------------
+
+Build framework makefiles
+-------------------------

The build framework consists of 2 Makefiles:

@@ -23,7 +24,7 @@ While the 'Build.include' file contains just some generic definitions, the
'Makefile.build' file is the makefile used from the outside. It's
interface/usage is following:

- $ make -f tools/build/Makefile srctree=$(KSRC) dir=$(DIR) obj=$(OBJECT)
+ $ make -f tools/build/Makefile.build srctree=$(KSRC) dir=$(DIR) obj=$(OBJECT)

where:

@@ -38,8 +39,9 @@ called $(OBJECT)-in.o:

which includes all compiled sources described in 'Build' makefiles.

-a) Build makefiles
-------------------
+
+Build makefiles
+---------------

The user supplies 'Build' makefiles that contains a objects list, and connects
the build to nested directories.
@@ -95,8 +97,24 @@ It's only a matter of 2 single commands to create the final binaries:

You can check the 'ex' example in 'tools/build/tests/ex' for more details.

-b) Rules
---------
+
+Makefile.include
+----------------
+
+The tools/build/Makefile.include makefile could be included
+via user makefiles to get usefull definitions.
+
+It defines following interface:
+
+ - build macro definition:
+ build := -f $(srctree)/tools/build/Makefile.build dir=. obj
+
+ to make it easier to invoke build like:
+ make $(build)=ex
+
+
+Rules
+-----

The build framework provides standard compilation rules to handle .S and .c
compilation.
@@ -104,8 +122,9 @@ compilation.
It's possible to include special rule if needed (like we do for flex or bison
code generation).

-c) CFLAGS
----------
+
+CFLAGS
+------

It's possible to alter the standard object C flags in the following way:

@@ -115,8 +134,8 @@ It's possible to alter the standard object C flags in the following way:
This C flags changes has the scope of the Build makefile they are defined in.


-d) Dependencies
----------------
+Dependencies
+------------

For each built object file 'a.o' the '.a.cmd' is created and holds:

@@ -130,8 +149,8 @@ All existing '.cmd' files are included in the Build process to follow properly
the dependencies and trigger a rebuild when necessary.


-e) Single rules
----------------
+Single rules
+------------

It's possible to build single object file by choice, like:

diff --git a/tools/build/Makefile.include b/tools/build/Makefile.include
new file mode 100644
index 000000000000..91bc60616de5
--- /dev/null
+++ b/tools/build/Makefile.include
@@ -0,0 +1 @@
+build := -f $(srctree)/tools/build/Makefile.build dir=. obj
diff --git a/tools/build/tests/ex/Makefile b/tools/build/tests/ex/Makefile
index 52d2476073a3..a8f596e37fd2 100644
--- a/tools/build/tests/ex/Makefile
+++ b/tools/build/tests/ex/Makefile
@@ -3,7 +3,8 @@ export CC := gcc
export LD := ld
export AR := ar

-build := -f $(srctree)/tools/build/Makefile.build dir=. obj
+include $(srctree)/tools/build/Makefile.include
+
ex: ex-in.o libex-in.o
gcc -o $@ $^

diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index fe1b02c2c95b..8806ea7c2f99 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -21,10 +21,10 @@ CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64

RM = rm -f

-build := -f $(srctree)/tools/build/Makefile.build dir=. obj
API_IN := $(OUTPUT)libapi-in.o

export srctree OUTPUT CC LD CFLAGS V
+include $(srctree)/tools/build/Makefile.include

all: $(LIBFILE)

diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index e630f9fc4fb6..c66ade68d4a1 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -124,7 +124,7 @@ endif
MAKEOVERRIDES=

export srctree OUTPUT CC LD CFLAGS V
-build := -f $(srctree)/tools/build/Makefile.build dir=. obj
+include $(srctree)/tools/build/Makefile.include

BPF_IN := $(OUTPUT)libbpf-in.o
LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 18ffccf00426..d12081da383b 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -94,7 +94,7 @@ else
endif

export srctree OUTPUT CC LD CFLAGS V
-build := -f $(srctree)/tools/build/Makefile.build dir=. obj
+include $(srctree)/tools/build/Makefile.include

do_compile_shared_library = \
($(print_shared_lib_compile) \
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 6c5c699002cb..6dec86665acc 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -297,7 +297,7 @@ strip: $(PROGRAMS) $(OUTPUT)perf
PERF_IN := $(OUTPUT)perf-in.o

export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
-build := -f $(srctree)/tools/build/Makefile.build dir=. obj
+include $(srctree)/tools/build/Makefile.include

$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE
$(Q)$(MAKE) $(build)=perf

Vinson Lee

unread,
Sep 29, 2015, 2:36:26 AM9/29/15
to H. Peter Anvin, Thomas Gleixner, Namhyung Kim, David Ahern, Jiri Olsa, Ingo Molnar, Peter Zijlstra, raphael....@gmail.com, ma...@codeblueprint.co.uk, Arnaldo Carvalho de Melo, linux-ti...@vger.kernel.org, LKML
On Mon, Sep 21, 2015 at 4:41 PM, Vinson Lee <vl...@twopensource.com> wrote:
> On Wed, Sep 16, 2015 at 12:28 AM, tip-bot for Jiri Olsa
> <tip...@zytor.com> wrote:
>> Commit-ID: 01ca9fd41d6f2ad796a6b109b5253e06b6ae6dc7
>> Gitweb: http://git.kernel.org/tip/01ca9fd41d6f2ad796a6b109b5253e06b6ae6dc7
>> Author: Jiri Olsa <jo...@kernel.org>
>> AuthorDate: Mon, 7 Sep 2015 10:38:03 +0200
>> Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
>> CommitDate: Tue, 15 Sep 2015 09:48:32 -0300
>>
>> tools: Add err.h with ERR_PTR PTR_ERR interface
>>
>> Adding part of the kernel's <linux/err.h> interface:
>>
>> inline void * __must_check ERR_PTR(long error);
>> inline long __must_check PTR_ERR(__force const void *ptr);
>> inline bool __must_check IS_ERR(__force const void *ptr);
>>
>> It will be used to propagate error through pointers in following
>> patches.
>>
>> Signed-off-by: Jiri Olsa <jo...@kernel.org>
>> Reviewed-by: Raphael Beamonte <raphael....@gmail.com>
>> Cc: David Ahern <dsa...@gmail.com>
>> Cc: Matt Fleming <ma...@codeblueprint.co.uk>
>> Cc: Namhyung Kim <namh...@kernel.org>
>> Cc: Peter Zijlstra <a.p.zi...@chello.nl>
>> Link: http://lkml.kernel.org/r/1441615087-13886-2-...@kernel.org
>> Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
>
>
> Hi.
>
> This patch appears to have introduced a build error on CentOS 6.7 with GCC 4.4.
>
> This build error occurs on next-20150921.
>
> CC util/evlist.o
> cc1: warnings being treated as errors
> In file included from util/evlist.c:28:
> tools/include/linux/err.h: In function ‘ERR_PTR’:
> tools/include/linux/err.h:34: error: declaration of ‘error’ shadows a
> global declaration
> util/util.h:135: error: shadowed declaration is here
>
> $ gcc --version
> gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
> Copyright (C) 2010 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions. There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>
> Cheers,
> Vinson

Hi.

This build error still occurs with next-20150929.

Cheers,
Vinson

Jiri Olsa

unread,
Sep 29, 2015, 3:14:28 AM9/29/15
to Vinson Lee, H. Peter Anvin, Thomas Gleixner, Namhyung Kim, David Ahern, Jiri Olsa, Ingo Molnar, Peter Zijlstra, raphael....@gmail.com, ma...@codeblueprint.co.uk, Arnaldo Carvalho de Melo, linux-ti...@vger.kernel.org, LKML
attached patch should fix it

FYI there's another instance of this bug in parse-events.c in
Arnaldo's perf/core due to recent fixes, I'll send out fix shortly

thanks,
jirka


---
The error variable breaks build on CentOS 6.7, due to
collision with global error symbol:

CC util/evlist.o
cc1: warnings being treated as errors
In file included from util/evlist.c:28:
tools/include/linux/err.h: In function ‘ERR_PTR’:
tools/include/linux/err.h:34: error: declaration of ‘error’ shadows a global declaration
util/util.h:135: error: shadowed declaration is here

Using 'err' name instead to fix it.

Reported-by: Vinson Lee <vl...@twopensource.com>
Link: http://lkml.kernel.org/n/tip-i9mdgdbrga...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
tools/include/linux/err.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/err.h b/tools/include/linux/err.h
index c9ada48f5156..1156cd20e0b7 100644
--- a/tools/include/linux/err.h
+++ b/tools/include/linux/err.h
@@ -31,9 +31,9 @@

#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)

-static inline void * __must_check ERR_PTR(long error)
+static inline void * __must_check ERR_PTR(long err)
{
- return (void *) error;
+ return (void *) err;
}

static inline long __must_check PTR_ERR(__force const void *ptr)
--
2.4.3

Jiri Olsa

unread,
Sep 29, 2015, 3:20:48 AM9/29/15
to Vinson Lee, H. Peter Anvin, Thomas Gleixner, Namhyung Kim, David Ahern, Jiri Olsa, Ingo Molnar, Peter Zijlstra, raphael....@gmail.com, ma...@codeblueprint.co.uk, Arnaldo Carvalho de Melo, linux-ti...@vger.kernel.org, LKML, He Kuang
On Tue, Sep 29, 2015 at 09:14:10AM +0200, Jiri Olsa wrote:

SNIP

> > > $ gcc --version
> > > gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
> > > Copyright (C) 2010 Free Software Foundation, Inc.
> > > This is free software; see the source for copying conditions. There is NO
> > > warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> > >
> > > Cheers,
> > > Vinson
> >
> > Hi.
> >
> > This build error still occurs with next-20150929.
>
> attached patch should fix it
>
> FYI there's another instance of this bug in parse-events.c in
> Arnaldo's perf/core due to recent fixes, I'll send out fix shortly

and here it is..

He Kuang,
this might collide with your recent fixes..

jirka


---
The error variable breaks build on CentOS 6.7, due to
collision with global error symbol:

CC util/parse-events.o
cc1: warnings being treated as errors
util/parse-events.c:419: error: declaration of ‘error’ shadows a global
declaration
util/util.h:135: error: shadowed declaration is here
util/parse-events.c: In function ‘add_tracepoint_multi_event’:
...

Using different argument names instead to fix it.

Reported-by: Vinson Lee <vl...@twopensource.com>
Link: http://lkml.kernel.org/n/tip-ujp5f63wvy...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
tools/perf/util/parse-events.c | 38 +++++++++++++++++++-------------------
1 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 61c2bc2..626bf85 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -387,7 +387,7 @@ int parse_events_add_cache(struct list_head *list, int *idx,
return add_event(list, idx, &attr, name, NULL);
}

-static void tracepoint_error(struct parse_events_error *error, int err,
+static void tracepoint_error(struct parse_events_error *e, int err,
char *sys, char *name)
{
char help[BUFSIZ];
@@ -400,29 +400,29 @@ static void tracepoint_error(struct parse_events_error *error, int err,

switch (err) {
case EACCES:
- error->str = strdup("can't access trace events");
+ e->str = strdup("can't access trace events");
break;
case ENOENT:
- error->str = strdup("unknown tracepoint");
+ e->str = strdup("unknown tracepoint");
break;
default:
- error->str = strdup("failed to add tracepoint");
+ e->str = strdup("failed to add tracepoint");
break;
}

tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name);
- error->help = strdup(help);
+ e->help = strdup(help);
}

static int add_tracepoint(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error __maybe_unused)
+ struct parse_events_error *err __maybe_unused)
{
struct perf_evsel *evsel;

evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
if (IS_ERR(evsel)) {
- tracepoint_error(error, PTR_ERR(evsel), sys_name, evt_name);
+ tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name);
return PTR_ERR(evsel);
}

@@ -432,7 +432,7 @@ static int add_tracepoint(struct list_head *list, int *idx,

static int add_tracepoint_multi_event(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error)
+ struct parse_events_error *err)
{
char evt_path[MAXPATHLEN];
struct dirent *evt_ent;
@@ -442,7 +442,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
evt_dir = opendir(evt_path);
if (!evt_dir) {
- tracepoint_error(error, errno, sys_name, evt_name);
+ tracepoint_error(err, errno, sys_name, evt_name);
return -1;
}

@@ -456,7 +456,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
if (!strglobmatch(evt_ent->d_name, evt_name))
continue;

- ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, error);
+ ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, err);
}

closedir(evt_dir);
@@ -465,16 +465,16 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,

static int add_tracepoint_event(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error)
+ struct parse_events_error *err)
{
return strpbrk(evt_name, "*?") ?
- add_tracepoint_multi_event(list, idx, sys_name, evt_name, error) :
- add_tracepoint(list, idx, sys_name, evt_name, error);
+ add_tracepoint_multi_event(list, idx, sys_name, evt_name, err) :
+ add_tracepoint(list, idx, sys_name, evt_name, err);
}

static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error)
+ struct parse_events_error *err)
{
struct dirent *events_ent;
DIR *events_dir;
@@ -482,7 +482,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,

events_dir = opendir(tracing_events_path);
if (!events_dir) {
- tracepoint_error(error, errno, sys_name, evt_name);
+ tracepoint_error(err, errno, sys_name, evt_name);
return -1;
}

@@ -498,7 +498,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
continue;

ret = add_tracepoint_event(list, idx, events_ent->d_name,
- evt_name, error);
+ evt_name, err);
}

closedir(events_dir);
@@ -507,12 +507,12 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,

int parse_events_add_tracepoint(struct list_head *list, int *idx,
char *sys, char *event,
- struct parse_events_error *error)
+ struct parse_events_error *err)
{
if (strpbrk(sys, "*?"))
- return add_tracepoint_multi_sys(list, idx, sys, event, error);
+ return add_tracepoint_multi_sys(list, idx, sys, event, err);
else
- return add_tracepoint_event(list, idx, sys, event, error);
+ return add_tracepoint_event(list, idx, sys, event, err);
}

static int
--
1.7.1

Ingo Molnar

unread,
Sep 29, 2015, 3:47:57 AM9/29/15
to Arnaldo Carvalho de Melo, linux-...@vger.kernel.org, Adrian Hunter, Borislav Petkov, David Ahern, Frederic Weisbecker, He Kuang, Jiri Olsa, Kai Germaschewski, Kan Liang, Matt Fleming, Namhyung Kim, Peter Zijlstra, pi3o...@163.com, Raphael Beamonte, Stephane Eranian, Wang Nan, Arnaldo Carvalho de Melo

* Arnaldo Carvalho de Melo <ac...@kernel.org> wrote:

> Hi Ingo,
>
> Please consider pulling,
>
> - Arnaldo
>
> The following changes since commit 18ab2cd3ee9d52dc64c5ae984146a261a328c4e8:
>
> perf/core, perf/x86: Change needlessly global functions and a variable to static (2015-09-28 08:09:52 +0200)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo
>
> for you to fetch changes up to e637d17757a10732fa5d573c18f20b3cd4d31245:
>
> perf tools: Enable event_config terms to tracepoint events (2015-09-28 17:30:07 -0300)
>
> ----------------------------------------------------------------
> perf/core improvements and fixes:
>
> - Accept a zero --itrace period, meaning "as often as possible". In the case
> of Intel PT that is the same as a period of 1 and a unit of 'instructions'
> (i.e. --itrace=i1i). (Adrian Hunter)
>
> - Harmonise itrace's synthesized callchains with the existing --max-stack
> tool option (Adrian Hunter)
>
> - Allow time to be displayed in nanoseconds in 'perf script' (Adrian Hunter)
>
> - Fix potential loop forever when handling Intel PT timestamps (Adrian Hunter)
>
> - Slighly improve Intel PT debug logging (Adrian Hunter)
>
> - Warn when AUX data has been lost, just like when processing PERF_RECORD_LOST
> (Adrian Hunter)
>
> - Further document export-to-postgresql.py script (Adrian Hunter)
>
> - Add option to synthesize branch stack from auxtrace data (Adrian Hunter)
>
> - Use equivalent logic to avoid using dso->kernel (Arnaldo Carvalho de Melo)
>
> - Show proper error messages when parsing bad terms for hw/sw events (He Kuang)
>
> - Tracepoint event parsing improvements (He Kuang)
>
> - Store tracing mountpoint for better error message (Jiri Olsa)
>
> - Add fixdep to tools/build, bringing it closer to the kernel counterpart, from
> where it is being lifted (Jiri Olsa)
>
> Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
>
> ----------------------------------------------------------------
> Adrian Hunter (24):
> perf auxtrace: Fix 'instructions' period of zero
> perf report: Fix sample type validation for synthesized callchains
> perf intel-pt: Fix potential loop forever
> perf intel-pt: Make logging slightly more efficient
> perf script: Allow time to be displayed in nanoseconds
> perf session: Warn when AUX data has been lost
> perf tools: Add more documentation to export-to-postgresql.py script
> perf auxtrace: Add option to synthesize branch stacks on samples
> perf report: Adjust sample type validation for synthesized branch stacks
> perf report: Also do default setup for synthesized branch stacks
> perf report: Skip events with null branch stacks
> perf inject: Set branch stack feature flag when synthesizing branch stacks
> perf intel-pt: Move branch filter logic
> perf intel-pt: Support generating branch stack
> perf report: Make max_stack value allow for synthesized callchains
> perf hists: Allow for max_stack greater than PERF_MAX_STACK_DEPTH
> perf script: Add a setting for maximum stack depth
> perf scripting python: Allow for max_stack greater than PERF_MAX_STACK_DEPTH
> perf script: Make scripting_max_stack value allow for synthesized callchains
> perf evlist: Add perf_evlist__id2evsel_strict()
> perf evlist: Add perf_evlist__remove()
> perf inject: Remove more aux-related stuff when processing instruction traces
> perf inject: Add --strip option to strip out non-synthesized events
> perf intel-pt: Add mispred-all config option to aid use with autofdo
>
> Arnaldo Carvalho de Melo (3):
> perf top: Filter symbols based on __map__is_kernel(map)
> perf hists browser: Use the map to determine if a DSO is being used as a kernel
> perf tools: Use __map__is_kernel() when synthesizing kernel module mmap records
>
> He Kuang (4):
> perf tools: Adds the config_term callback for different type events
> perf tools: Show proper error message for wrong terms of hw/sw events
> perf tools: Adds the tracepoint name parsing support
> perf tools: Enable event_config terms to tracepoint events
>
> Jiri Olsa (8):
> tools lib api fs: Store tracing mountpoint for better error message
> tools build: Add Makefile.include
> tools build: Add test for missing include
> tools build: Add fixdep dependency helper
> tools build: Move dependency copy into function
> tools build: Make the fixdep helper part of the build process
> perf tools: Rename the 'single_dep' target to 'prepare'
> tools build: Build fixdep helper from perf and basic libs
>
> tools/build/Build | 1 +
> tools/build/Build.include | 17 +-
> tools/build/Documentation/Build.txt | 52 +++--
> tools/build/Makefile | 43 ++++
> tools/build/Makefile.build | 7 +
> tools/build/Makefile.include | 6 +
> tools/build/fixdep.c | 168 ++++++++++++++++
> tools/build/tests/ex/Build | 1 +
> tools/build/tests/ex/Makefile | 13 +-
> tools/build/tests/ex/ex.c | 2 +
> tools/build/tests/ex/inc.c | 8 +
> tools/build/tests/run.sh | 27 +++
> tools/lib/api/Makefile | 6 +-
> tools/lib/api/fs/tracing_path.c | 13 +-
> tools/lib/bpf/Makefile | 6 +-
> tools/lib/lockdep/Makefile | 6 +-
> tools/perf/Documentation/intel-pt.txt | 44 ++++
> tools/perf/Documentation/itrace.txt | 4 +
> tools/perf/Documentation/perf-inject.txt | 3 +
> tools/perf/Documentation/perf-script.txt | 3 +
> tools/perf/Makefile.perf | 32 +--
> tools/perf/builtin-inject.c | 127 +++++++++++-
> tools/perf/builtin-report.c | 31 ++-
> tools/perf/builtin-script.c | 18 +-
> tools/perf/builtin-top.c | 2 +-
> tools/perf/scripts/python/export-to-postgresql.py | 221 +++++++++++++++++++++
> tools/perf/ui/browsers/hists.c | 24 ++-
> tools/perf/util/auxtrace.c | 24 ++-
> tools/perf/util/auxtrace.h | 4 +
> tools/perf/util/event.c | 2 +-
> tools/perf/util/event.h | 1 +
> tools/perf/util/evlist.c | 22 ++
> tools/perf/util/evlist.h | 3 +
> tools/perf/util/hist.c | 6 +-
> tools/perf/util/hist.h | 1 +
> .../perf/util/intel-pt-decoder/intel-pt-decoder.c | 4 +-
> tools/perf/util/intel-pt-decoder/intel-pt-log.c | 21 +-
> tools/perf/util/intel-pt-decoder/intel-pt-log.h | 38 +++-
> tools/perf/util/intel-pt.c | 135 ++++++++++++-
> tools/perf/util/parse-events.c | 151 +++++++++++---
> tools/perf/util/parse-events.h | 4 +-
> tools/perf/util/parse-events.l | 2 +-
> tools/perf/util/parse-events.y | 51 +++--
> tools/perf/util/pmu.c | 37 ++--
> .../util/scripting-engines/trace-event-python.c | 2 +-
> tools/perf/util/session.c | 12 +-
> tools/perf/util/trace-event.h | 2 +
> 47 files changed, 1240 insertions(+), 167 deletions(-)
> create mode 100644 tools/build/Build
> create mode 100644 tools/build/Makefile
> create mode 100644 tools/build/Makefile.include
> create mode 100644 tools/build/fixdep.c
> create mode 100644 tools/build/tests/ex/inc.c

Pulled, thanks a lot Arnaldo!

Ingo

He Kuang

unread,
Sep 29, 2015, 3:54:26 AM9/29/15
to Jiri Olsa, Vinson Lee, H. Peter Anvin, Thomas Gleixner, Namhyung Kim, David Ahern, Jiri Olsa, Ingo Molnar, Peter Zijlstra, raphael....@gmail.com, ma...@codeblueprint.co.uk, Arnaldo Carvalho de Melo, linux-ti...@vger.kernel.org, LKML
hi, jirka

On 2015/9/29 15:20, Jiri Olsa wrote:
> On Tue, Sep 29, 2015 at 09:14:10AM +0200, Jiri Olsa wrote:
>
> SNIP
>
>>>> $ gcc --version
>>>> gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
>>>> Copyright (C) 2010 Free Software Foundation, Inc.
>>>> This is free software; see the source for copying conditions. There is NO
>>>> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>>>>
>>>> Cheers,
>>>> Vinson
>>>
>>> Hi.
>>>
>>> This build error still occurs with next-20150929.
>>
>> attached patch should fix it
>>
>> FYI there's another instance of this bug in parse-events.c in
>> Arnaldo's perf/core due to recent fixes, I'll send out fix shortly
>
> and here it is..
>
> He Kuang,
> this might collide with your recent fixes..
>

Do I need to send new ones based on your patch below now?

Jiri Olsa

unread,
Sep 29, 2015, 3:57:39 AM9/29/15
to He Kuang, Vinson Lee, H. Peter Anvin, Thomas Gleixner, Namhyung Kim, David Ahern, Jiri Olsa, Ingo Molnar, Peter Zijlstra, raphael....@gmail.com, ma...@codeblueprint.co.uk, Arnaldo Carvalho de Melo, linux-ti...@vger.kernel.org, LKML
On Tue, Sep 29, 2015 at 03:52:09PM +0800, He Kuang wrote:
> hi, jirka
>
> On 2015/9/29 15:20, Jiri Olsa wrote:
> >On Tue, Sep 29, 2015 at 09:14:10AM +0200, Jiri Olsa wrote:
> >
> >SNIP
> >
> >>>>$ gcc --version
> >>>>gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
> >>>>Copyright (C) 2010 Free Software Foundation, Inc.
> >>>>This is free software; see the source for copying conditions. There is NO
> >>>>warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> >>>>
> >>>>Cheers,
> >>>>Vinson
> >>>
> >>>Hi.
> >>>
> >>>This build error still occurs with next-20150929.
> >>
> >>attached patch should fix it
> >>
> >>FYI there's another instance of this bug in parse-events.c in
> >>Arnaldo's perf/core due to recent fixes, I'll send out fix shortly
> >
> >and here it is..
> >
> >He Kuang,
> >this might collide with your recent fixes..
> >
>
> Do I need to send new ones based on your patch below now?

that'd be great.. also please make sure you don't reintroduce it

thanks,
jirka

He Kuang

unread,
Sep 29, 2015, 4:21:00 AM9/29/15
to Jiri Olsa, Vinson Lee, H. Peter Anvin, Thomas Gleixner, Namhyung Kim, David Ahern, Jiri Olsa, Ingo Molnar, Peter Zijlstra, raphael....@gmail.com, ma...@codeblueprint.co.uk, Arnaldo Carvalho de Melo, linux-ti...@vger.kernel.org, LKML


On 2015/9/29 15:57, Jiri Olsa wrote:
> On Tue, Sep 29, 2015 at 03:52:09PM +0800, He Kuang wrote:
>> hi, jirka
>>
>> On 2015/9/29 15:20, Jiri Olsa wrote:
>>> On Tue, Sep 29, 2015 at 09:14:10AM +0200, Jiri Olsa wrote:
>>>
>>> SNIP
>>>
>>>>>> $ gcc --version
>>>>>> gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
>>>>>> Copyright (C) 2010 Free Software Foundation, Inc.
>>>>>> This is free software; see the source for copying conditions. There is NO
>>>>>> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>>>>>>
>>>>>> Cheers,
>>>>>> Vinson
>>>>>
>>>>> Hi.
>>>>>
>>>>> This build error still occurs with next-20150929.
>>>>
>>>> attached patch should fix it
>>>>
>>>> FYI there's another instance of this bug in parse-events.c in
>>>> Arnaldo's perf/core due to recent fixes, I'll send out fix shortly
>>>
>>> and here it is..
>>>
>>> He Kuang,
>>> this might collide with your recent fixes..
>>>
>>
>> Do I need to send new ones based on your patch below now?
>
> that'd be great.. also please make sure you don't reintroduce it
>

I saw Ingo just accepted ACME's pull request which contains my patches,
then resend may reintroduce or conflict things, I will wait for ACME's
suggestion for my lack of experience in this.

Thank you.

tip-bot for Arnaldo Carvalho de Melo

unread,
Sep 29, 2015, 4:38:23 AM9/29/15
to linux-ti...@vger.kernel.org, era...@google.com, linux-...@vger.kernel.org, b...@suse.de, h...@zytor.com, tg...@linutronix.de, mi...@kernel.org, adrian...@intel.com, fwei...@gmail.com, dsa...@gmail.com, ac...@redhat.com, jo...@redhat.com, wang...@huawei.com, namh...@kernel.org
Commit-ID: cfc5acd4c80b875d2f739d6a93562034aee5563f
Gitweb: http://git.kernel.org/tip/cfc5acd4c80b875d2f739d6a93562034aee5563f
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Wed, 23 Sep 2015 15:15:54 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Mon, 28 Sep 2015 15:50:53 -0300

perf top: Filter symbols based on __map__is_kernel(map)

Instead of using dso->kernel, this is equivalent at the moment,
and helps in reducing the accesses to dso->kernel.

Cc: Adrian Hunter <adrian...@intel.com>
Cc: Borislav Petkov <b...@suse.de>
Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Namhyung Kim <namh...@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/builtin-top.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index bdaf44f..38d4d6c 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -655,7 +655,7 @@ static int symbol_filter(struct map *map, struct symbol *sym)
{
const char *name = sym->name;

- if (!map->dso->kernel)
+ if (!__map__is_kernel(map))
return 0;
/*
* ppc64 uses function descriptors and appends a '.' to the

tip-bot for Arnaldo Carvalho de Melo

unread,
Sep 29, 2015, 4:39:48 AM9/29/15
to linux-ti...@vger.kernel.org, namh...@kernel.org, jo...@redhat.com, h...@zytor.com, linux-...@vger.kernel.org, era...@google.com, b...@suse.de, fwei...@gmail.com, mi...@kernel.org, adrian...@intel.com, ac...@redhat.com, tg...@linutronix.de, wang...@huawei.com, dsa...@gmail.com
Commit-ID: ab9c2bdc8947482057b81258c0128952763661cb
Gitweb: http://git.kernel.org/tip/ab9c2bdc8947482057b81258c0128952763661cb
Author: Arnaldo Carvalho de Melo <ac...@redhat.com>
AuthorDate: Wed, 23 Sep 2015 15:45:20 -0300
Committer: Arnaldo Carvalho de Melo <ac...@redhat.com>
CommitDate: Mon, 28 Sep 2015 15:50:54 -0300

perf tools: Use __map__is_kernel() when synthesizing kernel module mmap records

Equivalent and removes one more case of using dso->kernel.

# perf record -a usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.768 MB perf.data (30 samples) ]

Before:

[root@zoo ~]# perf script --show-task --show-mmap | head -3
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffff81000000(0x1f000000) @ 0xffffffff81000000]: x [kernel.kallsyms]_text
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffffa0000000(0xa000) @ 0]: x /lib/modules/4.3.0-rc1+/kernel/drivers/acpi/video.ko
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffffa000a000(0x5000) @ 0]: x /lib/modules/4.3.0-rc1+/kernel/drivers/i2c/algos/i2c-algo-bit.ko
#

# perf script --show-task --show-mmap | head -3
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffff81000000(0x1f000000) @ 0xffffffff81000000]: x [kernel.kallsyms]_text
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffffa0000000(0xa000) @ 0]: x /lib/modules/4.3.0-rc1+/kernel/drivers/acpi/video.ko
swapper 0 [0] 0.0: PERF_RECORD_MMAP -1/0: [0xffffffffa000a000(0x5000) @ 0]: x /lib/modules/4.3.0-rc1+/kernel/drivers/i2c/algos/i2c-algo-bit.ko
#

Cc: Adrian Hunter <adrian...@intel.com>
Cc: Borislav Petkov <b...@suse.de>
Cc: David Ahern <dsa...@gmail.com>
Cc: Frederic Weisbecker <fwei...@gmail.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Stephane Eranian <era...@google.com>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/n/tip-b65xe578dw...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/event.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 6214ad4..b1bb348 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -378,7 +378,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
for (pos = maps__first(maps); pos; pos = map__next(pos)) {
size_t size;

- if (pos->dso->kernel)
+ if (__map__is_kernel(pos))
continue;

size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));

Jiri Olsa

unread,
Sep 29, 2015, 6:42:08 AM9/29/15
to He Kuang, Vinson Lee, H. Peter Anvin, Thomas Gleixner, Namhyung Kim, David Ahern, Jiri Olsa, Ingo Molnar, Peter Zijlstra, raphael....@gmail.com, ma...@codeblueprint.co.uk, Arnaldo Carvalho de Melo, linux-ti...@vger.kernel.org, LKML
hum, I can see your changes in pull request to Ingo,
but not in acme's perf/core.. strange.. let's wait
for Arnaldo to sort it out ;-)

Arnaldo Carvalho de Melo

unread,
Sep 29, 2015, 10:53:23 AM9/29/15
to Jiri Olsa, He Kuang, Vinson Lee, H. Peter Anvin, Thomas Gleixner, Namhyung Kim, David Ahern, Jiri Olsa, Ingo Molnar, Peter Zijlstra, raphael....@gmail.com, ma...@codeblueprint.co.uk, linux-ti...@vger.kernel.org, LKML
Sorry, probably I didn't push perf/core yesterday, just the
perf-core-for-mingo tag.

Anyway, please pull again, should have everything in there now plus some
patches I processed today.

- Arnaldo

Jiri Olsa

unread,
Sep 29, 2015, 11:05:52 AM9/29/15
to Arnaldo Carvalho de Melo, He Kuang, Vinson Lee, H. Peter Anvin, Thomas Gleixner, Namhyung Kim, David Ahern, Jiri Olsa, Ingo Molnar, Peter Zijlstra, raphael....@gmail.com, ma...@codeblueprint.co.uk, linux-ti...@vger.kernel.org, LKML
On Tue, Sep 29, 2015 at 11:52:59AM -0300, Arnaldo Carvalho de Melo wrote:

SNIP

> > > >>>
> > > >>
> > > >>Do I need to send new ones based on your patch below now?
> > > >
> > > >that'd be great.. also please make sure you don't reintroduce it
> > > >
> > >
> > > I saw Ingo just accepted ACME's pull request which contains my patches,
> > > then resend may reintroduce or conflict things, I will wait for ACME's
> > > suggestion for my lack of experience in this.
> >
> > hum, I can see your changes in pull request to Ingo,
> > but not in acme's perf/core.. strange.. let's wait
> > for Arnaldo to sort it out ;-)
>
> Sorry, probably I didn't push perf/core yesterday, just the
> perf-core-for-mingo tag.
>
> Anyway, please pull again, should have everything in there now plus some
> patches I processed today.

np, resending the patch rebase on your latest perf/core

thanks,
jirka


---
The error variable breaks build on CentOS 6.7, due to
collision with global error symbol:

CC util/parse-events.o
cc1: warnings being treated as errors
util/parse-events.c:419: error: declaration of ‘error’ shadows a global
declaration
util/util.h:135: error: shadowed declaration is here
util/parse-events.c: In function ‘add_tracepoint_multi_event’:
...

Using different argument names instead to fix it.

Reported-by: Vinson Lee <vl...@twopensource.com>
Link: http://lkml.kernel.org/n/tip-i9mdgdbrga...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
tools/perf/util/parse-events.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5ffb356cbcc6..c01a44b18faf 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -389,7 +389,7 @@ int parse_events_add_cache(struct list_head *list, int *idx,
return add_event(list, idx, &attr, name, NULL);
}

-static void tracepoint_error(struct parse_events_error *error, int err,
+static void tracepoint_error(struct parse_events_error *e, int err,
char *sys, char *name)
{
char help[BUFSIZ];
@@ -402,30 +402,30 @@ static void tracepoint_error(struct parse_events_error *error, int err,

switch (err) {
case EACCES:
- error->str = strdup("can't access trace events");
+ e->str = strdup("can't access trace events");
break;
case ENOENT:
- error->str = strdup("unknown tracepoint");
+ e->str = strdup("unknown tracepoint");
break;
default:
- error->str = strdup("failed to add tracepoint");
+ e->str = strdup("failed to add tracepoint");
break;
}

tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name);
- error->help = strdup(help);
+ e->help = strdup(help);
}

static int add_tracepoint(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error __maybe_unused,
+ struct parse_events_error *err,
struct list_head *head_config)
{
struct perf_evsel *evsel;

evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
if (IS_ERR(evsel)) {
- tracepoint_error(error, PTR_ERR(evsel), sys_name, evt_name);
+ tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name);
return PTR_ERR(evsel);
}

@@ -443,7 +443,7 @@ static int add_tracepoint(struct list_head *list, int *idx,

static int add_tracepoint_multi_event(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error,
+ struct parse_events_error *err,
struct list_head *head_config)
{
char evt_path[MAXPATHLEN];
@@ -454,7 +454,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
evt_dir = opendir(evt_path);
if (!evt_dir) {
- tracepoint_error(error, errno, sys_name, evt_name);
+ tracepoint_error(err, errno, sys_name, evt_name);
return -1;
}

@@ -469,7 +469,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
continue;

ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name,
- error, head_config);
+ err, head_config);
}

closedir(evt_dir);
@@ -478,19 +478,19 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,

static int add_tracepoint_event(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error,
+ struct parse_events_error *err,
struct list_head *head_config)
{
return strpbrk(evt_name, "*?") ?
add_tracepoint_multi_event(list, idx, sys_name, evt_name,
- error, head_config) :
+ err, head_config) :
add_tracepoint(list, idx, sys_name, evt_name,
- error, head_config);
+ err, head_config);
}

static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
char *sys_name, char *evt_name,
- struct parse_events_error *error,
+ struct parse_events_error *err,
struct list_head *head_config)
{
struct dirent *events_ent;
@@ -499,7 +499,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,

events_dir = opendir(tracing_events_path);
if (!events_dir) {
- tracepoint_error(error, errno, sys_name, evt_name);
+ tracepoint_error(err, errno, sys_name, evt_name);
return -1;
}

@@ -515,7 +515,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
continue;

ret = add_tracepoint_event(list, idx, events_ent->d_name,
- evt_name, error, head_config);
+ evt_name, err, head_config);
}

closedir(events_dir);
--
2.4.3

Arnaldo Carvalho de Melo

unread,
Sep 30, 2015, 5:56:06 PM9/30/15
to Ingo Molnar, linux-...@vger.kernel.org, Arnaldo Carvalho de Melo, Adrian Hunter, Borislav Petkov, Chandler Carruth, David Ahern, Dominik Dingel, Frederic Weisbecker, He Kuang, H . Peter Anvin, Jiri Olsa, linuxp...@ozlabs.org, linux-ti...@vger.kernel.org, Masami Hiramatsu, Matt Fleming, Namhyung Kim, Naveen N . Rao, Peter Zijlstra, Raphael Beamonte, Stephane Eranian, Sukadev Bhattiprolu, Thomas Gleixner, Vinson Lee, Wang Nan, Arnaldo Carvalho de Melo
Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit 9c17dbc6eb73bdd8a6aaea1baefd37ff78d86148:

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2015-09-29 09:43:46 +0200)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo

for you to fetch changes up to 7f8d1ade1b19f684ed3a7c4fb1dc5d347127b438:

perf tools: By default use the most precise "cycles" hw counter available (2015-09-30 18:34:39 -0300)

----------------------------------------------------------------
perf/core improvements and fixes:

User visible:

- By default use the most precise "cycles" hw counter available, i.e.
when the user doesn't specify any event, it will try using cycles:ppp,
cycles:pp, etc (Arnaldo Carvalho de Melo)

- Remove blank lines, headers when piping output in 'perf list', so that it can
be sanely used with 'wc -l', etc (Arnaldo Carvalho de Melo)

- Amend documentation about max_stack and synthesized callchains (Adrian Hunter)

- Fix 'perf probe -l' for probes added to kernel module functions (Masami Hiramatsu)

Build fixes:

- Fix shadowed declarations that break the build on older distros (Jiri Olsa)

- Fix build break on powerpc due to sample_reg_masks (Sukadev Bhattiprolu)

Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>

----------------------------------------------------------------
Adrian Hunter (1):
perf report: Amend documentation about max_stack and synthesized callchains

Arnaldo Carvalho de Melo (7):
perf maps: Introduce maps__find_symbol_by_name()
perf machine: Use machine__kernel_map() thoroughly
perf machine: Add method for common kernel_map(FUNCTION) operation
tools lib symbol: Rename kallsyms2elf_type to kallsyms2elf_binding
tools lib symbol: Introduce kallsyms2elf_type
perf list: Remove blank lines, headers when piping output
perf tools: By default use the most precise "cycles" hw counter available

Jiri Olsa (2):
tools: Fix shadowed declaration in err.h
perf tools: Fix shadowed declaration in parse-events.c

Masami Hiramatsu (5):
perf probe: Fix to remove dot suffix from second or latter events
perf probe: Begin and end libdwfl report session correctly
perf probe: Show correct source lines of probes on kmodules
perf probe: Fix a segfault bug in debuginfo_cache
perf probe: Improve error message when %return is on inlined function

Sukadev Bhattiprolu (1):
perf tools: Fix build break on powerpc due to sample_reg_masks

tools/include/linux/err.h | 4 +-
tools/lib/symbol/kallsyms.c | 6 ++
tools/lib/symbol/kallsyms.h | 4 +-
tools/perf/Documentation/perf-report.txt | 2 +
tools/perf/builtin-kmem.c | 2 +-
tools/perf/builtin-list.c | 2 +-
tools/perf/builtin-report.c | 2 +-
tools/perf/tests/code-reading.c | 2 +-
tools/perf/tests/vmlinux-kallsyms.c | 4 +-
tools/perf/util/Build | 2 +-
tools/perf/util/event.c | 7 +--
tools/perf/util/evlist.c | 22 +++++++-
tools/perf/util/intel-pt.c | 2 +-
tools/perf/util/machine.c | 26 ++++-----
tools/perf/util/machine.h | 8 ++-
tools/perf/util/map.c | 21 ++++---
tools/perf/util/map.h | 2 +
tools/perf/util/parse-events.c | 53 +++++++++---------
tools/perf/util/perf_regs.c | 2 +
tools/perf/util/perf_regs.h | 1 +
tools/perf/util/pmu.c | 2 +-
tools/perf/util/probe-event.c | 96 ++++++++++++++++++++------------
tools/perf/util/probe-finder.c | 58 +++++++++++++++++--
tools/perf/util/symbol.c | 2 +-
24 files changed, 224 insertions(+), 108 deletions(-)

Arnaldo Carvalho de Melo

unread,
Sep 30, 2015, 5:56:32 PM9/30/15
to Ingo Molnar, linux-...@vger.kernel.org, Sukadev Bhattiprolu, Dominik Dingel, Naveen N. Rao, Stephane Eranian, linuxp...@ozlabs.org, Arnaldo Carvalho de Melo
From: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>

The perf_regs.c file does not get built on Powerpc as CONFIG_PERF_REGS
is false. So the weak definition for 'sample_regs_masks' doesn't get
picked up.

Adding perf_regs.o to util/Build unconditionally, exposes a redefinition
error for 'perf_reg_value()' function (due to the static inline version
in util/perf_regs.h). So use #ifdef HAVE_PERF_REGS_SUPPORT' around that
function.

Signed-off-by: Sukadev Bhattiprolu <suk...@linux.vnet.ibm.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Dominik Dingel <din...@linux.vnet.ibm.com>
Cc: Naveen N. Rao <naveen...@linux.vnet.ibm.com>
Cc: Stephane Eranian <era...@google.com>
Cc: linuxp...@ozlabs.org
Link: http://lkml.kernel.org/r/20150930182...@us.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/Build | 2 +-
tools/perf/util/perf_regs.c | 2 ++
tools/perf/util/perf_regs.h | 1 +
3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 4bc7a9ab45b1..9217119c4108 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -18,6 +18,7 @@ libperf-y += levenshtein.o
libperf-y += llvm-utils.o
libperf-y += parse-options.o
libperf-y += parse-events.o
+libperf-y += perf_regs.o
libperf-y += path.o
libperf-y += rbtree.o
libperf-y += bitmap.o
@@ -104,7 +105,6 @@ libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o

libperf-y += scripting-engines/

-libperf-$(CONFIG_PERF_REGS) += perf_regs.o
libperf-$(CONFIG_ZLIB) += zlib.o
libperf-$(CONFIG_LZMA) += lzma.o

diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index 885e8ac83997..6b8eb13e14e4 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -6,6 +6,7 @@ const struct sample_reg __weak sample_reg_masks[] = {
SMPL_REG_END
};

+#ifdef HAVE_PERF_REGS_SUPPORT
int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
{
int i, idx = 0;
@@ -29,3 +30,4 @@ out:
*valp = regs->cache_regs[id];
return 0;
}
+#endif
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 2984dcc54d67..679d6e493962 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -2,6 +2,7 @@
#define __PERF_REGS_H

#include <linux/types.h>
+#include <linux/compiler.h>

struct regs_dump;

--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 30, 2015, 5:56:46 PM9/30/15
to Ingo Molnar, linux-...@vger.kernel.org, Masami Hiramatsu, Jiri Olsa, Namhyung Kim, Wang Nan, Arnaldo Carvalho de Melo
From: Masami Hiramatsu <masami.hi...@hitachi.com>

Perf probe always failed to find appropriate line numbers because of
failing to find .text start address offset from debuginfo.

e.g.
----
# ./perf probe -m pcspkr pcspkr_event:5
Added new events:
probe:pcspkr_event (on pcspkr_event:5 in pcspkr)
probe:pcspkr_event_1 (on pcspkr_event:5 in pcspkr)

You can now use it in all perf tools, such as:

perf record -e probe:pcspkr_event_1 -aR sleep 1

# ./perf probe -l
Failed to find debug information for address ffffffffa031f006
Failed to find debug information for address ffffffffa031f016
probe:pcspkr_event (on pcspkr_event+6 in pcspkr)
probe:pcspkr_event_1 (on pcspkr_event+22 in pcspkr)
----

This fixes the above issue as below.
1. Get the relative address of the symbol in .text by using
map->start.
2. Adjust the address by adding the offset of .text section
in the kernel module binary.

With this fix, perf probe -l shows lines correctly.
----
# ./perf probe -l
probe:pcspkr_event (on pcspkr_event:5@drivers/input/misc/pcspkr.c in pcspkr)
probe:pcspkr_event_1 (on pcspkr_event:5@drivers/input/misc/pcspkr.c in pcspkr)
----

Reported-by: Arnaldo Carvalho de Melo <ac...@kernel.org>
Signed-off-by: Masami Hiramatsu <masami.hi...@hitachi.com>
Tested-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Wang Nan <wang...@huawei.com>
Link: http://lkml.kernel.org/r/20150930164132....@localhost.localdomain
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/probe-event.c | 35 +++++++++++++++++++++++------------
tools/perf/util/probe-finder.c | 42 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 5d68f68797a9..65be284823d5 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -137,7 +137,8 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
return kmap->ref_reloc_sym;
}

-static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
+static int kernel_get_symbol_address_by_name(const char *name, u64 *addr,
+ bool reloc, bool reladdr)
{
struct ref_reloc_sym *reloc_sym;
struct symbol *sym;
@@ -146,12 +147,14 @@ static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
/* ref_reloc_sym is just a label. Need a special fix*/
reloc_sym = kernel_get_ref_reloc_sym();
if (reloc_sym && strcmp(name, reloc_sym->name) == 0)
- return (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
+ *addr = (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
else {
sym = __find_kernel_function_by_name(name, &map);
- if (sym)
- return map->unmap_ip(map, sym->start) -
- ((reloc) ? 0 : map->reloc);
+ if (!sym)
+ return -ENOENT;
+ *addr = map->unmap_ip(map, sym->start) -
+ ((reloc) ? 0 : map->reloc) -
+ ((reladdr) ? map->start : 0);
}
return 0;
}
@@ -245,12 +248,14 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
static bool kprobe_blacklist__listed(unsigned long address);
static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
{
- u64 etext_addr;
+ u64 etext_addr = 0;
+ int ret;

/* Get the address of _etext for checking non-probable text symbol */
- etext_addr = kernel_get_symbol_address_by_name("_etext", false);
+ ret = kernel_get_symbol_address_by_name("_etext", &etext_addr,
+ false, false);

- if (etext_addr != 0 && etext_addr < address)
+ if (ret == 0 && etext_addr < address)
pr_warning("%s is out of .text, skip it.\n", symbol);
else if (kprobe_blacklist__listed(address))
pr_warning("%s is blacklisted function, skip it.\n", symbol);
@@ -517,8 +522,10 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
goto error;
addr += stext;
} else if (tp->symbol) {
- addr = kernel_get_symbol_address_by_name(tp->symbol, false);
- if (addr == 0)
+ /* If the module is given, this returns relative address */
+ ret = kernel_get_symbol_address_by_name(tp->symbol, &addr,
+ false, !!tp->module);
+ if (ret != 0)
goto error;
addr += tp->offset;
}
@@ -1884,8 +1891,12 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
goto out;
sym = map__find_symbol(map, addr, NULL);
} else {
- if (tp->symbol)
- addr = kernel_get_symbol_address_by_name(tp->symbol, true);
+ if (tp->symbol && !addr) {
+ ret = kernel_get_symbol_address_by_name(tp->symbol,
+ &addr, true, false);
+ if (ret < 0)
+ goto out;
+ }
if (addr) {
addr += tp->offset;
sym = __find_kernel_function(addr, &map);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 35f905f4f34c..f0708ffd5e07 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1402,6 +1402,41 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg,
return (ret < 0) ? ret : af.nvls;
}

+/* For the kernel module, we need a special code to get a DIE */
+static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs)
+{
+ int n, i;
+ Elf32_Word shndx;
+ Elf_Scn *scn;
+ Elf *elf;
+ GElf_Shdr mem, *shdr;
+ const char *p;
+
+ elf = dwfl_module_getelf(dbg->mod, &dbg->bias);
+ if (!elf)
+ return -EINVAL;
+
+ /* Get the number of relocations */
+ n = dwfl_module_relocations(dbg->mod);
+ if (n < 0)
+ return -ENOENT;
+ /* Search the relocation related .text section */
+ for (i = 0; i < n; i++) {
+ p = dwfl_module_relocation_info(dbg->mod, i, &shndx);
+ if (strcmp(p, ".text") == 0) {
+ /* OK, get the section header */
+ scn = elf_getscn(elf, shndx);
+ if (!scn)
+ return -ENOENT;
+ shdr = gelf_getshdr(scn, &mem);
+ if (!shdr)
+ return -ENOENT;
+ *offs = shdr->sh_addr;
+ }
+ }
+ return 0;
+}
+
/* Reverse search */
int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
struct perf_probe_point *ppt)
@@ -1410,9 +1445,16 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
Dwarf_Addr _addr = 0, baseaddr = 0;
const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
int baseline = 0, lineno = 0, ret = 0;
+ bool reloc = false;

+retry:
/* Find cu die */
if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
+ if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) {
+ addr += baseaddr;
+ reloc = true;
+ goto retry;
+ }
pr_warning("Failed to find debug information for address %lx\n",
addr);
ret = -EINVAL;
--
2.1.0

Arnaldo Carvalho de Melo

unread,
Sep 30, 2015, 5:57:10 PM9/30/15
to Ingo Molnar, linux-...@vger.kernel.org, Jiri Olsa, Jiri Olsa, David Ahern, He Kuang, H. Peter Anvin, linux-ti...@vger.kernel.org, Matt Fleming, Namhyung Kim, Peter Zijlstra, Raphael Beamonte, Thomas Gleixner, Arnaldo Carvalho de Melo
From: Jiri Olsa <jo...@redhat.com>

The error variable breaks build on CentOS 6.7, due to a collision with a
global error symbol:

CC util/parse-events.o
cc1: warnings being treated as errors
util/parse-events.c:419: error: declaration of ‘error’ shadows a global
declaration
util/util.h:135: error: shadowed declaration is here
util/parse-events.c: In function ‘add_tracepoint_multi_event’:
...

Using different argument names instead to fix it.

Reported-by: Vinson Lee <vl...@twopensource.com>
Signed-off-by: Jiri Olsa <jo...@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
Cc: David Ahern <dsa...@gmail.com>
Cc: He Kuang <hek...@huawei.com>
Cc: H. Peter Anvin <h...@zytor.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: linux-ti...@vger.kernel.org
Cc: Matt Fleming <ma...@codeblueprint.co.uk>
Cc: Namhyung Kim <namh...@kernel.org>
Cc: Peter Zijlstra <a.p.zi...@chello.nl>
Cc: Raphael Beamonte <raphael....@gmail.com>
Cc: Thomas Gleixner <tg...@linutronix.de>
Link: http://lkml.kernel.org/r/20150929150...@krava.redhat.com
[ Fix one more case, at line 770 ]
Signed-off-by: Arnaldo Carvalho de Melo <ac...@redhat.com>
---
tools/perf/util/parse-events.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5ffb356cbcc6..c1c64fb647aa 100644
@@ -767,23 +767,23 @@ do { \

int parse_events_add_tracepoint(struct list_head *list, int *idx,
char *sys, char *event,
- struct parse_events_error *error,
+ struct parse_events_error *err,
struct list_head *head_config)
{
if (head_config) {
struct perf_event_attr attr;

- if (config_attr(&attr, head_config, error,
+ if (config_attr(&attr, head_config, err,
config_term_tracepoint))
return -EINVAL;
}

if (strpbrk(sys, "*?"))
return add_tracepoint_multi_sys(list, idx, sys, event,
- error, head_config);
+ err, head_config);
else
return add_tracepoint_event(list, idx, sys, event,
- error, head_config);
+ err, head_config);
}

int parse_events_add_numeric(struct parse_events_evlist *data,
--
2.1.0
It is loading more messages.
0 new messages