[tip:perf/core] perf tools: Fix compile error with libunwind x86

2018-01-10 Thread tip-bot for Wang Nan
Commit-ID:  44df1afdb174fd6038e419f80efd914c0b5f2f85
Gitweb: https://git.kernel.org/tip/44df1afdb174fd6038e419f80efd914c0b5f2f85
Author: Wang Nan 
AuthorDate: Wed, 6 Dec 2017 01:50:40 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 8 Jan 2018 11:11:57 -0300

perf tools: Fix compile error with libunwind x86

Fix a compile error:

 ...
   CC   util/libunwind/x86_32.o
 In file included from util/libunwind/x86_32.c:33:0:
 util/libunwind/../../arch/x86/util/unwind-libunwind.c: In function 
'libunwind__x86_reg_id':
 util/libunwind/../../arch/x86/util/unwind-libunwind.c:110:11: error: 'EINVAL' 
undeclared (first use in this function)
return -EINVAL;
^
 util/libunwind/../../arch/x86/util/unwind-libunwind.c:110:11: note: each 
undeclared identifier is reported only once for each function it appears in
 mv: cannot stat 'util/libunwind/.x86_32.o.tmp': No such file or directory
 make[4]: *** [util/libunwind/x86_32.o] Error 1
 make[3]: *** [util] Error 2
 make[2]: *** [libperf-in.o] Error 2
 make[1]: *** [sub-make] Error 2
 make: *** [all] Error 2

It happens when libunwind-x86 feature is detected.

Signed-off-by: Wang Nan 
Link: http://lkml.kernel.org/r/20171206015040.114574-1-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/arch/x86/util/unwind-libunwind.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c 
b/tools/perf/arch/x86/util/unwind-libunwind.c
index 9c917f8..05920e3 100644
--- a/tools/perf/arch/x86/util/unwind-libunwind.c
+++ b/tools/perf/arch/x86/util/unwind-libunwind.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
-#ifndef REMOTE_UNWIND_LIBUNWIND
 #include 
+#ifndef REMOTE_UNWIND_LIBUNWIND
 #include 
 #include "perf_regs.h"
 #include "../../util/unwind.h"


[RESEND PATCH] perf tools: Fix compiling error in libunwind x86

2017-12-17 Thread Wang Nan
Fix a compiling error:

 ...
   CC   util/libunwind/x86_32.o
 In file included from util/libunwind/x86_32.c:33:0:
 util/libunwind/../../arch/x86/util/unwind-libunwind.c: In function 
'libunwind__x86_reg_id':
 util/libunwind/../../arch/x86/util/unwind-libunwind.c:110:11: error: 'EINVAL' 
undeclared (first use in this function)
return -EINVAL;
^
 util/libunwind/../../arch/x86/util/unwind-libunwind.c:110:11: note: each 
undeclared identifier is reported only once for each function it appears in
 mv: cannot stat 'util/libunwind/.x86_32.o.tmp': No such file or directory
 make[4]: *** [util/libunwind/x86_32.o] Error 1
 make[3]: *** [util] Error 2
 make[2]: *** [libperf-in.o] Error 2
 make[1]: *** [sub-make] Error 2
 make: *** [all] Error 2

It happens when libunwind-x86 feature is detected.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Jiri Olsa 
---
 tools/perf/arch/x86/util/unwind-libunwind.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c 
b/tools/perf/arch/x86/util/unwind-libunwind.c
index 9c917f8..05920e3 100644
--- a/tools/perf/arch/x86/util/unwind-libunwind.c
+++ b/tools/perf/arch/x86/util/unwind-libunwind.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
-#ifndef REMOTE_UNWIND_LIBUNWIND
 #include 
+#ifndef REMOTE_UNWIND_LIBUNWIND
 #include 
 #include "perf_regs.h"
 #include "../../util/unwind.h"
-- 
2.10.1



[tip:perf/core] perf mmap: Don't discard prev in backward mode

2017-12-06 Thread tip-bot for Wang Nan
Commit-ID:  7fb4b407a1242dbc85ea3ed1be065dca8f9a6f5b
Gitweb: https://git.kernel.org/tip/7fb4b407a1242dbc85ea3ed1be065dca8f9a6f5b
Author: Wang Nan 
AuthorDate: Mon, 4 Dec 2017 16:51:06 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 5 Dec 2017 15:59:37 -0300

perf mmap: Don't discard prev in backward mode

'perf record' can switch its output data file. The new output should
only store the data after switching. However, in overwrite backward
mode, the new output still can have data from before switching. That
also brings extra overhead.

At the end of mmap_read(), the position of the processed ring buffer is
saved in md->prev. Next mmap_read should be end in md->prev if it is not
overwriten. That avoids processing duplicate data.  However, md->prev is
discarded. So next the mmap_read() has to process whole valid ring
buffer, which probably includes old processed data.

Avoid calling backward_rb_find_range() when md->prev is still
available.

Signed-off-by: Wang Nan 
Tested-by: Kan Liang 
Acked-by: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Mengting Zhang 
Link: http://lkml.kernel.org/r/20171204165107.95327-3-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/mmap.c | 33 +++--
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 3f262e7..5f8cb15 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -267,18 +267,6 @@ static int backward_rb_find_range(void *buf, int mask, u64 
head, u64 *start, u64
return -1;
 }
 
-static int rb_find_range(void *data, int mask, u64 head, u64 old,
-u64 *start, u64 *end, bool backward)
-{
-   if (!backward) {
-   *start = old;
-   *end = head;
-   return 0;
-   }
-
-   return backward_rb_find_range(data, mask, head, start, end);
-}
-
 int perf_mmap__push(struct perf_mmap *md, bool backward,
void *to, int push(void *to, void *buf, size_t size))
 {
@@ -290,19 +278,28 @@ int perf_mmap__push(struct perf_mmap *md, bool backward,
void *buf;
int rc = 0;
 
-   if (rb_find_range(data, md->mask, head, old, &start, &end, backward))
-   return -1;
+   start = backward ? head : old;
+   end = backward ? old : head;
 
if (start == end)
return 0;
 
size = end - start;
if (size > (unsigned long)(md->mask) + 1) {
-   WARN_ONCE(1, "failed to keep up with mmap data. (warn only 
once)\n");
+   if (!backward) {
+   WARN_ONCE(1, "failed to keep up with mmap data. (warn 
only once)\n");
 
-   md->prev = head;
-   perf_mmap__consume(md, backward);
-   return 0;
+   md->prev = head;
+   perf_mmap__consume(md, backward);
+   return 0;
+   }
+
+   /*
+* Backward ring buffer is full. We still have a chance to read
+* most of data from it.
+*/
+   if (backward_rb_find_range(data, md->mask, head, &start, &end))
+   return -1;
}
 
if ((start & md->mask) + size != (end & md->mask)) {


[tip:perf/core] perf tools: Rename 'backward' to 'overwrite' in evlist, mmap and record

2017-12-06 Thread tip-bot for Wang Nan
Commit-ID:  0b72d69a542873ee098867deeb37d27ad4629c64
Gitweb: https://git.kernel.org/tip/0b72d69a542873ee098867deeb37d27ad4629c64
Author: Wang Nan 
AuthorDate: Mon, 4 Dec 2017 16:51:07 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 5 Dec 2017 16:02:39 -0300

perf tools: Rename 'backward' to 'overwrite' in evlist, mmap and record

Remove the backward/forward concept to make it uniform with user
interface (the '--overwrite' option).

Signed-off-by: Wang Nan 
Acked-by: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Kan Liang 
Cc: Mengting Zhang 
Link: http://lkml.kernel.org/r/20171204165107.95327-4-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/builtin-record.c | 14 +++---
 tools/perf/tests/backward-ring-buffer.c |  4 ++--
 tools/perf/util/evlist.c| 30 +++---
 tools/perf/util/evlist.h|  2 +-
 tools/perf/util/mmap.c  | 22 +++---
 5 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 26b8571..0a5749e 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -479,7 +479,7 @@ static struct perf_event_header finished_round_event = {
 };
 
 static int record__mmap_read_evlist(struct record *rec, struct perf_evlist 
*evlist,
-   bool backward)
+   bool overwrite)
 {
u64 bytes_written = rec->bytes_written;
int i;
@@ -489,18 +489,18 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
if (!evlist)
return 0;
 
-   maps = backward ? evlist->backward_mmap : evlist->mmap;
+   maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
if (!maps)
return 0;
 
-   if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
+   if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
return 0;
 
for (i = 0; i < evlist->nr_mmaps; i++) {
struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
 
if (maps[i].base) {
-   if (perf_mmap__push(&maps[i], backward, rec, 
record__pushfn) != 0) {
+   if (perf_mmap__push(&maps[i], overwrite, rec, 
record__pushfn) != 0) {
rc = -1;
goto out;
}
@@ -520,7 +520,7 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
if (bytes_written != rec->bytes_written)
rc = record__write(rec, &finished_round_event, 
sizeof(finished_round_event));
 
-   if (backward)
+   if (overwrite)
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
 out:
return rc;
@@ -692,8 +692,8 @@ perf_evlist__pick_pc(struct perf_evlist *evlist)
if (evlist) {
if (evlist->mmap && evlist->mmap[0].base)
return evlist->mmap[0].base;
-   if (evlist->backward_mmap && evlist->backward_mmap[0].base)
-   return evlist->backward_mmap[0].base;
+   if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base)
+   return evlist->overwrite_mmap[0].base;
}
return NULL;
 }
diff --git a/tools/perf/tests/backward-ring-buffer.c 
b/tools/perf/tests/backward-ring-buffer.c
index cf37e43..4035d43 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -33,8 +33,8 @@ static int count_samples(struct perf_evlist *evlist, int 
*sample_count,
for (i = 0; i < evlist->nr_mmaps; i++) {
union perf_event *event;
 
-   perf_mmap__read_catchup(&evlist->backward_mmap[i]);
-   while ((event = 
perf_mmap__read_backward(&evlist->backward_mmap[i])) != NULL) {
+   perf_mmap__read_catchup(&evlist->overwrite_mmap[i]);
+   while ((event = 
perf_mmap__read_backward(&evlist->overwrite_mmap[i])) != NULL) {
const u32 type = event->header.type;
 
switch (type) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b1cea71..3570355 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -125,7 +125,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
 void perf_evlist__exit(struct perf_evlist *evlist)
 {
zfree(&evlist->mmap);
-   zfree(&evlist->backward_mmap);
+   zfree(&evlist->overwrite_mmap);
fdarray__exit(&evlist->pollfd);
 }
 
@@ -675,11 +675,11 @@ static int perf_evlist__set_paused(struct perf_evlist 
*evlist, bool value)
 {
 

[tip:perf/core] perf mmap: Fix perf backward recording

2017-12-06 Thread tip-bot for Wang Nan
Commit-ID:  71f566a34986f4a86a8c546c7a36f70f0132b8a9
Gitweb: https://git.kernel.org/tip/71f566a34986f4a86a8c546c7a36f70f0132b8a9
Author: Wang Nan 
AuthorDate: Mon, 4 Dec 2017 16:51:05 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 5 Dec 2017 15:45:36 -0300

perf mmap: Fix perf backward recording

'perf record' backward recording doesn't work as we expected: it never
overwrites when ring buffer gets full.

Test:

Run a busy python printing task background like this:

 while True:
 print 123

send SIGUSR2 to perf to capture snapshot, then:

 # ./perf record --overwrite -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit 
--exclude-perf -a --switch-output
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101520743 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101521251 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101521692 ]
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Dump perf.data.2017110101521936 ]
 [ perf record: Captured and wrote 0.826 MB perf.data. ]

 # ./perf script -i ./perf.data.2017110101520743 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101521251 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101521692 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4

Timestamps never change, but my background task is a dead loop, can
easily overwhelm the ring buffer.

This patch fixes it by forcing unsetting PROT_WRITE for a backward ring
buffer, so all backward ring buffers become overwrite ring buffers.

Test result:

 # ./perf record --overwrite -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit 
--exclude-perf -a --switch-output
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101285323 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101290053 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101290446 ]
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Dump perf.data.2017110101290837 ]
 [ perf record: Captured and wrote 0.826 MB perf.data. ]
 # ./perf script -i ./perf.data.2017110101285323 | head -n3
   python  2545 [000] 11064.268083:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11064.268084: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11064.268086:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101290 | head -n3
 failed to open ./perf.data.2017110101290: No such file or directory
 # ./perf script -i ./perf.data.2017110101290053 | head -n3
   python  2545 [000] 11071.564062: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11071.564064:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11071.564066: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
 # ./perf script -i ./perf.data.2017110101290 | head -n3
 perf.data.2017110101290053  perf.data.2017110101290446  
perf.data.2017110101290837
 # ./perf script -i ./perf.data.2017110101290446 | head -n3
 sshd  1321 [000] 11075.499473:  raw_syscalls:sys_exit: NR 14 = 0
 sshd  1321 [000] 11075.499474: raw_syscalls:sys_enter: NR 14 (2, 
7ffe98899490, 0, 8, 0, 3000)
 sshd  1321 [000] 11075.499474:  raw_syscalls:sys_exit: NR 14 = 0
 # ./perf script -i ./perf.data.2017110101290837 | head -n3
   python  2545 [000] 11079.280844:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11079.280847: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11079.280850:  raw_syscalls:sys_exit: NR 1 = 4

Signed-off-by: Wang Nan 
Acked-by: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Kan Liang 
Cc: Mengting Zhang 
Link: http://lkml.kernel.org/r/20171204165107.95327-2-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/evlist.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/

[tip:perf/core] perf mmap: Remove overwrite and check_messup from mmap read

2017-12-06 Thread tip-bot for Wang Nan
Commit-ID:  8eb7a1fe31612fd3e8ae8042dd2ebaf7575504cb
Gitweb: https://git.kernel.org/tip/8eb7a1fe31612fd3e8ae8042dd2ebaf7575504cb
Author: Wang Nan 
AuthorDate: Sun, 3 Dec 2017 02:00:41 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 5 Dec 2017 15:43:54 -0300

perf mmap: Remove overwrite and check_messup from mmap read

All perf_mmap__read_forward() read from read-write ring buffer, so no
need check_messup. Reading from backward ring buffer doesn't require
check_messup because it never mess up. Cleanup arguments lists.

Signed-off-by: Wang Nan 
Acked-by: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Kan Liang 
Link: http://lkml.kernel.org/r/20171203020044.81680-6-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/evlist.c |  2 +-
 tools/perf/util/mmap.c   | 28 
 tools/perf/util/mmap.h   |  2 +-
 3 files changed, 6 insertions(+), 26 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a59134f..68c1f95 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -711,7 +711,7 @@ union perf_event *perf_evlist__mmap_read_forward(struct 
perf_evlist *evlist, int
 * No need for read-write ring buffer: kernel stop outputting when
 * it hit md->prev (perf_mmap__consume()).
 */
-   return perf_mmap__read_forward(md, false);
+   return perf_mmap__read_forward(md);
 }
 
 union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, 
int idx)
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 703ed41..3f262e7 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -21,33 +21,13 @@ size_t perf_mmap__mmap_len(struct perf_mmap *map)
 }
 
 /* When check_messup is true, 'end' must points to a good entry */
-static union perf_event *perf_mmap__read(struct perf_mmap *map, bool 
check_messup,
+static union perf_event *perf_mmap__read(struct perf_mmap *map,
 u64 start, u64 end, u64 *prev)
 {
unsigned char *data = map->base + page_size;
union perf_event *event = NULL;
int diff = end - start;
 
-   if (check_messup) {
-   /*
-* If we're further behind than half the buffer, there's a 
chance
-* the writer will bite our tail and mess up the samples under 
us.
-*
-* If we somehow ended up ahead of the 'end', we got messed up.
-*
-* In either case, truncate and restart at 'end'.
-*/
-   if (diff > map->mask / 2 || diff < 0) {
-   fprintf(stderr, "WARNING: failed to keep up with mmap 
data.\n");
-
-   /*
-* 'end' points to a known good entry, start there.
-*/
-   start = end;
-   diff = 0;
-   }
-   }
-
if (diff >= (int)sizeof(event->header)) {
size_t size;
 
@@ -89,7 +69,7 @@ broken_event:
return event;
 }
 
-union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool 
check_messup)
+union perf_event *perf_mmap__read_forward(struct perf_mmap *map)
 {
u64 head;
u64 old = map->prev;
@@ -102,7 +82,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap 
*map, bool check_mess
 
head = perf_mmap__read_head(map);
 
-   return perf_mmap__read(map, check_messup, old, head, &map->prev);
+   return perf_mmap__read(map, old, head, &map->prev);
 }
 
 union perf_event *perf_mmap__read_backward(struct perf_mmap *map)
@@ -138,7 +118,7 @@ union perf_event *perf_mmap__read_backward(struct perf_mmap 
*map)
else
end = head + map->mask + 1;
 
-   return perf_mmap__read(map, false, start, end, &map->prev);
+   return perf_mmap__read(map, start, end, &map->prev);
 }
 
 void perf_mmap__read_catchup(struct perf_mmap *map)
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index 2c3d291..d640273 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -86,7 +86,7 @@ static inline void perf_mmap__write_tail(struct perf_mmap 
*md, u64 tail)
pc->data_tail = tail;
 }
 
-union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool 
check_messup);
+union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
 union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
 
 int perf_mmap__push(struct perf_mmap *md, bool backward,


[tip:perf/core] perf mmap: Remove overwrite from arguments list of perf_mmap__push

2017-12-06 Thread tip-bot for Wang Nan
Commit-ID:  ca6a9a05391960be5e8161a59a9854b32325d901
Gitweb: https://git.kernel.org/tip/ca6a9a05391960be5e8161a59a9854b32325d901
Author: Wang Nan 
AuthorDate: Sun, 3 Dec 2017 02:00:40 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 5 Dec 2017 15:43:54 -0300

perf mmap: Remove overwrite from arguments list of perf_mmap__push

'overwrite' argument is always 'false'. Remove it from arguments list of
perf_mmap__push().

Signed-off-by: Wang Nan 
Acked-by: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Kan Liang 
Link: http://lkml.kernel.org/r/20171203020044.81680-5-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/builtin-record.c | 2 +-
 tools/perf/util/mmap.c  | 6 +++---
 tools/perf/util/mmap.h  | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 3bc6cee..26b8571 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -500,7 +500,7 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
 
if (maps[i].base) {
-   if (perf_mmap__push(&maps[i], false, backward, rec, 
record__pushfn) != 0) {
+   if (perf_mmap__push(&maps[i], backward, rec, 
record__pushfn) != 0) {
rc = -1;
goto out;
}
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 9fe5f9c..703ed41 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -299,7 +299,7 @@ static int rb_find_range(void *data, int mask, u64 head, 
u64 old,
return backward_rb_find_range(data, mask, head, start, end);
 }
 
-int perf_mmap__push(struct perf_mmap *md, bool overwrite, bool backward,
+int perf_mmap__push(struct perf_mmap *md, bool backward,
void *to, int push(void *to, void *buf, size_t size))
 {
u64 head = perf_mmap__read_head(md);
@@ -321,7 +321,7 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite, 
bool backward,
WARN_ONCE(1, "failed to keep up with mmap data. (warn only 
once)\n");
 
md->prev = head;
-   perf_mmap__consume(md, overwrite || backward);
+   perf_mmap__consume(md, backward);
return 0;
}
 
@@ -346,7 +346,7 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite, 
bool backward,
}
 
md->prev = head;
-   perf_mmap__consume(md, overwrite || backward);
+   perf_mmap__consume(md, backward);
 out:
return rc;
 }
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index efd78b8..2c3d291 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -89,7 +89,7 @@ static inline void perf_mmap__write_tail(struct perf_mmap 
*md, u64 tail)
 union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool 
check_messup);
 union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
 
-int perf_mmap__push(struct perf_mmap *md, bool overwrite, bool backward,
+int perf_mmap__push(struct perf_mmap *md, bool backward,
void *to, int push(void *to, void *buf, size_t size));
 
 size_t perf_mmap__mmap_len(struct perf_mmap *map);


[tip:perf/core] perf evlist: Remove evlist->overwrite

2017-12-06 Thread tip-bot for Wang Nan
Commit-ID:  144b9a4fc53039c09007b71a06640560a6e62140
Gitweb: https://git.kernel.org/tip/144b9a4fc53039c09007b71a06640560a6e62140
Author: Wang Nan 
AuthorDate: Sun, 3 Dec 2017 02:00:39 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 5 Dec 2017 15:43:54 -0300

perf evlist: Remove evlist->overwrite

evlist->overwrite is set to false in all users. It can be removed.

Signed-off-by: Wang Nan 
Acked-by: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Kan Liang 
Link: http://lkml.kernel.org/r/20171203020044.81680-4-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/builtin-record.c | 2 +-
 tools/perf/util/evlist.c| 5 ++---
 tools/perf/util/evlist.h| 1 -
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 08070f8..3bc6cee 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -500,7 +500,7 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
 
if (maps[i].base) {
-   if (perf_mmap__push(&maps[i], evlist->overwrite, 
backward, rec, record__pushfn) != 0) {
+   if (perf_mmap__push(&maps[i], false, backward, rec, 
record__pushfn) != 0) {
rc = -1;
goto out;
}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 93272d9..a59134f 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -711,7 +711,7 @@ union perf_event *perf_evlist__mmap_read_forward(struct 
perf_evlist *evlist, int
 * No need for read-write ring buffer: kernel stop outputting when
 * it hit md->prev (perf_mmap__consume()).
 */
-   return perf_mmap__read_forward(md, evlist->overwrite);
+   return perf_mmap__read_forward(md, false);
 }
 
 union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, 
int idx)
@@ -738,7 +738,7 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist 
*evlist, int idx)
 
 void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
 {
-   perf_mmap__consume(&evlist->mmap[idx], evlist->overwrite);
+   perf_mmap__consume(&evlist->mmap[idx], false);
 }
 
 static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
@@ -1070,7 +1070,6 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, 
unsigned int pages,
if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) 
< 0)
return -ENOMEM;
 
-   evlist->overwrite = false;
evlist->mmap_len = perf_evlist__mmap_size(pages);
pr_debug("mmap size %zuB\n", evlist->mmap_len);
mp.mask = evlist->mmap_len - page_size - 1;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 424a3d6..eec3377 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -31,7 +31,6 @@ struct perf_evlist {
int  nr_entries;
int  nr_groups;
int  nr_mmaps;
-   bool overwrite;
bool enabled;
bool has_user_cpus;
size_t   mmap_len;


[tip:perf/core] perf evlist: Remove 'overwrite' parameter from perf_evlist__mmap_ex

2017-12-06 Thread tip-bot for Wang Nan
Commit-ID:  7a276ff6c3202697c3c15cad757dec3bb07d14bf
Gitweb: https://git.kernel.org/tip/7a276ff6c3202697c3c15cad757dec3bb07d14bf
Author: Wang Nan 
AuthorDate: Sun, 3 Dec 2017 02:00:38 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 5 Dec 2017 15:43:53 -0300

perf evlist: Remove 'overwrite' parameter from perf_evlist__mmap_ex

All users of perf_evlist__mmap_ex set !overwrite. Remove it from its
arguments list.

Signed-off-by: Wang Nan 
Acked-by: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Kan Liang 
Link: http://lkml.kernel.org/r/20171203020044.81680-3-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/builtin-record.c | 2 +-
 tools/perf/util/evlist.c| 8 
 tools/perf/util/evlist.h| 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e304bc4..08070f8 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -301,7 +301,7 @@ static int record__mmap_evlist(struct record *rec,
struct record_opts *opts = &rec->opts;
char msg[512];
 
-   if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
+   if (perf_evlist__mmap_ex(evlist, opts->mmap_pages,
 opts->auxtrace_mmap_pages,
 opts->auxtrace_snapshot_mode) < 0) {
if (errno == EPERM) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3c1778b..93272d9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1052,14 +1052,14 @@ int perf_evlist__parse_mmap_pages(const struct option 
*opt, const char *str,
  * Return: %0 on success, negative error code otherwise.
  */
 int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
-bool overwrite, unsigned int auxtrace_pages,
+unsigned int auxtrace_pages,
 bool auxtrace_overwrite)
 {
struct perf_evsel *evsel;
const struct cpu_map *cpus = evlist->cpus;
const struct thread_map *threads = evlist->threads;
struct mmap_params mp = {
-   .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
+   .prot = PROT_READ | PROT_WRITE,
};
 
if (!evlist->mmap)
@@ -1070,7 +1070,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, 
unsigned int pages,
if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) 
< 0)
return -ENOMEM;
 
-   evlist->overwrite = overwrite;
+   evlist->overwrite = false;
evlist->mmap_len = perf_evlist__mmap_size(pages);
pr_debug("mmap size %zuB\n", evlist->mmap_len);
mp.mask = evlist->mmap_len - page_size - 1;
@@ -1093,7 +1093,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, 
unsigned int pages,
 
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages)
 {
-   return perf_evlist__mmap_ex(evlist, pages, false, 0, false);
+   return perf_evlist__mmap_ex(evlist, pages, 0, false);
 }
 
 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index f0f2c8b..424a3d6 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -169,7 +169,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt,
 unsigned long perf_event_mlock_kb_in_pages(void);
 
 int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
-bool overwrite, unsigned int auxtrace_pages,
+unsigned int auxtrace_pages,
 bool auxtrace_overwrite);
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages);
 void perf_evlist__munmap(struct perf_evlist *evlist);


[tip:perf/core] perf evlist: Remove 'overwrite' parameter from perf_evlist__mmap

2017-12-06 Thread tip-bot for Wang Nan
Commit-ID:  f74b9d3a1ac2b9c3ae1475f474ca0e6644746fbf
Gitweb: https://git.kernel.org/tip/f74b9d3a1ac2b9c3ae1475f474ca0e6644746fbf
Author: Wang Nan 
AuthorDate: Sun, 3 Dec 2017 02:00:37 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 5 Dec 2017 15:43:53 -0300

perf evlist: Remove 'overwrite' parameter from perf_evlist__mmap

Now all perf_evlist__mmap's users doesn't set 'overwrite'. Remove it
from arguments list.

Signed-off-by: Wang Nan 
Acked-by: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Kan Liang 
Link: http://lkml.kernel.org/r/20171203020044.81680-2-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +-
 tools/perf/builtin-kvm.c | 2 +-
 tools/perf/builtin-top.c | 2 +-
 tools/perf/builtin-trace.c   | 2 +-
 tools/perf/tests/backward-ring-buffer.c  | 2 +-
 tools/perf/tests/bpf.c   | 2 +-
 tools/perf/tests/code-reading.c  | 2 +-
 tools/perf/tests/keep-tracking.c | 2 +-
 tools/perf/tests/mmap-basic.c| 2 +-
 tools/perf/tests/openat-syscall-tp-fields.c  | 2 +-
 tools/perf/tests/perf-record.c   | 2 +-
 tools/perf/tests/sw-clock.c  | 2 +-
 tools/perf/tests/switch-tracking.c   | 2 +-
 tools/perf/tests/task-exit.c | 2 +-
 tools/perf/util/evlist.c | 5 ++---
 tools/perf/util/evlist.h | 3 +--
 tools/perf/util/python.c | 2 +-
 17 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c 
b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index b59678e..06abe81 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -84,7 +84,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, 
int subtest __maybe
 
CHECK__(perf_evlist__open(evlist));
 
-   CHECK__(perf_evlist__mmap(evlist, UINT_MAX, false));
+   CHECK__(perf_evlist__mmap(evlist, UINT_MAX));
 
pc = evlist->mmap[0].base;
ret = perf_read_tsc_conversion(pc, &tc);
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 597c7de..9885316 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1044,7 +1044,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
goto out;
}
 
-   if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
+   if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) {
ui__error("Failed to mmap the events: %s\n",
  str_error_r(errno, sbuf, sizeof(sbuf)));
perf_evlist__close(evlist);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 0077724..540461f 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -907,7 +907,7 @@ try_again:
}
}
 
-   if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
+   if (perf_evlist__mmap(evlist, opts->mmap_pages) < 0) {
ui__error("Failed to mmap with %d (%s)\n",
errno, str_error_r(errno, msg, sizeof(msg)));
goto out_err;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 84debdb..7c57898 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2437,7 +2437,7 @@ static int trace__run(struct trace *trace, int argc, 
const char **argv)
if (err < 0)
goto out_error_apply_filters;
 
-   err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
+   err = perf_evlist__mmap(evlist, trace->opts.mmap_pages);
if (err < 0)
goto out_error_mmap;
 
diff --git a/tools/perf/tests/backward-ring-buffer.c 
b/tools/perf/tests/backward-ring-buffer.c
index 43a8c6a..cf37e43 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -59,7 +59,7 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages,
int err;
char sbuf[STRERR_BUFSIZE];
 
-   err = perf_evlist__mmap(evlist, mmap_pages, false);
+   err = perf_evlist__mmap(evlist, mmap_pages);
if (err < 0) {
pr_debug("perf_evlist__mmap: %s\n",
 str_error_r(errno, sbuf, sizeof(sbuf)));
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 34c22cd..c433dd3 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -167,7 +167,7 @@ static int do_test(struct bpf_object *obj, int 
(*func)(void),
goto out_delete_evlist;
}
 
-   err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
+   err = perf_evlist__mmap(evlist, opts.mmap_pages);
if (err < 0) {
pr_debug("perf_ev

[PATCH] perf tools: Fix compiling error in libunwind x86

2017-12-05 Thread Wang Nan
Fix a compiling error:

 ...
   CC   util/libunwind/x86_32.o
 In file included from util/libunwind/x86_32.c:33:0:
 util/libunwind/../../arch/x86/util/unwind-libunwind.c: In function 
'libunwind__x86_reg_id':
 util/libunwind/../../arch/x86/util/unwind-libunwind.c:110:11: error: 'EINVAL' 
undeclared (first use in this function)
return -EINVAL;
^
 util/libunwind/../../arch/x86/util/unwind-libunwind.c:110:11: note: each 
undeclared identifier is reported only once for each function it appears in
 mv: cannot stat 'util/libunwind/.x86_32.o.tmp': No such file or directory
 make[4]: *** [util/libunwind/x86_32.o] Error 1
 make[3]: *** [util] Error 2
 make[2]: *** [libperf-in.o] Error 2
 make[1]: *** [sub-make] Error 2
 make: *** [all] Error 2

It happens when libunwind-x86 feature is detected.

Signed-off-by: Wang Nan 
---
 tools/perf/arch/x86/util/unwind-libunwind.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c 
b/tools/perf/arch/x86/util/unwind-libunwind.c
index 9c917f8..05920e3 100644
--- a/tools/perf/arch/x86/util/unwind-libunwind.c
+++ b/tools/perf/arch/x86/util/unwind-libunwind.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
-#ifndef REMOTE_UNWIND_LIBUNWIND
 #include 
+#ifndef REMOTE_UNWIND_LIBUNWIND
 #include 
 #include "perf_regs.h"
 #include "../../util/unwind.h"
-- 
2.10.1



[PATCH v3 2/3] perf tools: Don't discard prev in backward mode

2017-12-04 Thread Wang Nan
Perf record can switch output. The new output should only store the
data after switching. However, in overwrite backward mode, the new
output still have the data from old output. That also brings extra
overhead.

At the end of mmap_read, the position of processed ring buffer is
saved in md->prev. Next mmap_read should be end in md->prev if it is
not overwriten. That avoids to process duplicate data.
However, the md->prev is discarded. So next mmap_read has to process
whole valid ring buffer, which probably include the old processed
data.

Avoid calling backward_rb_find_range() when md->prev is still
available.

Signed-off-by: Wang Nan 
Tested-by: Kan Liang 
---
 tools/perf/util/mmap.c | 33 +++--
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 3f262e7..5f8cb15 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -267,18 +267,6 @@ static int backward_rb_find_range(void *buf, int mask, u64 
head, u64 *start, u64
return -1;
 }
 
-static int rb_find_range(void *data, int mask, u64 head, u64 old,
-u64 *start, u64 *end, bool backward)
-{
-   if (!backward) {
-   *start = old;
-   *end = head;
-   return 0;
-   }
-
-   return backward_rb_find_range(data, mask, head, start, end);
-}
-
 int perf_mmap__push(struct perf_mmap *md, bool backward,
void *to, int push(void *to, void *buf, size_t size))
 {
@@ -290,19 +278,28 @@ int perf_mmap__push(struct perf_mmap *md, bool backward,
void *buf;
int rc = 0;
 
-   if (rb_find_range(data, md->mask, head, old, &start, &end, backward))
-   return -1;
+   start = backward ? head : old;
+   end = backward ? old : head;
 
if (start == end)
return 0;
 
size = end - start;
if (size > (unsigned long)(md->mask) + 1) {
-   WARN_ONCE(1, "failed to keep up with mmap data. (warn only 
once)\n");
+   if (!backward) {
+   WARN_ONCE(1, "failed to keep up with mmap data. (warn 
only once)\n");
 
-   md->prev = head;
-   perf_mmap__consume(md, backward);
-   return 0;
+   md->prev = head;
+   perf_mmap__consume(md, backward);
+   return 0;
+   }
+
+   /*
+* Backward ring buffer is full. We still have a chance to read
+* most of data from it.
+*/
+   if (backward_rb_find_range(data, md->mask, head, &start, &end))
+   return -1;
}
 
if ((start & md->mask) + size != (end & md->mask)) {
-- 
2.10.1



[PATCH v3 3/3] perf tools: Replace 'backward' to 'overwrite' in evlist. mmap and record

2017-12-04 Thread Wang Nan
Remove the backward/forward concept to make it uniform with user
interface (the '--overwrite' option).

Signed-off-by: Wang Nan 
---
 tools/perf/builtin-record.c | 14 +++---
 tools/perf/tests/backward-ring-buffer.c |  4 ++--
 tools/perf/util/evlist.c| 30 +++---
 tools/perf/util/evlist.h|  2 +-
 tools/perf/util/mmap.c  | 22 +++---
 5 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 26b8571..0a5749e 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -479,7 +479,7 @@ static struct perf_event_header finished_round_event = {
 };
 
 static int record__mmap_read_evlist(struct record *rec, struct perf_evlist 
*evlist,
-   bool backward)
+   bool overwrite)
 {
u64 bytes_written = rec->bytes_written;
int i;
@@ -489,18 +489,18 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
if (!evlist)
return 0;
 
-   maps = backward ? evlist->backward_mmap : evlist->mmap;
+   maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
if (!maps)
return 0;
 
-   if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
+   if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
return 0;
 
for (i = 0; i < evlist->nr_mmaps; i++) {
struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
 
if (maps[i].base) {
-   if (perf_mmap__push(&maps[i], backward, rec, 
record__pushfn) != 0) {
+   if (perf_mmap__push(&maps[i], overwrite, rec, 
record__pushfn) != 0) {
rc = -1;
goto out;
}
@@ -520,7 +520,7 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
if (bytes_written != rec->bytes_written)
rc = record__write(rec, &finished_round_event, 
sizeof(finished_round_event));
 
-   if (backward)
+   if (overwrite)
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
 out:
return rc;
@@ -692,8 +692,8 @@ perf_evlist__pick_pc(struct perf_evlist *evlist)
if (evlist) {
if (evlist->mmap && evlist->mmap[0].base)
return evlist->mmap[0].base;
-   if (evlist->backward_mmap && evlist->backward_mmap[0].base)
-   return evlist->backward_mmap[0].base;
+   if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base)
+   return evlist->overwrite_mmap[0].base;
}
return NULL;
 }
diff --git a/tools/perf/tests/backward-ring-buffer.c 
b/tools/perf/tests/backward-ring-buffer.c
index cf37e43..4035d43 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -33,8 +33,8 @@ static int count_samples(struct perf_evlist *evlist, int 
*sample_count,
for (i = 0; i < evlist->nr_mmaps; i++) {
union perf_event *event;
 
-   perf_mmap__read_catchup(&evlist->backward_mmap[i]);
-   while ((event = 
perf_mmap__read_backward(&evlist->backward_mmap[i])) != NULL) {
+   perf_mmap__read_catchup(&evlist->overwrite_mmap[i]);
+   while ((event = 
perf_mmap__read_backward(&evlist->overwrite_mmap[i])) != NULL) {
const u32 type = event->header.type;
 
switch (type) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b1cea71..3570355 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -125,7 +125,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
 void perf_evlist__exit(struct perf_evlist *evlist)
 {
zfree(&evlist->mmap);
-   zfree(&evlist->backward_mmap);
+   zfree(&evlist->overwrite_mmap);
fdarray__exit(&evlist->pollfd);
 }
 
@@ -675,11 +675,11 @@ static int perf_evlist__set_paused(struct perf_evlist 
*evlist, bool value)
 {
int i;
 
-   if (!evlist->backward_mmap)
+   if (!evlist->overwrite_mmap)
return 0;
 
for (i = 0; i < evlist->nr_mmaps; i++) {
-   int fd = evlist->backward_mmap[i].fd;
+   int fd = evlist->overwrite_mmap[i].fd;
int err;
 
if (fd < 0)
@@ -749,16 +749,16 @@ static void perf_evlist__munmap_nofree(struct perf_evlist 
*evlist)
for (i = 0; i < evlist->nr_mmaps; i++)
perf_mmap__munma

[PATCH v3 1/3] perf mmap: Fix perf backward recording

2017-12-04 Thread Wang Nan
perf record backward recording doesn't work as we expected: it never
overwrite when ring buffer full.

Test:

(Run a busy python printing task background like this:

 while True:
 print 123

send SIGUSR2 to perf to capture snapshot.)

 # ./perf record --overwrite -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit 
--exclude-perf -a --switch-output
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101520743 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101521251 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101521692 ]
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Dump perf.data.2017110101521936 ]
 [ perf record: Captured and wrote 0.826 MB perf.data. ]

 # ./perf script -i ./perf.data.2017110101520743 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101521251 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101521692 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4

Timestamps are never change, but my background task is a dead loop, can
easily overwhelme the ring buffer.

This patch fix it by force unsetting PROT_WRITE for backward ring
buffer, so all backward ring buffer become overwrite ring buffer.

Test result:

 # ./perf record --overwrite -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit 
--exclude-perf -a --switch-output
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101285323 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101290053 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101290446 ]
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Dump perf.data.2017110101290837 ]
 [ perf record: Captured and wrote 0.826 MB perf.data. ]
 # ./perf script -i ./perf.data.2017110101285323 | head -n3
   python  2545 [000] 11064.268083:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11064.268084: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11064.268086:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101290 | head -n3
 failed to open ./perf.data.2017110101290: No such file or directory
 # ./perf script -i ./perf.data.2017110101290053 | head -n3
   python  2545 [000] 11071.564062: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11071.564064:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11071.564066: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
 # ./perf script -i ./perf.data.2017110101290 | head -n3
 perf.data.2017110101290053  perf.data.2017110101290446  
perf.data.2017110101290837
 # ./perf script -i ./perf.data.2017110101290446 | head -n3
 sshd  1321 [000] 11075.499473:  raw_syscalls:sys_exit: NR 14 = 0
 sshd  1321 [000] 11075.499474: raw_syscalls:sys_enter: NR 14 (2, 
7ffe98899490, 0, 8, 0, 3000)
 sshd  1321 [000] 11075.499474:  raw_syscalls:sys_exit: NR 14 = 0
 # ./perf script -i ./perf.data.2017110101290837 | head -n3
   python  2545 [000] 11079.280844:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11079.280847: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11079.280850:  raw_syscalls:sys_exit: NR 1 = 4

Signed-off-by: Wang Nan 
---
 tools/perf/util/evlist.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 68c1f95..b1cea71 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -812,6 +812,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist 
*evlist, int idx,
int fd;
int cpu;
 
+   mp->prot = PROT_READ | PROT_WRITE;
if (evsel->attr.write_backward) {
output = _output_backward;
maps = evlist->backward_mmap;
@@ -824,6 +825,7

[PATCH v3 0/3] perf tools: perf tools: Clarify overwrite and backward, bugfix

2017-12-04 Thread Wang Nan
Simplify patch 1/3 following Namhyung's suggestion.

Context adjustment for patch 2 and 3.

Wang Nan (3):
  perf mmap: Fix perf backward recording
  perf tools: Don't discard prev in backward mode
  perf tools: Replace 'backward' to 'overwrite' in evlist. mmap and
record

 tools/perf/builtin-record.c | 14 +-
 tools/perf/tests/backward-ring-buffer.c |  4 +--
 tools/perf/util/evlist.c| 41 +-
 tools/perf/util/evlist.h|  2 +-
 tools/perf/util/mmap.c  | 45 +++--
 5 files changed, 54 insertions(+), 52 deletions(-)

-- 
2.10.1



[PATCH v2 0/8] perf tools: perf tools: Clarify overwrite and backward, bugfix

2017-12-02 Thread Wang Nan
THe final result of this patchset is removing the concept of
'forward/backward', merge them into the concept of 'overwrite'.

Patch 1 to 5 clear arguments lists of many functions, remove the
'overwrite'. Because all callers of these functions doesn't need
the overwrite be set, we can simply remove them from arguments
lists and adjust code as if a 'false' is given.

Patch 6 fix a bug that forget to setting readonly for overwrite
ring buffers.

Patch 7 is suggested by Liang Kan, prevent dumpping duplicated
data if there's no so many events between two dumpping commands.

Patch 8 is 's/backward/overwrite'. After patch 8, the concept of
'backward' is removed from most of the code, make it uniform with
user interface ('--overwrite').

Cc: Kan Liang 
Cc: Arnaldo Carvalho de Melo 
Cc: Jiri Olsa 
Cc: Namhyung Kim 
Cc: Zhang Mengting 

Wang Nan (8):
  perf tools: Remove 'overwrite' parameter from perf_evlist__mmap
  perf tools: Remove 'overwrite' parameter from perf_evlist__mmap_ex
  perf tools: Remove evlist->overwrite
  perf tools: Remove overwrite from arguments list of perf_mmap__push
  perf tools: Remove overwrite and check_messup from mmap read
  perf mmap: Fix perf backward recording
  perf tool: Don't discard prev in backward mode
  perf tools: Replace 'backward' to 'overwrite' in evlist, mmap and
record

 tools/perf/arch/x86/tests/perf-time-to-tsc.c |  2 +-
 tools/perf/builtin-kvm.c |  2 +-
 tools/perf/builtin-record.c  | 16 +++---
 tools/perf/builtin-top.c |  2 +-
 tools/perf/builtin-trace.c   |  2 +-
 tools/perf/tests/backward-ring-buffer.c  |  6 +--
 tools/perf/tests/bpf.c   |  2 +-
 tools/perf/tests/code-reading.c  |  2 +-
 tools/perf/tests/keep-tracking.c |  2 +-
 tools/perf/tests/mmap-basic.c|  2 +-
 tools/perf/tests/openat-syscall-tp-fields.c  |  2 +-
 tools/perf/tests/perf-record.c   |  2 +-
 tools/perf/tests/sw-clock.c  |  2 +-
 tools/perf/tests/switch-tracking.c   |  2 +-
 tools/perf/tests/task-exit.c |  2 +-
 tools/perf/util/evlist.c | 53 ++--
 tools/perf/util/evlist.h |  8 ++-
 tools/perf/util/mmap.c   | 73 ++--
 tools/perf/util/mmap.h   |  4 +-
 tools/perf/util/python.c |  2 +-
 20 files changed, 81 insertions(+), 107 deletions(-)

-- 
2.10.1



[PATCH v2 6/8] perf mmap: Fix perf backward recording

2017-12-02 Thread Wang Nan
perf record backward recording doesn't work as we expected: it never
overwrite when ring buffer full.

Test:

(Run a busy printing task background like this:

 while True:
 print 123

send SIGUSR2 to perf to capture snapshot.)

 # ./perf record --overwrite -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit 
--exclude-perf -a --switch-output
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101520743 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101521251 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101521692 ]
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Dump perf.data.2017110101521936 ]
 [ perf record: Captured and wrote 0.826 MB perf.data. ]

 # ./perf script -i ./perf.data.2017110101520743 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101521251 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101521692 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4

Timestamps are never change, but my background task is a dead loop, can
easily overwhelme the ring buffer.

This patch fix it by force unsetting PROT_WRITE for backward ring
buffer, so all backward ring buffer become overwrite ring buffer.

Test result:

 # ./perf record --overwrite -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit 
--exclude-perf -a --switch-output
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101285323 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101290053 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101290446 ]
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Dump perf.data.2017110101290837 ]
 [ perf record: Captured and wrote 0.826 MB perf.data. ]
 # ./perf script -i ./perf.data.2017110101285323 | head -n3
   python  2545 [000] 11064.268083:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11064.268084: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11064.268086:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101290 | head -n3
 failed to open ./perf.data.2017110101290: No such file or directory
 # ./perf script -i ./perf.data.2017110101290053 | head -n3
   python  2545 [000] 11071.564062: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11071.564064:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11071.564066: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
 # ./perf script -i ./perf.data.2017110101290 | head -n3
 perf.data.2017110101290053  perf.data.2017110101290446  
perf.data.2017110101290837
 # ./perf script -i ./perf.data.2017110101290446 | head -n3
 sshd  1321 [000] 11075.499473:  raw_syscalls:sys_exit: NR 14 = 0
 sshd  1321 [000] 11075.499474: raw_syscalls:sys_enter: NR 14 (2, 
7ffe98899490, 0, 8, 0, 3000)
 sshd  1321 [000] 11075.499474:  raw_syscalls:sys_exit: NR 14 = 0
 # ./perf script -i ./perf.data.2017110101290837 | head -n3
   python  2545 [000] 11079.280844:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11079.280847: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11079.280850:  raw_syscalls:sys_exit: NR 1 = 4

Signed-off-by: Wang Nan 
---
 tools/perf/util/evlist.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 68c1f95..bb70aef 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -799,7 +799,7 @@ perf_evlist__should_poll(struct perf_evlist *evlist 
__maybe_unused,
 }
 
 static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
-  struct mmap_params *mp, int cpu_idx,
+  struct mmap_params mp, int cpu_idx,
   int thread, int *_output, int 
*_output_bac

[PATCH v2 7/8] perf tools: Don't discard prev in backward mode

2017-12-02 Thread Wang Nan
Perf record can switch output. The new output should only store the
data after switching. However, in overwrite backward mode, the new
output still have the data from old output. That also brings extra
overhead.

At the end of mmap_read, the position of processed ring buffer is
saved in md->prev. Next mmap_read should be end in md->prev if it is
not overwriten. That avoids to process duplicate data.
However, the md->prev is discarded. So next mmap_read has to process
whole valid ring buffer, which probably include the old processed
data.

Avoid calling backward_rb_find_range() when md->prev is still
available.

Signed-off-by: Wang Nan 
Tested-by: Kan Liang 
---
 tools/perf/util/mmap.c | 33 +++--
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 3f262e7..5f8cb15 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -267,18 +267,6 @@ static int backward_rb_find_range(void *buf, int mask, u64 
head, u64 *start, u64
return -1;
 }
 
-static int rb_find_range(void *data, int mask, u64 head, u64 old,
-u64 *start, u64 *end, bool backward)
-{
-   if (!backward) {
-   *start = old;
-   *end = head;
-   return 0;
-   }
-
-   return backward_rb_find_range(data, mask, head, start, end);
-}
-
 int perf_mmap__push(struct perf_mmap *md, bool backward,
void *to, int push(void *to, void *buf, size_t size))
 {
@@ -290,19 +278,28 @@ int perf_mmap__push(struct perf_mmap *md, bool backward,
void *buf;
int rc = 0;
 
-   if (rb_find_range(data, md->mask, head, old, &start, &end, backward))
-   return -1;
+   start = backward ? head : old;
+   end = backward ? old : head;
 
if (start == end)
return 0;
 
size = end - start;
if (size > (unsigned long)(md->mask) + 1) {
-   WARN_ONCE(1, "failed to keep up with mmap data. (warn only 
once)\n");
+   if (!backward) {
+   WARN_ONCE(1, "failed to keep up with mmap data. (warn 
only once)\n");
 
-   md->prev = head;
-   perf_mmap__consume(md, backward);
-   return 0;
+   md->prev = head;
+   perf_mmap__consume(md, backward);
+   return 0;
+   }
+
+   /*
+* Backward ring buffer is full. We still have a chance to read
+* most of data from it.
+*/
+   if (backward_rb_find_range(data, md->mask, head, &start, &end))
+   return -1;
}
 
if ((start & md->mask) + size != (end & md->mask)) {
-- 
2.10.1



[PATCH v2 5/8] perf tools: Remove overwrite and check_messup from mmap read

2017-12-02 Thread Wang Nan
All perf_mmap__read_forward() read from read-write ring buffer,
so no need check_messup. Reading from backward ring buffer doesn't
require check_messup because it never mess up. Cleanup arguments
lists.

Signed-off-by: Wang Nan 
---
 tools/perf/util/evlist.c |  2 +-
 tools/perf/util/mmap.c   | 28 
 tools/perf/util/mmap.h   |  2 +-
 3 files changed, 6 insertions(+), 26 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a59134f..68c1f95 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -711,7 +711,7 @@ union perf_event *perf_evlist__mmap_read_forward(struct 
perf_evlist *evlist, int
 * No need for read-write ring buffer: kernel stop outputting when
 * it hit md->prev (perf_mmap__consume()).
 */
-   return perf_mmap__read_forward(md, false);
+   return perf_mmap__read_forward(md);
 }
 
 union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, 
int idx)
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 703ed41..3f262e7 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -21,33 +21,13 @@ size_t perf_mmap__mmap_len(struct perf_mmap *map)
 }
 
 /* When check_messup is true, 'end' must points to a good entry */
-static union perf_event *perf_mmap__read(struct perf_mmap *map, bool 
check_messup,
+static union perf_event *perf_mmap__read(struct perf_mmap *map,
 u64 start, u64 end, u64 *prev)
 {
unsigned char *data = map->base + page_size;
union perf_event *event = NULL;
int diff = end - start;
 
-   if (check_messup) {
-   /*
-* If we're further behind than half the buffer, there's a 
chance
-* the writer will bite our tail and mess up the samples under 
us.
-*
-* If we somehow ended up ahead of the 'end', we got messed up.
-*
-* In either case, truncate and restart at 'end'.
-*/
-   if (diff > map->mask / 2 || diff < 0) {
-   fprintf(stderr, "WARNING: failed to keep up with mmap 
data.\n");
-
-   /*
-* 'end' points to a known good entry, start there.
-*/
-   start = end;
-   diff = 0;
-   }
-   }
-
if (diff >= (int)sizeof(event->header)) {
size_t size;
 
@@ -89,7 +69,7 @@ static union perf_event *perf_mmap__read(struct perf_mmap 
*map, bool check_messu
return event;
 }
 
-union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool 
check_messup)
+union perf_event *perf_mmap__read_forward(struct perf_mmap *map)
 {
u64 head;
u64 old = map->prev;
@@ -102,7 +82,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap 
*map, bool check_mess
 
head = perf_mmap__read_head(map);
 
-   return perf_mmap__read(map, check_messup, old, head, &map->prev);
+   return perf_mmap__read(map, old, head, &map->prev);
 }
 
 union perf_event *perf_mmap__read_backward(struct perf_mmap *map)
@@ -138,7 +118,7 @@ union perf_event *perf_mmap__read_backward(struct perf_mmap 
*map)
else
end = head + map->mask + 1;
 
-   return perf_mmap__read(map, false, start, end, &map->prev);
+   return perf_mmap__read(map, start, end, &map->prev);
 }
 
 void perf_mmap__read_catchup(struct perf_mmap *map)
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index 2c3d291..d640273 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -86,7 +86,7 @@ static inline void perf_mmap__write_tail(struct perf_mmap 
*md, u64 tail)
pc->data_tail = tail;
 }
 
-union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool 
check_messup);
+union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
 union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
 
 int perf_mmap__push(struct perf_mmap *md, bool backward,
-- 
2.10.1



[PATCH v2 4/8] perf tools: Remove overwrite from arguments list of perf_mmap__push

2017-12-02 Thread Wang Nan
'overwrite' argument is always 'false'. Revmove it from arguments
list of perf_mmap__push.

Signed-off-by: Wang Nan 
---
 tools/perf/builtin-record.c | 2 +-
 tools/perf/util/mmap.c  | 6 +++---
 tools/perf/util/mmap.h  | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 3bc6cee..26b8571 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -500,7 +500,7 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
 
if (maps[i].base) {
-   if (perf_mmap__push(&maps[i], false, backward, rec, 
record__pushfn) != 0) {
+   if (perf_mmap__push(&maps[i], backward, rec, 
record__pushfn) != 0) {
rc = -1;
goto out;
}
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 9fe5f9c..703ed41 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -299,7 +299,7 @@ static int rb_find_range(void *data, int mask, u64 head, 
u64 old,
return backward_rb_find_range(data, mask, head, start, end);
 }
 
-int perf_mmap__push(struct perf_mmap *md, bool overwrite, bool backward,
+int perf_mmap__push(struct perf_mmap *md, bool backward,
void *to, int push(void *to, void *buf, size_t size))
 {
u64 head = perf_mmap__read_head(md);
@@ -321,7 +321,7 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite, 
bool backward,
WARN_ONCE(1, "failed to keep up with mmap data. (warn only 
once)\n");
 
md->prev = head;
-   perf_mmap__consume(md, overwrite || backward);
+   perf_mmap__consume(md, backward);
return 0;
}
 
@@ -346,7 +346,7 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite, 
bool backward,
}
 
md->prev = head;
-   perf_mmap__consume(md, overwrite || backward);
+   perf_mmap__consume(md, backward);
 out:
return rc;
 }
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index efd78b8..2c3d291 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -89,7 +89,7 @@ static inline void perf_mmap__write_tail(struct perf_mmap 
*md, u64 tail)
 union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool 
check_messup);
 union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
 
-int perf_mmap__push(struct perf_mmap *md, bool overwrite, bool backward,
+int perf_mmap__push(struct perf_mmap *md, bool backward,
void *to, int push(void *to, void *buf, size_t size));
 
 size_t perf_mmap__mmap_len(struct perf_mmap *map);
-- 
2.10.1



[PATCH v2 2/8] perf tools: Remove 'overwrite' parameter from perf_evlist__mmap_ex

2017-12-02 Thread Wang Nan
All users of perf_evlist__mmap_ex set !overwrite. Remove it from its
arguments list.

Signed-off-by: Wang Nan 
---
 tools/perf/builtin-record.c | 2 +-
 tools/perf/util/evlist.c| 8 
 tools/perf/util/evlist.h| 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e304bc4..08070f8 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -301,7 +301,7 @@ static int record__mmap_evlist(struct record *rec,
struct record_opts *opts = &rec->opts;
char msg[512];
 
-   if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
+   if (perf_evlist__mmap_ex(evlist, opts->mmap_pages,
 opts->auxtrace_mmap_pages,
 opts->auxtrace_snapshot_mode) < 0) {
if (errno == EPERM) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3c1778b..93272d9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1052,14 +1052,14 @@ int perf_evlist__parse_mmap_pages(const struct option 
*opt, const char *str,
  * Return: %0 on success, negative error code otherwise.
  */
 int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
-bool overwrite, unsigned int auxtrace_pages,
+unsigned int auxtrace_pages,
 bool auxtrace_overwrite)
 {
struct perf_evsel *evsel;
const struct cpu_map *cpus = evlist->cpus;
const struct thread_map *threads = evlist->threads;
struct mmap_params mp = {
-   .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
+   .prot = PROT_READ | PROT_WRITE,
};
 
if (!evlist->mmap)
@@ -1070,7 +1070,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, 
unsigned int pages,
if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) 
< 0)
return -ENOMEM;
 
-   evlist->overwrite = overwrite;
+   evlist->overwrite = false;
evlist->mmap_len = perf_evlist__mmap_size(pages);
pr_debug("mmap size %zuB\n", evlist->mmap_len);
mp.mask = evlist->mmap_len - page_size - 1;
@@ -1093,7 +1093,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, 
unsigned int pages,
 
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages)
 {
-   return perf_evlist__mmap_ex(evlist, pages, false, 0, false);
+   return perf_evlist__mmap_ex(evlist, pages, 0, false);
 }
 
 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index f0f2c8b..424a3d6 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -169,7 +169,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt,
 unsigned long perf_event_mlock_kb_in_pages(void);
 
 int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
-bool overwrite, unsigned int auxtrace_pages,
+unsigned int auxtrace_pages,
 bool auxtrace_overwrite);
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages);
 void perf_evlist__munmap(struct perf_evlist *evlist);
-- 
2.10.1



[PATCH v2 8/8] perf tools: Replace 'backward' to 'overwrite' in evlist, mmap and record

2017-12-02 Thread Wang Nan
Remove the backward/forward concept to make it uniform with user
interface (the '--overwrite' option).

Signed-off-by: Wang Nan 
---
 tools/perf/builtin-record.c | 14 +++---
 tools/perf/tests/backward-ring-buffer.c |  4 ++--
 tools/perf/util/evlist.c| 30 +++---
 tools/perf/util/evlist.h|  2 +-
 tools/perf/util/mmap.c  | 22 +++---
 5 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 26b8571..0a5749e 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -479,7 +479,7 @@ static struct perf_event_header finished_round_event = {
 };
 
 static int record__mmap_read_evlist(struct record *rec, struct perf_evlist 
*evlist,
-   bool backward)
+   bool overwrite)
 {
u64 bytes_written = rec->bytes_written;
int i;
@@ -489,18 +489,18 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
if (!evlist)
return 0;
 
-   maps = backward ? evlist->backward_mmap : evlist->mmap;
+   maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
if (!maps)
return 0;
 
-   if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
+   if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
return 0;
 
for (i = 0; i < evlist->nr_mmaps; i++) {
struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
 
if (maps[i].base) {
-   if (perf_mmap__push(&maps[i], backward, rec, 
record__pushfn) != 0) {
+   if (perf_mmap__push(&maps[i], overwrite, rec, 
record__pushfn) != 0) {
rc = -1;
goto out;
}
@@ -520,7 +520,7 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
if (bytes_written != rec->bytes_written)
rc = record__write(rec, &finished_round_event, 
sizeof(finished_round_event));
 
-   if (backward)
+   if (overwrite)
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
 out:
return rc;
@@ -692,8 +692,8 @@ perf_evlist__pick_pc(struct perf_evlist *evlist)
if (evlist) {
if (evlist->mmap && evlist->mmap[0].base)
return evlist->mmap[0].base;
-   if (evlist->backward_mmap && evlist->backward_mmap[0].base)
-   return evlist->backward_mmap[0].base;
+   if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base)
+   return evlist->overwrite_mmap[0].base;
}
return NULL;
 }
diff --git a/tools/perf/tests/backward-ring-buffer.c 
b/tools/perf/tests/backward-ring-buffer.c
index cf37e43..4035d43 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -33,8 +33,8 @@ static int count_samples(struct perf_evlist *evlist, int 
*sample_count,
for (i = 0; i < evlist->nr_mmaps; i++) {
union perf_event *event;
 
-   perf_mmap__read_catchup(&evlist->backward_mmap[i]);
-   while ((event = 
perf_mmap__read_backward(&evlist->backward_mmap[i])) != NULL) {
+   perf_mmap__read_catchup(&evlist->overwrite_mmap[i]);
+   while ((event = 
perf_mmap__read_backward(&evlist->overwrite_mmap[i])) != NULL) {
const u32 type = event->header.type;
 
switch (type) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index bb70aef..2774528a 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -125,7 +125,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
 void perf_evlist__exit(struct perf_evlist *evlist)
 {
zfree(&evlist->mmap);
-   zfree(&evlist->backward_mmap);
+   zfree(&evlist->overwrite_mmap);
fdarray__exit(&evlist->pollfd);
 }
 
@@ -675,11 +675,11 @@ static int perf_evlist__set_paused(struct perf_evlist 
*evlist, bool value)
 {
int i;
 
-   if (!evlist->backward_mmap)
+   if (!evlist->overwrite_mmap)
return 0;
 
for (i = 0; i < evlist->nr_mmaps; i++) {
-   int fd = evlist->backward_mmap[i].fd;
+   int fd = evlist->overwrite_mmap[i].fd;
int err;
 
if (fd < 0)
@@ -749,16 +749,16 @@ static void perf_evlist__munmap_nofree(struct perf_evlist 
*evlist)
for (i = 0; i < evlist->nr_mmaps; i++)
perf_mmap__munma

[PATCH v2 1/8] perf tools: Remove 'overwrite' parameter from perf_evlist__mmap

2017-12-02 Thread Wang Nan
Now all perf_evlist__mmap's users doesn't set 'overwrite'. Remove it from
arguments list.

Signed-off-by: Wang Nan 
---
 tools/perf/arch/x86/tests/perf-time-to-tsc.c | 2 +-
 tools/perf/builtin-kvm.c | 2 +-
 tools/perf/builtin-top.c | 2 +-
 tools/perf/builtin-trace.c   | 2 +-
 tools/perf/tests/backward-ring-buffer.c  | 2 +-
 tools/perf/tests/bpf.c   | 2 +-
 tools/perf/tests/code-reading.c  | 2 +-
 tools/perf/tests/keep-tracking.c | 2 +-
 tools/perf/tests/mmap-basic.c| 2 +-
 tools/perf/tests/openat-syscall-tp-fields.c  | 2 +-
 tools/perf/tests/perf-record.c   | 2 +-
 tools/perf/tests/sw-clock.c  | 2 +-
 tools/perf/tests/switch-tracking.c   | 2 +-
 tools/perf/tests/task-exit.c | 2 +-
 tools/perf/util/evlist.c | 5 ++---
 tools/perf/util/evlist.h | 3 +--
 tools/perf/util/python.c | 2 +-
 17 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c 
b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index b59678e..06abe81 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -84,7 +84,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, 
int subtest __maybe
 
CHECK__(perf_evlist__open(evlist));
 
-   CHECK__(perf_evlist__mmap(evlist, UINT_MAX, false));
+   CHECK__(perf_evlist__mmap(evlist, UINT_MAX));
 
pc = evlist->mmap[0].base;
ret = perf_read_tsc_conversion(pc, &tc);
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 597c7de..9885316 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1044,7 +1044,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
goto out;
}
 
-   if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
+   if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) {
ui__error("Failed to mmap the events: %s\n",
  str_error_r(errno, sbuf, sizeof(sbuf)));
perf_evlist__close(evlist);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 0077724..540461f 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -907,7 +907,7 @@ static int perf_top__start_counters(struct perf_top *top)
}
}
 
-   if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
+   if (perf_evlist__mmap(evlist, opts->mmap_pages) < 0) {
ui__error("Failed to mmap with %d (%s)\n",
errno, str_error_r(errno, msg, sizeof(msg)));
goto out_err;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 84debdb..7c57898 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2437,7 +2437,7 @@ static int trace__run(struct trace *trace, int argc, 
const char **argv)
if (err < 0)
goto out_error_apply_filters;
 
-   err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
+   err = perf_evlist__mmap(evlist, trace->opts.mmap_pages);
if (err < 0)
goto out_error_mmap;
 
diff --git a/tools/perf/tests/backward-ring-buffer.c 
b/tools/perf/tests/backward-ring-buffer.c
index 43a8c6a..cf37e43 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -59,7 +59,7 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages,
int err;
char sbuf[STRERR_BUFSIZE];
 
-   err = perf_evlist__mmap(evlist, mmap_pages, false);
+   err = perf_evlist__mmap(evlist, mmap_pages);
if (err < 0) {
pr_debug("perf_evlist__mmap: %s\n",
 str_error_r(errno, sbuf, sizeof(sbuf)));
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 34c22cd..c433dd3 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -167,7 +167,7 @@ static int do_test(struct bpf_object *obj, int 
(*func)(void),
goto out_delete_evlist;
}
 
-   err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
+   err = perf_evlist__mmap(evlist, opts.mmap_pages);
if (err < 0) {
pr_debug("perf_evlist__mmap: %s\n",
 str_error_r(errno, sbuf, sizeof(sbuf)));
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index fcc8984..3bf7b14 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -639,7 +639,7 @@ static int do_test_code_reading(bool try_kcore)
break;
}
 
-   ret = perf_evlist__mmap(evlist, UINT_MAX, false);
+   ret = perf_evlist__mmap(evlist, U

[PATCH v2 3/8] perf tools: Remove evlist->overwrite

2017-12-02 Thread Wang Nan
evlist->overwrite is set to false in all users. It can be removed.

Signed-off-by: Wang Nan 
---
 tools/perf/builtin-record.c | 2 +-
 tools/perf/util/evlist.c| 5 ++---
 tools/perf/util/evlist.h| 1 -
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 08070f8..3bc6cee 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -500,7 +500,7 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
 
if (maps[i].base) {
-   if (perf_mmap__push(&maps[i], evlist->overwrite, 
backward, rec, record__pushfn) != 0) {
+   if (perf_mmap__push(&maps[i], false, backward, rec, 
record__pushfn) != 0) {
rc = -1;
goto out;
}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 93272d9..a59134f 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -711,7 +711,7 @@ union perf_event *perf_evlist__mmap_read_forward(struct 
perf_evlist *evlist, int
 * No need for read-write ring buffer: kernel stop outputting when
 * it hit md->prev (perf_mmap__consume()).
 */
-   return perf_mmap__read_forward(md, evlist->overwrite);
+   return perf_mmap__read_forward(md, false);
 }
 
 union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, 
int idx)
@@ -738,7 +738,7 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist 
*evlist, int idx)
 
 void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
 {
-   perf_mmap__consume(&evlist->mmap[idx], evlist->overwrite);
+   perf_mmap__consume(&evlist->mmap[idx], false);
 }
 
 static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
@@ -1070,7 +1070,6 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, 
unsigned int pages,
if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) 
< 0)
return -ENOMEM;
 
-   evlist->overwrite = false;
evlist->mmap_len = perf_evlist__mmap_size(pages);
pr_debug("mmap size %zuB\n", evlist->mmap_len);
mp.mask = evlist->mmap_len - page_size - 1;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 424a3d6..eec3377 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -31,7 +31,6 @@ struct perf_evlist {
int  nr_entries;
int  nr_groups;
int  nr_mmaps;
-   bool overwrite;
bool enabled;
bool has_user_cpus;
size_t   mmap_len;
-- 
2.10.1



[tip:perf/core] perf tests: Set evlist of test__task_exit() to !overwrite

2017-11-18 Thread tip-bot for Wang Nan
Commit-ID:  a0e3dd79cdd8ad838cbcefeff530a15193f8336e
Gitweb: https://git.kernel.org/tip/a0e3dd79cdd8ad838cbcefeff530a15193f8336e
Author: Wang Nan 
AuthorDate: Mon, 13 Nov 2017 01:38:07 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Thu, 16 Nov 2017 14:49:58 -0300

perf tests: Set evlist of test__task_exit() to !overwrite

Changing ringbuffer to !overwrite in this task is harmless because
this test uses a very low frequency (1) and using a very simple program
(true). There should have only 3 events in the whole test.  Overwriting
is impossible to happen.

Signed-off-by: Wang Nan 
Cc: Jiri Olsa 
Cc: Kan Liang 
Cc: Namhyung Kim 
Link: http://lkml.kernel.org/r/20171113013809.212417-6-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/tests/task-exit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index bc4a734..98c0984 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -97,7 +97,7 @@ int test__task_exit(struct test *test __maybe_unused, int 
subtest __maybe_unused
goto out_delete_evlist;
}
 
-   if (perf_evlist__mmap(evlist, 128, true) < 0) {
+   if (perf_evlist__mmap(evlist, 128, false) < 0) {
pr_debug("failed to mmap events: %d (%s)\n", errno,
 str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;


[tip:perf/core] perf tests: Set evlist of test__sw_clock_freq() to !overwrite

2017-11-18 Thread tip-bot for Wang Nan
Commit-ID:  677b0601768881934f658bebb1713c3c843893fa
Gitweb: https://git.kernel.org/tip/677b0601768881934f658bebb1713c3c843893fa
Author: Wang Nan 
AuthorDate: Mon, 13 Nov 2017 01:38:05 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Thu, 16 Nov 2017 14:49:57 -0300

perf tests: Set evlist of test__sw_clock_freq() to !overwrite

Unsetting overwrite when calling perf_evlist__mmap is harmless. This
commit passes false to it, makes following commits eliminate the
overwrite argument easier.

Signed-off-by: Wang Nan 
Cc: Jiri Olsa 
Cc: Kan Liang 
Cc: Namhyung Kim 
Link: http://lkml.kernel.org/r/20171113013809.212417-4-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/tests/sw-clock.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 725a196..c6937ed 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
goto out_delete_evlist;
}
 
-   err = perf_evlist__mmap(evlist, 128, true);
+   err = perf_evlist__mmap(evlist, 128, false);
if (err < 0) {
pr_debug("failed to mmap event: %d (%s)\n", errno,
 str_error_r(errno, sbuf, sizeof(sbuf)));


[tip:perf/core] perf tests: Set evlist of test__backward_ring_buffer() to !overwrite

2017-11-18 Thread tip-bot for Wang Nan
Commit-ID:  d492326f160e44e08fcf132a63163b36dd8e8839
Gitweb: https://git.kernel.org/tip/d492326f160e44e08fcf132a63163b36dd8e8839
Author: Wang Nan 
AuthorDate: Mon, 13 Nov 2017 01:38:04 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Thu, 16 Nov 2017 14:49:57 -0300

perf tests: Set evlist of test__backward_ring_buffer() to !overwrite

Setting overwrite in perf_evlist__mmap() is meaningless because the
event in this evlist is already have 'overwrite' postfix and goes to
backward ring buffer automatically. Pass 'false' to perf_evlist__mmap()
to make it similar to others.

Signed-off-by: Wang Nan 
Cc: Jiri Olsa 
Cc: Kan Liang 
Cc: Namhyung Kim 
Link: http://lkml.kernel.org/r/20171113013809.212417-3-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/tests/backward-ring-buffer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/backward-ring-buffer.c 
b/tools/perf/tests/backward-ring-buffer.c
index 71b9a0b..43a8c6a 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -59,7 +59,7 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages,
int err;
char sbuf[STRERR_BUFSIZE];
 
-   err = perf_evlist__mmap(evlist, mmap_pages, true);
+   err = perf_evlist__mmap(evlist, mmap_pages, false);
if (err < 0) {
pr_debug("perf_evlist__mmap: %s\n",
 str_error_r(errno, sbuf, sizeof(sbuf)));


[tip:perf/core] perf tests: Set evlist of test__basic_mmap() to !overwrite

2017-11-18 Thread tip-bot for Wang Nan
Commit-ID:  301d724aa19add1c0cf3ec8cad0d10151d30393f
Gitweb: https://git.kernel.org/tip/301d724aa19add1c0cf3ec8cad0d10151d30393f
Author: Wang Nan 
AuthorDate: Mon, 13 Nov 2017 01:38:06 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Thu, 16 Nov 2017 14:49:58 -0300

perf tests: Set evlist of test__basic_mmap() to !overwrite

In this test, a large ring buffer is required so all events can feed
into, so overwrite or not is meaningless.

Change to !overwrite so following commits can remove this argument.

Signed-off-by: Wang Nan 
Cc: Jiri Olsa 
Cc: Kan Liang 
Cc: Namhyung Kim 
Link: http://lkml.kernel.org/r/20171113013809.212417-5-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/tests/mmap-basic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 5a8bf31..91f10d6 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -94,7 +94,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int 
subtest __maybe_unuse
expected_nr_events[i] = 1 + rand() % 127;
}
 
-   if (perf_evlist__mmap(evlist, 128, true) < 0) {
+   if (perf_evlist__mmap(evlist, 128, false) < 0) {
pr_debug("failed to mmap events: %d (%s)\n", errno,
 str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;


[PATCH 7/7] perf tools: Remove prot field in mmap param

2017-11-12 Thread Wang Nan
After removing the concept of 'overwrite' in code level, now the
prot is determinated by write_backward. There's no need to pass
prot from perf_evlist__mmap_ex().

Signed-off-by: Wang Nan 
---
 tools/perf/util/evlist.c | 17 ++---
 tools/perf/util/mmap.c   |  4 ++--
 tools/perf/util/mmap.h   |  4 ++--
 3 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 4948d3d..0d713e0 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -799,28 +799,23 @@ perf_evlist__should_poll(struct perf_evlist *evlist 
__maybe_unused,
 }
 
 static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
-  struct mmap_params *_mp, int cpu_idx,
+  struct mmap_params *mp, int cpu_idx,
   int thread, int *_output, int 
*_output_backward)
 {
struct perf_evsel *evsel;
int revent;
int evlist_cpu = cpu_map__cpu(evlist->cpus, cpu_idx);
-   struct mmap_params *mp;
 
evlist__for_each_entry(evlist, evsel) {
struct perf_mmap *maps = evlist->mmap;
-   struct mmap_params rdonly_mp;
int *output = _output;
int fd;
int cpu;
+   int prot = PROT_READ;
 
-   mp = _mp;
if (evsel->attr.write_backward) {
output = _output_backward;
maps = evlist->backward_mmap;
-   rdonly_mp = *_mp;
-   rdonly_mp.prot &= ~PROT_WRITE;
-   mp = &rdonly_mp;
 
if (!maps) {
maps = perf_evlist__alloc_mmap(evlist);
@@ -830,6 +825,8 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist 
*evlist, int idx,
if (evlist->bkw_mmap_state == BKW_MMAP_NOTREADY)
perf_evlist__toggle_bkw_mmap(evlist, 
BKW_MMAP_RUNNING);
}
+   } else {
+   prot |= PROT_WRITE;
}
 
if (evsel->system_wide && thread)
@@ -844,7 +841,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist 
*evlist, int idx,
if (*output == -1) {
*output = fd;
 
-   if (perf_mmap__mmap(&maps[idx], mp, *output)  < 0)
+   if (perf_mmap__mmap(&maps[idx], mp, prot, *output)  < 0)
return -1;
} else {
if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
@@ -1064,9 +1061,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, 
unsigned int pages,
struct perf_evsel *evsel;
const struct cpu_map *cpus = evlist->cpus;
const struct thread_map *threads = evlist->threads;
-   struct mmap_params mp = {
-   .prot = PROT_READ | PROT_WRITE,
-   };
+   struct mmap_params mp;
 
if (!evlist->mmap)
evlist->mmap = perf_evlist__alloc_mmap(evlist);
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 703ed41..40e91a0 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -219,7 +219,7 @@ void perf_mmap__munmap(struct perf_mmap *map)
auxtrace_mmap__munmap(&map->auxtrace_mmap);
 }
 
-int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
+int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int prot, 
int fd)
 {
/*
 * The last one will be done at perf_evlist__mmap_consume(), so that we
@@ -237,7 +237,7 @@ int perf_mmap__mmap(struct perf_mmap *map, struct 
mmap_params *mp, int fd)
refcount_set(&map->refcnt, 2);
map->prev = 0;
map->mask = mp->mask;
-   map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot,
+   map->base = mmap(NULL, perf_mmap__mmap_len(map), prot,
 MAP_SHARED, fd, 0);
if (map->base == MAP_FAILED) {
pr_debug2("failed to mmap perf event ring buffer, error %d\n",
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index 2c3d291..1f6fcc6 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -53,11 +53,11 @@ enum bkw_mmap_state {
 };
 
 struct mmap_params {
-   int prot, mask;
+   int mask;
struct auxtrace_mmap_params auxtrace_mp;
 };
 
-int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd);
+int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int prot, 
int fd);
 void perf_mmap__munmap(struct perf_mmap *map);
 
 void perf_mmap__get(struct perf_mmap *map);
-- 
2.10.1



[PATCH 5/7] perf tests: Set evlist of test__task_exit() to !overwrite

2017-11-12 Thread Wang Nan
Changing ringbuffer to !overwrite in this task is harmless because
this test uses a very low frequency (1) and using a very simple
program (true). There should have only 3 events in the whole test.
Overwriting is impossible to happen.

Signed-off-by: Wang Nan 
---
 tools/perf/tests/task-exit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index f0881d0..4fb6609 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -96,7 +96,7 @@ int test__task_exit(struct test *test __maybe_unused, int 
subtest __maybe_unused
goto out_delete_evlist;
}
 
-   if (perf_evlist__mmap(evlist, 128, true) < 0) {
+   if (perf_evlist__mmap(evlist, 128, false) < 0) {
pr_debug("failed to mmap events: %d (%s)\n", errno,
 str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
-- 
2.10.1



[PATCH 1/7] perf mmap: Fix perf backward recording

2017-11-12 Thread Wang Nan
perf record backward recording doesn't work as we expected: it never
overwrite when ring buffer full.

Test:

(Run a busy printing task background like this:

 while True:
 print 123

send SIGUSR2 to perf to capture snapshot.)

 # ./perf record --overwrite -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit 
--exclude-perf -a --switch-output
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101520743 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101521251 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101521692 ]
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Dump perf.data.2017110101521936 ]
 [ perf record: Captured and wrote 0.826 MB perf.data. ]

 # ./perf script -i ./perf.data.2017110101520743 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101521251 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101521692 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4

Timestamps are never change, but my background task is a dead loop, can
easily overwhelme the ring buffer.

This patch fix it by force unsetting PROT_WRITE for backward ring
buffer, so all backward ring buffer become overwrite ring buffer.

Test result:

 # ./perf record --overwrite -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit 
--exclude-perf -a --switch-output
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101285323 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101290053 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101290446 ]
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Dump perf.data.2017110101290837 ]
 [ perf record: Captured and wrote 0.826 MB perf.data. ]
 # ./perf script -i ./perf.data.2017110101285323 | head -n3
   python  2545 [000] 11064.268083:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11064.268084: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11064.268086:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101290 | head -n3
 failed to open ./perf.data.2017110101290: No such file or directory
 # ./perf script -i ./perf.data.2017110101290053 | head -n3
   python  2545 [000] 11071.564062: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11071.564064:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11071.564066: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
 # ./perf script -i ./perf.data.2017110101290 | head -n3
 perf.data.2017110101290053  perf.data.2017110101290446  
perf.data.2017110101290837
 # ./perf script -i ./perf.data.2017110101290446 | head -n3
 sshd  1321 [000] 11075.499473:  raw_syscalls:sys_exit: NR 14 = 0
 sshd  1321 [000] 11075.499474: raw_syscalls:sys_enter: NR 14 (2, 
7ffe98899490, 0, 8, 0, 3000)
 sshd  1321 [000] 11075.499474:  raw_syscalls:sys_exit: NR 14 = 0
 # ./perf script -i ./perf.data.2017110101290837 | head -n3
   python  2545 [000] 11079.280844:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11079.280847: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11079.280850:  raw_syscalls:sys_exit: NR 1 = 4

Signed-off-by: Wang Nan 
---
 tools/perf/util/evlist.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index c6c891e..4c5daba 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -799,22 +799,28 @@ perf_evlist__should_poll(struct perf_evlist *evlist 
__maybe_unused,
 }
 
 static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
-  struct mmap_params *mp, int cpu_idx,
+  struct mmap_params *_mp, int cpu_idx,
   int thread, int *_output, int 
*_output_bac

[PATCH 0/7] perf tools: Clarify overwrite and backward, bugfix

2017-11-12 Thread Wang Nan
Based on previous discussion, perf needs to support only two types
of ringbuffer: read-write + forward, readonly + backward. This patchset
completly removes the concept of 'overwrite' from code level, controls
mapping permission using write_backward instead.

Wang Nan (7):
  perf mmap: Fix perf backward recording
  perf tests: Set evlist of test__backward_ring_buffer() to !overwrite
  perf tests: Set evlist of test__sw_clock_freq() to !overwrite
  perf tests: Set evlist of test__basic_mmap() to !overwrite
  perf tests: Set evlist of test__task_exit() to !overwrite
  perf tools: Remove 'overwrite' concept from code level
  perf tools: Remove prot field in mmap param

 tools/perf/arch/x86/tests/perf-time-to-tsc.c |  2 +-
 tools/perf/builtin-kvm.c |  2 +-
 tools/perf/builtin-record.c  |  4 ++--
 tools/perf/builtin-top.c |  2 +-
 tools/perf/builtin-trace.c   |  2 +-
 tools/perf/tests/backward-ring-buffer.c  |  2 +-
 tools/perf/tests/bpf.c   |  2 +-
 tools/perf/tests/code-reading.c  |  2 +-
 tools/perf/tests/keep-tracking.c |  2 +-
 tools/perf/tests/mmap-basic.c|  2 +-
 tools/perf/tests/openat-syscall-tp-fields.c  |  2 +-
 tools/perf/tests/perf-record.c   |  2 +-
 tools/perf/tests/sw-clock.c  |  2 +-
 tools/perf/tests/switch-tracking.c   |  2 +-
 tools/perf/tests/task-exit.c |  2 +-
 tools/perf/util/evlist.c | 21 ++---
 tools/perf/util/evlist.h |  6 ++
 tools/perf/util/mmap.c   | 10 +-
 tools/perf/util/mmap.h   |  6 +++---
 tools/perf/util/python.c | 10 +-
 20 files changed, 41 insertions(+), 44 deletions(-)

-- 
2.10.1



[PATCH 3/7] perf tests: Set evlist of test__sw_clock_freq() to !overwrite

2017-11-12 Thread Wang Nan
Unsetting overwrite when calling perf_evlist__mmap is harmless. This commit
passes false to it, makes following commits eliminate the overwrite argument
easier.

Signed-off-by: Wang Nan 
---
 tools/perf/tests/sw-clock.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index d88511f..c468e6c 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -77,7 +77,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
goto out_delete_evlist;
}
 
-   err = perf_evlist__mmap(evlist, 128, true);
+   err = perf_evlist__mmap(evlist, 128, false);
if (err < 0) {
pr_debug("failed to mmap event: %d (%s)\n", errno,
 str_error_r(errno, sbuf, sizeof(sbuf)));
-- 
2.10.1



[PATCH 4/7] perf tests: Set evlist of test__basic_mmap() to !overwrite

2017-11-12 Thread Wang Nan
In this test, a large ring buffer is required so all events can feed into,
so overwrite or not is meaningless.

Change to !overwrite so following commits can remove this argument.

Signed-off-by: Wang Nan 
---
 tools/perf/tests/mmap-basic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index bc8a70e..667d696 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -93,7 +93,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int 
subtest __maybe_unuse
expected_nr_events[i] = 1 + rand() % 127;
}
 
-   if (perf_evlist__mmap(evlist, 128, true) < 0) {
+   if (perf_evlist__mmap(evlist, 128, false) < 0) {
pr_debug("failed to mmap events: %d (%s)\n", errno,
 str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
-- 
2.10.1



[PATCH 2/7] perf tests: Set evlist of test__backward_ring_buffer() to !overwrite

2017-11-12 Thread Wang Nan
Setting overwrite in perf_evlist__mmap() is meaningless because the
event in this evlist is already have 'overwrite' postfix and goes to
backward ring buffer automatically. Pass 'false' to perf_evlist__mmap()
to make it similar to others.

Signed-off-by: Wang Nan 
---
 tools/perf/tests/backward-ring-buffer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/backward-ring-buffer.c 
b/tools/perf/tests/backward-ring-buffer.c
index d233ad3..992c917 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -58,7 +58,7 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages,
int err;
char sbuf[STRERR_BUFSIZE];
 
-   err = perf_evlist__mmap(evlist, mmap_pages, true);
+   err = perf_evlist__mmap(evlist, mmap_pages, false);
if (err < 0) {
pr_debug("perf_evlist__mmap: %s\n",
 str_error_r(errno, sbuf, sizeof(sbuf)));
-- 
2.10.1



[PATCH 6/7] perf tools: Remove 'overwrite' concept from code level

2017-11-12 Thread Wang Nan
Since all 'overwrite' usage are cleaned and no one really use a readonly main
ringbuffer, remove 'overwrite' from function arguments and evlist. The concept
of 'overwrite' and 'write_backward' are cleanner than before:

  1. In code level, there's no 'overwrite' concept. Each evlist has two
 ringbuffer groups. One is read-write/forward, another is readonly/backward.
 Don't support read-write/backward and readonly/forward.

  2. In user interface, we keep '--overwrite' and translate it into 
write_backward
 in each event.

Signed-off-by: Wang Nan 
---
 tools/perf/arch/x86/tests/perf-time-to-tsc.c |  2 +-
 tools/perf/builtin-kvm.c |  2 +-
 tools/perf/builtin-record.c  |  4 ++--
 tools/perf/builtin-top.c |  2 +-
 tools/perf/builtin-trace.c   |  2 +-
 tools/perf/tests/backward-ring-buffer.c  |  2 +-
 tools/perf/tests/bpf.c   |  2 +-
 tools/perf/tests/code-reading.c  |  2 +-
 tools/perf/tests/keep-tracking.c |  2 +-
 tools/perf/tests/mmap-basic.c|  2 +-
 tools/perf/tests/openat-syscall-tp-fields.c  |  2 +-
 tools/perf/tests/perf-record.c   |  2 +-
 tools/perf/tests/sw-clock.c  |  2 +-
 tools/perf/tests/switch-tracking.c   |  2 +-
 tools/perf/tests/task-exit.c |  2 +-
 tools/perf/util/evlist.c | 14 ++
 tools/perf/util/evlist.h |  6 ++
 tools/perf/util/mmap.c   |  6 +++---
 tools/perf/util/mmap.h   |  2 +-
 tools/perf/util/python.c | 10 +-
 20 files changed, 33 insertions(+), 37 deletions(-)

diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c 
b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index 5dd7efb..c7ea843 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -83,7 +83,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, 
int subtest __maybe
 
CHECK__(perf_evlist__open(evlist));
 
-   CHECK__(perf_evlist__mmap(evlist, UINT_MAX, false));
+   CHECK__(perf_evlist__mmap(evlist, UINT_MAX));
 
pc = evlist->mmap[0].base;
ret = perf_read_tsc_conversion(pc, &tc);
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 0af4c09..e3e2a80 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1043,7 +1043,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
goto out;
}
 
-   if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
+   if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages) < 0) {
ui__error("Failed to mmap the events: %s\n",
  str_error_r(errno, sbuf, sizeof(sbuf)));
perf_evlist__close(evlist);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f4d9fc5..b3ef33f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -300,7 +300,7 @@ static int record__mmap_evlist(struct record *rec,
struct record_opts *opts = &rec->opts;
char msg[512];
 
-   if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
+   if (perf_evlist__mmap_ex(evlist, opts->mmap_pages,
 opts->auxtrace_mmap_pages,
 opts->auxtrace_snapshot_mode) < 0) {
if (errno == EPERM) {
@@ -481,7 +481,7 @@ static int record__mmap_read_evlist(struct record *rec, 
struct perf_evlist *evli
struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
 
if (maps[i].base) {
-   if (perf_mmap__push(&maps[i], evlist->overwrite, 
backward, rec, record__pushfn) != 0) {
+   if (perf_mmap__push(&maps[i], backward, rec, 
record__pushfn) != 0) {
rc = -1;
goto out;
}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 477a869..83d2ae2 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -902,7 +902,7 @@ static int perf_top__start_counters(struct perf_top *top)
}
}
 
-   if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
+   if (perf_evlist__mmap(evlist, opts->mmap_pages) < 0) {
ui__error("Failed to mmap with %d (%s)\n",
errno, str_error_r(errno, msg, sizeof(msg)));
goto out_err;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index c373f9a..c3f2f98 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2404,7 +2404,7 @@ static int trace__run(struct trace *trace, int argc, 

[RESEND PATCH] mm, oom_reaper: gather each vma to prevent leaking TLB entry

2017-11-07 Thread Wang Nan
tlb_gather_mmu(&tlb, mm, 0, -1) means gathering the whole virtual memory
space. In this case, tlb->fullmm is true. Some archs like arm64 doesn't
flush TLB when tlb->fullmm is true:

  commit 5a7862e83000 ("arm64: tlbflush: avoid flushing when fullmm == 1").

Which makes leaking of tlb entries.

Will clarifies his patch:

> Basically, we tag each address space with an ASID (PCID on x86) which
> is resident in the TLB. This means we can elide TLB invalidation when
> pulling down a full mm because we won't ever assign that ASID to another mm
> without doing TLB invalidation elsewhere (which actually just nukes the
> whole TLB).
>
> I think that means that we could potentially not fault on a kernel uaccess,
> because we could hit in the TLB.

There could be a window between complete_signal() sending IPI to other
cores and all threads sharing this mm are really kicked off from cores.
In this window, the oom reaper may calls tlb_flush_mmu_tlbonly() to flush
TLB then frees pages. However, due to the above problem, the TLB entries
are not really flushed on arm64. Other threads are possible to access
these pages through TLB entries. Moreover, a copy_to_user() can also
write to these pages without generating page fault, causes use-after-free
bugs.

This patch gathers each vma instead of gathering full vm space.
In this case tlb->fullmm is not true. The behavior of oom reaper become
similar to munmapping before do_exit, which should be safe for all archs.

Signed-off-by: Wang Nan 
Cc: Bob Liu 
Cc: Andrew Morton 
Cc: Michal Hocko 
Cc: David Rientjes 
Cc: Ingo Molnar 
Cc: Roman Gushchin 
Cc: Konstantin Khlebnikov 
Cc: Andrea Arcangeli 
---
 mm/oom_kill.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index dee0f75..18c5b35 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -532,7 +532,6 @@ static bool __oom_reap_task_mm(struct task_struct *tsk, 
struct mm_struct *mm)
 */
set_bit(MMF_UNSTABLE, &mm->flags);
 
-   tlb_gather_mmu(&tlb, mm, 0, -1);
for (vma = mm->mmap ; vma; vma = vma->vm_next) {
if (!can_madv_dontneed_vma(vma))
continue;
@@ -547,11 +546,13 @@ static bool __oom_reap_task_mm(struct task_struct *tsk, 
struct mm_struct *mm)
 * we do not want to block exit_mmap by keeping mm ref
 * count elevated without a good reason.
 */
-   if (vma_is_anonymous(vma) || !(vma->vm_flags & VM_SHARED))
+   if (vma_is_anonymous(vma) || !(vma->vm_flags & VM_SHARED)) {
+   tlb_gather_mmu(&tlb, mm, vma->vm_start, vma->vm_end);
unmap_page_range(&tlb, vma, vma->vm_start, vma->vm_end,
 NULL);
+   tlb_finish_mmu(&tlb, vma->vm_start, vma->vm_end);
+   }
}
-   tlb_finish_mmu(&tlb, 0, -1);
pr_info("oom_reaper: reaped process %d (%s), now anon-rss:%lukB, 
file-rss:%lukB, shmem-rss:%lukB\n",
task_pid_nr(tsk), tsk->comm,
K(get_mm_counter(mm, MM_ANONPAGES)),
-- 
2.10.1



[RFC PATCH] mm, oom_reaper: gather each vma to prevent leaking TLB entry

2017-11-05 Thread Wang Nan
tlb_gather_mmu(&tlb, mm, 0, -1) means gathering all virtual memory space.
In this case, tlb->fullmm is true. Some archs like arm64 doesn't flush
TLB when tlb->fullmm is true:

  commit 5a7862e83000 ("arm64: tlbflush: avoid flushing when fullmm == 1").

Which makes leaking of tlb entries. For example, when oom_reaper
selects a task and reaps its virtual memory space, another thread
in this task group may still running on another core and access
these already freed memory through tlb entries.

This patch gather each vma instead of gathering full vm space,
tlb->fullmm is not true. The behavior of oom reaper become similar
to munmapping before do_exit, which should be safe for all archs.

Signed-off-by: Wang Nan 
Cc: Bob Liu 
Cc: Michal Hocko 
Cc: Andrew Morton 
Cc: Michal Hocko 
Cc: David Rientjes 
Cc: Ingo Molnar 
Cc: Roman Gushchin 
Cc: Konstantin Khlebnikov 
Cc: Andrea Arcangeli 
---
 mm/oom_kill.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index dee0f75..18c5b35 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -532,7 +532,6 @@ static bool __oom_reap_task_mm(struct task_struct *tsk, 
struct mm_struct *mm)
 */
set_bit(MMF_UNSTABLE, &mm->flags);
 
-   tlb_gather_mmu(&tlb, mm, 0, -1);
for (vma = mm->mmap ; vma; vma = vma->vm_next) {
if (!can_madv_dontneed_vma(vma))
continue;
@@ -547,11 +546,13 @@ static bool __oom_reap_task_mm(struct task_struct *tsk, 
struct mm_struct *mm)
 * we do not want to block exit_mmap by keeping mm ref
 * count elevated without a good reason.
 */
-   if (vma_is_anonymous(vma) || !(vma->vm_flags & VM_SHARED))
+   if (vma_is_anonymous(vma) || !(vma->vm_flags & VM_SHARED)) {
+   tlb_gather_mmu(&tlb, mm, vma->vm_start, vma->vm_end);
unmap_page_range(&tlb, vma, vma->vm_start, vma->vm_end,
 NULL);
+   tlb_finish_mmu(&tlb, vma->vm_start, vma->vm_end);
+   }
}
-   tlb_finish_mmu(&tlb, 0, -1);
pr_info("oom_reaper: reaped process %d (%s), now anon-rss:%lukB, 
file-rss:%lukB, shmem-rss:%lukB\n",
task_pid_nr(tsk), tsk->comm,
K(get_mm_counter(mm, MM_ANONPAGES)),
-- 
2.10.1



[PATCH 2/2] perf record: Replace 'overwrite' by 'flightrecorder' for better naming

2017-10-31 Thread Wang Nan
The meaning of perf record's "overwrite" option and many "overwrite" in
source code are not clear. In perf's code, the 'overwrite' has 2 meanings:
 1. Make ringbuffer readonly (perf_evlist__mmap_ex's argument).
 2. Set evsel's "backward" attribute (in apply_config_terms).

perf record doesn't use meaning 1 at all, but have a overwrite option, its
real meaning is setting backward.

This patch separates these two concepts, introduce 'flightrecorder' mode
which is what we really want. It combines these 2 concept together, wraps
them into a record mode. In flight recorder mode, perf only dumps data before
something happen.

Signed-off-by: Wang Nan 
---
 tools/perf/Documentation/perf-record.txt |  8 
 tools/perf/builtin-record.c  |  4 ++--
 tools/perf/perf.h|  2 +-
 tools/perf/util/evsel.c  |  6 +++---
 tools/perf/util/evsel.h  |  4 ++--
 tools/perf/util/parse-events.c   | 20 ++--
 tools/perf/util/parse-events.h   |  4 ++--
 tools/perf/util/parse-events.l   |  4 ++--
 8 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt 
b/tools/perf/Documentation/perf-record.txt
index 5a626ef..463c2d3 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -467,19 +467,19 @@ the beginning of record, collect them during finalizing 
an output file.
 The collected non-sample events reflects the status of the system when
 record is finished.
 
---overwrite::
+--flight-recorder::
 Makes all events use an overwritable ring buffer. An overwritable ring
 buffer works like a flight recorder: when it gets full, the kernel will
 overwrite the oldest records, that thus will never make it to the
 perf.data file.
 
-When '--overwrite' and '--switch-output' are used perf records and drops
+When '--flight-recorder' and '--switch-output' are used perf records and drops
 events until it receives a signal, meaning that something unusual was
 detected that warrants taking a snapshot of the most current events,
 those fitting in the ring buffer at that moment.
 
-'overwrite' attribute can also be set or canceled for an event using
-config terms. For example: 'cycles/overwrite/' and 
'instructions/no-overwrite/'.
+'flightrecorder' attribute can also be set or canceled separately for an event 
using
+config terms. For example: 'cycles/flightrecorder/' and 
'instructions/no-flightrecorder/'.
 
 Implies --tail-synthesize.
 
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f4d9fc5..315ea09 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1489,7 +1489,7 @@ static struct option __record_options[] = {
"child tasks do not inherit counters"),
OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
"synthesize non-sample events at the end of output"),
-   OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite 
mode"),
+   OPT_BOOLEAN(0, "flight-recoder", &record.opts.flight_recorder, "use 
flight recoder mode"),
OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this 
frequency"),
OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
 "number of mmap data pages and AUX area tracing mmap 
pages",
@@ -1733,7 +1733,7 @@ int cmd_record(int argc, const char **argv)
}
}
 
-   if (record.opts.overwrite)
+   if (record.opts.flight_recorder)
record.opts.tail_synthesize = true;
 
if (rec->evlist->nr_entries == 0 &&
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index fbb0a9c..a7f7618 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -57,7 +57,7 @@ struct record_opts {
bool all_kernel;
bool all_user;
bool tail_synthesize;
-   bool overwrite;
+   bool flight_recorder;
bool ignore_missing_thread;
unsigned int freq;
unsigned int mmap_pages;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index f894893..0e1e8e8 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -772,8 +772,8 @@ static void apply_config_terms(struct perf_evsel *evsel,
 */
attr->inherit = term->val.inherit ? 1 : 0;
break;
-   case PERF_EVSEL__CONFIG_TERM_OVERWRITE:
-   attr->write_backward = term->val.overwrite ? 1

[PATCH 0/2] perf record: Fix --overwrite and clarify concepts

2017-10-31 Thread Wang Nan
Kan reports that 'perf record --overwrite' not working as it should be.

Patch 1/2 fix a bug, map backward events to readonly ring buffer so kernel
can overwrite that ring buffer.

Patch 2/2 clarify concepts of 'overwrite' and 'backward' in the source code
by introducing the concept of 'flightrecorder' and convert many 'overwrite'
to it to clarify that what we really want is a perf record flightrecorder
mode, not only mapping the ring buffer overwritable.

Wang Nan (2):
  perf mmap: Fix perf backward recording
  perf record: Replace 'overwrite' by 'flightrecorder' for better naming

 tools/perf/Documentation/perf-record.txt |  8 
 tools/perf/builtin-record.c  |  4 ++--
 tools/perf/perf.h|  2 +-
 tools/perf/util/evlist.c |  8 +++-
 tools/perf/util/evsel.c  |  6 +++---
 tools/perf/util/evsel.h  |  4 ++--
 tools/perf/util/parse-events.c   | 20 ++--
 tools/perf/util/parse-events.h   |  4 ++--
 tools/perf/util/parse-events.l   |  4 ++--
 9 files changed, 33 insertions(+), 27 deletions(-)

-- 
2.10.1



[PATCH 1/2] perf mmap: Fix perf backward recording

2017-10-31 Thread Wang Nan
perf record backward recording doesn't work as we expected: it never
overwrite when ring buffer full.

Test:

(Run a busy printing python task background like this:

 while True:
 print 123

send SIGUSR2 to perf to capture snapshot.)

 # ./perf record --overwrite -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit 
--exclude-perf -a --switch-output
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101520743 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101521251 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101521692 ]
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Dump perf.data.2017110101521936 ]
 [ perf record: Captured and wrote 0.826 MB perf.data. ]

 # ./perf script -i ./perf.data.2017110101520743 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101521251 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101521692 | head -n3
 perf  2717 [000] 12449.310785: raw_syscalls:sys_enter: NR 16 (5, 
2400, 0, 59, 100, 0)
 perf  2717 [000] 12449.310790: raw_syscalls:sys_enter: NR 7 
(4112340, 2, , 3df, 100, 0)
   python  2545 [000] 12449.310800:  raw_syscalls:sys_exit: NR 1 = 4

Timestamps are never change, but my background task is a dead loop, can
easily overwhelme the ring buffer.

This patch fix it by force unsetting PROT_WRITE for backward ring
buffer, so all backward ring buffer become overwrite ring buffer.

Test result:

 # ./perf record --overwrite -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit 
--exclude-perf -a --switch-output
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101285323 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101290053 ]
 [ perf record: dump data: Woken up 1 times ]
 [ perf record: Dump perf.data.2017110101290446 ]
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Dump perf.data.2017110101290837 ]
 [ perf record: Captured and wrote 0.826 MB perf.data. ]
 # ./perf script -i ./perf.data.2017110101285323 | head -n3
   python  2545 [000] 11064.268083:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11064.268084: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11064.268086:  raw_syscalls:sys_exit: NR 1 = 4
 # ./perf script -i ./perf.data.2017110101290 | head -n3
 failed to open ./perf.data.2017110101290: No such file or directory
 # ./perf script -i ./perf.data.2017110101290053 | head -n3
   python  2545 [000] 11071.564062: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11071.564064:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11071.564066: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
 # ./perf script -i ./perf.data.2017110101290 | head -n3
 perf.data.2017110101290053  perf.data.2017110101290446  
perf.data.2017110101290837
 # ./perf script -i ./perf.data.2017110101290446 | head -n3
 sshd  1321 [000] 11075.499473:  raw_syscalls:sys_exit: NR 14 = 0
 sshd  1321 [000] 11075.499474: raw_syscalls:sys_enter: NR 14 (2, 
7ffe98899490, 0, 8, 0, 3000)
 sshd  1321 [000] 11075.499474:  raw_syscalls:sys_exit: NR 14 = 0
 # ./perf script -i ./perf.data.2017110101290837 | head -n3
   python  2545 [000] 11079.280844:  raw_syscalls:sys_exit: NR 1 = 4
   python  2545 [000] 11079.280847: raw_syscalls:sys_enter: NR 1 (1, 
12cc330, 4, 7fc237280370, 7fc2373d0700, 2c7b0)
   python  2545 [000] 11079.280850:  raw_syscalls:sys_exit: NR 1 = 4

Signed-off-by: Wang Nan 
---
 tools/perf/util/evlist.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index c6c891e..4c5daba 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -799,22 +799,28 @@ perf_evlist__should_poll(struct perf_evlist *evlist 
__maybe_unused,
 }
 
 static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
-  struct mmap_params *mp, int cpu_idx,
+  struct mmap_params *_mp, int cpu_idx,
   int thread, int *_output

[PATCH] perf tool: Don't discard prev in backward mode

2017-10-12 Thread Wang Nan
Perf record can switch output. The new output should only store the
data after switching. However, in overwrite backward mode, the new
output still have the data from old output. That also brings extra overhead.

At the end of mmap_read, the position of processed ring buffer is
saved in md->prev. Next mmap_read should be end in md->prev if it is
not overwriten. That avoids to process duplicate data.
However, the md->prev is discarded. So next mmap_read has to process
whole valid ring buffer, which probably include the old processed
data.

Avoid calling backward_rb_find_range() when md->prev is still
available.

Signed-off-by: Wang Nan 
Cc: Liang Kan 
---
 tools/perf/util/mmap.c | 33 +++--
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 9fe5f9c..df1de55 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -287,18 +287,6 @@ static int backward_rb_find_range(void *buf, int mask, u64 
head, u64 *start, u64
return -1;
 }
 
-static int rb_find_range(void *data, int mask, u64 head, u64 old,
-u64 *start, u64 *end, bool backward)
-{
-   if (!backward) {
-   *start = old;
-   *end = head;
-   return 0;
-   }
-
-   return backward_rb_find_range(data, mask, head, start, end);
-}
-
 int perf_mmap__push(struct perf_mmap *md, bool overwrite, bool backward,
void *to, int push(void *to, void *buf, size_t size))
 {
@@ -310,19 +298,28 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite, 
bool backward,
void *buf;
int rc = 0;
 
-   if (rb_find_range(data, md->mask, head, old, &start, &end, backward))
-   return -1;
+   start = backward ? head : old;
+   end = backward ? old : head;
 
if (start == end)
return 0;
 
size = end - start;
if (size > (unsigned long)(md->mask) + 1) {
-   WARN_ONCE(1, "failed to keep up with mmap data. (warn only 
once)\n");
+   if (!backward) {
+   WARN_ONCE(1, "failed to keep up with mmap data. (warn 
only once)\n");
 
-   md->prev = head;
-   perf_mmap__consume(md, overwrite || backward);
-   return 0;
+   md->prev = head;
+   perf_mmap__consume(md, overwrite || backward);
+   return 0;
+   }
+
+   /*
+* Backward ring buffer is full. We still have a chance to read
+* most of data from it.
+*/
+   if (backward_rb_find_range(data, md->mask, head, &start, &end))
+   return -1;
}
 
if ((start & md->mask) + size != (end & md->mask)) {
-- 
2.9.3



[PATCH] perf tools: fix: Force backward ring buffer mapped readonly

2017-10-10 Thread Wang Nan
perf record's --overwrite option doesn't work as we expect.
For example:

$ ~/linux/tools/perf$ sudo rm ./perf.data*
rm: cannot remove './perf.data*': No such file or directory
: ~/linux/tools/perf$ sudo ./perf record -m 4 -e raw_syscalls:* -g 
--overwrite \
--switch-output=1s --tail-synthesize   
dd if=/dev/zero of=/dev/null
[ perf record: dump data: Woken up 1 times ]
[ perf record: Dump perf.data.2017101221460002 ]
[ perf record: dump data: Woken up 1 times ]
[ perf record: Dump perf.data.2017101221460102 ]
[ perf record: dump data: Woken up 1 times ]
[ perf record: Dump perf.data.2017101221460202 ]
[ perf record: dump data: Woken up 1 times ]
[ perf record: Dump perf.data.2017101221460302 ]
^C[ perf record: Woken up 1 times to write data ]
2066346+0 records in
2066346+0 records out
1057969152 bytes (1.1 GB, 1009 MiB) copied, 4.25983 s, 248 MB/s
[ perf record: Dump perf.data.2017101221460332 ]
[ perf record: Captured and wrote 0.034 MB perf.data. ]

$ ~/linux/tools/perf$ sudo ./perf script -i ./perf.data.2017101221460002 | 
head -n 1
dd  3918 [006] 182589.668954:  raw_syscalls:sys_exit: NR 59 = 0
$ ~/linux/tools/perf$ sudo ./perf script -i ./perf.data.2017101221460102 | 
head -n 1
dd  3918 [006] 182589.668954:  raw_syscalls:sys_exit: NR 59 = 0
$ ~/linux/tools/perf$ sudo ./perf script -i ./perf.data.2017101221460202 | 
head -n 1
dd  3918 [006] 182589.668954:  raw_syscalls:sys_exit: NR 59 = 0
$ ~/linux/tools/perf$ sudo ./perf script -i ./perf.data.2017101221460302 | 
head -n 1
dd  3918 [006] 182589.668954:  raw_syscalls:sys_exit: NR 59 = 0

In the above example we get same records from the backward ring buffer
all the time. Overwriting is not triggered.

This commit maps backward ring buffers readonly, make it overwritable.
It is safe because we assume backward ring buffer always overwritable
in other part of code.

After applying this patch:

$ ~/linux/tools/perf$ sudo ./perf record -m 4 -e raw_syscalls:* -g 
--overwrite \
   --switch-output=1s --tail-synthesize   dd 
if=/dev/zero of=/dev/null
[ perf record: dump data: Woken up 1 times ]
[ perf record: Dump perf.data.2017101221540350 ]
[ perf record: dump data: Woken up 1 times ]
[ perf record: Dump perf.data.2017101221540451 ]
[ perf record: dump data: Woken up 1 times ]
[ perf record: Dump perf.data.2017101221540551 ]
[ perf record: dump data: Woken up 1 times ]
[ perf record: Dump perf.data.2017101221540651 ]
^C[ perf record: Woken up 1 times to write data ]
1604606+0 records in
1604605+0 records out
821557760 bytes (822 MB, 783 MiB) copied, 4.42736 s, 186 MB/s
[ perf record: Dump perf.data.2017101221540700 ]
[ perf record: Captured and wrote 0.034 MB perf.data. ]

$ ~/linux/tools/perf$ sudo ./perf script -i ./perf.data.2017101221540350 | 
head -n 1
dd  5126 [003] 183074.104581:  raw_syscalls:sys_exit: NR 0 = 512
$ ~/linux/tools/perf$ sudo ./perf script -i ./perf.data.2017101221540451 | 
head -n 1
dd  5126 [003] 183075.106496:  raw_syscalls:sys_exit: NR 1 = 512
$ ~/linux/tools/perf$ sudo ./perf script -i ./perf.data.2017101221540551 | 
head -n 1
dd  5126 [003] 183076.108093: raw_syscalls:sys_enter: NR 1 (1, af8000, 200, 
871, 0, af8060)
$ ~/linux/tools/perf$ sudo ./perf script -i ./perf.data.2017101221540651 | 
head -n 1
dd  5126 [003] 183077.109676:  raw_syscalls:sys_exit: NR 1 = 512


Signed-off-by: Wang Nan 
Cc: Liang Kan 
Cc: Arnaldo Carvalho de Melo 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Jiri Olsa 
Cc: Namhyung Kim 
Cc: Alexander Shishkin 
Cc: Adrian Hunter 
Cc: Andi Kleen 
Cc: Li Zefan 
---
 tools/perf/util/evlist.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index c6c891e..a86b0d2 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -799,12 +799,14 @@ perf_evlist__should_poll(struct perf_evlist *evlist 
__maybe_unused,
 }
 
 static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
-  struct mmap_params *mp, int cpu_idx,
+  struct mmap_params *_mp, int cpu_idx,
   int thread, int *_output, int 
*_output_backward)
 {
struct perf_evsel *evsel;
int revent;
int evlist_cpu = cpu_map__cpu(evlist->cpus, cpu_idx);
+   struct mmap_params *mp = _mp;
+   struct mmap_params backward_mp;
 
evlist__for_each_entry(evlist, evsel) {
struct perf_mmap *maps = evlist->mmap;
@@ -815,6 +817,9 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist 
*evlist, int idx,
if (evsel->attr.write_backward) {
output = _output_backward;
   

[tip:perf/core] perf bpf: Fix endianness problem when loading parameters in prologue

2017-08-17 Thread tip-bot for Wang Nan
Commit-ID:  db26984a363e8b8e35783c402978e8acdf9041a5
Gitweb: http://git.kernel.org/tip/db26984a363e8b8e35783c402978e8acdf9041a5
Author: Wang Nan 
AuthorDate: Tue, 15 Aug 2017 11:21:59 +0200
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Wed, 16 Aug 2017 10:31:11 -0300

perf bpf: Fix endianness problem when loading parameters in prologue

Perf's BPF prologue generator unconditionally fetches 8 bytes for
function parameters, which causes problems on big endian machines. Thomas
gives a detailed analysis for this problem:

 
http://lkml.kernel.org/r/968ebda5-abe4-8830-8d69-49f62529d...@linux.vnet.ibm.com

  8< 
  I investigated perf test BPF for s390x and have a question regarding
  the 38.3 subtest (bpf-prologue test) which fails on s390x.

  When I turn on trace_printk in tests/bpf-script-test-prologue.c
  I see this output in /sys/kernel/debug/tracing/trace:

  [root@s8360047 perf]# cat /sys/kernel/debug/tracing/trace
  perf-30229 [000] d..2 170161.535791: : f_mode 2001d offset:0 orig:0
  perf-30229 [000] d..2 170161.535809: : f_mode 6001f offset:0 orig:0
  perf-30229 [000] d..2 170161.535815: : f_mode 6001f offset:1 orig:0
  perf-30229 [000] d..2 170161.535819: : f_mode 2001d offset:1 orig:0
  perf-30229 [000] d..2 170161.535822: : f_mode 2001d offset:2 orig:1
  perf-30229 [000] d..2 170161.535825: : f_mode 6001f offset:2 orig:1
  perf-30229 [000] d..2 170161.535828: : f_mode 6001f offset:3 orig:1
  perf-30229 [000] d..2 170161.535832: : f_mode 2001d offset:3 orig:1
  perf-30229 [000] d..2 170161.535835: : f_mode 2001d offset:4 orig:0
  perf-30229 [000] d..2 170161.535841: : f_mode 6001f offset:4 orig:0

  [...]

  There are 3 parameters the eBPF program tests/bpf-script-test-prologue.c
  accesses: f_mode (member of struct file at offset 140) offset and orig.  They
  are parameters of the lseek() system call triggered in this test case in
  function llseek_loop().

  What is really strange is the value of f_mode. It is an 8 byte value, whereas
  in the probe event it is defined as a 4 byte value.  The lower 4 bytes are all
  zero and do not belong to member f_mode.  The correct value should be 2001d 
for
  read-only and 6001f for read-write open mode.

  Here is the output of the 'perf test -vv bpf' trace:
  Try to find probe point from debuginfo.
  Matched function: null_lseek [2d9310d]
   Probe point found: null_lseek+0
  Searching 'file' variable in context.
  Converting variable file into trace event.
  converting f_mode in file
  f_mode type is unsigned int.
  Opening /sys/kernel/debug/tracing//README write=0
  Searching 'offset' variable in context.
  Converting variable offset into trace event.
  offset type is long long int.
  Searching 'orig' variable in context.
  Converting variable orig into trace event.
  orig type is int.
  Found 1 probe_trace_events.
  Opening /sys/kernel/debug/tracing//kprobe_events write=1
  Writing event: p:perf_bpf_probe/func _text+8794224 f_mode=+140(%r2):x32
  8< 

This patch parses the type of each argument and converts data from memory to
expected type.

Now the test runs successfully on 4.13.0-rc5:

  [root@s8360046 perf]# ./perf test  bpf
  38: BPF filter :
  38.1: Basic BPF filtering  : Ok
  38.2: BPF pinning  : Ok
  38.3: BPF prologue generation  : Ok
  38.4: BPF relocation checker   : Ok
  [root@s8360046 perf]#

Signed-off-by: Wang Nan 
Cc: Hendrik Brueckner 
Link: http://lkml.kernel.org/r/20170815092159.31912-1-tmri...@linux.vnet.ibm.com
Signed-off-by: Thomas-Mich Richter 
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/tests/bpf-script-test-prologue.c |  4 ++-
 tools/perf/util/bpf-prologue.c  | 49 +++--
 2 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/tools/perf/tests/bpf-script-test-prologue.c 
b/tools/perf/tests/bpf-script-test-prologue.c
index b4ebc75..43f1e16 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -26,9 +26,11 @@ static void (*bpf_trace_printk)(const char *fmt, int 
fmt_size, ...) =
(void *) 6;
 
 SEC("func=null_lseek file->f_mode offset orig")
-int bpf_func__null_lseek(void *ctx, int err, unsigned long f_mode,
+int bpf_func__null_lseek(void *ctx, int err, unsigned long _f_mode,
 unsigned long offset, unsigned long orig)
 {
+   fmode_t f_mode = (fmode_t)_f_mode;
+
if (err)
return 0;
if (f_mode & FMODE_WRITE)
diff --git a/tools/perf/util/bpf-prologue.c b/tools/perf/util/bpf-prologue.c
index 1356220..827f914 100644
--- a/tools/perf/util/bpf-prologue.c
+++ b/tools/perf/util/bpf-prologue.c
@@ -58,6 +58,46 @@ check_pos(struct bpf_insn_pos *pos)
return 0;
 }
 

[PATCH] perf bpf: Fix endianness problem when loading parameters in prologue

2017-08-11 Thread Wang Nan
Perf BPF prologue generator unconditionally fetches 8 bytes for function
parameters, which causes problem on big endian machine. Thomas gives a
detail analysis for this problem:

 
http://lkml.kernel.org/r/968ebda5-abe4-8830-8d69-49f62529d...@linux.vnet.ibm.com

This patch parses the type of each argument and converts data from
memory to expected type.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Thomas Richter 
Cc: Alexei Starovoitov 
Cc: Hendrik Brueckner 
Cc: Li Zefan 
---
 tools/perf/tests/bpf-script-test-prologue.c |  4 ++-
 tools/perf/util/bpf-prologue.c  | 49 +++--
 2 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/tools/perf/tests/bpf-script-test-prologue.c 
b/tools/perf/tests/bpf-script-test-prologue.c
index b4ebc75..43f1e16 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -26,9 +26,11 @@ static void (*bpf_trace_printk)(const char *fmt, int 
fmt_size, ...) =
(void *) 6;
 
 SEC("func=null_lseek file->f_mode offset orig")
-int bpf_func__null_lseek(void *ctx, int err, unsigned long f_mode,
+int bpf_func__null_lseek(void *ctx, int err, unsigned long _f_mode,
 unsigned long offset, unsigned long orig)
 {
+   fmode_t f_mode = (fmode_t)_f_mode;
+
if (err)
return 0;
if (f_mode & FMODE_WRITE)
diff --git a/tools/perf/util/bpf-prologue.c b/tools/perf/util/bpf-prologue.c
index 6cdbee1..ce28993 100644
--- a/tools/perf/util/bpf-prologue.c
+++ b/tools/perf/util/bpf-prologue.c
@@ -57,6 +57,46 @@ check_pos(struct bpf_insn_pos *pos)
return 0;
 }
 
+/*
+ * Convert type string (u8/u16/u32/u64/s8/s16/s32/s64 ..., see
+ * Documentation/trace/kprobetrace.txt) to size field of BPF_LDX_MEM
+ * instruction (BPF_{B,H,W,DW}).
+ */
+static int
+argtype_to_ldx_size(const char *type)
+{
+   int arg_size = type ? atoi(&type[1]) : 64;
+
+   switch (arg_size) {
+   case 8:
+   return BPF_B;
+   case 16:
+   return BPF_H;
+   case 32:
+   return BPF_W;
+   case 64:
+   default:
+   return BPF_DW;
+   }
+}
+
+static const char *
+insn_sz_to_str(int insn_sz)
+{
+   switch (insn_sz) {
+   case BPF_B:
+   return "BPF_B";
+   case BPF_H:
+   return "BPF_H";
+   case BPF_W:
+   return "BPF_W";
+   case BPF_DW:
+   return "BPF_DW";
+   default:
+   return "UNKNOWN";
+   }
+}
+
 /* Give it a shorter name */
 #define ins(i, p) append_insn((i), (p))
 
@@ -257,9 +297,14 @@ gen_prologue_slowpath(struct bpf_insn_pos *pos,
}
 
/* Final pass: read to registers */
-   for (i = 0; i < nargs; i++)
-   ins(BPF_LDX_MEM(BPF_DW, BPF_PROLOGUE_START_ARG_REG + i,
+   for (i = 0; i < nargs; i++) {
+   int insn_sz = argtype_to_ldx_size(args[i].type);
+
+   pr_debug("prologue: load arg %d, insn_sz is %s\n",
+i, insn_sz_to_str(insn_sz));
+   ins(BPF_LDX_MEM(insn_sz, BPF_PROLOGUE_START_ARG_REG + i,
BPF_REG_FP, -BPF_REG_SIZE * (i + 1)), pos);
+   }
 
ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_SUCCESS_CODE), pos);
 
-- 
2.10.1



[PATCH] perf test llvm: Fix f_mode endianness problem

2017-08-10 Thread Wang Nan
Perf BPF prologue generator unconditionally fetches 8 bytes for function
parameters. On big endian machine, a casting is resquired if the parameter
is not u64.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Thomas Richter 
Cc: Alexei Starovoitov 
Cc: Hendrik Brueckner 
Cc: Li Zefan 
---
 tools/perf/tests/bpf-script-test-prologue.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tools/perf/tests/bpf-script-test-prologue.c 
b/tools/perf/tests/bpf-script-test-prologue.c
index b4ebc75..43f1e16 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -26,9 +26,11 @@ static void (*bpf_trace_printk)(const char *fmt, int 
fmt_size, ...) =
(void *) 6;
 
 SEC("func=null_lseek file->f_mode offset orig")
-int bpf_func__null_lseek(void *ctx, int err, unsigned long f_mode,
+int bpf_func__null_lseek(void *ctx, int err, unsigned long _f_mode,
 unsigned long offset, unsigned long orig)
 {
+   fmode_t f_mode = (fmode_t)_f_mode;
+
if (err)
return 0;
if (f_mode & FMODE_WRITE)
-- 
2.10.1



[tip:perf/core] perf test llvm: Avoid error when PROFILE_ALL_BRANCHES is set

2017-06-20 Thread tip-bot for Wang Nan
Commit-ID:  9b57fb7e35957c6838f89f4ed7e3f8433a4bbfc5
Gitweb: http://git.kernel.org/tip/9b57fb7e35957c6838f89f4ed7e3f8433a4bbfc5
Author: Wang Nan 
AuthorDate: Wed, 21 Jun 2017 02:32:03 +0800
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 19 Jun 2017 16:11:26 -0300

perf test llvm: Avoid error when PROFILE_ALL_BRANCHES is set

The 'if' keyword is a define that expands to complex code when
CONFIG_PROFILE_ALL_BRANCHES is selected, which causes a 'perf test LLVM'
failure like:

  $ ./perf test LLVM
  35: LLVM search and compile:
  35.1: Basic BPF llvm compile: Ok
  35.2: kbuild searching  : Ok
  35.3: Compile source for BPF prologue generation: FAILED!
  35.4: Compile source for BPF relocation : Skip

The only affected test case is bpf-script-test-prologue.c
because it uses kernel headers and has 'if' inside.

This patch undefines 'if' to make it passes perf test.

More detailed analysis from a message in this thread, also by Wang:

The problem is caused by following relocation information:

  $ readelf -a ./llvmsubtest3
  ...
 [ 5] _ftrace_branchPROGBITS   0260
  00a0    WA   0 0 4
  ...
  Relocation section '.relfunc=null_lseek file->f_mode offset orig' at
  offset 0x490 contains 4 entries:
 Offset  Info   Type   Sym. ValueSym. Name
  0038  000b0001 unrecognized: 1    
_ftrace_branch
  00b0  000b0001 unrecognized: 1    
_ftrace_branch
  0128  000b0001 unrecognized: 1    
_ftrace_branch
  01c0  000b0001 unrecognized: 1    
_ftrace_branch

  Relocation section '.rel_ftrace_branch' at offset 0x4d0 contains 8 entries:
 Offset  Info   Type   Sym. ValueSym. Name
    00020001 unrecognized: 1    
.L__func__.bpf_func__n
  0008  00010001 unrecognized: 1   0015 .L.str
  0028  00020001 unrecognized: 1    
.L__func__.bpf_func__n
  0030  00010001 unrecognized: 1   0015 .L.str
  0050  00020001 unrecognized: 1    
.L__func__.bpf_func__n
  0058  00010001 unrecognized: 1   0015 .L.str
  0078  00020001 unrecognized: 1    
.L__func__.bpf_func__n
  0080  00010001 unrecognized: 1   0015 .L.str
  ...

So I think the failure is because you enabled CONFIG_PROFILE_ALL_BRANCHES.

I can reproduce your buggy result by selecting
CONFIG_PROFILE_ALL_BRANCHES in my kbuild:

  $ ./perf test LLVM
  35: LLVM search and compile:
  35.1: Basic BPF llvm compile: Ok
  35.2: kbuild searching  : Ok
  35.3: Compile source for BPF prologue generation: FAILED!
  35.4: Compile source for BPF relocation : Skip

Simply undef CONFIG_PROFILE_ALL_BRANCHES in clang opts not working
because it is introduced by "#include ", which override
cmdline options. So I think the best way is to undefine 'if' inside BPF
script.

Reported-and-Tested-by: Thomas-Mich Richter 
Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: Hendrik Brueckner 
Cc: Zefan Li 
Link: http://lkml.kernel.org/r/20170620183203.2517-1-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/tests/bpf-script-test-prologue.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/tools/perf/tests/bpf-script-test-prologue.c 
b/tools/perf/tests/bpf-script-test-prologue.c
index 7230e62..b4ebc75 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -10,6 +10,15 @@
 
 #include 
 
+/*
+ * If CONFIG_PROFILE_ALL_BRANCHES is selected,
+ * 'if' is redefined after include kernel header.
+ * Recover 'if' for BPF object code.
+ */
+#ifdef if
+# undef if
+#endif
+
 #define FMODE_READ 0x1
 #define FMODE_WRITE0x2
 


[PATCH] perf test llvm: Avoid error when PROFILE_ALL_BRANCHES is set

2017-06-19 Thread Wang Nan
'if' is defined to complex code when CONFIG_PROFILE_ALL_BRANCHES is
selected, which cause a 'perf test LLVM' failure like:

 $ ./perf test LLVM
 35: LLVM search and compile:
 35.1: Basic BPF llvm compile: Ok
 35.2: kbuild searching  : Ok
 35.3: Compile source for BPF prologue generation: FAILED!
 35.4: Compile source for BPF relocation : Skip

The only affected test case is bpf-script-test-prologue.c
because it uses kernel headers and has 'if' inside.

This patch undefines 'if' to make it passes perf test.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Thomas-Mich Richter 
Cc: Hendrik Brueckner 
Cc: Alexei Starovoitov 
Cc: Li Zefan 
---
 tools/perf/tests/bpf-script-test-prologue.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/tools/perf/tests/bpf-script-test-prologue.c 
b/tools/perf/tests/bpf-script-test-prologue.c
index 7230e62..b4ebc75 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -10,6 +10,15 @@
 
 #include 
 
+/*
+ * If CONFIG_PROFILE_ALL_BRANCHES is selected,
+ * 'if' is redefined after include kernel header.
+ * Recover 'if' for BPF object code.
+ */
+#ifdef if
+# undef if
+#endif
+
 #define FMODE_READ 0x1
 #define FMODE_WRITE0x2
 
-- 
2.9.3



[PATCH -stable 4.1 2/2] perf/core: Fix concurrent sys_perf_event_open() vs. 'move_group' race

2017-02-24 Thread Wang Nan
From: Peter Zijlstra 

[ Upstream commit 321027c1fe77f892f4ea07846aeae08cefbbb290 ]

Di Shen reported a race between two concurrent sys_perf_event_open()
calls where both try and move the same pre-existing software group
into a hardware context.

The problem is exactly that described in commit:

  f63a8daa5812 ("perf: Fix event->ctx locking")

... where, while we wait for a ctx->mutex acquisition, the event->ctx
relation can have changed under us.

That very same commit failed to recognise sys_perf_event_context() as an
external access vector to the events and thereby didn't apply the
established locking rules correctly.

So while one sys_perf_event_open() call is stuck waiting on
mutex_lock_double(), the other (which owns said locks) moves the group
about. So by the time the former sys_perf_event_open() acquires the
locks, the context we've acquired is stale (and possibly dead).

Apply the established locking rules as per perf_event_ctx_lock_nested()
to the mutex_lock_double() for the 'move_group' case. This obviously means
we need to validate state after we acquire the locks.

CVE-2017-6001

Reported-by: Di Shen (Keen Lab)
Tested-by: John Dias 
Signed-off-by: Peter Zijlstra (Intel) 
Cc: Alexander Shishkin 
Cc: Arnaldo Carvalho de Melo 
Cc: Arnaldo Carvalho de Melo 
Cc: Jiri Olsa 
Cc: Kees Cook 
Cc: Linus Torvalds 
Cc: Min Chong 
Cc: Peter Zijlstra 
Cc: Stephane Eranian 
Cc: Thomas Gleixner 
Cc: Vince Weaver 
Fixes: f63a8daa5812 ("perf: Fix event->ctx locking")
Link: 
http://lkml.kernel.org/r/20170106131444.gz3...@twins.programming.kicks-ass.net
Signed-off-by: Ingo Molnar 
Signed-off-by: Wang Nan 
[ - Correct code context
  - Use group_flags instead of group_caps
]
---
 kernel/events/core.c | 57 
 1 file changed, 53 insertions(+), 4 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 77be116..3973df8 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7900,6 +7900,37 @@ static int perf_event_set_clock(struct perf_event 
*event, clockid_t clk_id)
return 0;
 }
 
+/*
+ * Variation on perf_event_ctx_lock_nested(), except we take two context
+ * mutexes.
+ */
+static struct perf_event_context *
+__perf_event_ctx_lock_double(struct perf_event *group_leader,
+struct perf_event_context *ctx)
+{
+   struct perf_event_context *gctx;
+
+again:
+   rcu_read_lock();
+   gctx = READ_ONCE(group_leader->ctx);
+   if (!atomic_inc_not_zero(&gctx->refcount)) {
+   rcu_read_unlock();
+   goto again;
+   }
+   rcu_read_unlock();
+
+   mutex_lock_double(&gctx->mutex, &ctx->mutex);
+
+   if (group_leader->ctx != gctx) {
+   mutex_unlock(&ctx->mutex);
+   mutex_unlock(&gctx->mutex);
+   put_ctx(gctx);
+   goto again;
+   }
+
+   return gctx;
+}
+
 /**
  * sys_perf_event_open - open a performance event, associate it to a task/cpu
  *
@@ -8123,8 +8154,26 @@ SYSCALL_DEFINE5(perf_event_open,
}
 
if (move_group) {
-   gctx = group_leader->ctx;
-   mutex_lock_double(&gctx->mutex, &ctx->mutex);
+   gctx = __perf_event_ctx_lock_double(group_leader, ctx);
+
+   /*
+* Check if we raced against another sys_perf_event_open() call
+* moving the software group underneath us.
+*/
+   if (!(group_leader->group_flags & PERF_GROUP_SOFTWARE)) {
+   /*
+* If someone moved the group out from under us, check
+* if this new event wound up on the same ctx, if so
+* its the regular !move_group case, otherwise fail.
+*/
+   if (gctx != ctx) {
+   err = -EINVAL;
+   goto err_locked;
+   } else {
+   perf_event_ctx_unlock(group_leader, gctx);
+   move_group = 0;
+   }
+   }
} else {
mutex_lock(&ctx->mutex);
}
@@ -8200,7 +8249,7 @@ SYSCALL_DEFINE5(perf_event_open,
perf_unpin_context(ctx);
 
if (move_group)
-   mutex_unlock(&gctx->mutex);
+   perf_event_ctx_unlock(group_leader, gctx);
mutex_unlock(&ctx->mutex);
 
put_online_cpus();
@@ -8229,7 +8278,7 @@ SYSCALL_DEFINE5(perf_event_open,
 
 err_locked:
if (move_group)
-   mutex_unlock(&gctx->mutex);
+   perf_event_ctx_unlock(group_leader, gctx);
mutex_unlock(&ctx->mutex);
 /* err_file: */
fput(event_file);
-- 
2.10.1



[PATCH -stable 4.1 1/2] perf: Restructure perf syscall point of no return

2017-02-24 Thread Wang Nan
From: Peter Zijlstra 

[ Upstream commit f55fc2a57cc9ca3b1bb4fb8eb25b6e1989e5b993 ]

The exclusive_event_installable() stuff only works because its
exclusive with the grouping bits.

Rework the code such that there is a sane place to error out before we
go do things we cannot undo.

CVE 2017-6001

Signed-off-by: Peter Zijlstra (Intel) 
Cc: Alexander Shishkin 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar 
Signed-off-by: Wang Nan 
---
 kernel/events/core.c | 49 -
 1 file changed, 32 insertions(+), 17 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6da64f0..77be116 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -8124,13 +8124,30 @@ SYSCALL_DEFINE5(perf_event_open,
 
if (move_group) {
gctx = group_leader->ctx;
+   mutex_lock_double(&gctx->mutex, &ctx->mutex);
+   } else {
+   mutex_lock(&ctx->mutex);
+   }
+
+   /*
+* Must be under the same ctx::mutex as perf_install_in_context(),
+* because we need to serialize with concurrent event creation.
+*/
+   if (!exclusive_event_installable(event, ctx)) {
+   /* exclusive and group stuff are assumed mutually exclusive */
+   WARN_ON_ONCE(move_group);
+
+   err = -EBUSY;
+   goto err_locked;
+   }
 
+   WARN_ON_ONCE(ctx->parent_ctx);
+
+   if (move_group) {
/*
 * See perf_event_ctx_lock() for comments on the details
 * of swizzling perf_event::ctx.
 */
-   mutex_lock_double(&gctx->mutex, &ctx->mutex);
-
perf_remove_from_context(group_leader, false);
 
list_for_each_entry(sibling, &group_leader->sibling_list,
@@ -8138,13 +8155,7 @@ SYSCALL_DEFINE5(perf_event_open,
perf_remove_from_context(sibling, false);
put_ctx(gctx);
}
-   } else {
-   mutex_lock(&ctx->mutex);
-   }
-
-   WARN_ON_ONCE(ctx->parent_ctx);
 
-   if (move_group) {
/*
 * Wait for everybody to stop referencing the events through
 * the old lists, before installing it on new lists.
@@ -8176,22 +8187,20 @@ SYSCALL_DEFINE5(perf_event_open,
perf_event__state_init(group_leader);
perf_install_in_context(ctx, group_leader, group_leader->cpu);
get_ctx(ctx);
-   }
 
-   if (!exclusive_event_installable(event, ctx)) {
-   err = -EBUSY;
-   mutex_unlock(&ctx->mutex);
-   fput(event_file);
-   goto err_context;
+   /*
+* Now that all events are installed in @ctx, nothing
+* references @gctx anymore, so drop the last reference we have
+* on it.
+*/
+   put_ctx(gctx);
}
 
perf_install_in_context(ctx, event, event->cpu);
perf_unpin_context(ctx);
 
-   if (move_group) {
+   if (move_group)
mutex_unlock(&gctx->mutex);
-   put_ctx(gctx);
-   }
mutex_unlock(&ctx->mutex);
 
put_online_cpus();
@@ -8218,6 +8227,12 @@ SYSCALL_DEFINE5(perf_event_open,
fd_install(event_fd, event_file);
return event_fd;
 
+err_locked:
+   if (move_group)
+   mutex_unlock(&gctx->mutex);
+   mutex_unlock(&ctx->mutex);
+/* err_file: */
+   fput(event_file);
 err_context:
perf_unpin_context(ctx);
put_ctx(ctx);
-- 
2.10.1



[PATCH -stable 4.1 0/2] perf/core: Fix CVE-2017-6001

2017-02-24 Thread Wang Nan
These two patch are needed for stable 4.1. They fix CVE-2017-6001.

Peter Zijlstra (2):
  perf: Restructure perf syscall point of no return
  perf/core: Fix concurrent sys_perf_event_open() vs. 'move_group' race

 kernel/events/core.c | 102 +--
 1 file changed, 83 insertions(+), 19 deletions(-)

-- 
2.10.1



[PATCH -improve] tools lib bpf: Fix map offsets in relocation

2017-01-19 Thread Wang Nan
From: Joe Stringer 

Commit 4708bbda5cb2 ("tools lib bpf: Fix maps resolution") attempted to
fix map resolution by identifying the number of symbols that point to
maps, and using this number to resolve each of the maps.

However, during relocation the original definition of the map size was
still in use. For up to two maps, the calculation was correct if there
was a small difference in size between the map definition in libbpf and
the one that the client library uses. However if the difference was
large, particularly if more than two maps were used in the BPF program,
the relocation would fail.

For example, when using a map definition with size 28, with three maps,
map relocation would count
(sym_offset / sizeof(struct bpf_map_def) => map_idx)
(0 / 16 => 0), ie map_idx = 0
(28 / 16 => 1), ie map_idx = 1
(56 / 16 => 3), ie map_idx = 3

So, libbpf reports:
libbpf: bpf relocation: map_idx 3 large than 2

Fix map relocation by checking the exact offset of maps when doing
relocation.

Fixes: 4708bbda5cb2 ("tools lib bpf: Fix maps resolution")
Signed-off-by: Joe Stringer 
Signed-off-by: Wang Nan 
[Allow different map size in an object]
Cc: Alexei Starovoitov 
Cc: Daniel Borkmann 
Cc: Arnaldo Carvalho de Melo 
---
 tools/lib/bpf/libbpf.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 84e6b35..671d5ad 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -779,7 +779,7 @@ static int
 bpf_program__collect_reloc(struct bpf_program *prog,
   size_t nr_maps, GElf_Shdr *shdr,
   Elf_Data *data, Elf_Data *symbols,
-  int maps_shndx)
+  int maps_shndx, struct bpf_map *maps)
 {
int i, nrels;
 
@@ -829,7 +829,15 @@ bpf_program__collect_reloc(struct bpf_program *prog,
return -LIBBPF_ERRNO__RELOC;
}
 
-   map_idx = sym.st_value / sizeof(struct bpf_map_def);
+   /* TODO: 'maps' is sorted. We can use bsearch to make it 
faster. */
+   for (map_idx = 0; map_idx < nr_maps; map_idx++) {
+   if (maps[map_idx].offset == sym.st_value) {
+   pr_debug("relocation: find map %zd (%s) for 
insn %u\n",
+map_idx, maps[map_idx].name, insn_idx);
+   break;
+   }
+   }
+
if (map_idx >= nr_maps) {
pr_warning("bpf relocation: map_idx %d large than %d\n",
   (int)map_idx, (int)nr_maps - 1);
@@ -953,7 +961,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
err = bpf_program__collect_reloc(prog, nr_maps,
 shdr, data,
 obj->efile.symbols,
-obj->efile.maps_shndx);
+obj->efile.maps_shndx,
+obj->maps);
if (err)
return err;
}
-- 
2.10.1



[PATCH] coresight: fix kernel panic caused by invalid CPU

2016-12-25 Thread Wang Nan
Commit d52c9750f150 ("coresight: reset 'enable_sink' flag when need be")
caused a kernel panic because of the using of an invalid value: after
'for_each_cpu(cpu, mask)', value of local variable 'cpu' become invalid,
causes following 'cpu_to_node' access invalid memory area.

This patch brings the deleted 'cpu = cpumask_first(mask)' back.

Panic log:

 $ perf record -e cs_etm// ls

 Unable to handle kernel paging request at virtual address fffe801804af4f10
 pgd = 8017ce031600
 [fffe801804af4f10] *pgd=, *pud=
 Internal error: Oops: 9604 [#1] SMP
 Modules linked in:
 CPU: 33 PID: 1619 Comm: perf Not tainted 4.7.1+ #16
 Hardware name: Huawei Taishan 2280 /CH05TEVBA, BIOS 1.10 11/24/2016
 task: 8017cb0c8400 ti: 8017cb154000 task.ti: 8017cb154000
 PC is at tmc_alloc_etf_buffer+0x60/0xd4
 LR is at tmc_alloc_etf_buffer+0x44/0xd4
 pc : [] lr : [] pstate: 6145
 sp : 8017cb157b40
 x29: 8017cb157b40 x28: 
 ...skip...
 7a60: 08c64dc8 0006 0253 
 7a80:   080872cc 0001
 [] tmc_alloc_etf_buffer+0x60/0xd4
 [] etm_setup_aux+0x1dc/0x1e8
 [] rb_alloc_aux+0x2b0/0x338
 [] perf_mmap+0x414/0x568
 [] mmap_region+0x324/0x544
 [] do_mmap+0x334/0x3e0
 [] vm_mmap_pgoff+0xa4/0xc8
 [] SyS_mmap_pgoff+0xb0/0x22c
 [] sys_mmap+0x18/0x28
 [] el0_svc_naked+0x24/0x28
 Code: 912040a5 d0001c00 f873d821 911c6000 (b8656822)
 ---[ end trace 98933da8f92b0c9a ]---

Signed-off-by: Wang Nan 
Cc: Xia Kaixu 
Cc: Li Zefan 
Cc: Mathieu Poirier 
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/hwtracing/coresight/coresight-etm-perf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c 
b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 1774196..26cfac3 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -242,6 +242,7 @@ static void *etm_setup_aux(int event_cpu, void **pages,
if (!sink_ops(sink)->alloc_buffer)
goto err;
 
+   cpu = cpumask_first(mask);
/* Get the AUX specific data from the sink buffer */
event_data->snk_config =
sink_ops(sink)->alloc_buffer(sink, cpu, pages,
-- 
2.10.1



[tip:perf/core] perf build: Check LLVM version in feature check

2016-12-07 Thread tip-bot for Wang Nan
Commit-ID:  a940cad331e79cc03d9ae74f56a2c7cb810bdce9
Gitweb: http://git.kernel.org/tip/a940cad331e79cc03d9ae74f56a2c7cb810bdce9
Author: Wang Nan 
AuthorDate: Tue, 6 Dec 2016 07:22:30 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 6 Dec 2016 13:21:55 -0300

perf build: Check LLVM version in feature check

Cancel builtin llvm and clang support when LLVM version is less than
3.9.0: following commits uses newer API.

Since Clang/LLVM's API is not guaranteed to be stable, add a
test-llvm-version.cpp feature checker, issue warning if LLVM found in
compiling environment is not tested yet.

Committer Notes:

Testing it:

Environment:

  $ cat /etc/fedora-release
  Fedora release 25 (Twenty Five)
  $ rpm -q llvm-devel clang-devel
  llvm-devel-3.8.0-1.fc25.x86_64
  clang-devel-3.8.0-2.fc25.x86_64
  $

Before:

  $  make -k LIBCLANGLLVM=1 O=/tmp/build/perf -C tools/perf install-bin
  make: Entering directory '/home/acme/git/linux/tools/perf'
BUILD:   Doing 'make -j4' parallel build
  Warning: tools/include/uapi/linux/bpf.h differs from kernel
  Warning: tools/arch/arm/include/uapi/asm/kvm.h differs from kernel
INSTALL  GTK UI
LINK /tmp/build/perf/perf
  /tmp/build/perf/libperf.a(libperf-in.o): In function 
`perf::createCompilerInvocation(llvm::SmallVector, 
llvm::StringRef&, clang::DiagnosticsEngine&)':
  /home/acme/git/linux/tools/perf/util/c++/clang.cpp:56: undefined reference to 
`clang::tooling::newInvocation(clang::DiagnosticsEngine*, 
llvm::SmallVector const&)'
  /tmp/build/perf/libperf.a(libperf-in.o): In function 
`perf::getModuleFromSource(llvm::SmallVector, 
llvm::StringRef, llvm::IntrusiveRefCntPtr)':
  /home/acme/git/linux/tools/perf/util/c++/clang.cpp:68: undefined reference to 
`clang::CompilerInstance::CompilerInstance(std::shared_ptr,
 bool)'
  /home/acme/git/linux/tools/perf/util/c++/clang.cpp:69: undefined reference to 
`clang::CompilerInstance::createDiagnostics(clang::DiagnosticConsumer*, bool)'
  

After:

  Makefile.config:807: No suitable libLLVM found, disabling builtin clang and 
llvm support. Please install llvm-dev(el) (>= 3.9.0)

Updating the environment to a locally built LLVM 4.0 + clang 3.9 (forgot
to git pull, duh) combo, all works as expected, it is properly detected
and built into the resulting perf binary.

Signed-off-by: Wang Nan 
Reported-and-Tested-by: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161206072230.7651-1-wangn...@huawei.com
[ Change the warning message a bit (add 'suitable' and 'builtin'), clarifying 
it, see committer notes above ]
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/build/feature/Makefile  |  8 ++--
 tools/build/feature/test-llvm-version.cpp | 11 +++
 tools/build/feature/test-llvm.cpp |  5 +
 tools/perf/Makefile.config|  8 ++--
 4 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 303196c..b564a2e 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -231,14 +231,18 @@ $(OUTPUT)test-jvmti.bin:
$(BUILD)
 
 $(OUTPUT)test-llvm.bin:
-   $(BUILDXX) -std=gnu++11 \
+   $(BUILDXX) -std=gnu++11 \
-I$(shell $(LLVM_CONFIG) --includedir)  \
-L$(shell $(LLVM_CONFIG) --libdir)  \
$(shell $(LLVM_CONFIG) --libs Core BPF) \
$(shell $(LLVM_CONFIG) --system-libs)
 
+$(OUTPUT)test-llvm-version.bin:
+   $(BUILDXX) -std=gnu++11 \
+   -I$(shell $(LLVM_CONFIG) --includedir)
+
 $(OUTPUT)test-clang.bin:
-   $(BUILDXX) -std=gnu++11 \
+   $(BUILDXX) -std=gnu++11 \
-I$(shell $(LLVM_CONFIG) --includedir)  \
-L$(shell $(LLVM_CONFIG) --libdir)  \
-Wl,--start-group -lclangBasic -lclangDriver\
diff --git a/tools/build/feature/test-llvm-version.cpp 
b/tools/build/feature/test-llvm-version.cpp
new file mode 100644
index 000..896d317
--- /dev/null
+++ b/tools/build/feature/test-llvm-version.cpp
@@ -0,0 +1,11 @@
+#include 
+#include "llvm/Config/llvm-config.h"
+
+#define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) 
+ LLVM_VERSION_PATCH)
+#define pass int main() {printf("%x\n", NUM_VERSION); return 0;}
+
+#if NUM_VERSION >= 0x030900
+pass
+#else
+# error This LLVM is not tested yet.
+#endif
diff --git a/tools/build/feature/test-llvm.cpp 
b/tools/build/feature/test-llvm.cpp
index d8d2cee..455a332 100644
--- a/tools/build/feature/test-llvm.cpp
+++ b/tools/bui

[tip:perf/core] perf clang: Compile BPF script using builtin clang support

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  edd695b032ba3a90c3bb07d934500b2c390a61ff
Gitweb: http://git.kernel.org/tip/edd695b032ba3a90c3bb07d934500b2c390a61ff
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:39 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:45 -0300

perf clang: Compile BPF script using builtin clang support

After this patch, perf utilizes builtin clang support to build BPF
script, no longer depend on external clang, but fallbacking to it
if for some reason the builtin compiling framework fails.

Test:

  $ type clang
  -bash: type: clang: not found
  $ cat ~/.perfconfig
  $ echo '#define LINUX_VERSION_CODE 0x040700' > ./test.c
  $ cat ./tools/perf/tests/bpf-script-example.c >> ./test.c
  $ ./perf record -v --dry-run -e ./test.c 2>&1 | grep builtin
  bpf: successfull builtin compilation
  $

Can't pass cflags so unable to include kernel headers now. Will be fixed
by following commits.

Committer notes:

Make sure '-v' comes before the '-e ./test.c' in the command line otherwise the
'verbose' variable will not be set when the bpf event is parsed and thus the
pr_debug indicating a 'successfull builtin compilation' will not be output, as
the debug level (1) will be less than what 'verbose' has at that point (0).

Signed-off-by: Wang Nan 
Tested-by: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-16-wangn...@huawei.com
[ Spell check/reflow successfull pr_debug string ]
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/bpf-loader.c  | 15 +++
 tools/perf/util/c++/clang-c.h | 26 ++
 tools/perf/util/c++/clang.cpp | 29 +
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index cf16b941..36c8611 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -14,11 +14,11 @@
 #include "debug.h"
 #include "bpf-loader.h"
 #include "bpf-prologue.h"
-#include "llvm-utils.h"
 #include "probe-event.h"
 #include "probe-finder.h" // for MAX_PROBES
 #include "parse-events.h"
 #include "llvm-utils.h"
+#include "c++/clang-c.h"
 
 #define DEFINE_PRINT_FN(name, level) \
 static int libbpf_##name(const char *fmt, ...) \
@@ -86,9 +86,16 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
void *obj_buf;
size_t obj_buf_sz;
 
-   err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
-   if (err)
-   return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+   perf_clang__init();
+   err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+   perf_clang__cleanup();
+   if (err) {
+   pr_warning("bpf: builtin compilation failed: %d, try 
external compiler\n", err);
+   err = llvm__compile_bpf(filename, &obj_buf, 
&obj_buf_sz);
+   if (err)
+   return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+   } else
+   pr_debug("bpf: successfull builtin compilation\n");
obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
 
if (!IS_ERR(obj) && llvm_param.dump_obj)
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 22b3936..0eadd79 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -1,16 +1,42 @@
 #ifndef PERF_UTIL_CLANG_C_H
 #define PERF_UTIL_CLANG_C_H
 
+#include /* for size_t */
+#include   /* for __maybe_unused */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
 extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
 
 extern int test__clang_to_IR(void);
 extern int test__clang_to_obj(void);
 
+extern int perf_clang__compile_bpf(const char *filename,
+  void **p_obj_buf,
+  size_t *p_obj_buf_sz);
+#else
+
+
+static inline void perf_clang__init(void) { }
+static inline void perf_clang__cleanup(void) { }
+
+static inline int test__clang_to_IR(void) { return -1; }
+static inline int test__clang_to_obj(void) { return -1;}
+
+static inline int
+perf_clang__compile_bpf(const char *filename __maybe_unused,
+   void **p_obj_buf __maybe_unused,
+   size_t *p_obj_buf_sz __maybe_unused)
+{
+   return -ENOTSUP;
+}
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 2a1a75d..1e97415 100644
--- a/tools/pe

[tip:perf/core] perf clang: Support compile IR to BPF object and add testcase

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  5e08a76525b8f5e9aeb8b27d0466614abec070a9
Gitweb: http://git.kernel.org/tip/5e08a76525b8f5e9aeb8b27d0466614abec070a9
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:38 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:44 -0300

perf clang: Support compile IR to BPF object and add testcase

getBPFObjectFromModule() is introduced to compile LLVM IR(Module)
to BPF object. Add new testcase for it.

Test result:
  $ ./buildperf/perf test -v clang
  51: builtin clang support   :
  51.1: builtin clang compile C source to IR  :
  --- start ---
  test child forked, pid 21822
  test child finished with 0
   end 
  builtin clang support subtest 0: Ok
  51.2: builtin clang compile C source to ELF object  :
  --- start ---
  test child forked, pid 21823
  test child finished with 0
   end 
  builtin clang support subtest 1: Ok

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-15-wangn...@huawei.com
[ Remove redundant "Test" from entry descriptions ]
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/tests/clang.c   |  6 -
 tools/perf/util/c++/clang-c.h  |  1 +
 tools/perf/util/c++/clang-test.cpp | 31 +-
 tools/perf/util/c++/clang.cpp  | 45 ++
 tools/perf/util/c++/clang.h|  3 +++
 5 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
index 636d6d0..f853e24 100644
--- a/tools/perf/tests/clang.c
+++ b/tools/perf/tests/clang.c
@@ -12,6 +12,10 @@ static struct {
.func = test__clang_to_IR,
.desc = "builtin clang compile C source to IR",
},
+   {
+   .func = test__clang_to_obj,
+   .desc = "builtin clang compile C source to ELF object",
+   },
 #endif
 };
 
@@ -33,7 +37,7 @@ int test__clang(int i __maybe_unused)
return TEST_SKIP;
 }
 #else
-int test__clang(int i __maybe_unused)
+int test__clang(int i)
 {
if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
return TEST_FAIL;
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index dcde4b5..22b3936 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -9,6 +9,7 @@ extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
 
 extern int test__clang_to_IR(void);
+extern int test__clang_to_obj(void);
 
 #ifdef __cplusplus
 }
diff --git a/tools/perf/util/c++/clang-test.cpp 
b/tools/perf/util/c++/clang-test.cpp
index d84e760..9b11e8c 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -13,15 +13,13 @@ public:
~perf_clang_scope() {perf_clang__cleanup();}
 };
 
-extern "C" {
-
-int test__clang_to_IR(void)
+static std::unique_ptr
+__test__clang_to_IR(void)
 {
-   perf_clang_scope _scope;
unsigned int kernel_version;
 
if (fetch_kernel_version(&kernel_version, NULL, 0))
-   return -1;
+   return std::unique_ptr(nullptr);
 
std::string cflag_kver("-DLINUX_VERSION_CODE=" +
std::to_string(kernel_version));
@@ -30,14 +28,35 @@ int test__clang_to_IR(void)
perf::getModuleFromSource({cflag_kver.c_str()},
  "perf-test.c",
  test_llvm__bpf_base_prog);
+   return M;
+}
+
+extern "C" {
+int test__clang_to_IR(void)
+{
+   perf_clang_scope _scope;
 
+   auto M = __test__clang_to_IR();
if (!M)
return -1;
-
for (llvm::Function& F : *M)
if (F.getName() == "bpf_func__SyS_epoll_wait")
return 0;
return -1;
 }
 
+int test__clang_to_obj(void)
+{
+   perf_clang_scope _scope;
+
+   auto M = __test__clang_to_IR();
+   if (!M)
+   return -1;
+
+   auto Buffer = perf::getBPFObjectFromModule(&*M);
+   if (!Buffer)
+   return -1;
+   return 0;
+}
+
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 715ca0a..2a1a75d 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -13,10 +13,15 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Target

[tip:perf/core] perf clang: Allow passing CFLAGS to builtin clang

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  a9495fe9dc63bee1166772b6f10e199ef1747892
Gitweb: http://git.kernel.org/tip/a9495fe9dc63bee1166772b6f10e199ef1747892
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:36 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:44 -0300

perf clang: Allow passing CFLAGS to builtin clang

Improve getModuleFromSource() API to accept a cflags list. This feature
will be used to pass LINUX_VERSION_CODE and -I flags.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-13-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/c++/clang-test.cpp |  5 +++--
 tools/perf/util/c++/clang.cpp  | 21 +
 tools/perf/util/c++/clang.h|  8 ++--
 3 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/c++/clang-test.cpp 
b/tools/perf/util/c++/clang-test.cpp
index 3da6bfa..0f484fb 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -16,8 +16,9 @@ int test__clang_to_IR(void)
perf_clang_scope _scope;
 
std::unique_ptr M =
-   perf::getModuleFromSource("perf-test.c",
- "int myfunc(void) {return 1;}");
+   perf::getModuleFromSource({"-DRESULT=1"},
+ "perf-test.c",
+ "int myfunc(void) {return RESULT;}");
 
if (!M)
return -1;
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index cf96199..715ca0a 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -29,7 +29,8 @@ static std::unique_ptr LLVMCtx;
 using namespace clang;
 
 static CompilerInvocation *
-createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
+createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
+DiagnosticsEngine& Diags)
 {
llvm::opt::ArgStringList CCArgs {
"-cc1",
@@ -45,6 +46,8 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& 
Diags)
"-Wno-unused-value",
"-Wno-pointer-sign",
"-x", "c"};
+
+   CCArgs.append(CFlags.begin(), CFlags.end());
CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
 
FrontendOptions& Opts = CI->getFrontendOpts();
@@ -54,8 +57,8 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& 
Diags)
 }
 
 static std::unique_ptr
-getModuleFromSource(StringRef Path,
-   IntrusiveRefCntPtr VFS)
+getModuleFromSource(llvm::opt::ArgStringList CFlags,
+   StringRef Path, IntrusiveRefCntPtr VFS)
 {
CompilerInstance Clang;
Clang.createDiagnostics();
@@ -63,7 +66,8 @@ getModuleFromSource(StringRef Path,
Clang.setVirtualFileSystem(&*VFS);
 
IntrusiveRefCntPtr CI =
-   createCompilerInvocation(Path, Clang.getDiagnostics());
+   createCompilerInvocation(std::move(CFlags), Path,
+Clang.getDiagnostics());
Clang.setInvocation(&*CI);
 
std::unique_ptr Act(new EmitLLVMOnlyAction(&*LLVMCtx));
@@ -74,7 +78,8 @@ getModuleFromSource(StringRef Path,
 }
 
 std::unique_ptr
-getModuleFromSource(StringRef Name, StringRef Content)
+getModuleFromSource(llvm::opt::ArgStringList CFlags,
+   StringRef Name, StringRef Content)
 {
using namespace vfs;
 
@@ -90,14 +95,14 @@ getModuleFromSource(StringRef Name, StringRef Content)
OverlayFS->pushOverlay(MemFS);
MemFS->addFile(Twine(Name), 0, 
llvm::MemoryBuffer::getMemBuffer(Content));
 
-   return getModuleFromSource(Name, OverlayFS);
+   return getModuleFromSource(std::move(CFlags), Name, OverlayFS);
 }
 
 std::unique_ptr
-getModuleFromSource(StringRef Path)
+getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 {
IntrusiveRefCntPtr VFS(vfs::getRealFileSystem());
-   return getModuleFromSource(Path, VFS);
+   return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
 }
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index 90aff01..b4fc2a9 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -4,16 +4,20 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Option/Option.h"
 #include 
+
 namespace perf {
 
 using namespace llvm;
 
 std::unique_ptr
-getModuleFromSource(StringRef Name, StringRef Content);
+getModuleFromSource(opt::ArgStringList CFlags,
+   StringRef Name, StringRef Content);
 
 std::unique_ptr
-getModuleFromSource(StringRef Path);
+getModuleFromSource(opt::ArgStringList CFlags,
+   StringRef Path);
 
 }
 #endif


[tip:perf/core] perf clang: Update test case to use real BPF script

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  e67d52d411c3562263735479db2efd2ebd178db9
Gitweb: http://git.kernel.org/tip/e67d52d411c3562263735479db2efd2ebd178db9
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:37 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:44 -0300

perf clang: Update test case to use real BPF script

Allow C++ code to use util.h and tests/llvm.h. Let 'perf test' compile a
real BPF script.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-14-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/Makefile.config | 27 +++
 tools/perf/tests/llvm.h|  7 +++
 tools/perf/util/c++/clang-test.cpp | 17 ++---
 tools/perf/util/util-cxx.h | 26 ++
 4 files changed, 62 insertions(+), 15 deletions(-)

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index b7c9c80..09c2a98 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -212,24 +212,27 @@ ifeq ($(DEBUG),0)
   endif
 endif
 
-CFLAGS += -I$(src-perf)/util/include
-CFLAGS += -I$(src-perf)/arch/$(ARCH)/include
-CFLAGS += -I$(srctree)/tools/include/uapi
-CFLAGS += -I$(srctree)/tools/include/
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
-CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/
+INC_FLAGS += -I$(src-perf)/util/include
+INC_FLAGS += -I$(src-perf)/arch/$(ARCH)/include
+INC_FLAGS += -I$(srctree)/tools/include/uapi
+INC_FLAGS += -I$(srctree)/tools/include/
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
+INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/
 
 # $(obj-perf)  for generated common-cmds.h
 # $(obj-perf)/util for generated bison/flex headers
 ifneq ($(OUTPUT),)
-CFLAGS += -I$(obj-perf)/util
-CFLAGS += -I$(obj-perf)
+INC_FLAGS += -I$(obj-perf)/util
+INC_FLAGS += -I$(obj-perf)
 endif
 
-CFLAGS += -I$(src-perf)/util
-CFLAGS += -I$(src-perf)
-CFLAGS += -I$(srctree)/tools/lib/
+INC_FLAGS += -I$(src-perf)/util
+INC_FLAGS += -I$(src-perf)
+INC_FLAGS += -I$(srctree)/tools/lib/
+
+CFLAGS   += $(INC_FLAGS)
+CXXFLAGS += $(INC_FLAGS)
 
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index 0eaa604..b835717 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -1,6 +1,10 @@
 #ifndef PERF_TEST_LLVM_H
 #define PERF_TEST_LLVM_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include  /* for size_t */
 #include  /* for bool */
 
@@ -20,4 +24,7 @@ enum test_llvm__testcase {
 int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
 enum test_llvm__testcase index, bool force,
 bool *should_load_fail);
+#ifdef __cplusplus
+}
+#endif
 #endif
diff --git a/tools/perf/util/c++/clang-test.cpp 
b/tools/perf/util/c++/clang-test.cpp
index 0f484fb..d84e760 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -3,6 +3,10 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/LLVMContext.h"
 
+#include 
+#include 
+#include 
+
 class perf_clang_scope {
 public:
explicit perf_clang_scope() {perf_clang__init();}
@@ -14,17 +18,24 @@ extern "C" {
 int test__clang_to_IR(void)
 {
perf_clang_scope _scope;
+   unsigned int kernel_version;
+
+   if (fetch_kernel_version(&kernel_version, NULL, 0))
+   return -1;
+
+   std::string cflag_kver("-DLINUX_VERSION_CODE=" +
+   std::to_string(kernel_version));
 
std::unique_ptr M =
-   perf::getModuleFromSource({"-DRESULT=1"},
+   perf::getModuleFromSource({cflag_kver.c_str()},
  "perf-test.c",
- "int myfunc(void) {return RESULT;}");
+ test_llvm__bpf_base_prog);
 
if (!M)
return -1;
 
for (llvm::Function& F : *M)
-   if (F.getName() == "myfunc")
+   if (F.getName() == "bpf_func__SyS_epoll_wait")
return 0;
return -1;
 }
diff --git a/tools/perf/util/util-cxx.h b/tools/perf/util/util-cxx.h
new file mode 100644
index 000..0e0e019
--- /dev/null
+++ b/tools/perf/util/util-cxx.h
@@ -0,0 +1,26 @@
+/*
+ * Support C++ source use utilities defined in util.h
+ */
+
+#ifndef PERF_UTIL_UTIL_CXX_H
+#define PERF_UTIL_UTIL_CXX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Now 'new' is the only C++ keyword found in util.h:
+ * in tools/include/linux/rbtree.h
+ *
+ * Other keywords

[tip:perf/core] perf clang: Use real file system for #include

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  77dfa84a843c0bc935a6c8664f2556573e30845f
Gitweb: http://git.kernel.org/tip/77dfa84a843c0bc935a6c8664f2556573e30845f
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:35 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:44 -0300

perf clang: Use real file system for #include

Utilize clang's OverlayFileSystem facility, allow CompilerInstance to
access real file system.

With this patch the '#include' directive can be used.

Add a new getModuleFromSource for real file.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-12-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/c++/clang.cpp | 44 +++
 tools/perf/util/c++/clang.h   |  3 +++
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index c17b117..cf96199 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -15,6 +15,7 @@
 #include "clang/Tooling/Tooling.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/ManagedStatic.h"
 #include 
 
@@ -27,14 +28,6 @@ static std::unique_ptr LLVMCtx;
 
 using namespace clang;
 
-static vfs::InMemoryFileSystem *
-buildVFS(StringRef& Name, StringRef& Content)
-{
-   vfs::InMemoryFileSystem *VFS = new vfs::InMemoryFileSystem(true);
-   VFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
-   return VFS;
-}
-
 static CompilerInvocation *
 createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
 {
@@ -60,17 +53,17 @@ createCompilerInvocation(StringRef& Path, 
DiagnosticsEngine& Diags)
return CI;
 }
 
-std::unique_ptr
-getModuleFromSource(StringRef Name, StringRef Content)
+static std::unique_ptr
+getModuleFromSource(StringRef Path,
+   IntrusiveRefCntPtr VFS)
 {
CompilerInstance Clang;
Clang.createDiagnostics();
 
-   IntrusiveRefCntPtr VFS = buildVFS(Name, Content);
Clang.setVirtualFileSystem(&*VFS);
 
IntrusiveRefCntPtr CI =
-   createCompilerInvocation(Name, Clang.getDiagnostics());
+   createCompilerInvocation(Path, Clang.getDiagnostics());
Clang.setInvocation(&*CI);
 
std::unique_ptr Act(new EmitLLVMOnlyAction(&*LLVMCtx));
@@ -80,6 +73,33 @@ getModuleFromSource(StringRef Name, StringRef Content)
return Act->takeModule();
 }
 
+std::unique_ptr
+getModuleFromSource(StringRef Name, StringRef Content)
+{
+   using namespace vfs;
+
+   llvm::IntrusiveRefCntPtr OverlayFS(
+   new OverlayFileSystem(getRealFileSystem()));
+   llvm::IntrusiveRefCntPtr MemFS(
+   new InMemoryFileSystem(true));
+
+   /*
+* pushOverlay helps setting working dir for MemFS. Must call
+* before addFile.
+*/
+   OverlayFS->pushOverlay(MemFS);
+   MemFS->addFile(Twine(Name), 0, 
llvm::MemoryBuffer::getMemBuffer(Content));
+
+   return getModuleFromSource(Name, OverlayFS);
+}
+
+std::unique_ptr
+getModuleFromSource(StringRef Path)
+{
+   IntrusiveRefCntPtr VFS(vfs::getRealFileSystem());
+   return getModuleFromSource(Path, VFS);
+}
+
 }
 
 extern "C" {
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index f64483b..90aff01 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -12,5 +12,8 @@ using namespace llvm;
 std::unique_ptr
 getModuleFromSource(StringRef Name, StringRef Content);
 
+std::unique_ptr
+getModuleFromSource(StringRef Path);
+
 }
 #endif


[tip:perf/core] perf clang: Add builtin clang support ant test case

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  00b86691c77c6576861b82a3cfe4d609800758fe
Gitweb: http://git.kernel.org/tip/00b86691c77c6576861b82a3cfe4d609800758fe
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:34 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:43 -0300

perf clang: Add builtin clang support ant test case

Add basic clang support in clang.cpp and test__clang() testcase. The
first testcase checks if builtin clang is able to generate LLVM IR.

tests/clang.c is a proxy. Real testcase resides in
utils/c++/clang-test.cpp in c++ and exports C interface to perf test
subsystem.

Test result:

   $ perf test -v clang
   51: builtin clang support   :
   51.1: Test builtin clang compile C source to IR  :
   --- start ---
   test child forked, pid 13215
   test child finished with 0
    end 
   Test builtin clang support subtest 0: Ok

Committer note:

Make sure you've enabled CLANG and LLVM builtin support by setting
the LIBCLANGLLVM variable on the make command line, e.g.:

  make LIBCLANGLLVM=1 O=/tmp/build/perf -C tools/perf install-bin

Otherwise you'll get this when trying to do the 'perf test' call above:

  # perf test clang
  51: builtin clang support  : Skip (not compiled in)
  #

Signed-off-by: Wang Nan 
Tested-by: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-11-wangn...@huawei.com
[ Removed "Test" from descriptions, redundant and already removed from all the 
other entries ]
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/tests/Build |  1 +
 tools/perf/tests/builtin-test.c|  9 
 tools/perf/tests/clang.c   | 42 +
 tools/perf/tests/tests.h   |  3 ++
 tools/perf/util/Build  |  2 +
 tools/perf/util/c++/Build  |  2 +
 tools/perf/util/c++/clang-c.h  | 16 +++
 tools/perf/util/c++/clang-test.cpp | 31 
 tools/perf/util/c++/clang.cpp  | 96 ++
 tools/perf/util/c++/clang.h| 16 +++
 10 files changed, 218 insertions(+)

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index af3ec94..6676c2d 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -43,6 +43,7 @@ perf-y += sdt.o
 perf-y += is_printable_array.o
 perf-y += bitmap.o
 perf-y += perf-hooks.o
+perf-y += clang.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index d1bec04..2360520 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -234,6 +234,15 @@ static struct test generic_tests[] = {
.func = test__perf_hooks,
},
{
+   .desc = "builtin clang support",
+   .func = test__clang,
+   .subtest = {
+   .skip_if_fail   = true,
+   .get_nr = test__clang_subtest_get_nr,
+   .get_desc   = test__clang_subtest_get_desc,
+   }
+   },
+   {
.func = NULL,
},
 };
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
new file mode 100644
index 000..636d6d0
--- /dev/null
+++ b/tools/perf/tests/clang.c
@@ -0,0 +1,42 @@
+#include "tests.h"
+#include "debug.h"
+#include "util.h"
+#include "c++/clang-c.h"
+
+static struct {
+   int (*func)(void);
+   const char *desc;
+} clang_testcase_table[] = {
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
+   {
+   .func = test__clang_to_IR,
+   .desc = "builtin clang compile C source to IR",
+   },
+#endif
+};
+
+int test__clang_subtest_get_nr(void)
+{
+   return (int)ARRAY_SIZE(clang_testcase_table);
+}
+
+const char *test__clang_subtest_get_desc(int i)
+{
+   if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
+   return NULL;
+   return clang_testcase_table[i].desc;
+}
+
+#ifndef HAVE_LIBCLANGLLVM_SUPPORT
+int test__clang(int i __maybe_unused)
+{
+   return TEST_SKIP;
+}
+#else
+int test__clang(int i __maybe_unused)
+{
+   if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
+   return TEST_FAIL;
+   return clang_testcase_table[i].func();
+}
+#endif
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 3a1f98f..0d7b251 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -92,6 +92,9 @@ int test__sdt_event(int subtest);
 int test__is_printable_array(int subtest);
 int test__bitmap_print(int subtest);
 int test__perf_hooks(int subtest);
+int test__clang(int subtest);
+const char *test__clang_subtest_get_desc(int subtest);
+int test__clang_subtest_get_nr(void)

[tip:perf/core] perf build: Add clang and llvm compile and linking support

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  d58ac0bf8d1e6ffbfcb0a77e459cf4737b131b75
Gitweb: http://git.kernel.org/tip/d58ac0bf8d1e6ffbfcb0a77e459cf4737b131b75
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:33 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:43 -0300

perf build: Add clang and llvm compile and linking support

Add necessary c++ flags and link libraries to support builtin clang and
LLVM. Add all llvm and clang libraries, so don't need to worry about
clang changes its libraries setting. However, linking perf would take
much longer than usual.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-10-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/Makefile.config | 35 +++
 tools/perf/Makefile.perf   | 23 ++-
 tools/perf/tests/make  |  2 ++
 3 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 8a493d4..b7c9c80 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -136,6 +136,7 @@ endif
 # Treat warnings as errors unless directed not to
 ifneq ($(WERROR),0)
   CFLAGS += -Werror
+  CXXFLAGS += -Werror
 endif
 
 ifndef DEBUG
@@ -182,6 +183,13 @@ CFLAGS += -Wall
 CFLAGS += -Wextra
 CFLAGS += -std=gnu99
 
+CXXFLAGS += -std=gnu++11 -fno-exceptions -fno-rtti
+CXXFLAGS += -Wall
+CXXFLAGS += -fno-omit-frame-pointer
+CXXFLAGS += -ggdb3
+CXXFLAGS += -funwind-tables
+CXXFLAGS += -Wno-strict-aliasing
+
 # Enforce a non-executable stack, as we may regress (again) in the future by
 # adding assembler files missing the .GNU-stack linker note.
 LDFLAGS += -Wl,-z,noexecstack
@@ -783,6 +791,33 @@ ifndef NO_JVMTI
   endif
 endif
 
+USE_CXX = 0
+USE_CLANGLLVM = 0
+ifdef LIBCLANGLLVM
+  $(call feature_check,cxx)
+  ifneq ($(feature-cxx), 1)
+msg := $(warning No g++ found, disable clang and llvm support. Please 
install g++)
+  else
+$(call feature_check,llvm)
+ifneq ($(feature-llvm), 1)
+  msg := $(warning No libLLVM found, disable clang and llvm support. 
Please install llvm-dev)
+else
+  $(call feature_check,clang)
+  ifneq ($(feature-clang), 1)
+msg := $(warning No libclang found, disable clang and llvm support. 
Please install libclang-dev)
+  else
+CFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT
+CXXFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT -I$(shell $(LLVM_CONFIG) 
--includedir)
+$(call detected,CONFIG_CXX)
+$(call detected,CONFIG_CLANGLLVM)
+   USE_CXX = 1
+   USE_LLVM = 1
+   USE_CLANG = 1
+  endif
+endif
+  endif
+endif
+
 # Among the variables below, these:
 #   perfexecdir
 #   template_dir
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 3cb1df4..dfb20dd 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -88,6 +88,10 @@ include ../scripts/utilities.mak
 # and bypass the feature detection
 #
 # Define NO_JVMTI if you do not want jvmti agent built
+#
+# Define LIBCLANGLLVM if you DO want builtin clang and llvm support.
+# When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if
+# llvm-config is not in $PATH.
 
 # As per kernel Makefile, avoid funny character set dependencies
 unexport LC_ALL
@@ -143,6 +147,7 @@ endef
 $(call allow-override,CC,$(CROSS_COMPILE)gcc)
 $(call allow-override,AR,$(CROSS_COMPILE)ar)
 $(call allow-override,LD,$(CROSS_COMPILE)ld)
+$(call allow-override,CXX,$(CROSS_COMPILE)g++)
 
 LD += $(EXTRA_LDFLAGS)
 
@@ -151,6 +156,7 @@ HOSTLD  ?= ld
 HOSTAR  ?= ar
 
 PKG_CONFIG = $(CROSS_COMPILE)pkg-config
+LLVM_CONFIG ?= llvm-config
 
 RM  = rm -f
 LN  = ln -f
@@ -338,6 +344,21 @@ endif
 
 LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive 
-Wl,--start-group $(EXTLIBS) -Wl,--end-group
 
+ifeq ($(USE_CLANG), 1)
+  CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema 
Analysis Parse Serialization
+  LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) 
--libdir)/libclang$(l).a))
+  LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
+endif
+
+ifeq ($(USE_LLVM), 1)
+  LIBLLVM = $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG) 
--system-libs)
+  LIBS += -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM)
+endif
+
+ifeq ($(USE_CXX), 1)
+  LIBS += -lstdc++
+endif
+
 export INSTALL SHELL_PATH
 
 ### Build rules
@@ -356,7 +377,7 @@ strip: $(PROGRAMS) $(OUTPUT)perf
 
 PERF_IN := $(OUTPUT)perf-in.o
 
-export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+export srctree OUTPUT RM CC CXX LD AR CFLAGS CXXFLAGS V BISON FLEX AWK
 export HOSTCC HOSTLD HOSTAR
 include $(srctree)/tools/build/Makefile.include
 
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 08ed7f1..aa49b66 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -83,6 +83,7 @@ make

[tip:perf/core] tools build: Add feature detection for LLVM

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  cb40d55b595cd117ef7c1880247605875b2115e8
Gitweb: http://git.kernel.org/tip/cb40d55b595cd117ef7c1880247605875b2115e8
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:31 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:42 -0300

tools build: Add feature detection for LLVM

Check if basic LLVM compiling environment is ready.

Use llvm-config to detect include and library directories. Avoid using
'llvm-config --cxxflags' because its result contain some unwanted flags
like --sysroot (if LLVM is built by yocto).

Use '?=' to set LLVM_CONFIG, so explicitly passing LLVM_CONFIG to make
would override it.

Use 'llvm-config --libs BPF' to check if BPF backend is compiled in.
Since now BPF bytecode is the only required backend, no need to waste
time linking llvm and clang if BPF backend is missing. This also
introduce an implicit requirement that LLVM should be new enough.  Old
LLVM doesn't support BPF backend.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-8-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/build/feature/Makefile  | 8 
 tools/build/feature/test-llvm.cpp | 8 
 2 files changed, 16 insertions(+)

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 8f668bc..c09de59 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -55,6 +55,7 @@ FILES := $(addprefix $(OUTPUT),$(FILES))
 CC := $(CROSS_COMPILE)gcc -MD
 CXX := $(CROSS_COMPILE)g++ -MD
 PKG_CONFIG := $(CROSS_COMPILE)pkg-config
+LLVM_CONFIG ?= llvm-config
 
 all: $(FILES)
 
@@ -229,6 +230,13 @@ $(OUTPUT)test-cxx.bin:
 $(OUTPUT)test-jvmti.bin:
$(BUILD)
 
+$(OUTPUT)test-llvm.bin:
+   $(BUILDXX) -std=gnu++11 \
+   -I$(shell $(LLVM_CONFIG) --includedir)  \
+   -L$(shell $(LLVM_CONFIG) --libdir)  \
+   $(shell $(LLVM_CONFIG) --libs Core BPF) \
+   $(shell $(LLVM_CONFIG) --system-libs)
+
 -include $(OUTPUT)*.d
 
 ###
diff --git a/tools/build/feature/test-llvm.cpp 
b/tools/build/feature/test-llvm.cpp
new file mode 100644
index 000..d8d2cee
--- /dev/null
+++ b/tools/build/feature/test-llvm.cpp
@@ -0,0 +1,8 @@
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+int main()
+{
+   llvm::errs() << "Hello World!\n";
+   llvm::llvm_shutdown();
+   return 0;
+}


[tip:perf/core] tools build: Add feature detection for clang

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  c7fb4f62e2a97bd25d555263ef501fe053edcbb6
Gitweb: http://git.kernel.org/tip/c7fb4f62e2a97bd25d555263ef501fe053edcbb6
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:32 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:43 -0300

tools build: Add feature detection for clang

Check if basic clang compiling environment is ready.

Doesn't like 'llvm-config --libs' which can returns llvm libraries in right
order and duplicates some libraries if necessary, there's no correspondence for
clang libraries (-lclangxxx). to avoid extra complexity and to avoid new clang
breaking libraries ordering, use --start-group and --end-group.

In this test case, manually identify required clang libs and hope it to be
stable. Putting all clang libraries here is possible (use make's wildcard), but
then feature checking becomes very slow.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-9-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/build/feature/Makefile   | 10 ++
 tools/build/feature/test-clang.cpp | 21 +
 2 files changed, 31 insertions(+)

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index c09de59..871d553 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -237,6 +237,16 @@ $(OUTPUT)test-llvm.bin:
$(shell $(LLVM_CONFIG) --libs Core BPF) \
$(shell $(LLVM_CONFIG) --system-libs)
 
+$(OUTPUT)test-clang.bin:
+   $(BUILDXX) -std=gnu++11 \
+   -I$(shell $(LLVM_CONFIG) --includedir)  \
+   -L$(shell $(LLVM_CONFIG) --libdir)  \
+   -Wl,--start-group -lclangBasic -lclangDriver\
+ -lclangFrontend -lclangEdit -lclangLex\
+ -lclangAST -Wl,--end-group\
+   $(shell $(LLVM_CONFIG) --libs Core option)  \
+   $(shell $(LLVM_CONFIG) --system-libs)
+
 -include $(OUTPUT)*.d
 
 ###
diff --git a/tools/build/feature/test-clang.cpp 
b/tools/build/feature/test-clang.cpp
new file mode 100644
index 000..e23c1b1
--- /dev/null
+++ b/tools/build/feature/test-clang.cpp
@@ -0,0 +1,21 @@
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::driver;
+
+int main()
+{
+   IntrusiveRefCntPtr DiagID(new DiagnosticIDs());
+   IntrusiveRefCntPtr DiagOpts = new 
DiagnosticOptions();
+
+   DiagnosticsEngine Diags(DiagID, &*DiagOpts);
+   Driver TheDriver("test", "bpf-pc-linux", Diags);
+
+   llvm::llvm_shutdown();
+   return 0;
+}


[tip:perf/core] perf llvm: Extract helpers in llvm-utils.c

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  2bd42de0e196f89994cbae1990d2c7c5a9b6a529
Gitweb: http://git.kernel.org/tip/2bd42de0e196f89994cbae1990d2c7c5a9b6a529
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:30 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:42 -0300

perf llvm: Extract helpers in llvm-utils.c

The following commits will use builtin clang to compile BPF scripts.

llvm__get_kbuild_opts() and llvm__get_nr_cpus() are extracted to help
building '-DKERNEL_VERSION_CODE' and '-D__NR_CPUS__' macros.

Doing object dumping in bpf loader, so further builtin clang compiling
needn't consider it.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-7-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/bpf-loader.c |  4 +++
 tools/perf/util/llvm-utils.c | 76 +---
 tools/perf/util/llvm-utils.h |  6 
 3 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index a5fd275..cf16b941 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -90,6 +90,10 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
if (err)
return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
+
+   if (!IS_ERR(obj) && llvm_param.dump_obj)
+   llvm__dump_obj(filename, obj_buf, obj_buf_sz);
+
free(obj_buf);
} else
obj = bpf_object__open(filename);
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 27b6f303..b23ff44 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "debug.h"
 #include "llvm-utils.h"
 #include "config.h"
@@ -282,9 +283,10 @@ static const char *kinc_fetch_script =
 "rm -rf $TMPDIR\n"
 "exit $RET\n";
 
-static inline void
-get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
+void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 {
+   static char *saved_kbuild_dir;
+   static char *saved_kbuild_include_opts;
int err;
 
if (!kbuild_dir || !kbuild_include_opts)
@@ -293,10 +295,28 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
*kbuild_dir = NULL;
*kbuild_include_opts = NULL;
 
+   if (saved_kbuild_dir && saved_kbuild_include_opts &&
+   !IS_ERR(saved_kbuild_dir) && !IS_ERR(saved_kbuild_include_opts)) {
+   *kbuild_dir = strdup(saved_kbuild_dir);
+   *kbuild_include_opts = strdup(saved_kbuild_include_opts);
+
+   if (*kbuild_dir && *kbuild_include_opts)
+   return;
+
+   zfree(kbuild_dir);
+   zfree(kbuild_include_opts);
+   /*
+* Don't fall through: it may breaks saved_kbuild_dir and
+* saved_kbuild_include_opts if detect them again when
+* memory is low.
+*/
+   return;
+   }
+
if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) {
pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n");
pr_debug("Skip kbuild options detection.\n");
-   return;
+   goto errout;
}
 
err = detect_kbuild_dir(kbuild_dir);
@@ -306,7 +326,7 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
 "Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n"
 " \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n"
 " \tdetection.\n\n");
-   return;
+   goto errout;
}
 
pr_debug("Kernel build dir is set to %s\n", *kbuild_dir);
@@ -325,14 +345,43 @@ get_kbuild_opts(char **kbuild_dir, char 
**kbuild_include_opts)
 
free(*kbuild_dir);
*kbuild_dir = NULL;
-   return;
+   goto errout;
}
 
pr_debug("include option is set to %s\n", *kbuild_include_opts);
+
+   saved_kbuild_dir = strdup(*kbuild_dir);
+   saved_kbuild_include_opts = strdup(*kbuild_include_opts);
+
+   if (!saved_kbuild_dir || !saved_kbuild_include_opts) {
+   zfree(&saved_kbuild_dir);
+   zfree(&saved_kbuild_include_opts);
+   }
+   return;
+errout:
+   saved_kbuild_dir = ERR_PTR(-EINVAL);
+   saved_kbuild_include_opts = ERR_PTR(-EINVAL);
 }
 
-static void
-dump_obj(const cha

[tip:perf/core] perf tools: Pass context to perf hook functions

2016-12-06 Thread tip-bot for Wang Nan
Commit-ID:  8ad85e9e6fdaf996bf3ff60303ea00e696bcdd36
Gitweb: http://git.kernel.org/tip/8ad85e9e6fdaf996bf3ff60303ea00e696bcdd36
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:29 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 5 Dec 2016 15:51:42 -0300

perf tools: Pass context to perf hook functions

Pass a pointer to perf hook functions so they receive context
information during setup.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-6-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/tests/perf-hooks.c | 14 +-
 tools/perf/util/perf-hooks.c  | 10 +++---
 tools/perf/util/perf-hooks.h  |  6 --
 3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
index 9338cb2..665ecc1 100644
--- a/tools/perf/tests/perf-hooks.c
+++ b/tools/perf/tests/perf-hooks.c
@@ -15,13 +15,13 @@ static void sigsegv_handler(int sig __maybe_unused)
exit(-1);
 }
 
-static int hook_flags;
 
-static void the_hook(void)
+static void the_hook(void *_hook_flags)
 {
+   int *hook_flags = _hook_flags;
int *p = NULL;
 
-   hook_flags = 1234;
+   *hook_flags = 1234;
 
/* Generate a segfault, test perf_hooks__recover */
*p = 0;
@@ -29,13 +29,17 @@ static void the_hook(void)
 
 int test__perf_hooks(int subtest __maybe_unused)
 {
+   int hook_flags = 0;
+
signal(SIGSEGV, sigsegv_handler);
-   perf_hooks__set_hook("test", the_hook);
+   perf_hooks__set_hook("test", the_hook, &hook_flags);
perf_hooks__invoke_test();
 
/* hook is triggered? */
-   if (hook_flags != 1234)
+   if (hook_flags != 1234) {
+   pr_debug("Setting failed: %d (%p)\n", hook_flags, &hook_flags);
return TEST_FAIL;
+   }
 
/* the buggy hook is removed? */
if (perf_hooks__get_hook("test"))
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
index 4ce88e3..cb36830 100644
--- a/tools/perf/util/perf-hooks.c
+++ b/tools/perf/util/perf-hooks.c
@@ -27,7 +27,7 @@ void perf_hooks__invoke(const struct perf_hook_desc *desc)
*(current_perf_hook->p_hook_func) = NULL;
} else {
current_perf_hook = desc;
-   (**desc->p_hook_func)();
+   (**desc->p_hook_func)(desc->hook_ctx);
}
current_perf_hook = NULL;
 }
@@ -41,7 +41,9 @@ void perf_hooks__recover(void)
 #define PERF_HOOK(name)\
 perf_hook_func_t __perf_hook_func_##name = NULL;   \
 struct perf_hook_desc __perf_hook_desc_##name =\
-   {.hook_name = #name, .p_hook_func = &__perf_hook_func_##name};
+   {.hook_name = #name,\
+.p_hook_func = &__perf_hook_func_##name,   \
+.hook_ctx = NULL};
 #include "perf-hooks-list.h"
 #undef PERF_HOOK
 
@@ -54,7 +56,8 @@ static struct perf_hook_desc *perf_hooks[] = {
 #undef PERF_HOOK
 
 int perf_hooks__set_hook(const char *hook_name,
-perf_hook_func_t hook_func)
+perf_hook_func_t hook_func,
+void *hook_ctx)
 {
unsigned int i;
 
@@ -65,6 +68,7 @@ int perf_hooks__set_hook(const char *hook_name,
if (*(perf_hooks[i]->p_hook_func))
pr_warning("Overwrite existing hook: %s\n", hook_name);
*(perf_hooks[i]->p_hook_func) = hook_func;
+   perf_hooks[i]->hook_ctx = hook_ctx;
return 0;
}
return -ENOENT;
diff --git a/tools/perf/util/perf-hooks.h b/tools/perf/util/perf-hooks.h
index 1d482b2..838d579 100644
--- a/tools/perf/util/perf-hooks.h
+++ b/tools/perf/util/perf-hooks.h
@@ -5,10 +5,11 @@
 extern "C" {
 #endif
 
-typedef void (*perf_hook_func_t)(void);
+typedef void (*perf_hook_func_t)(void *ctx);
 struct perf_hook_desc {
const char * const hook_name;
perf_hook_func_t * const p_hook_func;
+   void *hook_ctx;
 };
 
 extern void perf_hooks__invoke(const struct perf_hook_desc *);
@@ -26,7 +27,8 @@ static inline void perf_hooks__invoke_##name(void)\
 
 extern int
 perf_hooks__set_hook(const char *hook_name,
-perf_hook_func_t hook_func);
+perf_hook_func_t hook_func,
+void *hook_ctx);
 
 extern perf_hook_func_t
 perf_hooks__get_hook(const char *hook_name);


[PATCH v4 01/18 -cleanup] perf build: Check LLVM version in feature check

2016-12-05 Thread Wang Nan
Cancel builtin llvm and clang support when LLVM version is
less than 3.9.0: following commits uses newer API.

Since Clang/LLVM's API is not guaranteed to be stable,
add a test-llvm-version.cpp feature checker, issue warning if
LLVM found in compiling environment is not tested yet.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: Arnaldo Carvalho de Melo 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/build/feature/Makefile  |  8 ++--
 tools/build/feature/test-llvm-version.cpp | 11 +++
 tools/build/feature/test-llvm.cpp |  5 +
 tools/perf/Makefile.config|  8 ++--
 4 files changed, 28 insertions(+), 4 deletions(-)
 create mode 100644 tools/build/feature/test-llvm-version.cpp

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 303196c..b564a2e 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -231,14 +231,18 @@ $(OUTPUT)test-jvmti.bin:
$(BUILD)
 
 $(OUTPUT)test-llvm.bin:
-   $(BUILDXX) -std=gnu++11 \
+   $(BUILDXX) -std=gnu++11 \
-I$(shell $(LLVM_CONFIG) --includedir)  \
-L$(shell $(LLVM_CONFIG) --libdir)  \
$(shell $(LLVM_CONFIG) --libs Core BPF) \
$(shell $(LLVM_CONFIG) --system-libs)
 
+$(OUTPUT)test-llvm-version.bin:
+   $(BUILDXX) -std=gnu++11 \
+   -I$(shell $(LLVM_CONFIG) --includedir)
+
 $(OUTPUT)test-clang.bin:
-   $(BUILDXX) -std=gnu++11 \
+   $(BUILDXX) -std=gnu++11 \
-I$(shell $(LLVM_CONFIG) --includedir)  \
-L$(shell $(LLVM_CONFIG) --libdir)  \
-Wl,--start-group -lclangBasic -lclangDriver\
diff --git a/tools/build/feature/test-llvm-version.cpp 
b/tools/build/feature/test-llvm-version.cpp
new file mode 100644
index 000..896d317
--- /dev/null
+++ b/tools/build/feature/test-llvm-version.cpp
@@ -0,0 +1,11 @@
+#include 
+#include "llvm/Config/llvm-config.h"
+
+#define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) 
+ LLVM_VERSION_PATCH)
+#define pass int main() {printf("%x\n", NUM_VERSION); return 0;}
+
+#if NUM_VERSION >= 0x030900
+pass
+#else
+# error This LLVM is not tested yet.
+#endif
diff --git a/tools/build/feature/test-llvm.cpp 
b/tools/build/feature/test-llvm.cpp
index d8d2cee..455a332 100644
--- a/tools/build/feature/test-llvm.cpp
+++ b/tools/build/feature/test-llvm.cpp
@@ -1,5 +1,10 @@
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/raw_ostream.h"
+#define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) 
+ LLVM_VERSION_PATCH)
+
+#if NUM_VERSION < 0x030900
+# error "LLVM version too low"
+#endif
 int main()
 {
llvm::errs() << "Hello World!\n";
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 09c2a98..2f4d5b0 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -802,12 +802,13 @@ ifdef LIBCLANGLLVM
 msg := $(warning No g++ found, disable clang and llvm support. Please 
install g++)
   else
 $(call feature_check,llvm)
+$(call feature_check,llvm-version)
 ifneq ($(feature-llvm), 1)
-  msg := $(warning No libLLVM found, disable clang and llvm support. 
Please install llvm-dev)
+  msg := $(warning No libLLVM found, disable clang and llvm support. 
Please install llvm-dev (>= 3.9.0))
 else
   $(call feature_check,clang)
   ifneq ($(feature-clang), 1)
-msg := $(warning No libclang found, disable clang and llvm support. 
Please install libclang-dev)
+msg := $(warning No libclang found, disable clang and llvm support. 
Please install libclang-dev (>= 3.9.0))
   else
 CFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT
 CXXFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT -I$(shell $(LLVM_CONFIG) 
--includedir)
@@ -816,6 +817,9 @@ ifdef LIBCLANGLLVM
USE_CXX = 1
USE_LLVM = 1
USE_CLANG = 1
+ifneq ($(feature-llvm-version),1)
+  msg := $(warning This version of llvm is not tested. May cause 
building error)
+endif
   endif
 endif
   endif
-- 
2.10.1



[PATCH v4 05/18] perf clang: Pass CFLAGS to builtin clang

2016-12-05 Thread Wang Nan
Pass -DLINUX_VERSION_CODE, -D__NR_CPUS__, llvm.clang-opt config options
and CFLAGS detected by kbuild detector to builtin clang so BPF scripts
can use kernel headers and user defined options like external clang
compiler.

Test:
  # perf record -v --dry-run -e tools/perf/tests/bpf-script-test-kbuild.c ls 
2>&1 | grep built
  bpf: builtin compiling successful

Committer notes:

Before installing the required clang/llvm devel files to have it
builtin:

  # perf record -v --dry-run -e tools/perf/tests/bpf-script-test-kbuild.c ls 
2>&1 | grep built
  bpf: builtin compiling failed: -95, try external compiler

I.e. it falls back to using the external compiler.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/clang.cpp | 105 --
 tools/perf/util/llvm-utils.h  |   9 +++-
 2 files changed, 109 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 340c948..6308aaf 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -27,6 +27,8 @@
 
 #include "clang.h"
 #include "clang-c.h"
+#include "llvm-utils.h"
+#include "util-cxx.h"
 
 namespace perf {
 
@@ -144,6 +146,101 @@ getBPFObjectFromModule(llvm::Module *Module)
return std::move(Buffer);
 }
 
+class ClangOptions {
+   llvm::SmallString FileName;
+   llvm::SmallString<64> KVerDef;
+   llvm::SmallString<64> NRCpusDef;
+   char *kbuild_dir;
+   char *kbuild_include_opts;
+   char *clang_opt;
+public:
+   ClangOptions(const char *filename) : FileName(filename),
+KVerDef(""),
+NRCpusDef(""),
+kbuild_dir(NULL),
+kbuild_include_opts(NULL),
+clang_opt(NULL)
+   {
+   llvm::sys::fs::make_absolute(FileName);
+
+   unsigned int kver;
+   if (!fetch_kernel_version(&kver, NULL, 0))
+   KVerDef = "-DLINUX_VERSION_CODE=" + 
std::to_string(kver);
+
+   int nr_cpus = llvm__get_nr_cpus();
+   if (nr_cpus > 0)
+   NRCpusDef = "-D__NR_CPUS__=" + std::to_string(nr_cpus);
+
+   if (llvm_param.clang_opt)
+   clang_opt = strdup(llvm_param.clang_opt);
+
+   llvm__get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
+   if (!kbuild_dir || !kbuild_include_opts) {
+   free(kbuild_dir);
+   free(kbuild_include_opts);
+   kbuild_dir = kbuild_include_opts = NULL;
+   }
+   }
+
+   ~ClangOptions()
+   {
+   free(kbuild_dir);
+   free(kbuild_include_opts);
+   free(clang_opt);
+   }
+
+   static void fillCFlagsFromString(opt::ArgStringList &CFlags, char *s, 
bool check = false)
+   {
+   if (!s)
+   return;
+
+   SmallVector Terms;
+   StringRef Opts(s);
+   Opts.split(Terms, ' ');
+
+   for (auto i = Terms.begin(); i != Terms.end(); i++)
+   s[i->end() - Opts.begin()] = '\0';
+
+   for (auto i = Terms.begin(); i != Terms.end(); i++) {
+   if (!check) {
+   CFlags.push_back(i->begin());
+   continue;
+   }
+
+   if (i->startswith("-I"))
+   CFlags.push_back(i->begin());
+   else if (i->startswith("-D"))
+   CFlags.push_back(i->begin());
+   else if (*i == "-include") {
+   CFlags.push_back((i++)->begin());
+   /* Let clang report this error */
+   if (i == Terms.end())
+   break;
+   CFlags.push_back(i->begin());
+   }
+   }
+   }
+
+   void getCFlags(opt::ArgStringList &CFlags)
+   {
+   CFlags.push_back(KVerDef.c_str());
+   CFlags.push_back(NRCpusDef.c_str());
+
+   fillCFlagsFromString(CFlags, clang_opt);
+   fillCFlagsFromString(CFlags, kbuild_include_opts, true);
+
+   if (kbuild_dir) {
+   CFlags.push_back("-working-directory");
+   CFlags.push_back(kbuild_dir);
+   }
+   }
+
+ 

[PATCH v4 03/18] perf clang: Cleanup clang options

2016-12-05 Thread Wang Nan
Follow Alexei's suggestion, remove "-ferror-limit=19",
"-fmessage-length=127", "-vectorize-loops" and "-vectorize-slp"
clang options: they are meaningless. Add comment for
"-Wno-unused-value" and "-Wno-pointer-sign".

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/clang.cpp | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 1e97415..7fe0222c5 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -41,13 +41,10 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, 
StringRef& Path,
"-cc1",
"-triple", "bpf-pc-linux",
"-fsyntax-only",
-   "-ferror-limit", "19",
-   "-fmessage-length", "127",
"-O2",
"-nostdsysteminc",
"-nobuiltininc",
-   "-vectorize-loops",
-   "-vectorize-slp",
+   /* Suppress warnings when using kernel headers */
"-Wno-unused-value",
"-Wno-pointer-sign",
"-x", "c"};
-- 
2.10.1



[PATCH v4 00/18] perf clang: Builtin clang and perfhook support

2016-12-05 Thread Wang Nan
This is version 4 of perf builtin clang and perfhook patch series.

In this patch set:
  1. Cleanup options passed to clang.
  2. Check LLVM version. Fail if llvm version < 3.9.0, and
 warn when it > 3.9.0. More version will be allowed after
 releasing of LLVM 3.9.1 / 4.0.0.
  3. Support dynamic linking LLVM and clang libraries.
  4. Rebase to Arnaldo's newest perf/core.

Wang Nan (18):
  perf build: Check LLVM version in feature check
  perf build: Support dynamic linking clang libraries
  perf clang: Cleanup clang options
  perf clang: Pass full path to builtin clang
  perf clang: Pass CFLAGS to builtin clang
  perf clang jit: Wrap llvm::Module using PerfModule
  perf clang jit: Insignt BPF and JIT functions in a Module
  perf clang jit: add PerfModule::doJIT to JIT perfhook functions
  perf clang jit: Export functions for jitted code
  perf clang jit: Actually JIT and hook in bpf loader
  perf clang jit: Collect the lowest address in maps section as map_base
  perf clang jit: Retrive fd of BPF map from its offset
  perf clang jit: Allow jitted perf hook access BPF maps
  perf clang: Link BPF functions declaration into perf
  perf clang: Declare BPF functions for BPF scripts automatically
  perf clang: Include helpers to BPF scripts
  perf clang builtin: Define hook helpers by default
  perf clang jit: Export getpid() to perf hook

 tools/build/feature/Makefile  |   8 +-
 tools/build/feature/test-llvm-version.cpp |  12 +
 tools/build/feature/test-llvm.cpp |   5 +
 tools/perf/Makefile.config|   8 +-
 tools/perf/Makefile.perf  |  20 +-
 tools/perf/tests/Build|   2 +-
 tools/perf/tests/bpf-script-example.c |  30 ++-
 tools/perf/tests/bpf-script-test-kbuild.c |   2 +
 tools/perf/tests/bpf-script-test-prologue.c   |   6 +-
 tools/perf/tests/bpf-script-test-relocation.c |  17 +-
 tools/perf/tests/clang.c  |   4 +
 tools/perf/util/Build |   1 +
 tools/perf/util/bpf-loader.c  |  85 ++-
 tools/perf/util/bpf-loader.h  |  19 ++
 tools/perf/util/c++/Build |   2 +
 tools/perf/util/c++/bpf-funcs-str.c   |  49 
 tools/perf/util/c++/bpf-helper-str.c  |  23 ++
 tools/perf/util/c++/clang-bpf-includes.h  |  13 +
 tools/perf/util/c++/clang-c.h |  24 +-
 tools/perf/util/c++/clang-test.cpp|  51 +++-
 tools/perf/util/c++/clang.cpp | 335 --
 tools/perf/util/c++/clang.h   |  47 +++-
 tools/perf/util/jit-helpers.c |  57 +
 tools/perf/util/jit-helpers.h |  28 +++
 tools/perf/util/llvm-utils.h  |   9 +-
 25 files changed, 802 insertions(+), 55 deletions(-)
 create mode 100644 tools/build/feature/test-llvm-version.cpp
 create mode 100644 tools/perf/util/c++/bpf-funcs-str.c
 create mode 100644 tools/perf/util/c++/bpf-helper-str.c
 create mode 100644 tools/perf/util/c++/clang-bpf-includes.h
 create mode 100644 tools/perf/util/jit-helpers.c
 create mode 100644 tools/perf/util/jit-helpers.h

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: Arnaldo Carvalho de Melo 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
-- 
2.10.1



[PATCH v4 04/18] perf clang: Pass full path to builtin clang

2016-12-05 Thread Wang Nan
If clang changes its working directory, relative path passed to
perf_clang__compile_bpf() becomes invalid. Before running clang,
convert it to absolute path so file can be found even working directory
is changed.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/clang.cpp | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 7fe0222c5..340c948 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -13,6 +13,7 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
@@ -161,7 +162,7 @@ void perf_clang__cleanup(void)
llvm::llvm_shutdown();
 }
 
-int perf_clang__compile_bpf(const char *filename,
+int perf_clang__compile_bpf(const char *_filename,
void **p_obj_buf,
size_t *p_obj_buf_sz)
 {
@@ -170,8 +171,11 @@ int perf_clang__compile_bpf(const char *filename,
if (!p_obj_buf || !p_obj_buf_sz)
return -EINVAL;
 
+   llvm::SmallString FileName(_filename);
+   llvm::sys::fs::make_absolute(FileName);
+
llvm::opt::ArgStringList CFlags;
-   auto M = getModuleFromSource(std::move(CFlags), filename);
+   auto M = getModuleFromSource(std::move(CFlags), FileName.data());
if (!M)
return  -EINVAL;
auto O = getBPFObjectFromModule(&*M);
-- 
2.10.1



[PATCH v4 02/18] perf build: Support dynamic linking clang libraries

2016-12-05 Thread Wang Nan
Statical linking result a very large perf executable. This patch makes
perf link clang libraries dynamically by using '-lclangBasic' style
linking option. If dynamic clang libraries are detected, gcc will use
them by default.

 Test result:

 (Build clang/llvm dynamically by setting -DBUILD_SHARED_LIBS=ON
  in its cmake configuration.)

 $ size ~/perf
 text  data bss dechex  filename
 4223234   754544   2395604828933826   1b97ec2  /home/wn/perf

 $ strip ~/perf
 $ ls -sh ~/perf
 4.8M /home/wn/perf

 Compare with statical linking:
 $ ls -sh ~/perf
 969M /home/wn/perf
 $ strip ~/perf
 $ ls -sh ~/perf
 52M /home/wn/perf

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/Makefile.perf | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 10495c9..192f2d6 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -329,9 +329,25 @@ endif
 LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive 
-Wl,--start-group $(EXTLIBS) -Wl,--end-group
 
 ifeq ($(USE_CLANG), 1)
+  # Only partial of the required clang libraries are listed.
+  #
+  # In case of dynamical linking, if clang is built and installed
+  # correctly, ld can infer the full list automatically. However,
+  # I observed a potential bug in 3.9.0 that four libraries
+  # (ASTMatchers, Format Rewrite and ToolingCore) are lost.
+  #
+  # In case of statical linking, providing the full list causes
+  # linking time dramatically increases because of --{start,end}-group.
+  #
+  # If linking error, replace CLANGLIBS_LIST with the full list
+  # and try again.
+  #
+  # The full list should be:
+  #
+  # Basic CodeGen Frontend Tooling AST Lex Driver Edit Parse Sema
+  # Serialization ASTMatchers Format Rewrite ToolingCore Analysis
   CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema 
Analysis Parse Serialization
-  LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) 
--libdir)/libclang$(l).a))
-  LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
+  LIBS += -L$(shell $(LLVM_CONFIG) --libdir) -Wl,--start-group $(foreach 
l,$(CLANGLIBS_LIST),-lclang$(l)) -Wl,--end-group
 endif
 
 ifeq ($(USE_LLVM), 1)
-- 
2.10.1



[PATCH v4 01/18] perf build: Check LLVM version in feature check

2016-12-05 Thread Wang Nan
Cancel builtin llvm and clang support when LLVM version is
less than 3.9.0: following commits uses newer API.

Since Clang/LLVM's API is not guaranteed to be stable,
add a test-llvm-version.cpp feature checker, issue warning if
LLVM found in compiling environment is not tested yet.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: Arnaldo Carvalho de Melo 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/build/feature/Makefile  |  8 ++--
 tools/build/feature/test-llvm-version.cpp | 12 
 tools/build/feature/test-llvm.cpp |  5 +
 tools/perf/Makefile.config|  8 ++--
 4 files changed, 29 insertions(+), 4 deletions(-)
 create mode 100644 tools/build/feature/test-llvm-version.cpp

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 303196c..b564a2e 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -231,14 +231,18 @@ $(OUTPUT)test-jvmti.bin:
$(BUILD)
 
 $(OUTPUT)test-llvm.bin:
-   $(BUILDXX) -std=gnu++11 \
+   $(BUILDXX) -std=gnu++11 \
-I$(shell $(LLVM_CONFIG) --includedir)  \
-L$(shell $(LLVM_CONFIG) --libdir)  \
$(shell $(LLVM_CONFIG) --libs Core BPF) \
$(shell $(LLVM_CONFIG) --system-libs)
 
+$(OUTPUT)test-llvm-version.bin:
+   $(BUILDXX) -std=gnu++11 \
+   -I$(shell $(LLVM_CONFIG) --includedir)
+
 $(OUTPUT)test-clang.bin:
-   $(BUILDXX) -std=gnu++11 \
+   $(BUILDXX) -std=gnu++11 \
-I$(shell $(LLVM_CONFIG) --includedir)  \
-L$(shell $(LLVM_CONFIG) --libdir)  \
-Wl,--start-group -lclangBasic -lclangDriver\
diff --git a/tools/build/feature/test-llvm-version.cpp 
b/tools/build/feature/test-llvm-version.cpp
new file mode 100644
index 000..e86b642
--- /dev/null
+++ b/tools/build/feature/test-llvm-version.cpp
@@ -0,0 +1,12 @@
+#include 
+#include "llvm/Config/llvm-config.h"
+
+#define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) 
+ LLVM_VERSION_PATCH)
+#define pass int main() {printf("%x\n", NUM_VERSION); return 0;}
+
+#if NUM_VERSION >= 0x030900
+pass
+#else
+# error This LLVM is not tested yet.
+#endif
+
diff --git a/tools/build/feature/test-llvm.cpp 
b/tools/build/feature/test-llvm.cpp
index d8d2cee..455a332 100644
--- a/tools/build/feature/test-llvm.cpp
+++ b/tools/build/feature/test-llvm.cpp
@@ -1,5 +1,10 @@
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/raw_ostream.h"
+#define NUM_VERSION (((LLVM_VERSION_MAJOR) << 16) + (LLVM_VERSION_MINOR << 8) 
+ LLVM_VERSION_PATCH)
+
+#if NUM_VERSION < 0x030900
+# error "LLVM version too low"
+#endif
 int main()
 {
llvm::errs() << "Hello World!\n";
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 09c2a98..2f4d5b0 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -802,12 +802,13 @@ ifdef LIBCLANGLLVM
 msg := $(warning No g++ found, disable clang and llvm support. Please 
install g++)
   else
 $(call feature_check,llvm)
+$(call feature_check,llvm-version)
 ifneq ($(feature-llvm), 1)
-  msg := $(warning No libLLVM found, disable clang and llvm support. 
Please install llvm-dev)
+  msg := $(warning No libLLVM found, disable clang and llvm support. 
Please install llvm-dev (>= 3.9.0))
 else
   $(call feature_check,clang)
   ifneq ($(feature-clang), 1)
-msg := $(warning No libclang found, disable clang and llvm support. 
Please install libclang-dev)
+msg := $(warning No libclang found, disable clang and llvm support. 
Please install libclang-dev (>= 3.9.0))
   else
 CFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT
 CXXFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT -I$(shell $(LLVM_CONFIG) 
--includedir)
@@ -816,6 +817,9 @@ ifdef LIBCLANGLLVM
USE_CXX = 1
USE_LLVM = 1
USE_CLANG = 1
+ifneq ($(feature-llvm-version),1)
+  msg := $(warning This version of llvm is not tested. May cause 
building error)
+endif
   endif
 endif
   endif
-- 
2.10.1



[PATCH v4 07/18] perf clang jit: Insignt BPF and JIT functions in a Module

2016-12-05 Thread Wang Nan
Identify BPF functions, JIT functions and maps during init. Functions in
section starting with "perfhook:" are JIT functions. They will be JIT
compiled and hooked at perfhooks.

During init of PerfModule, mark JIT functions as AvailableExternallyLinkage.
LLVM skips functions with linkage like this so they won't be compiled
into BPF objects.

Signed-off-by: Wang Nan 
Acked-by: Alexei Starovoitov 
Cc: Arnaldo Carvalho de Melo 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/clang.cpp | 38 ++
 tools/perf/util/c++/clang.h   |  7 +++
 2 files changed, 45 insertions(+)

diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 042db68..8a0f818 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -112,15 +112,53 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, 
StringRef Path)
 
 PerfModule::PerfModule(std::unique_ptr&& M) : 
Module(std::move(M))
 {
+   for (llvm::Function& F : *Module) {
+   if (F.getLinkage() != llvm::GlobalValue::ExternalLinkage)
+   continue;
+
+   if (StringRef(F.getSection()).startswith("perfhook:"))
+   JITFunctions.insert(&F);
+   else
+   BPFFunctions.insert(&F);
+   }
 
+   for (auto V = Module->global_begin(); V != Module->global_end(); V++) {
+   llvm::GlobalVariable *GV = &*V;
+   if (StringRef(GV->getSection()) == llvm::StringRef("maps"))
+   Maps.insert(GV);
+   }
 }
 
+void PerfModule::prepareBPF(void)
+{
+   /*
+* setLinkage(AvailableExternallyLinkage) causes LLVM
+* blindly skip the function. They still exist in Module
+* so we can bring them back by resetting linkage to
+* ExternalLinkage.
+*/
+   for (llvm::Function *F : JITFunctions)
+   F->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+   for (llvm::Function *F : BPFFunctions)
+   F->setLinkage(llvm::GlobalValue::ExternalLinkage);
+
+}
+
+void PerfModule::prepareJIT(void)
+{
+   for (llvm::Function *F : BPFFunctions)
+   F->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+   for (llvm::Function *F : JITFunctions)
+   F->setLinkage(llvm::GlobalValue::ExternalLinkage);
+
+}
 
 std::unique_ptr>
 PerfModule::toBPFObject(void)
 {
using namespace llvm;
 
+   prepareBPF();
std::string TargetTriple("bpf-pc-linux");
std::string Error;
const Target* Target = TargetRegistry::lookupTarget(TargetTriple, 
Error);
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index cbb291b..1eb71a6 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -6,6 +6,7 @@
 #include "llvm/IR/Module.h"
 #include "llvm/Option/Option.h"
 #include 
+#include 
 
 namespace perf {
 
@@ -14,6 +15,12 @@ using namespace llvm;
 class PerfModule {
 private:
std::unique_ptr Module;
+
+   std::set Maps;
+   std::set BPFFunctions;
+   std::set JITFunctions;
+   void prepareBPF(void);
+   void prepareJIT(void);
 public:
inline llvm::Module *getModule(void)
{
-- 
2.10.1



[PATCH v4 16/18] perf clang: Include helpers to BPF scripts

2016-12-05 Thread Wang Nan
Automatically include some commonly used macros and struct definitions
into BPF scripts. Script writers are no longer required to define
'SEC' and 'struct bpf_map_def' in each of their scripts.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/tests/bpf-script-example.c |  2 +-
 tools/perf/tests/bpf-script-test-kbuild.c |  2 ++
 tools/perf/tests/bpf-script-test-prologue.c   |  4 +++-
 tools/perf/tests/bpf-script-test-relocation.c |  3 +--
 tools/perf/util/c++/Build |  1 +
 tools/perf/util/c++/bpf-helper-str.c  | 15 +++
 tools/perf/util/c++/clang-bpf-includes.h  |  1 +
 tools/perf/util/c++/clang.cpp |  1 +
 8 files changed, 25 insertions(+), 4 deletions(-)
 create mode 100644 tools/perf/util/c++/bpf-helper-str.c

diff --git a/tools/perf/tests/bpf-script-example.c 
b/tools/perf/tests/bpf-script-example.c
index 42dc341..e60bebf 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -9,6 +9,7 @@
 #define BPF_ANY 0
 #define BPF_MAP_TYPE_ARRAY 2
 
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 struct bpf_map_def {
unsigned int type;
unsigned int key_size;
@@ -18,7 +19,6 @@ struct bpf_map_def {
 
 #define SEC(NAME) __attribute__((section(NAME), used))
 
-#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 #define BPF_FUNC_map_lookup_elem 1
 #define BPF_FUNC_map_update_elem 2
 
diff --git a/tools/perf/tests/bpf-script-test-kbuild.c 
b/tools/perf/tests/bpf-script-test-kbuild.c
index 3626924..f1b48a4 100644
--- a/tools/perf/tests/bpf-script-test-kbuild.c
+++ b/tools/perf/tests/bpf-script-test-kbuild.c
@@ -6,7 +6,9 @@
 # error Need LINUX_VERSION_CODE
 # error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" 
into llvm section of ~/.perfconfig'
 #endif
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 #define SEC(NAME) __attribute__((section(NAME), used))
+#endif
 
 #include 
 #include 
diff --git a/tools/perf/tests/bpf-script-test-prologue.c 
b/tools/perf/tests/bpf-script-test-prologue.c
index ada812b..e2176c9 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -6,7 +6,6 @@
 # error Need LINUX_VERSION_CODE
 # error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" 
into llvm section of ~/.perfconfig'
 #endif
-#define SEC(NAME) __attribute__((section(NAME), used))
 
 #include 
 
@@ -14,6 +13,9 @@
 #define FMODE_WRITE0x2
 
 #ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
+
+#define SEC(NAME) __attribute__((section(NAME), used))
+
 static void (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
(void *) 6;
 #endif
diff --git a/tools/perf/tests/bpf-script-test-relocation.c 
b/tools/perf/tests/bpf-script-test-relocation.c
index 57c96a3..bb54926 100644
--- a/tools/perf/tests/bpf-script-test-relocation.c
+++ b/tools/perf/tests/bpf-script-test-relocation.c
@@ -9,6 +9,7 @@
 #define BPF_ANY 0
 #define BPF_MAP_TYPE_ARRAY 2
 
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 struct bpf_map_def {
unsigned int type;
unsigned int key_size;
@@ -17,8 +18,6 @@ struct bpf_map_def {
 };
 
 #define SEC(NAME) __attribute__((section(NAME), used))
-
-#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 #define BPF_FUNC_map_lookup_elem 1
 #define BPF_FUNC_map_update_elem 2
 
diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
index bd71abf..faa0268 100644
--- a/tools/perf/util/c++/Build
+++ b/tools/perf/util/c++/Build
@@ -1,3 +1,4 @@
 libperf-$(CONFIG_CLANGLLVM) += clang.o
 libperf-$(CONFIG_CLANGLLVM) += clang-test.o
 libperf-$(CONFIG_CLANGLLVM) += bpf-funcs-str.o
+libperf-$(CONFIG_CLANGLLVM) += bpf-helper-str.o
diff --git a/tools/perf/util/c++/bpf-helper-str.c 
b/tools/perf/util/c++/bpf-helper-str.c
new file mode 100644
index 000..17f915c
--- /dev/null
+++ b/tools/perf/util/c++/bpf-helper-str.c
@@ -0,0 +1,15 @@
+#include "clang-bpf-includes.h"
+const char clang_builtin_bpf_helper_str[] =
+"#ifdef BUILTIN_CLANG_DEFAULT_INCLUDE\n"
+"#ifndef BPF_HELPER_DEFINED\n"
+"#define BPF_HELPER_DEFINED\n"
+"struct bpf_map_def {\n"
+"  unsigned int type;\n"
+"  unsigned int key_size;\n"
+"  unsigned int value_size;\n"
+"  unsigned int max_entries;\n"
+"};\n"
+"#define SEC(NAME) __attribute__((section(NAME), used))\n"
+"#endif\n"
+"#endif"
+;
diff --git a/tools/perf/util/c++/clang-bpf-includes.h 
b/tools/perf/util/c++/clang-bpf-includes.h
index 385a5bb..577b40c 100644
--- a/tools/perf/util/c++/clang-bpf-includes.h
+++ b/tools/perf/util/c++/clang-bpf-includes.h
@@ -5,6 +5,7 @@ extern "C" {
 #endif
 
 extern const char clang_builtin_bpf_funcs_str[];
+extern const char clang_builtin_bpf_helper_str[];
 
 #ifdef 

[PATCH v4 10/18] perf clang jit: Actually JIT and hook in bpf loader

2016-12-05 Thread Wang Nan
Makes perf_clang__compile_bpf() actually uses clang jit to compile perf
hooks. Returns a map through perf_clang__compile_bpf(), and set hooks
after bpf_object is created.

After this path jitting takes actions for bpf loader. For example:
  $ cat ./test.c
  /**/
  #define SEC(name) __attribute__((section(name), used))
  SEC("dofork=_do_fork")
  int dofork(void *ctx)
  {
  return 0;
  }
  extern int printf(const char *fmt, ...);
  SEC("perfhook:record_start")
  void record_start(void)
  {
  printf("Welcom to perf record\n");
  }
  SEC("perfhook:record_end")
  void record_end(void)
  {
  printf("Goodbye, perf record\n");
  }
  char _license[] SEC("license") = "GPL";
  int _version SEC("version") = LINUX_VERSION_CODE;
  /**/
  $ perf record -e ./test.c sleep 1
  Welcom to perf record
  [ perf record: Woken up 1 times to write data ]
  Goodbye, perf record
  [ perf record: Captured and wrote 0.014 MB perf.data ]

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/bpf-loader.c  | 11 ++-
 tools/perf/util/c++/clang-c.h | 18 --
 tools/perf/util/c++/clang.cpp | 28 +++-
 3 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 36c8611..bf61a6f 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -85,9 +85,11 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
int err;
void *obj_buf;
size_t obj_buf_sz;
+   jitted_funcs_map_t jitted_funcs_map;
 
perf_clang__init();
-   err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+   err = perf_clang__compile_bpf(filename, &obj_buf,
+ &obj_buf_sz, &jitted_funcs_map);
perf_clang__cleanup();
if (err) {
pr_warning("bpf: builtin compilation failed: %d, try 
external compiler\n", err);
@@ -101,6 +103,13 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
if (!IS_ERR(obj) && llvm_param.dump_obj)
llvm__dump_obj(filename, obj_buf, obj_buf_sz);
 
+   /*
+* Call perf_clang__hook_jitted_func even IS_ERR(obj) to make 
sure
+* the C++ map pointer is deleted.
+*/
+   if (jitted_funcs_map)
+   perf_clang__hook_jitted_func(jitted_funcs_map, obj, 
IS_ERR(obj));
+
free(obj_buf);
} else
obj = bpf_object__open(filename);
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 9f75e41..021b1ad 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -8,6 +8,7 @@
 extern "C" {
 #endif
 
+typedef void *jitted_funcs_map_t;
 #ifdef HAVE_LIBCLANGLLVM_SUPPORT
 extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
@@ -20,7 +21,11 @@ extern void test__clang_callback(int x);
 
 extern int perf_clang__compile_bpf(const char *filename,
   void **p_obj_buf,
-  size_t *p_obj_buf_sz);
+  size_t *p_obj_buf_sz,
+  jitted_funcs_map_t *p_funcs_map);
+
+extern int
+perf_clang__hook_jitted_func(jitted_funcs_map_t map, void *ctx, bool is_err);
 #else
 
 
@@ -34,7 +39,16 @@ static inline int test__clang_jit(void) { return -1;}
 static inline int
 perf_clang__compile_bpf(const char *filename __maybe_unused,
void **p_obj_buf __maybe_unused,
-   size_t *p_obj_buf_sz __maybe_unused)
+   size_t *p_obj_buf_sz __maybe_unused,
+   jitted_funcs_map_t *p_funcs_map __maybe_unused)
+{
+   return -ENOTSUP;
+}
+
+static inline int
+perf_clang__hook_jitted_func(jitted_funcs_map_t map __maybe_unused,
+void *ctx __maybe_unused,
+bool is_err __maybe_unused)
 {
return -ENOTSUP;
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 3ce2e0e..4a98597 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -391,7 +391,8 @@ void perf_clang__cleanup(void)
 
 int perf_clang__compile_bpf(const char *_filename,
void **p_obj_buf,
-   size_t *p_obj_buf_sz)
+   size_t *p_obj_buf_sz,
+   jitted_funcs_map_t *p_funcs_map)
 {
  

[PATCH v4 17/18] perf clang builtin: Define hook helpers by default

2016-12-05 Thread Wang Nan
Append declarations of helpers to default include file. All functions
appear in exported_funcs array should be declared here except
test__clang_callback, because it is used for perf test only.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/bpf-helper-str.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/tools/perf/util/c++/bpf-helper-str.c 
b/tools/perf/util/c++/bpf-helper-str.c
index 17f915c..f4d6d57 100644
--- a/tools/perf/util/c++/bpf-helper-str.c
+++ b/tools/perf/util/c++/bpf-helper-str.c
@@ -10,6 +10,13 @@ const char clang_builtin_bpf_helper_str[] =
 "  unsigned int max_entries;\n"
 "};\n"
 "#define SEC(NAME) __attribute__((section(NAME), used))\n"
+"extern int printf(const char *, ...);\n"
+"extern int puts(const char *);\n"
+"extern int perf_map_update_elem(void *, void *, void *, void *, unsigned 
long);\n"
+"extern int perf_map_lookup_elem(void *, void *, void *, void *);\n"
+"extern int perf_map_get_next_key(void *, void *, void *, void *);\n"
+"extern int perf_map_pin(void *, void *, const char *);\n"
+"extern int perf_map_get(const char *);\n"
 "#endif\n"
 "#endif"
 ;
-- 
2.10.1



[PATCH v4 18/18] perf clang jit: Export getpid() to perf hook

2016-12-05 Thread Wang Nan
After this patch perf hooks can retrive pid of perf itself by calling
getpid. It is important for excluding event from perf.

This commit is also an example to show how to export more helpers to
hooked script.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/bpf-helper-str.c | 1 +
 tools/perf/util/c++/clang.cpp| 1 +
 2 files changed, 2 insertions(+)

diff --git a/tools/perf/util/c++/bpf-helper-str.c 
b/tools/perf/util/c++/bpf-helper-str.c
index f4d6d57..1ad6ec0 100644
--- a/tools/perf/util/c++/bpf-helper-str.c
+++ b/tools/perf/util/c++/bpf-helper-str.c
@@ -12,6 +12,7 @@ const char clang_builtin_bpf_helper_str[] =
 "#define SEC(NAME) __attribute__((section(NAME), used))\n"
 "extern int printf(const char *, ...);\n"
 "extern int puts(const char *);\n"
+"extern int getpid(void);\n"
 "extern int perf_map_update_elem(void *, void *, void *, void *, unsigned 
long);\n"
 "extern int perf_map_lookup_elem(void *, void *, void *, void *);\n"
 "extern int perf_map_get_next_key(void *, void *, void *, void *);\n"
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index d49305a..ca5264c 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -239,6 +239,7 @@ static std::map 
exported_funcs =
EXPORT(test__clang_callback),
EXPORT(printf),
EXPORT(puts),
+   EXPORT(getpid),
EXPORT(JIT_HELPER_FUNC_NAME(map_update_elem)),
EXPORT(JIT_HELPER_FUNC_NAME(map_lookup_elem)),
EXPORT(JIT_HELPER_FUNC_NAME(map_get_next_key)),
-- 
2.10.1



[PATCH v4 11/18] perf clang jit: Collect the lowest address in maps section as map_base

2016-12-05 Thread Wang Nan
During jitting, find the lowest address in maps section and store its
value to _map_base. Pass its value out through perf_clang__compile_bpf().
map_base is useful for jitted functions accessing BPF maps.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/bpf-loader.c  | 39 +--
 tools/perf/util/c++/clang-c.h |  6 --
 tools/perf/util/c++/clang.cpp | 15 +--
 tools/perf/util/c++/clang.h   |  5 +
 4 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index bf61a6f..9a0c33d 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -47,6 +47,10 @@ struct bpf_prog_priv {
int *type_mapping;
 };
 
+struct bpf_obj_priv {
+   void *map_base;
+};
+
 static bool libbpf_initialized;
 
 struct bpf_object *
@@ -70,9 +74,20 @@ bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz, 
const char *name)
return obj;
 }
 
+static void
+clear_obj_priv(struct bpf_object *obj __maybe_unused,
+  void *_priv)
+{
+   struct bpf_obj_priv *priv = _priv;
+
+   free(priv);
+}
+
 struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 {
struct bpf_object *obj;
+   void *map_base = NULL;
+   int err;
 
if (!libbpf_initialized) {
libbpf_set_print(libbpf_warning,
@@ -82,14 +97,14 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
}
 
if (source) {
-   int err;
void *obj_buf;
size_t obj_buf_sz;
jitted_funcs_map_t jitted_funcs_map;
 
perf_clang__init();
err = perf_clang__compile_bpf(filename, &obj_buf,
- &obj_buf_sz, &jitted_funcs_map);
+ &obj_buf_sz, &jitted_funcs_map,
+ &map_base);
perf_clang__cleanup();
if (err) {
pr_warning("bpf: builtin compilation failed: %d, try 
external compiler\n", err);
@@ -119,7 +134,27 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
return obj;
}
 
+   if (map_base) {
+   struct bpf_obj_priv *priv = calloc(sizeof(*priv), 1);
+
+   if (!priv) {
+   pr_debug("bpf: failed to alloc priv for object\n");
+   err = -ENOMEM;
+   goto errout;
+   }
+   priv->map_base = map_base;
+
+   err = bpf_object__set_priv(obj, priv, clear_obj_priv);
+   if (err) {
+   pr_debug("Failed to set priv for object '%s'\n", 
filename);
+   goto errout;
+   }
+   }
+
return obj;
+errout:
+   bpf_object__close(obj);
+   return ERR_PTR(err);
 }
 
 void bpf__clear(void)
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 021b1ad..4cf651b 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -22,7 +22,8 @@ extern void test__clang_callback(int x);
 extern int perf_clang__compile_bpf(const char *filename,
   void **p_obj_buf,
   size_t *p_obj_buf_sz,
-  jitted_funcs_map_t *p_funcs_map);
+  jitted_funcs_map_t *p_funcs_map,
+  void **p_map_base);
 
 extern int
 perf_clang__hook_jitted_func(jitted_funcs_map_t map, void *ctx, bool is_err);
@@ -40,7 +41,8 @@ static inline int
 perf_clang__compile_bpf(const char *filename __maybe_unused,
void **p_obj_buf __maybe_unused,
size_t *p_obj_buf_sz __maybe_unused,
-   jitted_funcs_map_t *p_funcs_map __maybe_unused)
+   jitted_funcs_map_t *p_funcs_map __maybe_unused,
+   void **p_map_base __maybe_unused)
 {
return -ENOTSUP;
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 4a98597..684855c 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -119,7 +119,7 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, 
StringRef Path)
return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
-PerfModule::PerfModule(std::unique_ptr&& M) : 
Module(std::move(M))
+PerfModule::PerfModule(std::unique_ptr&& M) : 
Module(std::move(M)), _map_base(NULL)
 {
for (llvm::Function& F : *Module) {
if (F.getLinkage() != llvm::GlobalValue::ExternalLinkage)
@@ -250,6 +250,13 @@ int PerfModule::doJIT(void

[PATCH v4 12/18] perf clang jit: Retrive fd of BPF map from its offset

2016-12-05 Thread Wang Nan
bpf__map_fd() is introduced to retrive fd of a BPF map through its
offset in BPF object. This function is going be used in further
commits which allow scripts jitted by builtin clang access BPF maps.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/bpf-loader.c | 37 +
 tools/perf/util/bpf-loader.h | 19 +++
 2 files changed, 56 insertions(+)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 9a0c33d..3eb420e 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -19,6 +19,7 @@
 #include "parse-events.h"
 #include "llvm-utils.h"
 #include "c++/clang-c.h"
+#include "asm/bug.h"   // for WARN_ONCE
 
 #define DEFINE_PRINT_FN(name, level) \
 static int libbpf_##name(const char *fmt, ...) \
@@ -1644,6 +1645,28 @@ int bpf__setup_stdout(struct perf_evlist *evlist 
__maybe_unused)
return 0;
 }
 
+int bpf__map_fd(struct bpf_object *obj, void *jit_map)
+{
+   struct bpf_obj_priv *priv = bpf_object__priv(obj);
+   struct bpf_map *map;
+   size_t map_offset;
+   void *map_base;
+
+   if (IS_ERR(priv))
+   return PTR_ERR(priv);
+   if (!priv)
+   return -EINVAL;
+
+   map_base = priv->map_base;
+   map_offset = jit_map - map_base;
+   map = bpf_object__find_map_by_offset(obj, map_offset);
+   WARN_ONCE(IS_ERR(map), "can't find map offset %zu from '%s'\n",
+ map_offset, bpf_object__name(obj));
+   if (IS_ERR(map))
+   return -ENOENT;
+   return bpf_map__fd(map);
+}
+
 #define ERRNO_OFFSET(e)((e) - __BPF_LOADER_ERRNO__START)
 #define ERRCODE_OFFSET(c)  ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)
 #define NR_ERRNO   (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)
@@ -1825,3 +1848,17 @@ int bpf__strerror_setup_stdout(struct perf_evlist 
*evlist __maybe_unused,
bpf__strerror_end(buf, size);
return 0;
 }
+
+int bpf__strerror_map_fd(struct bpf_object *obj, void *jit_map,
+int err, char *buf, size_t size)
+{
+   struct bpf_obj_priv *priv = bpf_object__priv(obj);
+   ptrdiff_t offset = priv ? jit_map - priv->map_base : jit_map - NULL;
+
+   bpf__strerror_head(err, buf, size);
+   bpf__strerror_entry(EINVAL, "No map in BPF object %s", 
bpf_object__name(obj));
+   bpf__strerror_entry(ENOENT, "Can't find map offset %lx in BPF object 
%s",
+   (unsigned long)offset, bpf_object__name(obj));
+   bpf__strerror_end(buf, size);
+   return 0;
+}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index f2b737b..c40812b 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -84,6 +84,9 @@ int bpf__setup_stdout(struct perf_evlist *evlist);
 int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err,
   char *buf, size_t size);
 
+int bpf__map_fd(struct bpf_object *obj, void *jit_map);
+int bpf__strerror_map_fd(struct bpf_object *obj, void *jit_map,
+int err, char *buf, size_t size);
 #else
 static inline struct bpf_object *
 bpf__prepare_load(const char *filename __maybe_unused,
@@ -136,6 +139,13 @@ bpf__setup_stdout(struct perf_evlist *evlist 
__maybe_unused)
 }
 
 static inline int
+bpf__map_fd(struct bpf_object *obj __maybe_unused,
+   void *map_ptr __maybe_unused)
+{
+   return -ENOTSUP;
+}
+
+static inline int
 __bpf_strerror(char *buf, size_t size)
 {
if (!size)
@@ -196,5 +206,14 @@ bpf__strerror_setup_stdout(struct perf_evlist *evlist 
__maybe_unused,
 {
return __bpf_strerror(buf, size);
 }
+
+static inline int
+bpf__strerror_map_fd(struct bpf_object *obj __maybe_unused,
+void *jit_map __maybe_unused,
+int err __maybe_unused,
+char *buf, size_t size);
+{
+   return __bpf_strerror(buf, size);
+}
 #endif
 #endif
-- 
2.10.1



[PATCH v4 06/18] perf clang jit: Wrap llvm::Module using PerfModule

2016-12-05 Thread Wang Nan
Use PerfModule wrap llvm::Module and return perf::PerfModule in APIs to
replace llvm::Module. Following commits are going to add new functions
to PerfModule.

getBPFObjectFromModule is merged to a method of perf::PerfModule.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/clang-test.cpp | 10 +-
 tools/perf/util/c++/clang.cpp  | 20 +---
 tools/perf/util/c++/clang.h| 22 --
 3 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/c++/clang-test.cpp 
b/tools/perf/util/c++/clang-test.cpp
index 9b11e8c..fb05e56 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -13,18 +13,18 @@ public:
~perf_clang_scope() {perf_clang__cleanup();}
 };
 
-static std::unique_ptr
+static std::unique_ptr
 __test__clang_to_IR(void)
 {
unsigned int kernel_version;
 
if (fetch_kernel_version(&kernel_version, NULL, 0))
-   return std::unique_ptr(nullptr);
+   return std::unique_ptr(nullptr);
 
std::string cflag_kver("-DLINUX_VERSION_CODE=" +
std::to_string(kernel_version));
 
-   std::unique_ptr M =
+   std::unique_ptr M =
perf::getModuleFromSource({cflag_kver.c_str()},
  "perf-test.c",
  test_llvm__bpf_base_prog);
@@ -39,7 +39,7 @@ int test__clang_to_IR(void)
auto M = __test__clang_to_IR();
if (!M)
return -1;
-   for (llvm::Function& F : *M)
+   for (llvm::Function& F : *(M->getModule()))
if (F.getName() == "bpf_func__SyS_epoll_wait")
return 0;
return -1;
@@ -53,7 +53,7 @@ int test__clang_to_obj(void)
if (!M)
return -1;
 
-   auto Buffer = perf::getBPFObjectFromModule(&*M);
+   auto Buffer = M->toBPFObject();
if (!Buffer)
return -1;
return 0;
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 6308aaf..042db68 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -61,7 +61,7 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, 
StringRef& Path,
return CI;
 }
 
-static std::unique_ptr
+static std::unique_ptr
 getModuleFromSource(llvm::opt::ArgStringList CFlags,
StringRef Path, IntrusiveRefCntPtr VFS)
 {
@@ -77,12 +77,12 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags,
 
std::unique_ptr Act(new EmitLLVMOnlyAction(&*LLVMCtx));
if (!Clang.ExecuteAction(*Act))
-   return std::unique_ptr(nullptr);
+   return std::unique_ptr(nullptr);
 
-   return Act->takeModule();
+   return std::unique_ptr(new 
PerfModule(std::move(Act->takeModule(;
 }
 
-std::unique_ptr
+std::unique_ptr
 getModuleFromSource(llvm::opt::ArgStringList CFlags,
StringRef Name, StringRef Content)
 {
@@ -103,15 +103,21 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags,
return getModuleFromSource(std::move(CFlags), Name, OverlayFS);
 }
 
-std::unique_ptr
+std::unique_ptr
 getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 {
IntrusiveRefCntPtr VFS(vfs::getRealFileSystem());
return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
+PerfModule::PerfModule(std::unique_ptr&& M) : 
Module(std::move(M))
+{
+
+}
+
+
 std::unique_ptr>
-getBPFObjectFromModule(llvm::Module *Module)
+PerfModule::toBPFObject(void)
 {
using namespace llvm;
 
@@ -275,7 +281,7 @@ int perf_clang__compile_bpf(const char *_filename,
auto M = getModuleFromSource(std::move(CFlags), Opts.getFileName());
if (!M)
return  -EINVAL;
-   auto O = getBPFObjectFromModule(&*M);
+   auto O = M->toBPFObject();
if (!O)
return -EINVAL;
 
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index dd8b042..cbb291b 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -11,16 +11,26 @@ namespace perf {
 
 using namespace llvm;
 
-std::unique_ptr
+class PerfModule {
+private:
+   std::unique_ptr Module;
+public:
+   inline llvm::Module *getModule(void)
+   {
+   return Module.get();
+   }
+
+   PerfModule(std::unique_ptr&& M);
+
+   std::unique_ptr> toBPFObject(void);
+};
+
+std::unique_ptr
 getModuleFromSource(opt::ArgStringList CFlags,
StringRef Name, StringRef Content);
 
-std::unique_ptr
+std::unique_ptr
 getModuleFromSource(opt::ArgStringList CFlags,
StringRef Path);
-
-std::unique_ptr>
-getBPFObjectFromModule(llvm::Module *Module);
-
 }
 #endif
-- 
2.10.1



[PATCH v4 08/18] perf clang jit: add PerfModule::doJIT to JIT perfhook functions

2016-12-05 Thread Wang Nan
PerfModule::doJIT JIT compile perfhook functions and saves result into
a map. Add a test case for it.

At this stage perfhook functions can do no useful things because they
can't invoke external functions and can't return value. Following
commits are going to make improvment.

Don't hook functions right after jitted because bpf_object is unavailable
during jitting but it should be the context of jitted functions.

Signed-off-by: Wang Nan 
Acked-by: Alexei Starovoitov 
Cc: Arnaldo Carvalho de Melo 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/tests/bpf-script-example.c |  8 
 tools/perf/tests/clang.c  |  4 ++
 tools/perf/util/c++/clang-c.h |  2 +
 tools/perf/util/c++/clang-test.cpp| 32 +++-
 tools/perf/util/c++/clang.cpp | 71 +++
 tools/perf/util/c++/clang.h   | 13 +++
 6 files changed, 128 insertions(+), 2 deletions(-)

diff --git a/tools/perf/tests/bpf-script-example.c 
b/tools/perf/tests/bpf-script-example.c
index 268e5f8..265036e 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -46,3 +46,11 @@ int bpf_func__SyS_epoll_wait(void *ctx)
 }
 char _license[] SEC("license") = "GPL";
 int _version SEC("version") = LINUX_VERSION_CODE;
+
+#ifdef TEST_PERF_HOOK
+SEC("perfhook:test")
+void hook_test(void)
+{
+   return;
+}
+#endif
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
index f853e24..e7b35c4 100644
--- a/tools/perf/tests/clang.c
+++ b/tools/perf/tests/clang.c
@@ -16,6 +16,10 @@ static struct {
.func = test__clang_to_obj,
.desc = "builtin clang compile C source to ELF object",
},
+   {
+   .func = test__clang_jit,
+   .desc = "builtin clang compile mixed BPF and native code",
+   },
 #endif
 };
 
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 0eadd79..5ebcb41 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -14,6 +14,7 @@ extern void perf_clang__cleanup(void);
 
 extern int test__clang_to_IR(void);
 extern int test__clang_to_obj(void);
+extern int test__clang_jit(void);
 
 extern int perf_clang__compile_bpf(const char *filename,
   void **p_obj_buf,
@@ -26,6 +27,7 @@ static inline void perf_clang__cleanup(void) { }
 
 static inline int test__clang_to_IR(void) { return -1; }
 static inline int test__clang_to_obj(void) { return -1;}
+static inline int test__clang_jit(void) { return -1;}
 
 static inline int
 perf_clang__compile_bpf(const char *filename __maybe_unused,
diff --git a/tools/perf/util/c++/clang-test.cpp 
b/tools/perf/util/c++/clang-test.cpp
index fb05e56..2b4aa8d 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -5,6 +5,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 class perf_clang_scope {
@@ -14,7 +15,7 @@ public:
 };
 
 static std::unique_ptr
-__test__clang_to_IR(void)
+__test__clang_to_IR(bool perfhook)
 {
unsigned int kernel_version;
 
@@ -23,14 +24,22 @@ __test__clang_to_IR(void)
 
std::string cflag_kver("-DLINUX_VERSION_CODE=" +
std::to_string(kernel_version));
+   std::string cflag_perfhook(perfhook ? "-DTEST_PERF_HOOK=1" : "");
 
std::unique_ptr M =
-   perf::getModuleFromSource({cflag_kver.c_str()},
+   perf::getModuleFromSource({cflag_kver.c_str(),
+  cflag_perfhook.c_str()},
  "perf-test.c",
  test_llvm__bpf_base_prog);
return M;
 }
 
+static std::unique_ptr
+__test__clang_to_IR(void)
+{
+   return __test__clang_to_IR(false);
+}
+
 extern "C" {
 int test__clang_to_IR(void)
 {
@@ -59,4 +68,23 @@ int test__clang_to_obj(void)
return 0;
 }
 
+int test__clang_jit(void)
+{
+   perf_clang_scope _scope;
+
+   auto M = __test__clang_to_IR(true);
+   if (!M)
+   return -1;
+
+   if (M->doJIT())
+   return -1;
+
+   std::unique_ptr hooks(M->copyJITResult());
+   for (auto i : *hooks)
+   perf_hooks__set_hook(i.first.c_str(), i.second, NULL);
+
+   perf_hooks__invoke_test();
+   return 0;
+}
+
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 8a0f818..b996ec6 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -14,9 +14,14 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include

[PATCH v4 09/18] perf clang jit: Export functions for jitted code

2016-12-05 Thread Wang Nan
After this patch functions attached on perf hooks is allowed to invoke
external functions. Add a testcase for this feature.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/tests/Build|  2 +-
 tools/perf/tests/bpf-script-example.c |  4 
 tools/perf/util/c++/clang-c.h |  2 ++
 tools/perf/util/c++/clang-test.cpp|  9 +
 tools/perf/util/c++/clang.cpp | 17 -
 5 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 6676c2d..d6e6e00 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -49,7 +49,7 @@ $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c 
tests/Build
$(call rule_mkdir)
$(Q)echo '#include ' > $@
$(Q)echo 'const char test_llvm__bpf_base_prog[] =' >> $@
-   $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
+   $(Q)sed -e 's/\\//g' -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
$(Q)echo ';' >> $@
 
 $(OUTPUT)tests/llvm-src-kbuild.c: tests/bpf-script-test-kbuild.c tests/Build
diff --git a/tools/perf/tests/bpf-script-example.c 
b/tools/perf/tests/bpf-script-example.c
index 265036e..ccbc19c 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -48,9 +48,13 @@ char _license[] SEC("license") = "GPL";
 int _version SEC("version") = LINUX_VERSION_CODE;
 
 #ifdef TEST_PERF_HOOK
+extern int printf(const char *fmt, ...);
+extern void test__clang_callback(int x);
 SEC("perfhook:test")
 void hook_test(void)
 {
+   printf("Hello, hook_test\n");
+   test__clang_callback(1234);
return;
 }
 #endif
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 5ebcb41..9f75e41 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -16,6 +16,8 @@ extern int test__clang_to_IR(void);
 extern int test__clang_to_obj(void);
 extern int test__clang_jit(void);
 
+extern void test__clang_callback(int x);
+
 extern int perf_clang__compile_bpf(const char *filename,
   void **p_obj_buf,
   size_t *p_obj_buf_sz);
diff --git a/tools/perf/util/c++/clang-test.cpp 
b/tools/perf/util/c++/clang-test.cpp
index 2b4aa8d..0bdb807 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -68,6 +68,13 @@ int test__clang_to_obj(void)
return 0;
 }
 
+static int callback_flag;
+
+void test__clang_callback(int x)
+{
+   callback_flag = x;
+}
+
 int test__clang_jit(void)
 {
perf_clang_scope _scope;
@@ -84,6 +91,8 @@ int test__clang_jit(void)
perf_hooks__set_hook(i.first.c_str(), i.second, NULL);
 
perf_hooks__invoke_test();
+   if (callback_flag != 1234)
+   return -1;
return 0;
 }
 
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index b996ec6..3ce2e0e 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -30,6 +30,8 @@
 #include "llvm/Target/TargetOptions.h"
 #include 
 #include 
+#include 
+#include 
 
 #include "clang.h"
 #include "clang-c.h"
@@ -197,6 +199,15 @@ PerfModule::toBPFObject(void)
return std::move(Buffer);
 }
 
+static std::map exported_funcs =
+{
+#define EXPORT(f) {#f, (const void *)&f}
+   EXPORT(test__clang_callback),
+   EXPORT(printf),
+   EXPORT(puts),
+#undef EXPORT
+};
+
 /*
  * Use a global memory manager so allocated code and data won't be released
  * when object destroy.
@@ -223,7 +234,11 @@ int PerfModule::doJIT(void)
 
auto Resolver = createLambdaResolver(
[](const std::string &Name) {
-   return RuntimeDyld::SymbolInfo(nullptr);
+   auto i = exported_funcs.find(Name);
+   if (i == exported_funcs.end())
+   return RuntimeDyld::SymbolInfo(nullptr);
+   return 
RuntimeDyld::SymbolInfo((uint64_t)(i->second),
+  
JITSymbolFlags::Exported);
},
[](const std::string &Name) {
return RuntimeDyld::SymbolInfo(nullptr);
-- 
2.10.1



[PATCH v4 15/18] perf clang: Declare BPF functions for BPF scripts automatically

2016-12-05 Thread Wang Nan
Use Clang's OverlayFileSystem, add '-include' options to make builtin
clang define BPF functions. After this patch BPF script writer needn't
define BPF functions by their own.

Add -DBUILTIN_CLANG_DEFAULT_INCLUDE to builtin clang so when adopting
builtin clang BPF functions can be automatically defined, and keep
undefined when using external clang. Passing a
-UBUILTIN_CLANG_DEFAULT_INCLUDE to cancel this defaudefinition.

Test cases are updated to avoid redefinition of these functions.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/tests/bpf-script-example.c | 18 +--
 tools/perf/tests/bpf-script-test-prologue.c   |  2 ++
 tools/perf/tests/bpf-script-test-relocation.c | 18 +--
 tools/perf/util/c++/clang.cpp | 33 ++-
 4 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/tools/perf/tests/bpf-script-example.c 
b/tools/perf/tests/bpf-script-example.c
index ccbc19c..42dc341 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -8,13 +8,6 @@
 #endif
 #define BPF_ANY 0
 #define BPF_MAP_TYPE_ARRAY 2
-#define BPF_FUNC_map_lookup_elem 1
-#define BPF_FUNC_map_update_elem 2
-
-static void *(*bpf_map_lookup_elem)(void *map, void *key) =
-   (void *) BPF_FUNC_map_lookup_elem;
-static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int 
flags) =
-   (void *) BPF_FUNC_map_update_elem;
 
 struct bpf_map_def {
unsigned int type;
@@ -24,6 +17,17 @@ struct bpf_map_def {
 };
 
 #define SEC(NAME) __attribute__((section(NAME), used))
+
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
+#define BPF_FUNC_map_lookup_elem 1
+#define BPF_FUNC_map_update_elem 2
+
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+   (void *) BPF_FUNC_map_lookup_elem;
+static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int 
flags) =
+   (void *) BPF_FUNC_map_update_elem;
+#endif
+
 struct bpf_map_def SEC("maps") flip_table = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
diff --git a/tools/perf/tests/bpf-script-test-prologue.c 
b/tools/perf/tests/bpf-script-test-prologue.c
index 7230e62..ada812b 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -13,8 +13,10 @@
 #define FMODE_READ 0x1
 #define FMODE_WRITE0x2
 
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
 static void (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
(void *) 6;
+#endif
 
 SEC("func=null_lseek file->f_mode offset orig")
 int bpf_func__null_lseek(void *ctx, int err, unsigned long f_mode,
diff --git a/tools/perf/tests/bpf-script-test-relocation.c 
b/tools/perf/tests/bpf-script-test-relocation.c
index 93af774..57c96a3 100644
--- a/tools/perf/tests/bpf-script-test-relocation.c
+++ b/tools/perf/tests/bpf-script-test-relocation.c
@@ -8,13 +8,6 @@
 #endif
 #define BPF_ANY 0
 #define BPF_MAP_TYPE_ARRAY 2
-#define BPF_FUNC_map_lookup_elem 1
-#define BPF_FUNC_map_update_elem 2
-
-static void *(*bpf_map_lookup_elem)(void *map, void *key) =
-   (void *) BPF_FUNC_map_lookup_elem;
-static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int 
flags) =
-   (void *) BPF_FUNC_map_update_elem;
 
 struct bpf_map_def {
unsigned int type;
@@ -24,6 +17,17 @@ struct bpf_map_def {
 };
 
 #define SEC(NAME) __attribute__((section(NAME), used))
+
+#ifndef BUILTIN_CLANG_DEFAULT_INCLUDE
+#define BPF_FUNC_map_lookup_elem 1
+#define BPF_FUNC_map_update_elem 2
+
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+   (void *) BPF_FUNC_map_lookup_elem;
+static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int 
flags) =
+   (void *) BPF_FUNC_map_update_elem;
+#endif
+
 struct bpf_map_def SEC("maps") my_table = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 1bd92ea..feb69ea 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -39,9 +39,17 @@
 #include "util-cxx.h"
 #include "perf-hooks.h"
 #include "jit-helpers.h"
+#include "clang-bpf-includes.h"
 
 namespace perf {
 
+static struct BPFHeader {
+   llvm::StringRef Path;
+   llvm::StringRef Content;
+} BPFHeaders[] = {
+   {"/virtual/bpf-funcs.h", clang_builtin_bpf_funcs_str},
+};
+
 static std::unique_ptr LLVMCtx;
 
 using namespace clang;
@@ -63,6 +71,11 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, 
StringRef& Path,
"-x", "c"};
 
CCArgs.append(CFlags.begin(), CFlags.end());
+   for (BPFHeader &h : BPFHeaders) {
+   CCArgs.append(1, "-include

[PATCH v4 13/18] perf clang jit: Allow jitted perf hook access BPF maps

2016-12-05 Thread Wang Nan
Newly introduced jit-helpers.[ch] defines a series of helpers which helps
jitted perf hook functions accessing BPF maps defined in their BPF scripts.
The helpers fetches fd of 'struct bpf_map' from 'struct bpf_object' and the
address of 'struct bpf_map_def' in jitted file. 'struct bpf_object' is the
context passed to hooks.

Jit helpers added in this commits are all leading with 'perf_'. We don't use
'bpf_' prefix because in following commits 'bpf_' prefix is going to be assigned
to kernel side BPF map operations. Same operation has different protocol for
kernel and user.

 Example:

  $ cat ./test.c
  /***/
  #define SEC(name) __attribute__((section(name), used))
  #define BPF_MAP_TYPE_ARRAY 2
  #define BPF_MAP_TYPE_PERF_EVENT_ARRAY 4
  #define BPF_FUNC_map_lookup_elem 1
  static void *(*bpf_map_lookup_elem)(void *map, void *key) =
  (void *) BPF_FUNC_map_lookup_elem;
  struct bpf_map_def {
  unsigned int type;
  unsigned int key_size;
  unsigned int value_size;
  unsigned int max_entries;
  };
  struct bpf_map_def SEC("maps") counter = {
  .type = BPF_MAP_TYPE_ARRAY,
  .key_size = sizeof(int),
  .value_size = sizeof(int),
  .max_entries = 1,
  };
  extern int perf_map_update_elem(void *ctx, struct bpf_map_def *map,
 void *key, void *value, unsigned long flags);
  extern int perf_map_lookup_elem(void *ctx, struct bpf_map_def *map,
 void *key, void *value);
  SEC("sys_close=SyS_close")
  int sys_close(void *ctx)
  {
  int key = 0;
  int *value;
  value = bpf_map_lookup_elem(&counter, &key);
  if (!value)
  return 0;
  __sync_fetch_and_add(value, 1);
  return 0;
  }
  extern int printf(const char *fmt, ...);
  SEC("perfhook:record_start")
  void record_start(void *ctx)
  {
  int key = 0;
  int value = 1;
  printf("Welcom to perf record\n");
  perf_map_update_elem(ctx, &counter, &key, &value, 0);
  }

  SEC("perfhook:record_end")
  void record_end(void *ctx)
  {
  int key = 0;
  int value;
  perf_map_lookup_elem(ctx, &counter, &key, &value);
  printf("Goodbye, perf record, value=%d\n", value);
  }
  char _license[] SEC("license") = "GPL";
  int _version SEC("version") = LINUX_VERSION_CODE;
  /***/
  $ sudo perf record  -e ./test.c echo Hehe
  Welcom to perf record
  Hehe
  [ perf record: Woken up 1 times to write data ]
  Goodbye, perf record, value=10644
  [ perf record: Captured and wrote 0.014 MB perf.data ]

Signed-off-by: Wang Nan 
Acked-by: Alexei Starovoitov 
Cc: Arnaldo Carvalho de Melo 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/Build |  1 +
 tools/perf/util/c++/clang.cpp |  9 ++-
 tools/perf/util/jit-helpers.c | 57 +++
 tools/perf/util/jit-helpers.h | 28 +
 4 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/util/jit-helpers.c
 create mode 100644 tools/perf/util/jit-helpers.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 3840e3a..e42ae4f 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -125,6 +125,7 @@ libperf-$(CONFIG_DWARF) += genelf_debug.o
 endif
 
 libperf-y += perf-hooks.o
+libperf-y += jit-helpers.o
 
 libperf-$(CONFIG_CXX) += c++/
 
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 684855c..1bd92ea 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -38,6 +38,7 @@
 #include "llvm-utils.h"
 #include "util-cxx.h"
 #include "perf-hooks.h"
+#include "jit-helpers.h"
 
 namespace perf {
 
@@ -199,12 +200,18 @@ PerfModule::toBPFObject(void)
return std::move(Buffer);
 }
 
+#define __stringify_1(x)   #x
+#define __stringify(x) __stringify_1(x)
 static std::map exported_funcs =
 {
-#define EXPORT(f) {#f, (const void *)&f}
+#define EXPORT(f) {__stringify(f), (const void *)&f}
EXPORT(test__clang_callback),
EXPORT(printf),
EXPORT(puts),
+   EXPORT(JIT_HELPER_FUNC_NAME(map_update_elem)),
+   EXPORT(JIT_HELPER_FUNC_NAME(map_lookup_elem)),
+   EXPORT(JIT_HELPER_FUNC_NAME(map_get_next_key)),
+   EXPORT(JIT_HELPER_FUNC_NAME(map_pin)),
 #undef EXPORT
 };
 
diff --git a/tools/perf/util/jit-helpers.c b/tools/perf/util/jit-helpers.c
new file mode 100644
index 000..1a37a20
--- /dev/null
+++ b/tools/perf/util/jit-helpers.c
@@ -0,0 +1,57 @@
+/*
+ * jit-helper.c
+ *
+ * Copyright (C) 2016 Wang Nan 
+ * Copyright (C) 2016 Huawei Inc.
+ *
+ * Provide helpers which can be invoked by jit scripts attached to
+ * perf hooks

[PATCH v4 14/18] perf clang: Link BPF functions declaration into perf

2016-12-05 Thread Wang Nan
Hardcode BPF functions declarations. Following commits will utilizes
clang's virtual file system to automatically include this header to
all BPF scripts.

The generated header is wrapped by a BUILTIN_CLANG_NO_DEFAULT_INCLUDE.
This macro will be used by following commits to allow user disable this
feature.

The C string looks ugly and heavily uses magic numbers because the
header is designed to be included automatically at very first, makes
any dependency or potential conflict harmful. Actually it is
automatically generated using a script:
https://patchwork.kernel.org/patch/9350221
However, that script is fragile so not included by this commit.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/Build|  1 +
 tools/perf/util/c++/bpf-funcs-str.c  | 49 
 tools/perf/util/c++/clang-bpf-includes.h | 12 
 3 files changed, 62 insertions(+)
 create mode 100644 tools/perf/util/c++/bpf-funcs-str.c
 create mode 100644 tools/perf/util/c++/clang-bpf-includes.h

diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
index 988fef1..bd71abf 100644
--- a/tools/perf/util/c++/Build
+++ b/tools/perf/util/c++/Build
@@ -1,2 +1,3 @@
 libperf-$(CONFIG_CLANGLLVM) += clang.o
 libperf-$(CONFIG_CLANGLLVM) += clang-test.o
+libperf-$(CONFIG_CLANGLLVM) += bpf-funcs-str.o
diff --git a/tools/perf/util/c++/bpf-funcs-str.c 
b/tools/perf/util/c++/bpf-funcs-str.c
new file mode 100644
index 000..ab1a0e3
--- /dev/null
+++ b/tools/perf/util/c++/bpf-funcs-str.c
@@ -0,0 +1,49 @@
+#include "clang-bpf-includes.h"
+const char clang_builtin_bpf_funcs_str[] =
+"#ifdef BUILTIN_CLANG_DEFAULT_INCLUDE\n"
+"#ifndef BPF_FUNCS_DEFINED\n"
+"#define BPF_FUNCS_DEFINED\n"
+"static void *(*bpf_map_lookup_elem)(void *, void *) = (void *)1;\n"
+"static long (*bpf_map_update_elem)(void *, void *, void *, unsigned long) = 
(void *)2;\n"
+"static long (*bpf_map_delete_elem)(void *, void *) = (void *)3;\n"
+"static long (*bpf_probe_read)(void *, unsigned long, unsigned long) = (void 
*)4;\n"
+"static long (*bpf_ktime_get_ns)(void) = (void *)5;\n"
+"static long (*bpf_trace_printk)(void *, unsigned long, ...) = (void *)6;\n"
+"static long (*bpf_get_prandom_u32)(void) = (void *)7;\n"
+"static long (*bpf_get_smp_processor_id)(void) = (void *)8;\n"
+"static long (*bpf_skb_store_bytes)(void *, unsigned long, void *, unsigned 
long, unsigned long) = (void *)9;\n"
+"static long (*bpf_l3_csum_replace)(void *, unsigned long, unsigned long, 
unsigned long, unsigned long) = (void *)10;\n"
+"static long (*bpf_l4_csum_replace)(void *, unsigned long, unsigned long, 
unsigned long, unsigned long) = (void *)11;\n"
+"static void (*bpf_tail_call)(void *, void *, unsigned long) = (void *)12;\n"
+"static long (*bpf_clone_redirect)(void *, unsigned long, unsigned long) = 
(void *)13;\n"
+"static long (*bpf_get_current_pid_tgid)(void) = (void *)14;\n"
+"static long (*bpf_get_current_uid_gid)(void) = (void *)15;\n"
+"static long (*bpf_get_current_comm)(void *, unsigned long) = (void *)16;\n"
+"static long (*bpf_get_cgroup_classid)(void *) = (void *)17;\n"
+"static long (*bpf_skb_vlan_push)(void *, unsigned long, unsigned long) = 
(void *)18;\n"
+"static long (*bpf_skb_vlan_pop)(void *) = (void *)19;\n"
+"static long (*bpf_skb_get_tunnel_key)(void *, void *, unsigned long, unsigned 
long) = (void *)20;\n"
+"static long (*bpf_skb_set_tunnel_key)(void *, void *, unsigned long, unsigned 
long) = (void *)21;\n"
+"static long (*bpf_perf_event_read)(void *, unsigned long) = (void *)22;\n"
+"static long (*bpf_redirect)(unsigned long, unsigned long) = (void *)23;\n"
+"static long (*bpf_get_route_realm)(void *) = (void *)24;\n"
+"static long (*bpf_perf_event_output)(void *, void *, unsigned long, void *, 
unsigned long) = (void *)25;\n"
+"static long (*bpf_skb_load_bytes)(void *, unsigned long, void *, unsigned 
long) = (void *)26;\n"
+"static long (*bpf_get_stackid)(void *, void *, unsigned long) = (void *)27;\n"
+"static long (*bpf_csum_diff)(void *, unsigned long, void *, unsigned long, 
unsigned long) = (void *)28;\n"
+"static long (*bpf_skb_get_tunnel_opt)(void *, void *, unsigned long) = (void 
*)29;\n"
+"static long (*bpf_skb_set_tunnel_opt)(void *, void *, unsigned long) = (void 
*)30;\n"
+"static long (*bpf_skb_change_proto)(void *, unsigned long, unsigned long) = 
(void *)31;\n"
+"static long (*bpf_skb_change_type)(void *, unsigned long) = (void *)32;\n"
+"static long (*bpf_skb_under_cgroup)(void *, void *, unsigned long) = (void 
*)

[tip:perf/core] tools lib bpf: Retrive bpf_map through offset of bpf_map_def

2016-12-02 Thread tip-bot for Wang Nan
Commit-ID:  5a6acad17d2e81765dd4c2fce7346a6f045eab25
Gitweb: http://git.kernel.org/tip/5a6acad17d2e81765dd4c2fce7346a6f045eab25
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:27 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 29 Nov 2016 12:10:19 -0300

tools lib bpf: Retrive bpf_map through offset of bpf_map_def

Add a new API to libbpf, caller is able to get bpf_map through the
offset of bpf_map_def to 'maps' section.

The API will be used to help jitted perf hook code find fd of a map.

Signed-off-by: Wang Nan 
Acked-by: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-4-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/lib/bpf/libbpf.c | 12 
 tools/lib/bpf/libbpf.h |  8 
 2 files changed, 20 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 866d5cd..2e97459 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1524,3 +1524,15 @@ bpf_object__find_map_by_name(struct bpf_object *obj, 
const char *name)
}
return NULL;
 }
+
+struct bpf_map *
+bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset)
+{
+   int i;
+
+   for (i = 0; i < obj->nr_maps; i++) {
+   if (obj->maps[i].offset == offset)
+   return &obj->maps[i];
+   }
+   return ERR_PTR(-ENOENT);
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 0c0b012..a5a8b86 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include   // for size_t
 
 enum libbpf_errno {
__LIBBPF_ERRNO__START = 4000,
@@ -200,6 +201,13 @@ struct bpf_map;
 struct bpf_map *
 bpf_object__find_map_by_name(struct bpf_object *obj, const char *name);
 
+/*
+ * Get bpf_map through the offset of corresponding struct bpf_map_def
+ * in the bpf object file.
+ */
+struct bpf_map *
+bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset);
+
 struct bpf_map *
 bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
 #define bpf_map__for_each(pos, obj)\


[tip:perf/core] perf tools: Introduce perf hooks

2016-12-02 Thread tip-bot for Wang Nan
Commit-ID:  a074865e60edd762b99ec5dacec69b406f702e66
Gitweb: http://git.kernel.org/tip/a074865e60edd762b99ec5dacec69b406f702e66
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:28 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 29 Nov 2016 12:13:27 -0300

perf tools: Introduce perf hooks

Perf hooks allow hooking user code at perf events. They can be used for
manipulation of BPF maps, taking snapshot and reporting results. In this
patch two perf hook points are introduced: record_start and record_end.

To avoid buggy user actions, a SIGSEGV signal handler is introduced into
'perf record'. It turns off perf hook if it causes a segfault and report
an error to help debugging.

A test case for perf hook is introduced.

Test result:
  $ ./buildperf/perf test -v hook
  50: Test perf hooks  :
  --- start ---
  test child forked, pid 10311
  SIGSEGV is observed as expected, try to recover.
  Fatal error (SEGFAULT) in perf hook 'test'
  test child finished with 0
   end 
  Test perf hooks: Ok

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-5-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/builtin-record.c   | 11 +
 tools/perf/tests/Build|  1 +
 tools/perf/tests/builtin-test.c   |  4 ++
 tools/perf/tests/perf-hooks.c | 44 
 tools/perf/tests/tests.h  |  1 +
 tools/perf/util/Build |  2 +
 tools/perf/util/perf-hooks-list.h |  3 ++
 tools/perf/util/perf-hooks.c  | 84 +++
 tools/perf/util/perf-hooks.h  | 37 +
 9 files changed, 187 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 67d2a90..fa26865 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -37,6 +37,7 @@
 #include "util/llvm-utils.h"
 #include "util/bpf-loader.h"
 #include "util/trigger.h"
+#include "util/perf-hooks.h"
 #include "asm/bug.h"
 
 #include 
@@ -206,6 +207,12 @@ static void sig_handler(int sig)
done = 1;
 }
 
+static void sigsegv_handler(int sig)
+{
+   perf_hooks__recover();
+   sighandler_dump_stack(sig);
+}
+
 static void record__sig_exit(void)
 {
if (signr == -1)
@@ -833,6 +840,7 @@ static int __cmd_record(struct record *rec, int argc, const 
char **argv)
signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
+   signal(SIGSEGV, sigsegv_handler);
 
if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
signal(SIGUSR2, snapshot_sig_handler);
@@ -970,6 +978,7 @@ static int __cmd_record(struct record *rec, int argc, const 
char **argv)
 
trigger_ready(&auxtrace_snapshot_trigger);
trigger_ready(&switch_output_trigger);
+   perf_hooks__invoke_record_start();
for (;;) {
unsigned long long hits = rec->samples;
 
@@ -1114,6 +1123,8 @@ out_child:
}
}
 
+   perf_hooks__invoke_record_end();
+
if (!err && !quiet) {
char samples[128];
const char *postfix = rec->timestamp_filename ?
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 8a4ce49..af3ec94 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -42,6 +42,7 @@ perf-y += backward-ring-buffer.o
 perf-y += sdt.o
 perf-y += is_printable_array.o
 perf-y += bitmap.o
+perf-y += perf-hooks.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 778668a..dab83f7 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -230,6 +230,10 @@ static struct test generic_tests[] = {
.func = test__bitmap_print,
},
{
+   .desc = "Test perf hooks",
+   .func = test__perf_hooks,
+   },
+   {
.func = NULL,
},
 };
diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
new file mode 100644
index 000..9338cb2
--- /dev/null
+++ b/tools/perf/tests/perf-hooks.c
@@ -0,0 +1,44 @@
+#include 
+#include 
+
+#include "tests.h"
+#include "debug.h"
+#include "util.h"
+#include "perf-hooks.h"
+
+static void sigsegv_handler(int sig __maybe_unused)
+{
+   pr_debug("SIGSEGV is observed as expected, try to recover.\n");
+   perf_hooks__recover();
+   signal(SIGSEGV, SIG_DFL);
+   raise(SIGSEGV);
+   exit(-1);
+}
+
+static int hook_flags;
+
+static void the_hook(void)
+{
+   int *p = NULL;
+
+   hook_flags = 1234;

[tip:perf/core] tools lib bpf: Add missing BPF functions

2016-12-02 Thread tip-bot for Wang Nan
Commit-ID:  9742da0150788e6ea7796372c3e643f876a49741
Gitweb: http://git.kernel.org/tip/9742da0150788e6ea7796372c3e643f876a49741
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:25 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 29 Nov 2016 12:09:36 -0300

tools lib bpf: Add missing BPF functions

Add more BPF map operations to libbpf. Also add bpf_obj_{pin,get}(). They
can be used on not only BPF maps but also BPF programs.

Signed-off-by: Wang Nan 
Acked-by: Alexei Starovoitov 
Cc: He Kuang 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-2-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/lib/bpf/bpf.c | 56 +
 tools/lib/bpf/bpf.h |  7 +++
 2 files changed, 63 insertions(+)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 4212ed6..8143536 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -110,3 +110,59 @@ int bpf_map_update_elem(int fd, void *key, void *value,
 
return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
 }
+
+int bpf_map_lookup_elem(int fd, void *key, void *value)
+{
+   union bpf_attr attr;
+
+   bzero(&attr, sizeof(attr));
+   attr.map_fd = fd;
+   attr.key = ptr_to_u64(key);
+   attr.value = ptr_to_u64(value);
+
+   return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_map_delete_elem(int fd, void *key)
+{
+   union bpf_attr attr;
+
+   bzero(&attr, sizeof(attr));
+   attr.map_fd = fd;
+   attr.key = ptr_to_u64(key);
+
+   return sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_map_get_next_key(int fd, void *key, void *next_key)
+{
+   union bpf_attr attr;
+
+   bzero(&attr, sizeof(attr));
+   attr.map_fd = fd;
+   attr.key = ptr_to_u64(key);
+   attr.next_key = ptr_to_u64(next_key);
+
+   return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
+}
+
+int bpf_obj_pin(int fd, const char *pathname)
+{
+   union bpf_attr attr;
+
+   bzero(&attr, sizeof(attr));
+   attr.pathname = ptr_to_u64((void *)pathname);
+   attr.bpf_fd = fd;
+
+   return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
+}
+
+int bpf_obj_get(const char *pathname)
+{
+   union bpf_attr attr;
+
+   bzero(&attr, sizeof(attr));
+   attr.pathname = ptr_to_u64((void *)pathname);
+
+   return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
+}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index e8ba540..253c3db 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -35,4 +35,11 @@ int bpf_load_program(enum bpf_prog_type type, struct 
bpf_insn *insns,
 
 int bpf_map_update_elem(int fd, void *key, void *value,
u64 flags);
+
+int bpf_map_lookup_elem(int fd, void *key, void *value);
+int bpf_map_delete_elem(int fd, void *key);
+int bpf_map_get_next_key(int fd, void *key, void *next_key);
+int bpf_obj_pin(int fd, const char *pathname);
+int bpf_obj_get(const char *pathname);
+
 #endif


[tip:perf/core] tools lib bpf: Add private field for bpf_object

2016-12-02 Thread tip-bot for Wang Nan
Commit-ID:  10931d2413478239bdceac5546cce85d7a497a4e
Gitweb: http://git.kernel.org/tip/10931d2413478239bdceac5546cce85d7a497a4e
Author: Wang Nan 
AuthorDate: Sat, 26 Nov 2016 07:03:26 +
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 29 Nov 2016 12:09:41 -0300

tools lib bpf: Add private field for bpf_object

Similar to other classes defined in libbpf.h (map and program), allow
'object' class has its own private data.

Signed-off-by: Wang Nan 
Acked-by: Alexei Starovoitov 
Cc: He Kuang 
Cc: Joe Stringer 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-3-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/lib/bpf/libbpf.c | 23 +++
 tools/lib/bpf/libbpf.h |  5 +
 2 files changed, 28 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 96a2b2f..866d5cd 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -229,6 +229,10 @@ struct bpf_object {
 * all objects.
 */
struct list_head list;
+
+   void *priv;
+   bpf_object_clear_priv_t clear_priv;
+
char path[];
 };
 #define obj_elf_valid(o)   ((o)->efile.elf)
@@ -1229,6 +1233,9 @@ void bpf_object__close(struct bpf_object *obj)
if (!obj)
return;
 
+   if (obj->clear_priv)
+   obj->clear_priv(obj, obj->priv);
+
bpf_object__elf_finish(obj);
bpf_object__unload(obj);
 
@@ -1282,6 +1289,22 @@ unsigned int bpf_object__kversion(struct bpf_object *obj)
return obj ? obj->kern_version : 0;
 }
 
+int bpf_object__set_priv(struct bpf_object *obj, void *priv,
+bpf_object_clear_priv_t clear_priv)
+{
+   if (obj->priv && obj->clear_priv)
+   obj->clear_priv(obj, obj->priv);
+
+   obj->priv = priv;
+   obj->clear_priv = clear_priv;
+   return 0;
+}
+
+void *bpf_object__priv(struct bpf_object *obj)
+{
+   return obj ? obj->priv : ERR_PTR(-EINVAL);
+}
+
 struct bpf_program *
 bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
 {
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index dd7a513..0c0b012 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -79,6 +79,11 @@ struct bpf_object *bpf_object__next(struct bpf_object *prev);
 (pos) != NULL; \
 (pos) = (tmp), (tmp) = bpf_object__next(tmp))
 
+typedef void (*bpf_object_clear_priv_t)(struct bpf_object *, void *);
+int bpf_object__set_priv(struct bpf_object *obj, void *priv,
+bpf_object_clear_priv_t clear_priv);
+void *bpf_object__priv(struct bpf_object *prog);
+
 /* Accessors of bpf_program. */
 struct bpf_program;
 struct bpf_program *bpf_program__next(struct bpf_program *prog,


[PATCH v3 26/30 - cleanup] perf clang: Link BPF functions declaration into perf

2016-11-30 Thread Wang Nan
Hardcode BPF functions declarations. Following commits will utilizes
clang's virtual file system to automatically include this header to
all BPF scripts.

The generated header is wrapped by a BUILTIN_CLANG_NO_DEFAULT_INCLUDE.
This macro will be used by following commits to allow user disable this
feature.

The C string looks ugly and heavily uses magic numbers because the
header is designed to be included automatically at very first, makes
any dependency or potential conflict harmful. Actually it is
automatically generated using a script:
https://patchwork.kernel.org/patch/9350221
However, that script is fragile so not included by this commit.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/Build|  1 +
 tools/perf/util/c++/bpf-funcs-str.c  | 49 
 tools/perf/util/c++/clang-bpf-includes.h | 12 
 3 files changed, 62 insertions(+)
 create mode 100644 tools/perf/util/c++/bpf-funcs-str.c
 create mode 100644 tools/perf/util/c++/clang-bpf-includes.h

diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
index 988fef1..bd71abf 100644
--- a/tools/perf/util/c++/Build
+++ b/tools/perf/util/c++/Build
@@ -1,2 +1,3 @@
 libperf-$(CONFIG_CLANGLLVM) += clang.o
 libperf-$(CONFIG_CLANGLLVM) += clang-test.o
+libperf-$(CONFIG_CLANGLLVM) += bpf-funcs-str.o
diff --git a/tools/perf/util/c++/bpf-funcs-str.c 
b/tools/perf/util/c++/bpf-funcs-str.c
new file mode 100644
index 000..ab1a0e3
--- /dev/null
+++ b/tools/perf/util/c++/bpf-funcs-str.c
@@ -0,0 +1,49 @@
+#include "clang-bpf-includes.h"
+const char clang_builtin_bpf_funcs_str[] =
+"#ifdef BUILTIN_CLANG_DEFAULT_INCLUDE\n"
+"#ifndef BPF_FUNCS_DEFINED\n"
+"#define BPF_FUNCS_DEFINED\n"
+"static void *(*bpf_map_lookup_elem)(void *, void *) = (void *)1;\n"
+"static long (*bpf_map_update_elem)(void *, void *, void *, unsigned long) = 
(void *)2;\n"
+"static long (*bpf_map_delete_elem)(void *, void *) = (void *)3;\n"
+"static long (*bpf_probe_read)(void *, unsigned long, unsigned long) = (void 
*)4;\n"
+"static long (*bpf_ktime_get_ns)(void) = (void *)5;\n"
+"static long (*bpf_trace_printk)(void *, unsigned long, ...) = (void *)6;\n"
+"static long (*bpf_get_prandom_u32)(void) = (void *)7;\n"
+"static long (*bpf_get_smp_processor_id)(void) = (void *)8;\n"
+"static long (*bpf_skb_store_bytes)(void *, unsigned long, void *, unsigned 
long, unsigned long) = (void *)9;\n"
+"static long (*bpf_l3_csum_replace)(void *, unsigned long, unsigned long, 
unsigned long, unsigned long) = (void *)10;\n"
+"static long (*bpf_l4_csum_replace)(void *, unsigned long, unsigned long, 
unsigned long, unsigned long) = (void *)11;\n"
+"static void (*bpf_tail_call)(void *, void *, unsigned long) = (void *)12;\n"
+"static long (*bpf_clone_redirect)(void *, unsigned long, unsigned long) = 
(void *)13;\n"
+"static long (*bpf_get_current_pid_tgid)(void) = (void *)14;\n"
+"static long (*bpf_get_current_uid_gid)(void) = (void *)15;\n"
+"static long (*bpf_get_current_comm)(void *, unsigned long) = (void *)16;\n"
+"static long (*bpf_get_cgroup_classid)(void *) = (void *)17;\n"
+"static long (*bpf_skb_vlan_push)(void *, unsigned long, unsigned long) = 
(void *)18;\n"
+"static long (*bpf_skb_vlan_pop)(void *) = (void *)19;\n"
+"static long (*bpf_skb_get_tunnel_key)(void *, void *, unsigned long, unsigned 
long) = (void *)20;\n"
+"static long (*bpf_skb_set_tunnel_key)(void *, void *, unsigned long, unsigned 
long) = (void *)21;\n"
+"static long (*bpf_perf_event_read)(void *, unsigned long) = (void *)22;\n"
+"static long (*bpf_redirect)(unsigned long, unsigned long) = (void *)23;\n"
+"static long (*bpf_get_route_realm)(void *) = (void *)24;\n"
+"static long (*bpf_perf_event_output)(void *, void *, unsigned long, void *, 
unsigned long) = (void *)25;\n"
+"static long (*bpf_skb_load_bytes)(void *, unsigned long, void *, unsigned 
long) = (void *)26;\n"
+"static long (*bpf_get_stackid)(void *, void *, unsigned long) = (void *)27;\n"
+"static long (*bpf_csum_diff)(void *, unsigned long, void *, unsigned long, 
unsigned long) = (void *)28;\n"
+"static long (*bpf_skb_get_tunnel_opt)(void *, void *, unsigned long) = (void 
*)29;\n"
+"static long (*bpf_skb_set_tunnel_opt)(void *, void *, unsigned long) = (void 
*)30;\n"
+"static long (*bpf_skb_change_proto)(void *, unsigned long, unsigned long) = 
(void *)31;\n"
+"static long (*bpf_skb_change_type)(void *, unsigned long) = (void *)32;\n"
+"static long (*bpf_skb_under_cgroup)(void *, void *, unsigned long) = (void 
*)

[PATCH v3 15/30] perf clang: Compile BPF script use builtin clang support

2016-11-25 Thread Wang Nan
After this patch, perf utilizes builtin clang support to build BPF
script, no longer depend on external clang.

Test:

  $ type clang
  -bash: type: clang: not found
  $ cat ~/.perfconfig
  $ echo '#define LINUX_VERSION_CODE 0x040700' > ./test.c
  $ cat ./tools/perf/tests/bpf-script-example.c >> ./test.c
  $ ./perf record -v --dry-run -e ./test.c 2>&1 | grep builtin
  bpf: builtin compiling successful

Can't pass cflags so unable to include kernel headers now. Will be fixed
by following commits.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: 
http://lkml.kernel.org/r/1474874832-134786-13-git-send-email-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/bpf-loader.c  | 15 +++
 tools/perf/util/c++/clang-c.h | 26 ++
 tools/perf/util/c++/clang.cpp | 29 +
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index cf16b941..a0ea334f 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -14,11 +14,11 @@
 #include "debug.h"
 #include "bpf-loader.h"
 #include "bpf-prologue.h"
-#include "llvm-utils.h"
 #include "probe-event.h"
 #include "probe-finder.h" // for MAX_PROBES
 #include "parse-events.h"
 #include "llvm-utils.h"
+#include "c++/clang-c.h"
 
 #define DEFINE_PRINT_FN(name, level) \
 static int libbpf_##name(const char *fmt, ...) \
@@ -86,9 +86,16 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
void *obj_buf;
size_t obj_buf_sz;
 
-   err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
-   if (err)
-   return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+   perf_clang__init();
+   err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+   perf_clang__cleanup();
+   if (err) {
+   pr_warning("bpf: builtin compiling failed: %d, try 
external compiler\n", err);
+   err = llvm__compile_bpf(filename, &obj_buf, 
&obj_buf_sz);
+   if (err)
+   return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+   } else
+   pr_debug("bpf: builtin compiling successful\n");
obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
 
if (!IS_ERR(obj) && llvm_param.dump_obj)
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 22b3936..0eadd79 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -1,16 +1,42 @@
 #ifndef PERF_UTIL_CLANG_C_H
 #define PERF_UTIL_CLANG_C_H
 
+#include /* for size_t */
+#include   /* for __maybe_unused */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
 extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
 
 extern int test__clang_to_IR(void);
 extern int test__clang_to_obj(void);
 
+extern int perf_clang__compile_bpf(const char *filename,
+  void **p_obj_buf,
+  size_t *p_obj_buf_sz);
+#else
+
+
+static inline void perf_clang__init(void) { }
+static inline void perf_clang__cleanup(void) { }
+
+static inline int test__clang_to_IR(void) { return -1; }
+static inline int test__clang_to_obj(void) { return -1;}
+
+static inline int
+perf_clang__compile_bpf(const char *filename __maybe_unused,
+   void **p_obj_buf __maybe_unused,
+   size_t *p_obj_buf_sz __maybe_unused)
+{
+   return -ENOTSUP;
+}
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 2a1a75d..1e97415 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -163,4 +163,33 @@ void perf_clang__cleanup(void)
perf::LLVMCtx.reset(nullptr);
llvm::llvm_shutdown();
 }
+
+int perf_clang__compile_bpf(const char *filename,
+   void **p_obj_buf,
+   size_t *p_obj_buf_sz)
+{
+   using namespace perf;
+
+   if (!p_obj_buf || !p_obj_buf_sz)
+   return -EINVAL;
+
+   llvm::opt::ArgStringList CFlags;
+   auto M = getModuleFromSource(std::move(CFlags), filename);
+   if (!M)
+   return  -EINVAL;
+   auto O = getBPFObjectFromModule(&*M);
+   if (!O)
+   return -EINVAL;
+
+   size_t size = O->size_in_bytes();
+   void *buffer;
+
+   buffer = malloc(size);
+   if (!buffer)
+   return -ENOMEM;
+   memcpy(buffer, O->data(), size);
+   *p_obj_buf = buffer;
+   *p_obj_buf_sz = size;
+   return 0;
+}
 }
-- 
2.10.1



[PATCH v3 00/30] perf clang: Builtin clang and perfhook support

2016-11-25 Thread Wang Nan
This is version 3 of perf builtin clang and perfhook patch series.
Compare to v2 there is only minor changes:
 1. BPF map helpers in perf hooks now called 'perf_map_...',
instead of 'jit_helper_map_...'.
(Alexei Starovoitov)
 2. Rename bpf_map_{pin,get} to bpf_obj_{pin,get}, make them consist
with kernel.
(Joe Stringer).

Example in v2 should be changed accordingly:

  $ cat ./count_syscalls.c
  typedef unsigned long u64;
  
  #define BPF_MAP_TYPE_HASH 1
  #define BPF_MAP_TYPE_ARRAY 2
  
  enum GVAL {
  G_perf_pid,
  NR_GVALS
  };
  
  struct bpf_map_def SEC("maps") GVALS = {
  .type = BPF_MAP_TYPE_ARRAY,
  .key_size = sizeof(int),
  .value_size = sizeof(u64),
  .max_entries = NR_GVALS,
  };
  
  struct bpf_map_def SEC("maps") syscall_counter = {
  .type = BPF_MAP_TYPE_HASH,
  .key_size = sizeof(u64),
  .value_size = sizeof(u64),
  .max_entries = 512,
  };
  
  SEC("raw_syscalls:sys_enter")
  int func(void *ctx)
  {
  int key = G_perf_pid;
  u64 id = *((u64 *)(ctx + 8));
  int self_pid = bpf_get_current_pid_tgid() & 0x;
  int *perf_pid = bpf_map_lookup_elem(&GVALS, &key);
  u64 *counter;
  
  if (!perf_pid)
  return 0;
  if (*perf_pid == self_pid)
  return 0;
  counter = bpf_map_lookup_elem(&syscall_counter, &id);
  if (!counter) {
  u64 value = 1;
  bpf_map_update_elem(&syscall_counter, &id, &value, 0);
  return 0;
  }
  __sync_fetch_and_add(counter, 1);
  return 0;
  }
  
  SEC("perfhook:record_start")
  void record_start(void *ctx)
  {
  int perf_pid = getpid(), key = G_perf_pid;
  printf("Start count, perfpid=%d\n", perf_pid);
  perf_map_update_elem(ctx, &GVALS, &key, &perf_pid, 0);
  }
  
  SEC("perfhook:record_end")
  void record_end(void *ctx)
  {
  u64 key = -1, value;
  while (!perf_map_get_next_key(ctx, &syscall_counter, &key, &key)) {
  perf_map_lookup_elem(ctx, &syscall_counter, &key, &value);
  printf("syscall %ld\tcount: %ld\n", (long)key, (long)value);
  }
  }
  char _license[] SEC("license") = "GPL";
  int _version SEC("version") = LINUX_VERSION_CODE;
  $ sudo -s
  # ulimit -l unlimited
  # perf record -e ./count_syscalls.c echo "Haha"
  Start count, perfpid=25209
  Haha
  [ perf record: Woken up 1 times to write data ]
  syscall 293   count: 2
  syscall 8 count: 7
  syscall 11count: 763
  syscall 4 count: 43
  syscall 21count: 48
  syscall 86count: 1
  syscall 5 count: 791
  ...

Wang Nan (30):
  tools lib bpf: Add missing BPF functions
  tools lib bpf: Add private field for bpf_object
  tools lib bpf: Retrive bpf_map through offset of bpf_map_def
  perf tools: Introduce perf hooks
  perf tools: Pass context to perf hook functions
  perf llvm: Extract helpers in llvm-utils.c
  tools build: Add feature detection for LLVM
  tools build: Add feature detection for clang
  perf build: Add clang and llvm compile and linking support
  perf clang: Add builtin clang support ant test case
  perf clang: Use real file system for #include
  perf clang: Allow passing CFLAGS to builtin clang
  perf clang: Update test case to use real BPF script
  perf clang: Support compile IR to BPF object and add testcase
  perf clang: Compile BPF script use builtin clang support
  perf clang: Pass full path to builtin clang
  perf clang: Pass CFLAGS to builtin clang
  perf clang jit: Wrap llvm::Module using PerfModule
  perf clang jit: Insignt BPF and JIT functions in a Module
  perf clang jit: add PerfModule::doJIT to JIT perfhook functions
  perf clang jit: Export functions for jitted code
  perf clang jit: Actually JIT and hook in bpf loader
  perf clang jit: Collect the lowest address in maps section as map_base
  perf clang jit: Retrive fd of BPF map from its offset
  perf clang jit: Allow jitted perf hook access BPF maps
  perf clang: Link BPF functions declaration into perf
  perf clang: Declare BPF functions for BPF scripts automatically
  perf clang: Include helpers to BPF scripts
  perf clang builtin: Define hook helpers by default
  perf clang jit: Export getpid() to perf hook

 tools/build/feature/Makefile  |  18 +
 tools/build/feature/test-clang.cpp|  21 ++
 tools/build/feature/test-llvm.cpp |   8 +
 tools/lib/bpf/bpf.c   |  56 +++
 tools/lib/bpf/bpf.h   |   7 +
 tools/lib/bpf/libbpf.c|  35 ++
 tools/lib/bpf/libbpf.h|  13 +
 tools/perf/Makefile.config|  62 +++-
 tools/perf/Makefile.perf  |  23 +-
 tools/perf/builtin-record.c   |  11 +
 tools/perf/tests/Build|   4 +-
 tools/perf/tes

[PATCH v3 22/30] perf clang jit: Actually JIT and hook in bpf loader

2016-11-25 Thread Wang Nan
Makes perf_clang__compile_bpf() actually uses clang jit to compile perf
hooks. Returns a map through perf_clang__compile_bpf(), and set hooks
after bpf_object is created.

After this path jitting takes actions for bpf loader. For example:
  $ cat ./test.c
  /**/
  #define SEC(name) __attribute__((section(name), used))
  SEC("dofork=_do_fork")
  int dofork(void *ctx)
  {
  return 0;
  }
  extern int printf(const char *fmt, ...);
  SEC("perfhook:record_start")
  void record_start(void)
  {
  printf("Welcom to perf record\n");
  }
  SEC("perfhook:record_end")
  void record_end(void)
  {
  printf("Goodbye, perf record\n");
  }
  char _license[] SEC("license") = "GPL";
  int _version SEC("version") = LINUX_VERSION_CODE;
  /**/
  $ perf record -e ./test.c sleep 1
  Welcom to perf record
  [ perf record: Woken up 1 times to write data ]
  Goodbye, perf record
  [ perf record: Captured and wrote 0.014 MB perf.data ]

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/bpf-loader.c  | 11 ++-
 tools/perf/util/c++/clang-c.h | 18 --
 tools/perf/util/c++/clang.cpp | 28 +++-
 3 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index a0ea334f..e50045f 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -85,9 +85,11 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
int err;
void *obj_buf;
size_t obj_buf_sz;
+   jitted_funcs_map_t jitted_funcs_map;
 
perf_clang__init();
-   err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+   err = perf_clang__compile_bpf(filename, &obj_buf,
+ &obj_buf_sz, &jitted_funcs_map);
perf_clang__cleanup();
if (err) {
pr_warning("bpf: builtin compiling failed: %d, try 
external compiler\n", err);
@@ -101,6 +103,13 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
if (!IS_ERR(obj) && llvm_param.dump_obj)
llvm__dump_obj(filename, obj_buf, obj_buf_sz);
 
+   /*
+* Call perf_clang__hook_jitted_func even IS_ERR(obj) to make 
sure
+* the C++ map pointer is deleted.
+*/
+   if (jitted_funcs_map)
+   perf_clang__hook_jitted_func(jitted_funcs_map, obj, 
IS_ERR(obj));
+
free(obj_buf);
} else
obj = bpf_object__open(filename);
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 9f75e41..021b1ad 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -8,6 +8,7 @@
 extern "C" {
 #endif
 
+typedef void *jitted_funcs_map_t;
 #ifdef HAVE_LIBCLANGLLVM_SUPPORT
 extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
@@ -20,7 +21,11 @@ extern void test__clang_callback(int x);
 
 extern int perf_clang__compile_bpf(const char *filename,
   void **p_obj_buf,
-  size_t *p_obj_buf_sz);
+  size_t *p_obj_buf_sz,
+  jitted_funcs_map_t *p_funcs_map);
+
+extern int
+perf_clang__hook_jitted_func(jitted_funcs_map_t map, void *ctx, bool is_err);
 #else
 
 
@@ -34,7 +39,16 @@ static inline int test__clang_jit(void) { return -1;}
 static inline int
 perf_clang__compile_bpf(const char *filename __maybe_unused,
void **p_obj_buf __maybe_unused,
-   size_t *p_obj_buf_sz __maybe_unused)
+   size_t *p_obj_buf_sz __maybe_unused,
+   jitted_funcs_map_t *p_funcs_map __maybe_unused)
+{
+   return -ENOTSUP;
+}
+
+static inline int
+perf_clang__hook_jitted_func(jitted_funcs_map_t map __maybe_unused,
+void *ctx __maybe_unused,
+bool is_err __maybe_unused)
 {
return -ENOTSUP;
 }
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 325fbe4..f2608f5 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -388,7 +388,8 @@ void perf_clang__cleanup(void)
 
 int perf_clang__compile_bpf(const char *_filename,
void **p_obj_buf,
-   size_t *p_obj_buf_sz)
+   size_t *p_obj_buf_sz,
+   jitted_funcs_map_t *p_funcs_map)
 {
  

[PATCH v3 08/30] tools build: Add feature detection for clang

2016-11-25 Thread Wang Nan
Check if basic clang compiling environment is ready.

Doesn't like 'llvm-config --libs' which can returns llvm libraries in
right order and duplicates some libraries if necessary, there's no
correspondence for clang libraries (-lclangxxx). to avoid extra
complexity and to avoid new clang breaking libraries ordering, use
--start-group and --end-group.

In this test case, manually identify required clang libs and hope it to
be stable. Putting all clang libraries here is possible (use make's
wildcard), but then feature checking becomes very slow.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: 
http://lkml.kernel.org/r/1474874832-134786-5-git-send-email-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/build/feature/Makefile   | 10 ++
 tools/build/feature/test-clang.cpp | 21 +
 2 files changed, 31 insertions(+)
 create mode 100644 tools/build/feature/test-clang.cpp

diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index c09de59..871d553 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -237,6 +237,16 @@ $(OUTPUT)test-llvm.bin:
$(shell $(LLVM_CONFIG) --libs Core BPF) \
$(shell $(LLVM_CONFIG) --system-libs)
 
+$(OUTPUT)test-clang.bin:
+   $(BUILDXX) -std=gnu++11 \
+   -I$(shell $(LLVM_CONFIG) --includedir)  \
+   -L$(shell $(LLVM_CONFIG) --libdir)  \
+   -Wl,--start-group -lclangBasic -lclangDriver\
+ -lclangFrontend -lclangEdit -lclangLex\
+ -lclangAST -Wl,--end-group\
+   $(shell $(LLVM_CONFIG) --libs Core option)  \
+   $(shell $(LLVM_CONFIG) --system-libs)
+
 -include $(OUTPUT)*.d
 
 ###
diff --git a/tools/build/feature/test-clang.cpp 
b/tools/build/feature/test-clang.cpp
new file mode 100644
index 000..e23c1b1
--- /dev/null
+++ b/tools/build/feature/test-clang.cpp
@@ -0,0 +1,21 @@
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::driver;
+
+int main()
+{
+   IntrusiveRefCntPtr DiagID(new DiagnosticIDs());
+   IntrusiveRefCntPtr DiagOpts = new 
DiagnosticOptions();
+
+   DiagnosticsEngine Diags(DiagID, &*DiagOpts);
+   Driver TheDriver("test", "bpf-pc-linux", Diags);
+
+   llvm::llvm_shutdown();
+   return 0;
+}
-- 
2.10.1



[PATCH v3 05/30] perf tools: Pass context to perf hook functions

2016-11-25 Thread Wang Nan
Pass a pointer to perf hook functions so they receive context
information created durnig setup.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/tests/perf-hooks.c | 14 +-
 tools/perf/util/perf-hooks.c  | 10 +++---
 tools/perf/util/perf-hooks.h  |  6 --
 3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
index 9338cb2..665ecc1 100644
--- a/tools/perf/tests/perf-hooks.c
+++ b/tools/perf/tests/perf-hooks.c
@@ -15,13 +15,13 @@ static void sigsegv_handler(int sig __maybe_unused)
exit(-1);
 }
 
-static int hook_flags;
 
-static void the_hook(void)
+static void the_hook(void *_hook_flags)
 {
+   int *hook_flags = _hook_flags;
int *p = NULL;
 
-   hook_flags = 1234;
+   *hook_flags = 1234;
 
/* Generate a segfault, test perf_hooks__recover */
*p = 0;
@@ -29,13 +29,17 @@ static void the_hook(void)
 
 int test__perf_hooks(int subtest __maybe_unused)
 {
+   int hook_flags = 0;
+
signal(SIGSEGV, sigsegv_handler);
-   perf_hooks__set_hook("test", the_hook);
+   perf_hooks__set_hook("test", the_hook, &hook_flags);
perf_hooks__invoke_test();
 
/* hook is triggered? */
-   if (hook_flags != 1234)
+   if (hook_flags != 1234) {
+   pr_debug("Setting failed: %d (%p)\n", hook_flags, &hook_flags);
return TEST_FAIL;
+   }
 
/* the buggy hook is removed? */
if (perf_hooks__get_hook("test"))
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
index 4ce88e3..cb36830 100644
--- a/tools/perf/util/perf-hooks.c
+++ b/tools/perf/util/perf-hooks.c
@@ -27,7 +27,7 @@ void perf_hooks__invoke(const struct perf_hook_desc *desc)
*(current_perf_hook->p_hook_func) = NULL;
} else {
current_perf_hook = desc;
-   (**desc->p_hook_func)();
+   (**desc->p_hook_func)(desc->hook_ctx);
}
current_perf_hook = NULL;
 }
@@ -41,7 +41,9 @@ void perf_hooks__recover(void)
 #define PERF_HOOK(name)\
 perf_hook_func_t __perf_hook_func_##name = NULL;   \
 struct perf_hook_desc __perf_hook_desc_##name =\
-   {.hook_name = #name, .p_hook_func = &__perf_hook_func_##name};
+   {.hook_name = #name,\
+.p_hook_func = &__perf_hook_func_##name,   \
+.hook_ctx = NULL};
 #include "perf-hooks-list.h"
 #undef PERF_HOOK
 
@@ -54,7 +56,8 @@ static struct perf_hook_desc *perf_hooks[] = {
 #undef PERF_HOOK
 
 int perf_hooks__set_hook(const char *hook_name,
-perf_hook_func_t hook_func)
+perf_hook_func_t hook_func,
+void *hook_ctx)
 {
unsigned int i;
 
@@ -65,6 +68,7 @@ int perf_hooks__set_hook(const char *hook_name,
if (*(perf_hooks[i]->p_hook_func))
pr_warning("Overwrite existing hook: %s\n", hook_name);
*(perf_hooks[i]->p_hook_func) = hook_func;
+   perf_hooks[i]->hook_ctx = hook_ctx;
return 0;
}
return -ENOENT;
diff --git a/tools/perf/util/perf-hooks.h b/tools/perf/util/perf-hooks.h
index 1d482b2..838d579 100644
--- a/tools/perf/util/perf-hooks.h
+++ b/tools/perf/util/perf-hooks.h
@@ -5,10 +5,11 @@
 extern "C" {
 #endif
 
-typedef void (*perf_hook_func_t)(void);
+typedef void (*perf_hook_func_t)(void *ctx);
 struct perf_hook_desc {
const char * const hook_name;
perf_hook_func_t * const p_hook_func;
+   void *hook_ctx;
 };
 
 extern void perf_hooks__invoke(const struct perf_hook_desc *);
@@ -26,7 +27,8 @@ static inline void perf_hooks__invoke_##name(void)\
 
 extern int
 perf_hooks__set_hook(const char *hook_name,
-perf_hook_func_t hook_func);
+perf_hook_func_t hook_func,
+void *hook_ctx);
 
 extern perf_hook_func_t
 perf_hooks__get_hook(const char *hook_name);
-- 
2.10.1



[PATCH v3 10/30] perf clang: Add builtin clang support ant test case

2016-11-25 Thread Wang Nan
Add basic clang support in clang.cpp and test__clang() testcase. The
first testcase checks if builtin clang is able to generate LLVM IR.

tests/clang.c is a proxy. Real testcase resides in
utils/c++/clang-test.cpp in c++ and exports C interface to perf test
subsystem.

Test result:

   $ perf test -v clang
   51: Test builtin clang support   :
   51.1: Test builtin clang compile C source to IR  :
   --- start ---
   test child forked, pid 13215
   test child finished with 0
    end 
   Test builtin clang support subtest 0: Ok

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/tests/Build |  1 +
 tools/perf/tests/builtin-test.c|  9 
 tools/perf/tests/clang.c   | 42 +
 tools/perf/tests/tests.h   |  3 ++
 tools/perf/util/Build  |  2 +
 tools/perf/util/c++/Build  |  2 +
 tools/perf/util/c++/clang-c.h  | 16 +++
 tools/perf/util/c++/clang-test.cpp | 31 
 tools/perf/util/c++/clang.cpp  | 96 ++
 tools/perf/util/c++/clang.h| 16 +++
 10 files changed, 218 insertions(+)
 create mode 100644 tools/perf/tests/clang.c
 create mode 100644 tools/perf/util/c++/Build
 create mode 100644 tools/perf/util/c++/clang-c.h
 create mode 100644 tools/perf/util/c++/clang-test.cpp
 create mode 100644 tools/perf/util/c++/clang.cpp
 create mode 100644 tools/perf/util/c++/clang.h

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index af3ec94..6676c2d 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -43,6 +43,7 @@ perf-y += sdt.o
 perf-y += is_printable_array.o
 perf-y += bitmap.o
 perf-y += perf-hooks.o
+perf-y += clang.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
$(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index dab83f7..33aaa52 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -234,6 +234,15 @@ static struct test generic_tests[] = {
.func = test__perf_hooks,
},
{
+   .desc = "Test builtin clang support",
+   .func = test__clang,
+   .subtest = {
+   .skip_if_fail   = true,
+   .get_nr = test__clang_subtest_get_nr,
+   .get_desc   = test__clang_subtest_get_desc,
+   }
+   },
+   {
.func = NULL,
},
 };
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
new file mode 100644
index 000..57ee160
--- /dev/null
+++ b/tools/perf/tests/clang.c
@@ -0,0 +1,42 @@
+#include "tests.h"
+#include "debug.h"
+#include "util.h"
+#include "c++/clang-c.h"
+
+static struct {
+   int (*func)(void);
+   const char *desc;
+} clang_testcase_table[] = {
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
+   {
+   .func = test__clang_to_IR,
+   .desc = "Test builtin clang compile C source to IR",
+   },
+#endif
+};
+
+int test__clang_subtest_get_nr(void)
+{
+   return (int)ARRAY_SIZE(clang_testcase_table);
+}
+
+const char *test__clang_subtest_get_desc(int i)
+{
+   if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
+   return NULL;
+   return clang_testcase_table[i].desc;
+}
+
+#ifndef HAVE_LIBCLANGLLVM_SUPPORT
+int test__clang(int i __maybe_unused)
+{
+   return TEST_SKIP;
+}
+#else
+int test__clang(int i __maybe_unused)
+{
+   if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
+   return TEST_FAIL;
+   return clang_testcase_table[i].func();
+}
+#endif
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 3a1f98f..0d7b251 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -92,6 +92,9 @@ int test__sdt_event(int subtest);
 int test__is_printable_array(int subtest);
 int test__bitmap_print(int subtest);
 int test__perf_hooks(int subtest);
+int test__clang(int subtest);
+const char *test__clang_subtest_get_desc(int subtest);
+int test__clang_subtest_get_nr(void);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index b2a47aa..743a889 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -125,6 +125,8 @@ endif
 
 libperf-y += perf-hooks.o
 
+libperf-$(CONFIG_CXX) += c++/
+
 CFLAGS_config.o   += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
 # avoid compiler warnings in 32-bit mode
 CFLAGS_genelf_debug.o  += -Wno-packed
diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
new file mode 100644
index 000..988fef1
--- /dev/null
+++ b/tools/perf/util/c++/Build
@@ -0,0 +1,2 @@
+libperf-$(CONFIG_CLA

[PATCH v3 25/30] perf clang jit: Allow jitted perf hook access BPF maps

2016-11-25 Thread Wang Nan
Newly introduced jit-helpers.[ch] defines a series of helpers which helps
jitted perf hook functions accessing BPF maps defined in their BPF scripts.
The helpers fetches fd of 'struct bpf_map' from 'struct bpf_object' and the
address of 'struct bpf_map_def' in jitted file. 'struct bpf_object' is the
context passed to hooks.

Jit helpers added in this commits are all leading with 'perf_'. We don't use
'bpf_' prefix because in following commits 'bpf_' prefix is going to be assigned
to kernel side BPF map operations. Same operation has different protocol for
kernel and user.

 Example:

  $ cat ./test.c
  /***/
  #define SEC(name) __attribute__((section(name), used))
  #define BPF_MAP_TYPE_ARRAY 2
  #define BPF_MAP_TYPE_PERF_EVENT_ARRAY 4
  #define BPF_FUNC_map_lookup_elem 1
  static void *(*bpf_map_lookup_elem)(void *map, void *key) =
  (void *) BPF_FUNC_map_lookup_elem;
  struct bpf_map_def {
  unsigned int type;
  unsigned int key_size;
  unsigned int value_size;
  unsigned int max_entries;
  };
  struct bpf_map_def SEC("maps") counter = {
  .type = BPF_MAP_TYPE_ARRAY,
  .key_size = sizeof(int),
  .value_size = sizeof(int),
  .max_entries = 1,
  };
  extern int perf_map_update_elem(void *ctx, struct bpf_map_def *map,
 void *key, void *value, unsigned long flags);
  extern int perf_map_lookup_elem(void *ctx, struct bpf_map_def *map,
 void *key, void *value);
  SEC("sys_close=SyS_close")
  int sys_close(void *ctx)
  {
  int key = 0;
  int *value;
  value = bpf_map_lookup_elem(&counter, &key);
  if (!value)
  return 0;
  __sync_fetch_and_add(value, 1);
  return 0;
  }
  extern int printf(const char *fmt, ...);
  SEC("perfhook:record_start")
  void record_start(void *ctx)
  {
  int key = 0;
  int value = 1;
  printf("Welcom to perf record\n");
  perf_map_update_elem(ctx, &counter, &key, &value, 0);
  }

  SEC("perfhook:record_end")
  void record_end(void *ctx)
  {
  int key = 0;
  int value;
  perf_map_lookup_elem(ctx, &counter, &key, &value);
  printf("Goodbye, perf record, value=%d\n", value);
  }
  char _license[] SEC("license") = "GPL";
  int _version SEC("version") = LINUX_VERSION_CODE;
  /***/
  $ sudo perf record  -e ./test.c echo Hehe
  Welcom to perf record
  Hehe
  [ perf record: Woken up 1 times to write data ]
  Goodbye, perf record, value=10644
  [ perf record: Captured and wrote 0.014 MB perf.data ]

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/Build |  1 +
 tools/perf/util/c++/clang.cpp |  9 ++-
 tools/perf/util/jit-helpers.c | 57 +++
 tools/perf/util/jit-helpers.h | 28 +
 4 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/util/jit-helpers.c
 create mode 100644 tools/perf/util/jit-helpers.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 743a889..33773cb 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -124,6 +124,7 @@ libperf-$(CONFIG_DWARF) += genelf_debug.o
 endif
 
 libperf-y += perf-hooks.o
+libperf-y += jit-helpers.o
 
 libperf-$(CONFIG_CXX) += c++/
 
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index f8ea9bd..48bd3ee 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -38,6 +38,7 @@
 #include "llvm-utils.h"
 #include "util-cxx.h"
 #include "perf-hooks.h"
+#include "jit-helpers.h"
 
 namespace perf {
 
@@ -196,12 +197,18 @@ PerfModule::toBPFObject(void)
return std::move(Buffer);
 }
 
+#define __stringify_1(x)   #x
+#define __stringify(x) __stringify_1(x)
 static std::map exported_funcs =
 {
-#define EXPORT(f) {#f, (const void *)&f}
+#define EXPORT(f) {__stringify(f), (const void *)&f}
EXPORT(test__clang_callback),
EXPORT(printf),
EXPORT(puts),
+   EXPORT(JIT_HELPER_FUNC_NAME(map_update_elem)),
+   EXPORT(JIT_HELPER_FUNC_NAME(map_lookup_elem)),
+   EXPORT(JIT_HELPER_FUNC_NAME(map_get_next_key)),
+   EXPORT(JIT_HELPER_FUNC_NAME(map_pin)),
 #undef EXPORT
 };
 
diff --git a/tools/perf/util/jit-helpers.c b/tools/perf/util/jit-helpers.c
new file mode 100644
index 000..1a37a20
--- /dev/null
+++ b/tools/perf/util/jit-helpers.c
@@ -0,0 +1,57 @@
+/*
+ * jit-helper.c
+ *
+ * Copyright (C) 2016 Wang Nan 
+ * Copyright (C) 2016 Huawei Inc.
+ *
+ * Provide helpers which can be invoked by jit scripts attached to
+ * perf hooks

[PATCH v3 29/30] perf clang builtin: Define hook helpers by default

2016-11-25 Thread Wang Nan
Append declarations of helpers to default include file. All functions
appear in exported_funcs array should be declared here except
test__clang_callback, because it is used for perf test only.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/bpf-helper-str.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/tools/perf/util/c++/bpf-helper-str.c 
b/tools/perf/util/c++/bpf-helper-str.c
index 17f915c..f4d6d57 100644
--- a/tools/perf/util/c++/bpf-helper-str.c
+++ b/tools/perf/util/c++/bpf-helper-str.c
@@ -10,6 +10,13 @@ const char clang_builtin_bpf_helper_str[] =
 "  unsigned int max_entries;\n"
 "};\n"
 "#define SEC(NAME) __attribute__((section(NAME), used))\n"
+"extern int printf(const char *, ...);\n"
+"extern int puts(const char *);\n"
+"extern int perf_map_update_elem(void *, void *, void *, void *, unsigned 
long);\n"
+"extern int perf_map_lookup_elem(void *, void *, void *, void *);\n"
+"extern int perf_map_get_next_key(void *, void *, void *, void *);\n"
+"extern int perf_map_pin(void *, void *, const char *);\n"
+"extern int perf_map_get(const char *);\n"
 "#endif\n"
 "#endif"
 ;
-- 
2.10.1



[PATCH v3 18/30] perf clang jit: Wrap llvm::Module using PerfModule

2016-11-25 Thread Wang Nan
Use PerfModule wrap llvm::Module and return perf::PerfModule in APIs to
replace llvm::Module. Following commits are going to add new functions
to PerfModule.

getBPFObjectFromModule is merged to a method of perf::PerfModule.

Signed-off-by: Wang Nan 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
---
 tools/perf/util/c++/clang-test.cpp | 10 +-
 tools/perf/util/c++/clang.cpp  | 20 +---
 tools/perf/util/c++/clang.h| 22 --
 3 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/c++/clang-test.cpp 
b/tools/perf/util/c++/clang-test.cpp
index 9b11e8c..fb05e56 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -13,18 +13,18 @@ public:
~perf_clang_scope() {perf_clang__cleanup();}
 };
 
-static std::unique_ptr
+static std::unique_ptr
 __test__clang_to_IR(void)
 {
unsigned int kernel_version;
 
if (fetch_kernel_version(&kernel_version, NULL, 0))
-   return std::unique_ptr(nullptr);
+   return std::unique_ptr(nullptr);
 
std::string cflag_kver("-DLINUX_VERSION_CODE=" +
std::to_string(kernel_version));
 
-   std::unique_ptr M =
+   std::unique_ptr M =
perf::getModuleFromSource({cflag_kver.c_str()},
  "perf-test.c",
  test_llvm__bpf_base_prog);
@@ -39,7 +39,7 @@ int test__clang_to_IR(void)
auto M = __test__clang_to_IR();
if (!M)
return -1;
-   for (llvm::Function& F : *M)
+   for (llvm::Function& F : *(M->getModule()))
if (F.getName() == "bpf_func__SyS_epoll_wait")
return 0;
return -1;
@@ -53,7 +53,7 @@ int test__clang_to_obj(void)
if (!M)
return -1;
 
-   auto Buffer = perf::getBPFObjectFromModule(&*M);
+   auto Buffer = M->toBPFObject();
if (!Buffer)
return -1;
return 0;
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 3a3b9791..d31b0a5 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -64,7 +64,7 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, 
StringRef& Path,
return CI;
 }
 
-static std::unique_ptr
+static std::unique_ptr
 getModuleFromSource(llvm::opt::ArgStringList CFlags,
StringRef Path, IntrusiveRefCntPtr VFS)
 {
@@ -80,12 +80,12 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags,
 
std::unique_ptr Act(new EmitLLVMOnlyAction(&*LLVMCtx));
if (!Clang.ExecuteAction(*Act))
-   return std::unique_ptr(nullptr);
+   return std::unique_ptr(nullptr);
 
-   return Act->takeModule();
+   return std::unique_ptr(new 
PerfModule(std::move(Act->takeModule(;
 }
 
-std::unique_ptr
+std::unique_ptr
 getModuleFromSource(llvm::opt::ArgStringList CFlags,
StringRef Name, StringRef Content)
 {
@@ -106,15 +106,21 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags,
return getModuleFromSource(std::move(CFlags), Name, OverlayFS);
 }
 
-std::unique_ptr
+std::unique_ptr
 getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 {
IntrusiveRefCntPtr VFS(vfs::getRealFileSystem());
return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
+PerfModule::PerfModule(std::unique_ptr&& M) : 
Module(std::move(M))
+{
+
+}
+
+
 std::unique_ptr>
-getBPFObjectFromModule(llvm::Module *Module)
+PerfModule::toBPFObject(void)
 {
using namespace llvm;
 
@@ -278,7 +284,7 @@ int perf_clang__compile_bpf(const char *_filename,
auto M = getModuleFromSource(std::move(CFlags), Opts.getFileName());
if (!M)
return  -EINVAL;
-   auto O = getBPFObjectFromModule(&*M);
+   auto O = M->toBPFObject();
if (!O)
return -EINVAL;
 
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index dd8b042..cbb291b 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -11,16 +11,26 @@ namespace perf {
 
 using namespace llvm;
 
-std::unique_ptr
+class PerfModule {
+private:
+   std::unique_ptr Module;
+public:
+   inline llvm::Module *getModule(void)
+   {
+   return Module.get();
+   }
+
+   PerfModule(std::unique_ptr&& M);
+
+   std::unique_ptr> toBPFObject(void);
+};
+
+std::unique_ptr
 getModuleFromSource(opt::ArgStringList CFlags,
StringRef Name, StringRef Content);
 
-std::unique_ptr
+std::unique_ptr
 getModuleFromSource(opt::ArgStringList CFlags,
StringRef Path);
-
-std::unique_ptr>
-getBPFObjectFromModule(llvm::Module *Module);
-
 }
 #endif
-- 
2.10.1



[PATCH v3 12/30] perf clang: Allow passing CFLAGS to builtin clang

2016-11-25 Thread Wang Nan
Improve getModuleFromSource() API to accept a cflags list. This feature
will be used to pass LINUX_VERSION_CODE and -I flags.

Signed-off-by: Wang Nan 
Cc: Alexei Starovoitov 
Cc: He Kuang 
Cc: Jiri Olsa 
Cc: Zefan Li 
Cc: pi3or...@163.com
Link: 
http://lkml.kernel.org/r/1474874832-134786-9-git-send-email-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/util/c++/clang-test.cpp |  5 +++--
 tools/perf/util/c++/clang.cpp  | 21 +
 tools/perf/util/c++/clang.h|  8 ++--
 3 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/c++/clang-test.cpp 
b/tools/perf/util/c++/clang-test.cpp
index 3da6bfa..0f484fb 100644
--- a/tools/perf/util/c++/clang-test.cpp
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -16,8 +16,9 @@ int test__clang_to_IR(void)
perf_clang_scope _scope;
 
std::unique_ptr M =
-   perf::getModuleFromSource("perf-test.c",
- "int myfunc(void) {return 1;}");
+   perf::getModuleFromSource({"-DRESULT=1"},
+ "perf-test.c",
+ "int myfunc(void) {return RESULT;}");
 
if (!M)
return -1;
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index cf96199..715ca0a 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -29,7 +29,8 @@ static std::unique_ptr LLVMCtx;
 using namespace clang;
 
 static CompilerInvocation *
-createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags)
+createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
+DiagnosticsEngine& Diags)
 {
llvm::opt::ArgStringList CCArgs {
"-cc1",
@@ -45,6 +46,8 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& 
Diags)
"-Wno-unused-value",
"-Wno-pointer-sign",
"-x", "c"};
+
+   CCArgs.append(CFlags.begin(), CFlags.end());
CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
 
FrontendOptions& Opts = CI->getFrontendOpts();
@@ -54,8 +57,8 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& 
Diags)
 }
 
 static std::unique_ptr
-getModuleFromSource(StringRef Path,
-   IntrusiveRefCntPtr VFS)
+getModuleFromSource(llvm::opt::ArgStringList CFlags,
+   StringRef Path, IntrusiveRefCntPtr VFS)
 {
CompilerInstance Clang;
Clang.createDiagnostics();
@@ -63,7 +66,8 @@ getModuleFromSource(StringRef Path,
Clang.setVirtualFileSystem(&*VFS);
 
IntrusiveRefCntPtr CI =
-   createCompilerInvocation(Path, Clang.getDiagnostics());
+   createCompilerInvocation(std::move(CFlags), Path,
+Clang.getDiagnostics());
Clang.setInvocation(&*CI);
 
std::unique_ptr Act(new EmitLLVMOnlyAction(&*LLVMCtx));
@@ -74,7 +78,8 @@ getModuleFromSource(StringRef Path,
 }
 
 std::unique_ptr
-getModuleFromSource(StringRef Name, StringRef Content)
+getModuleFromSource(llvm::opt::ArgStringList CFlags,
+   StringRef Name, StringRef Content)
 {
using namespace vfs;
 
@@ -90,14 +95,14 @@ getModuleFromSource(StringRef Name, StringRef Content)
OverlayFS->pushOverlay(MemFS);
MemFS->addFile(Twine(Name), 0, 
llvm::MemoryBuffer::getMemBuffer(Content));
 
-   return getModuleFromSource(Name, OverlayFS);
+   return getModuleFromSource(std::move(CFlags), Name, OverlayFS);
 }
 
 std::unique_ptr
-getModuleFromSource(StringRef Path)
+getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
 {
IntrusiveRefCntPtr VFS(vfs::getRealFileSystem());
-   return getModuleFromSource(Path, VFS);
+   return getModuleFromSource(std::move(CFlags), Path, VFS);
 }
 
 }
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
index 90aff01..b4fc2a9 100644
--- a/tools/perf/util/c++/clang.h
+++ b/tools/perf/util/c++/clang.h
@@ -4,16 +4,20 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Option/Option.h"
 #include 
+
 namespace perf {
 
 using namespace llvm;
 
 std::unique_ptr
-getModuleFromSource(StringRef Name, StringRef Content);
+getModuleFromSource(opt::ArgStringList CFlags,
+   StringRef Name, StringRef Content);
 
 std::unique_ptr
-getModuleFromSource(StringRef Path);
+getModuleFromSource(opt::ArgStringList CFlags,
+   StringRef Path);
 
 }
 #endif
-- 
2.10.1



  1   2   3   4   5   6   7   8   9   10   >