Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1286157 > unrolled thread

[PATCH v4 00/16] perf tools: BPF related update and other improvements

Started byWang Nan <wangnan0@huawei.com>
First post2015-12-08 03:30 +0100
Last post2015-12-08 03:40 +0100
Articles 20 on this page of 28 — 6 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v4 00/16] perf tools: BPF related update and other improvements Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
    [PATCH v4 01/16] tools lib bpf: Check return value of strdup when reading map names Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
      [tip:perf/core] tools lib bpf:   Check return value of strdup when reading map names tip-bot for Wang Nan <tipbot@zytor.com> - 2015-12-14 09:40 +0100
    [PATCH v4 07/16] perf tools: Enable passing event to BPF object Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
    [PATCH v4 12/16] perf data: Support converting data from bpf_perf_event_output() Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
    [PATCH v4 14/16] perf record: Support custom vmlinux path Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
    [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
      Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for  BPF maps Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-11 13:20 +0100
        Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for  BPF maps Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-11 13:20 +0100
          Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for  BPF maps Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-11 13:50 +0100
            Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps pi3orama <pi3orama@163.com> - 2015-12-11 14:00 +0100
          Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps pi3orama <pi3orama@163.com> - 2015-12-11 13:50 +0100
            Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for  BPF maps Alexei Starovoitov <alexei.starovoitov@gmail.com> - 2015-12-11 19:30 +0100
              Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for  BPF maps "Wangnan (F)" <wangnan0@huawei.com> - 2015-12-14 04:30 +0100
                Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for  BPF maps Alexei Starovoitov <alexei.starovoitov@gmail.com> - 2015-12-14 05:30 +0100
                  Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for  BPF maps "Wangnan (F)" <wangnan0@huawei.com> - 2015-12-14 05:50 +0100
                    Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for  BPF maps Alexei Starovoitov <alexei.starovoitov@gmail.com> - 2015-12-14 07:00 +0100
    [PATCH v4 13/16] perf tools: Always give options even it not compiled Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
      Re: [PATCH v4 13/16] perf tools: Always give options even it not  compiled Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-11 13:50 +0100
    [PATCH v4 15/16] perf script: Add support for PERF_TYPE_BREAKPOINT Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:40 +0100
      [tip:perf/core] perf script: Add support for PERF_TYPE_BREAKPOINT tip-bot for Wang Nan <tipbot@zytor.com> - 2015-12-14 09:40 +0100
    [PATCH v4 06/16] perf tools: Support perf event alias name Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:40 +0100
      Re: [PATCH v4 06/16] perf tools: Support perf event alias name Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-11 13:10 +0100
        Re: [PATCH v4 06/16] perf tools: Support perf event alias name pi3orama <pi3orama@163.com> - 2015-12-11 13:20 +0100
    [PATCH v4 02/16] tools lib bpf: Fetch map names from correct strtab Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:40 +0100
      [tip:perf/core] tools lib bpf:   Fetch map names from correct strtab tip-bot for Wang Nan <tipbot@zytor.com> - 2015-12-14 09:40 +0100
    [PATCH v4 05/16] perf record: Apply config to BPF objects before recording Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:40 +0100
    [PATCH v4 04/16] perf tools: Enable BPF object configure syntax Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:40 +0100

Page 1 of 2  [1] 2  Next page →


#1286157 — [PATCH v4 00/16] perf tools: BPF related update and other improvements

FromWang Nan <wangnan0@huawei.com>
Date2015-12-08 03:30 +0100
Subject[PATCH v4 00/16] perf tools: BPF related update and other improvements
Message-ID<qDgcp-4Bz-3@gated-at.bofh.it>
Hi Arnaldo,

   Glad to see you start processing patches again. This patch set
contains all BPF related patches and two other patches in my local
tree. I have rebased them onto your newest perf/core. Please review
them when you have time.

This patch set is based on perf/core.

Compare with v3:

 - Rebase on newest perf/core

 - Small commit message improvements

 - Fetch map names from correct strtab (2/16)

 - Patch 15-16 are not related to BPF. Send them together because they
   stay in my local tree for sereval days.

He Kuang (2):
  perf tools: Support perf event alias name
  perf record: Support custom vmlinux path

Wang Nan (14):
  tools lib bpf: Check return value of strdup when reading map names
  tools lib bpf: Fetch map names from correct strtab
  perf tools: Add API to config maps in bpf object
  perf tools: Enable BPF object configure syntax
  perf record: Apply config to BPF objects before recording
  perf tools: Enable passing event to BPF object
  perf tools: Support setting different slots in a BPF map separately
  perf tools: Enable indices setting syntax for BPF maps
  perf tools: Introduce bpf-output event
  perf data: Add u32_hex data type
  perf data: Support converting data from bpf_perf_event_output()
  perf tools: Always give options even it not compiled
  perf script: Add support for PERF_TYPE_BREAKPOINT
  perf tools: Clear struct machine during machine__init()

 tools/lib/bpf/libbpf.c                   |  24 +-
 tools/perf/Documentation/perf-record.txt |  10 +-
 tools/perf/builtin-probe.c               |  15 +-
 tools/perf/builtin-record.c              |  36 +-
 tools/perf/builtin-script.c              |  14 +
 tools/perf/util/bpf-loader.c             | 700 +++++++++++++++++++++++++++++++
 tools/perf/util/bpf-loader.h             |  59 +++
 tools/perf/util/data-convert-bt.c        | 117 +++++-
 tools/perf/util/evlist.c                 |  16 +
 tools/perf/util/evlist.h                 |   4 +
 tools/perf/util/evsel.c                  |   7 +
 tools/perf/util/evsel.h                  |   1 +
 tools/perf/util/machine.c                |   1 +
 tools/perf/util/parse-events.c           | 125 +++++-
 tools/perf/util/parse-events.h           |  20 +-
 tools/perf/util/parse-events.l           |  16 +-
 tools/perf/util/parse-events.y           | 123 +++++-
 tools/perf/util/parse-options.c          | 113 ++++-
 tools/perf/util/parse-options.h          |   5 +
 19 files changed, 1369 insertions(+), 37 deletions(-)

-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1286158 — [PATCH v4 01/16] tools lib bpf: Check return value of strdup when reading map names

FromWang Nan <wangnan0@huawei.com>
Date2015-12-08 03:30 +0100
Subject[PATCH v4 01/16] tools lib bpf: Check return value of strdup when reading map names
Message-ID<qDgcq-4Bz-19@gated-at.bofh.it>
In reply to#1286157
Commit 561bbccac72d08babafaa33fd7fa9100ec4c9fb6 ("tools lib bpf:
Extract and collect map names from BPF object file") forgets checking
return value of strdup(). This patch fixes it. It also checks names
pointer before strcmp() for safty.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/libbpf.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index a298614..16485ab 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -527,14 +527,14 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
 	return 0;
 }
 
-static void
+static int
 bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
 {
 	int i;
 	Elf_Data *symbols = obj->efile.symbols;
 
 	if (!symbols || maps_shndx < 0)
-		return;
+		return -EINVAL;
 
 	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
 		GElf_Sym sym;
@@ -556,9 +556,14 @@ bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
 			continue;
 		}
 		obj->maps[map_idx].name = strdup(map_name);
+		if (!obj->maps[map_idx].name) {
+			pr_warning("failed to alloc map name\n");
+			return -ENOMEM;
+		}
 		pr_debug("map %zu is \"%s\"\n", map_idx,
 			 obj->maps[map_idx].name);
 	}
+	return 0;
 }
 
 static int bpf_object__elf_collect(struct bpf_object *obj)
@@ -663,7 +668,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 	}
 
 	if (maps_shndx >= 0)
-		bpf_object__init_maps_name(obj, maps_shndx);
+		err = bpf_object__init_maps_name(obj, maps_shndx);
 out:
 	return err;
 }
@@ -1372,7 +1377,7 @@ bpf_object__get_map_by_name(struct bpf_object *obj, const char *name)
 	struct bpf_map *pos;
 
 	bpf_map__for_each(pos, obj) {
-		if (strcmp(pos->name, name) == 0)
+		if (pos->name && !strcmp(pos->name, name))
 			return pos;
 	}
 	return NULL;
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1290950 — [tip:perf/core] tools lib bpf: Check return value of strdup when reading map names

Fromtip-bot for Wang Nan <tipbot@zytor.com>
Date2015-12-14 09:40 +0100
Subject[tip:perf/core] tools lib bpf: Check return value of strdup when reading map names
Message-ID<qFwPM-3DO-11@gated-at.bofh.it>
In reply to#1286158
Commit-ID:  973170e66726672518eb935eb0dc0e63876d133d
Gitweb:     http://git.kernel.org/tip/973170e66726672518eb935eb0dc0e63876d133d
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Tue, 8 Dec 2015 02:25:29 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 11 Dec 2015 08:51:09 -0300

tools lib bpf: Check return value of strdup when reading map names

Commit 561bbccac72d08babafaa33fd7fa9100ec4c9fb6 ("tools lib bpf:
Extract and collect map names from BPF object file") forgets checking
return value of strdup(). This patch fixes it. It also checks names
pointer before strcmp() for safety.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Fixes: 561bbccac72d ("tools lib bpf: Extract and collect map names from BPF object file")
Link: http://lkml.kernel.org/r/1449541544-67621-2-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/libbpf.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index a298614..16485ab 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -527,14 +527,14 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
 	return 0;
 }
 
-static void
+static int
 bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
 {
 	int i;
 	Elf_Data *symbols = obj->efile.symbols;
 
 	if (!symbols || maps_shndx < 0)
-		return;
+		return -EINVAL;
 
 	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
 		GElf_Sym sym;
@@ -556,9 +556,14 @@ bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
 			continue;
 		}
 		obj->maps[map_idx].name = strdup(map_name);
+		if (!obj->maps[map_idx].name) {
+			pr_warning("failed to alloc map name\n");
+			return -ENOMEM;
+		}
 		pr_debug("map %zu is \"%s\"\n", map_idx,
 			 obj->maps[map_idx].name);
 	}
+	return 0;
 }
 
 static int bpf_object__elf_collect(struct bpf_object *obj)
@@ -663,7 +668,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 	}
 
 	if (maps_shndx >= 0)
-		bpf_object__init_maps_name(obj, maps_shndx);
+		err = bpf_object__init_maps_name(obj, maps_shndx);
 out:
 	return err;
 }
@@ -1372,7 +1377,7 @@ bpf_object__get_map_by_name(struct bpf_object *obj, const char *name)
 	struct bpf_map *pos;
 
 	bpf_map__for_each(pos, obj) {
-		if (strcmp(pos->name, name) == 0)
+		if (pos->name && !strcmp(pos->name, name))
 			return pos;
 	}
 	return NULL;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286159 — [PATCH v4 07/16] perf tools: Enable passing event to BPF object

FromWang Nan <wangnan0@huawei.com>
Date2015-12-08 03:30 +0100
Subject[PATCH v4 07/16] perf tools: Enable passing event to BPF object
Message-ID<qDgcq-4Bz-23@gated-at.bofh.it>
In reply to#1286157
A new syntax is appended into parser so user can pass predefined perf
events into BPF objects.

After this patch, BPF programs for perf are finally able to utilize
bpf_perf_event_read() introduced in commit 35578d7984003097af2b1e3
(bpf: Implement function bpf_perf_event_read() that get the selected
hardware PMU conuter).

Test result:

 # cat ./test_bpf_map_2.c
 /************************ BEGIN **************************/
 #define SEC(NAME) __attribute__((section(NAME), used))
 enum bpf_map_type {
     BPF_MAP_TYPE_PERF_EVENT_ARRAY = 4,
 };
 struct bpf_map_def {
     unsigned int type;
     unsigned int key_size;
     unsigned int value_size;
     unsigned int max_entries;
 };
 static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
     (void *)1;
 static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
     (void *)6;
 static int (*bpf_get_smp_processor_id)(void) =
     (void *)8;
 static int (*bpf_perf_event_read)(struct bpf_map_def *, int) =
     (void *)22;

 struct bpf_map_def SEC("maps") pmu_map = {
     .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
     .key_size = sizeof(int),
     .value_size = sizeof(int),
     .max_entries = __NR_CPUS__,
 };
 SEC("func_write=sys_write")
 int func_write(void *ctx)
 {
     unsigned long long val;
     char fmt[] = "sys_write:        pmu=%llu\n";
     val = bpf_perf_event_read(&pmu_map, bpf_get_smp_processor_id());
     bpf_trace_printk(fmt, sizeof(fmt), val);
     return 0;
 }

 SEC("func_write_return=sys_write%return")
 int func_write_return(void *ctx)
 {
     unsigned long long val = 0;
     char fmt[] = "sys_write_return: pmu=%llu\n";
     val = bpf_perf_event_read(&pmu_map, bpf_get_smp_processor_id());
     bpf_trace_printk(fmt, sizeof(fmt), val);
     return 0;
 }
 char _license[] SEC("license") = "GPL";
 int _version SEC("version") = LINUX_VERSION_CODE;
 /************************* END ***************************/

Normal case 1:
 # echo "" > /sys/kernel/debug/tracing/trace
 # ./perf record -e evt=cycles/no-inherit/ -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' ls /
 [SNIP]
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.013 MB perf.data (7 samples) ]
 # cat /sys/kernel/debug/tracing/trace | grep ls
               ls-13865 [006] d... 2722740.933204: : sys_write:        pmu=1121685
               ls-13865 [006] dN.. 2722740.933242: : sys_write_return: pmu=1178149
               ls-13865 [006] d... 2722740.933248: : sys_write:        pmu=1194986
               ls-13865 [006] dN.. 2722740.933270: : sys_write_return: pmu=1220862

Normal case 2:
 # echo "" > /sys/kernel/debug/tracing/trace
 # ./perf record -e evt=cycles/period=0x7fffffffffffffff,no-inherit/ \
                 -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' ls /
 [SNIP]
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.013 MB perf.data ]
 # ./perf report --stdio
 Error:
 The perf.data file has no samples!

 (This is expected because we set period of cycles to a very large
 value to period of cycles event because we want to use this event
 as a counter only, don't need sampling)

 # cat /sys/kernel/debug/tracing/trace | grep ls
               ls-14446 [006] d... 2722976.486458: : sys_write:        pmu=1116233
               ls-14446 [006] dN.. 2722976.486486: : sys_write_return: pmu=1162108
               ls-14446 [006] d... 2722976.486491: : sys_write:        pmu=1177122
               ls-14446 [006] dN.. 2722976.486511: : sys_write_return: pmu=1202417

Normal case 3:
 # echo "" > /sys/kernel/debug/tracing/trace
 # ./perf record -i -e cycles -e './test_bpf_map_2.c/maps:pmu_map.event=cycles/' ls /

 (When doesn't explicitly set alias, event name can be used to search events)

 [SNIP]
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.013 MB perf.data (7 samples) ]
 # cat /sys/kernel/debug/tracing/trace | grep ls
               ls-16480 [005] d... 2724143.955040: : sys_write:        pmu=1150794
               ls-16480 [005] dN.. 2724143.955077: : sys_write_return: pmu=1207161
               ls-16480 [005] d... 2724143.955083: : sys_write:        pmu=1219145
               ls-16480 [005] dN.. 2724143.955104: : sys_write_return: pmu=1245433

Normal case 4 (one thread case):
 # ls /proc/11808/task/
 11808
 # echo "" > /sys/kernel/debug/tracing/trace
 # ./perf record -e evt=cycles/no-inherit/ -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' -p 11808
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.019 MB perf.data (2 samples) ]

 # cat /sys/kernel/debug/tracing/trace | grep 11808
             sshd-11808 [000] d... 2740454.781150: : sys_write:        pmu=18446744073709551594
             sshd-11808 [000] d... 2740454.781168: : sys_write_return: pmu=18446744073709551594
             sshd-11808 [003] d... 2740467.411799: : sys_write:        pmu=131031
             sshd-11808 [003] dN.. 2740467.411806: : sys_write_return: pmu=161549
             sshd-11808 [003] d... 2740467.411834: : sys_write:        pmu=210269

Normal case 5 (system wide):
 # echo "" > /sys/kernel/debug/tracing/trace
 # ./perf record -e evt=cycles/no-inherit/ -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' -a
 ^C[ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.811 MB perf.data (120 samples) ]

 # cat /sys/kernel/debug/tracing/trace | grep -v '18446744073709551594' | grep -v perf | head -n 20
 [SNIP]
 #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
 #              | |       |   ||||       |         |
            gmain-30828 [002] d... 2740551.068992: : sys_write:        pmu=84373
            gmain-30828 [002] d... 2740551.068992: : sys_write_return: pmu=87696
            gmain-30828 [002] d... 2740551.068996: : sys_write:        pmu=100658
            gmain-30828 [002] d... 2740551.068997: : sys_write_return: pmu=102572

Error case 1:

 # ./perf record -e './test_bpf_map_2.c' ls /
 [SNIP]
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.014 MB perf.data ]
 # cat /sys/kernel/debug/tracing/trace | grep ls
               ls-17115 [007] d... 2724279.665625: : sys_write:        pmu=18446744073709551614
               ls-17115 [007] dN.. 2724279.665651: : sys_write_return: pmu=18446744073709551614
               ls-17115 [007] d... 2724279.665658: : sys_write:        pmu=18446744073709551614
               ls-17115 [007] dN.. 2724279.665677: : sys_write_return: pmu=18446744073709551614

 (18446744073709551614 is 0xfffffffffffffffe (-2))

Error case 2:
 # ./perf record -e cycles -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' -a
 event syntax error: '..ps:pmu_map.event=evt/'
                                   \___ Event not found for map setting

 Hint:	Valid config terms:
      	maps:[<arraymap>].value=[value]
      	maps:[<eventmap>].event=[event]
 [SNIP]

Error case 3:
 # ls /proc/2342/task/
 2342  2373  2374  2375  2376
 # ./perf record -e evt=cycles/no-inherit/ -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' -p 2342
 ERROR: Apply config to BPF failed: Cannot set event to BPF maps in multi-thread tracing

Error case 4:
 # ./perf record -e cycles -e './test_bpf_map_2.c/maps:pmu_map.event=cycles/' ls /
 ERROR: Apply config to BPF failed: Doesn't support inherit event (Hint: use /no-inherit/ config term or use -i)

Error case 5:
 # ./perf record -e evt=raw_syscalls:sys_enter/no-inherit/ -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' ls
 ERROR: Apply config to BPF failed: Can only put raw, hardware and BPF output event into a BPF map

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/bpf-loader.c   | 138 ++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/bpf-loader.h   |   5 ++
 tools/perf/util/parse-events.c |   4 +-
 3 files changed, 145 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 96fd18b..97f5efc 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -742,6 +742,7 @@ int bpf__foreach_tev(struct bpf_object *obj,
 
 enum bpf_map_op_type {
 	BPF_MAP_OP_SET_VALUE,
+	BPF_MAP_OP_SET_EVSEL,
 };
 
 enum bpf_map_key_type {
@@ -754,6 +755,7 @@ struct bpf_map_op {
 	enum bpf_map_key_type key_type;
 	union {
 		u64 value;
+		struct perf_evsel *evsel;
 	} v;
 };
 
@@ -891,10 +893,73 @@ bpf__obj_config_map_value(struct bpf_map *map,
 	if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
 		return bpf__obj_config_map_array_value(map, term);
 
-	pr_debug("ERROR: wrong value type\n");
+	pr_debug("ERROR: wrong value type for 'value'\n");
 	return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE;
 }
 
+static int
+bpf__obj_config_map_array_event(struct bpf_map *map,
+				struct parse_events_term *term,
+				struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel;
+	struct bpf_map_def def;
+	struct bpf_map_op *op;
+	const char *map_name;
+	int err;
+
+	map_name = bpf_map__get_name(map);
+	evsel = perf_evlist__find_evsel_by_alias(evlist, term->val.str);
+	if (!evsel) {
+		pr_debug("Event (for '%s') '%s' doesn't exist\n",
+			 map_name, term->val.str);
+		return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT;
+	}
+
+	err = bpf_map__get_def(map, &def);
+	if (err) {
+		pr_debug("Unable to get map definition from '%s'\n",
+			 map_name);
+		return err;
+	}
+
+	/*
+	 * No need to check key_size and value_size:
+	 * kernel has already checked them.
+	 */
+	if (def.type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
+		pr_debug("Map %s type is not BPF_MAP_TYPE_PERF_EVENT_ARRAY\n",
+			 map_name);
+		return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
+	}
+
+	op = bpf_map_op__alloc(map);
+	if (IS_ERR(op))
+		return PTR_ERR(op);
+
+	op->v.evsel = evsel;
+	op->op_type = BPF_MAP_OP_SET_EVSEL;
+	return 0;
+}
+
+static int
+bpf__obj_config_map_event(struct bpf_map *map,
+			  struct parse_events_term *term,
+			  struct perf_evlist *evlist)
+{
+	if (!term->err_val) {
+		pr_debug("Config value not set\n");
+		return -BPF_LOADER_ERRNO__OBJCONF_CONF;
+	}
+
+	if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
+		return bpf__obj_config_map_array_event(map, term, evlist);
+
+	pr_debug("ERROR: wrong value type for 'event'\n");
+	return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE;
+}
+
+
 struct bpf_obj_config_map_func {
 	const char *config_opt;
 	int (*config_func)(struct bpf_map *, struct parse_events_term *,
@@ -903,6 +968,7 @@ struct bpf_obj_config_map_func {
 
 struct bpf_obj_config_map_func bpf_obj_config_map_funcs[] = {
 	{"value", bpf__obj_config_map_value},
+	{"event", bpf__obj_config_map_event},
 };
 
 static int
@@ -1047,6 +1113,7 @@ bpf_map_config_foreach_key(struct bpf_map *map,
 	list_for_each_entry(op, &priv->ops_list, list) {
 		switch (def.type) {
 		case BPF_MAP_TYPE_ARRAY:
+		case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
 			switch (op->key_type) {
 			case BPF_MAP_KEY_ALL:
 				return foreach_key_array_all(func, arg, name,
@@ -1101,6 +1168,60 @@ apply_config_value_for_key(int map_fd, void *pkey,
 }
 
 static int
+apply_config_evsel_for_key(const char *name, int map_fd, void *pkey,
+			   struct perf_evsel *evsel)
+{
+	struct xyarray *xy = evsel->fd;
+	struct perf_event_attr *attr;
+	unsigned int key, events;
+	bool check_pass = false;
+	int *evt_fd;
+	int err;
+
+	if (!xy) {
+		pr_debug("ERROR: evsel not ready for map %s\n", name);
+		return -BPF_LOADER_ERRNO__INTERNAL;
+	}
+
+	if (xy->row_size / xy->entry_size != 1) {
+		pr_debug("ERROR: Dimension of target event is incorrect for map %s\n",
+			 name);
+		return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM;
+	}
+
+	attr = &evsel->attr;
+	if (attr->inherit) {
+		pr_debug("ERROR: Can't put inherit event into map %s\n", name);
+		return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH;
+	}
+
+	if (attr->type == PERF_TYPE_RAW)
+		check_pass = true;
+	if (attr->type == PERF_TYPE_HARDWARE)
+		check_pass = true;
+	if (attr->type == PERF_TYPE_SOFTWARE &&
+			attr->config == PERF_COUNT_SW_BPF_OUTPUT)
+		check_pass = true;
+	if (!check_pass) {
+		pr_debug("ERROR: Event type is wrong for map %s\n", name);
+		return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE;
+	}
+
+	events = xy->entries / (xy->row_size / xy->entry_size);
+	key = *((unsigned int *)pkey);
+	if (key >= events) {
+		pr_debug("ERROR: there is no event %d for map %s\n",
+			 key, name);
+		return -BPF_LOADER_ERRNO__OBJCONF_MAP_MAPSIZE;
+	}
+	evt_fd = xyarray__entry(xy, key, 0);
+	err = bpf_map_update_elem(map_fd, pkey, evt_fd, BPF_ANY);
+	if (err && errno)
+		err = -errno;
+	return err;
+}
+
+static int
 apply_obj_config_map_for_key(const char *name, int map_fd,
 			     struct bpf_map_def *pdef __maybe_unused,
 			     struct bpf_map_op *op,
@@ -1114,6 +1235,10 @@ apply_obj_config_map_for_key(const char *name, int map_fd,
 						 pdef->value_size,
 						 op->v.value);
 		break;
+	case BPF_MAP_OP_SET_EVSEL:
+		err = apply_config_evsel_for_key(name, map_fd, pkey,
+						 op->v.evsel);
+		break;
 	default:
 		pr_debug("ERROR: unknown value type for '%s'\n", name);
 		err = -BPF_LOADER_ERRNO__INTERNAL;
@@ -1179,6 +1304,11 @@ static const char *bpf_loader_strerror_table[NR_ERRNO] = {
 	[ERRCODE_OFFSET(OBJCONF_MAP_TYPE)]	= "Incorrect map type",
 	[ERRCODE_OFFSET(OBJCONF_MAP_KEYSIZE)]	= "Incorrect map key size",
 	[ERRCODE_OFFSET(OBJCONF_MAP_VALUESIZE)]	= "Incorrect map value size",
+	[ERRCODE_OFFSET(OBJCONF_MAP_NOEVT)]	= "Event not found for map setting",
+	[ERRCODE_OFFSET(OBJCONF_MAP_MAPSIZE)]	= "Invalid map size for event setting",
+	[ERRCODE_OFFSET(OBJCONF_MAP_EVTDIM)]	= "Event dimension too large",
+	[ERRCODE_OFFSET(OBJCONF_MAP_EVTINH)]	= "Doesn't support inherit event",
+	[ERRCODE_OFFSET(OBJCONF_MAP_EVTTYPE)]	= "Wrong event type for map",
 };
 
 static int
@@ -1315,6 +1445,12 @@ int bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused,
 int bpf__strerror_apply_obj_config(int err, char *buf, size_t size)
 {
 	bpf__strerror_head(err, buf, size);
+	bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM,
+			    "Cannot set event to BPF maps in multi-thread tracing");
+	bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH,
+			    "%s (Hint: use /no-inherit/ config term or use -i)", emsg);
+	bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE,
+			    "Can only put raw, hardware and BPF output event into a BPF map");
 	bpf__strerror_end(buf, size);
 	return 0;
 }
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index db3c34c..c9ce792 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -33,6 +33,11 @@ enum bpf_loader_errno {
 	BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE,	/* Incorrect map type */
 	BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE,	/* Incorrect map key size */
 	BPF_LOADER_ERRNO__OBJCONF_MAP_VALUESIZE,/* Incorrect map value size */
+	BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT,	/* Event not found for map setting */
+	BPF_LOADER_ERRNO__OBJCONF_MAP_MAPSIZE,	/* Invalid map size for event setting */
+	BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM,	/* Event dimension too large */
+	BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH,	/* Doesn't support inherit event */
+	BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE,	/* Wrong event type for map */
 	__BPF_LOADER_ERRNO__END,
 };
 
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 484c8e4..5d682dd 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -659,8 +659,10 @@ parse_events_config_bpf(struct parse_events_evlist *data,
 						 &error_pos, err, errbuf,
 						 sizeof(errbuf));
 			data->error->help = strdup(
-"Hint:\tValid config term:\n"
+"Hint:\tValid config terms:\n"
 "     \tmaps:[<arraymap>].value=[value]\n"
+"     \tmaps:[<eventmap>].event=[event]\n"
+"\n"
 "     \t(add -v to see detail)");
 			data->error->str = strdup(errbuf);
 			if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286160 — [PATCH v4 12/16] perf data: Support converting data from bpf_perf_event_output()

FromWang Nan <wangnan0@huawei.com>
Date2015-12-08 03:30 +0100
Subject[PATCH v4 12/16] perf data: Support converting data from bpf_perf_event_output()
Message-ID<qDgcq-4Bz-25@gated-at.bofh.it>
In reply to#1286157
bpf_perf_event_output() outputs data through sample->raw_data. This
patch adds support to convert those data into CTF. A python script
then can be used to process output data from BPF programs.

Test result:

 # cat ./test_bpf_output.c
 /************************ BEGIN **************************/
 typedef int u32;
 typedef unsigned long long u64;

 enum bpf_map_type {
     BPF_MAP_TYPE_PERF_EVENT_ARRAY = 4,
 };

 struct bpf_map_def {
     unsigned int type;
     unsigned int key_size;
     unsigned int value_size;
     unsigned int max_entries;
 };
 #define SEC(NAME) __attribute__((section(NAME), used))
 static u64 (*bpf_ktime_get_ns)(void) =
     (void *)5;
 static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
     (void *)6;
 static int (*bpf_get_smp_processor_id)(void) =
     (void *)8;
 static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int, void *, unsigned long) =
     (void *)23;
 struct bpf_map_def SEC("maps") channel = {
     .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
     .key_size = sizeof(int),
     .value_size = sizeof(u32),
     .max_entries = __NR_CPUS__,
 };
 static inline int __attribute__((always_inline))
 func(void *ctx, int type)
 {
     struct {
         u64 ktime;
         int type;
     } __attribute__((packed)) output_data;
     char error_data[] = "Error: failed to output\n";
     int err;
     output_data.type = type;
     output_data.ktime = bpf_ktime_get_ns();
     err = bpf_perf_event_output(ctx, &channel, bpf_get_smp_processor_id(),
                     &output_data, sizeof(output_data));
     if (err)
         bpf_trace_printk(error_data, sizeof(error_data));
     return 0;
 }
 SEC("func_begin=sys_nanosleep")
 int func_begin(void *ctx) {return func(ctx, 1);}
 SEC("func_end=sys_nanosleep%return")
 int func_end(void *ctx) { return func(ctx, 2);}
 char _license[] SEC("license") = "GPL";
 int _version SEC("version") = LINUX_VERSION_CODE;
 /************************ END ***************************/

 # ./perf record -e evt=bpf-output/no-inherit/ \
                 -e ./test_bpf_output_2.c/maps:channel.event=evt/ \
                 usleep 100000
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.012 MB perf.data (2 samples) ]

 # ./perf script
          usleep 14942 92503.198504: evt=bpf-output/no-inherit/:  ffffffff810e0ba1 sys_nanosleep (/lib/modules/4.3.0....
          usleep 14942 92503.298562: evt=bpf-output/no-inherit/:  ffffffff810585e9 kretprobe_trampoline_holder (/lib....

 # ./perf data convert --to-ctf ./out.ctf
 [ perf data convert: Converted 'perf.data' into CTF data './out.ctf' ]
 [ perf data convert: Converted and wrote 0.000 MB (2 samples) ]

 # babeltrace ./out.ctf
 [01:41:43.198504134] (+?.?????????) evt=bpf-output/no-inherit/: { cpu_id = 0 }, { perf_ip = 0xFFFFFFFF810E0BA1, perf_tid = 14942, perf_pid = 14942, perf_id = 1044, raw_len = 3, raw_data = [ [0] = 0x32C0C07B, [1] = 0x5421, [2] = 0x1 ] }
 [01:41:43.298562257] (+0.100058123) evt=bpf-output/no-inherit/: { cpu_id = 0 }, { perf_ip = 0xFFFFFFFF810585E9, perf_tid = 14942, perf_pid = 14942, perf_id = 1044, raw_len = 3, raw_data = [ [0] = 0x38B77FAA, [1] = 0x5421, [2] = 0x2 ] }

 # cat ./test_bpf_output_2.py
 from babeltrace import TraceCollection
 tc = TraceCollection(
 tc.add_trace('./out.ctf', 'ctf')
 d = {1:[], 2:[]}
 for event in tc.events:
     if not event.name.startswith('evt=bpf-output/no-inherit/'):
         continue
     raw_data = event['raw_data']
     (time, type) = ((raw_data[0] + (raw_data[1] << 32)), raw_data[2])
     d[type].append(time)
 print(list(map(lambda i: d[2][i] - d[1][i], range(len(d[1]))))));

 # python3 ./test_bpf_output_2.py
 [100056879]

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/data-convert-bt.c | 115 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 114 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 34cd1e4..1fb472b 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -352,6 +352,84 @@ static int add_tracepoint_values(struct ctf_writer *cw,
 	return ret;
 }
 
+static int
+add_bpf_output_values(struct bt_ctf_event_class *event_class,
+		      struct bt_ctf_event *event,
+		      struct perf_sample *sample)
+{
+	struct bt_ctf_field_type *len_type, *seq_type;
+	struct bt_ctf_field *len_field, *seq_field;
+	unsigned int raw_size = sample->raw_size;
+	unsigned int nr_elements = raw_size / sizeof(u32);
+	unsigned int i;
+	int ret;
+
+	if (nr_elements * sizeof(u32) != raw_size)
+		pr_warning("Incorrect raw_size (%u) in bpf output event, skip %lu bytes\n",
+			   raw_size, nr_elements * sizeof(u32) - raw_size);
+
+	len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
+	len_field = bt_ctf_field_create(len_type);
+	if (!len_field) {
+		pr_err("failed to create 'raw_len' for bpf output event\n");
+		ret = -1;
+		goto put_len_type;
+	}
+
+	ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
+	if (ret) {
+		pr_err("failed to set field value for raw_len\n");
+		goto put_len_field;
+	}
+	ret = bt_ctf_event_set_payload(event, "raw_len", len_field);
+	if (ret) {
+		pr_err("failed to set payload to raw_len\n");
+		goto put_len_field;
+	}
+
+	seq_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_data");
+	seq_field = bt_ctf_field_create(seq_type);
+	if (!seq_field) {
+		pr_err("failed to create 'raw_data' for bpf output event\n");
+		ret = -1;
+		goto put_seq_type;
+	}
+
+	ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
+	if (ret) {
+		pr_err("failed to set length of 'raw_data'\n");
+		goto put_seq_field;
+	}
+
+	for (i = 0; i < nr_elements; i++) {
+		struct bt_ctf_field *elem_field =
+			bt_ctf_field_sequence_get_field(seq_field, i);
+
+		ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
+				((u32 *)(sample->raw_data))[i]);
+
+		bt_ctf_field_put(elem_field);
+		if (ret) {
+			pr_err("failed to set raw_data[%d]\n", i);
+			goto put_seq_field;
+		}
+	}
+
+	ret = bt_ctf_event_set_payload(event, "raw_data", seq_field);
+	if (ret)
+		pr_err("failed to set payload for raw_data\n");
+
+put_seq_field:
+	bt_ctf_field_put(seq_field);
+put_seq_type:
+	bt_ctf_field_type_put(seq_type);
+put_len_field:
+	bt_ctf_field_put(len_field);
+put_len_type:
+	bt_ctf_field_type_put(len_type);
+	return ret;
+}
+
 static int add_generic_values(struct ctf_writer *cw,
 			      struct bt_ctf_event *event,
 			      struct perf_evsel *evsel,
@@ -597,6 +675,13 @@ static int process_sample_event(struct perf_tool *tool,
 			return -1;
 	}
 
+	if ((evsel->attr.type == PERF_TYPE_SOFTWARE) &&
+	    (evsel->attr.config == PERF_COUNT_SW_BPF_OUTPUT)) {
+		ret = add_bpf_output_values(event_class, event, sample);
+		if (ret)
+			return -1;
+	}
+
 	cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
 	if (cs) {
 		if (is_flush_needed(cs))
@@ -744,6 +829,25 @@ static int add_tracepoint_types(struct ctf_writer *cw,
 	return ret;
 }
 
+static int add_bpf_output_types(struct ctf_writer *cw,
+				struct bt_ctf_event_class *class)
+{
+	struct bt_ctf_field_type *len_type = cw->data.u32;
+	struct bt_ctf_field_type *seq_base_type = cw->data.u32_hex;
+	struct bt_ctf_field_type *seq_type;
+	int ret;
+
+	ret = bt_ctf_event_class_add_field(class, len_type, "raw_len");
+	if (ret)
+		return ret;
+
+	seq_type = bt_ctf_field_type_sequence_create(seq_base_type, "raw_len");
+	if (!seq_type)
+		return -1;
+
+	return bt_ctf_event_class_add_field(class, seq_type, "raw_data");
+}
+
 static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
 			     struct bt_ctf_event_class *event_class)
 {
@@ -755,7 +859,8 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
 	 *                              ctf event header
 	 *   PERF_SAMPLE_READ         - TODO
 	 *   PERF_SAMPLE_CALLCHAIN    - TODO
-	 *   PERF_SAMPLE_RAW          - tracepoint fields are handled separately
+	 *   PERF_SAMPLE_RAW          - tracepoint fields and BPF output
+	 *                              are handled separately
 	 *   PERF_SAMPLE_BRANCH_STACK - TODO
 	 *   PERF_SAMPLE_REGS_USER    - TODO
 	 *   PERF_SAMPLE_STACK_USER   - TODO
@@ -824,6 +929,14 @@ static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
 			goto err;
 	}
 
+	if ((evsel->attr.type == PERF_TYPE_SOFTWARE) &&
+	    (evsel->attr.config == PERF_COUNT_SW_BPF_OUTPUT)) {
+		ret = add_bpf_output_types(cw, event_class);
+		if (ret)
+			goto err;
+
+	}
+
 	ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
 	if (ret) {
 		pr("Failed to add event class into stream.\n");
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286161 — [PATCH v4 14/16] perf record: Support custom vmlinux path

FromWang Nan <wangnan0@huawei.com>
Date2015-12-08 03:30 +0100
Subject[PATCH v4 14/16] perf record: Support custom vmlinux path
Message-ID<qDgcq-4Bz-27@gated-at.bofh.it>
In reply to#1286157
From: He Kuang <hekuang@huawei.com>

Make perf-record command support --vmlinux option if BPF_PROLOGUE is on.

'perf record' needs vmlinux as the source of DWARF info to generate
prologue for BPF programs, so path of vmlinux should be specified.

Short name 'k' has been taken by 'clockid'. This patch skips the short
option name and use '--vmlinux' for vmlinux path.

Documentation is also updated.

Test result:

In a production (or broken) environment:
 (built by
  # rm -rf ~/.debug/
  # mv /lib/modules/`uname -r`/build/vmlinux /tmp/
 )

 # ./perf record -e ./test_bpf_base.c ls
 Failed to find the path for kernel: No such file or directory
 event syntax error: './test_bpf_base.c'
                      \___ You need to check probing points in BPF file
 ...

 # ./perf record --vmlinux /tmp/vmlinux -e ./test_bpf_base.c ls
 ...
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.011 MB perf.data ]

Help messages when build with NO_LIBBPF:

 # ./perf record -h
        --transaction     sample transaction flags (special events only)
        --vmlinux <file>  vmlinux pathname
                          (not build because NO_LIBBPF=1)
 # ./perf record --vmlinux /tmp/vmlinux ls /
  Warning: option `vmlinux' is not built because NO_LIBBPF=1
 ...
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.011 MB perf.data (11 samples) ]

Help messages when build with NO_DWARF:

 # ./perf record -h
        --transaction     sample transaction flags (special events only)
        --vmlinux <file>  vmlinux pathname
                          (not build because NO_DWARF=1)

Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/Documentation/perf-record.txt | 10 ++++++++--
 tools/perf/builtin-record.c              | 16 ++++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index e630a7d..8d032f4 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -314,11 +314,17 @@ This option sets the time out limit. The default value is 500 ms.
 Record context switch events i.e. events of type PERF_RECORD_SWITCH or
 PERF_RECORD_SWITCH_CPU_WIDE.
 
---clang-path::
+--clang-path=PATH::
 Path to clang binary to use for compiling BPF scriptlets.
+(enabled when BPF support is on)
 
---clang-opt::
+--clang-opt=OPTIONS::
 Options passed to clang when compiling BPF scriptlets.
+(enabled when BPF support is on)
+
+--vmlinux=PATH::
+Specify vmlinux path which has debuginfo.
+(enabled when BPF prologue is on)
 
 SEE ALSO
 --------
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 11bf32d..2230b85 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1128,6 +1128,8 @@ struct option __record_options[] = {
 		   "clang binary to use for compiling BPF scriptlets"),
 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
 		   "options passed to clang when compiling BPF scriptlets"),
+	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
+		   "file", "vmlinux pathname"),
 	OPT_END()
 };
 
@@ -1146,6 +1148,20 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 # undef set_nobuild
 #endif
 
+#ifndef HAVE_BPF_PROLOGUE
+# if !defined (HAVE_DWARF_SUPPORT)
+#  define REASON  "NO_DWARF=1"
+# elif !defined (HAVE_LIBBPF_SUPPORT)
+#  define REASON  "NO_LIBBPF=1"
+# else
+#  define REASON  "this architecture doesn't support BPF prologue"
+# endif
+# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
+	set_nobuild('\0', "vmlinux", true);
+# undef set_nobuild
+# undef REASON
+#endif
+
 	rec->evlist = perf_evlist__new();
 	if (rec->evlist == NULL)
 		return -ENOMEM;
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286162 — [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

FromWang Nan <wangnan0@huawei.com>
Date2015-12-08 03:30 +0100
Subject[PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qDgcq-4Bz-31@gated-at.bofh.it>
In reply to#1286157
This patch introduce a new syntax to perf event parser:

 # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...

By utilizing the basic facilities in bpf-loader.c which allow setting
different slots in a BPF map separately, the newly introduced syntax
allows perf to control specific elements in a BPF map.

Test result:

 # cat ./test_bpf_map_3.c
 /************************ BEGIN **************************/
 #define SEC(NAME) __attribute__((section(NAME), used))
 enum bpf_map_type {
     BPF_MAP_TYPE_ARRAY = 2,
 };
 struct bpf_map_def {
     unsigned int type;
     unsigned int key_size;
     unsigned int value_size;
     unsigned int max_entries;
 };
 static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
     (void *)1;
 static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
     (void *)6;
 struct bpf_map_def SEC("maps") channel = {
     .type = BPF_MAP_TYPE_ARRAY,
     .key_size = sizeof(int),
     .value_size = sizeof(unsigned char),
     .max_entries = 100,
 };
 SEC("func=hrtimer_nanosleep rqtp->tv_nsec")
 int func(void *ctx, int err, long nsec)
 {
     char fmt[] = "%ld\n";
     long usec = nsec * 0x10624dd3 >> 38; // nsec / 1000
     int key = (int)usec;
     unsigned char *pval = map_lookup_elem(&channel, &key);

     if (!pval)
         return 0;
     bpf_trace_printk(fmt, sizeof(fmt), (unsigned char)*pval);
     return 0;
 }
 char _license[] SEC("license") = "GPL";
 int _version SEC("version") = LINUX_VERSION_CODE;
 /************************* END ***************************/

Normal case:
 # echo "" > /sys/kernel/debug/tracing/trace
 # ./perf record -e './test_bpf_map_3.c/maps:channel.value[0,1,2,3...5]=101/' usleep 2
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.012 MB perf.data ]
 # cat /sys/kernel/debug/tracing/trace | grep usleep
           usleep-405   [004] d... 2745423.547822: : 101
 # ./perf record -e './test_bpf_map_3.c/maps:channel.value[0...9,20...29]=102,maps:channel.value[10...19]=103/' usleep 3
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.012 MB perf.data ]
 # ./perf record -e './test_bpf_map_3.c/maps:channel.value[0...9,20...29]=102,maps:channel.value[10...19]=103/' usleep 15
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.012 MB perf.data ]
 # cat /sys/kernel/debug/tracing/trace | grep usleep
           usleep-405   [004] d... 2745423.547822: : 101
           usleep-655   [006] d... 2745434.122814: : 102
           usleep-904   [006] d... 2745439.916264: : 103
 # ./perf record -e './test_bpf_map_3.c/maps:channel.value[all]=104/' usleep 99
 # cat /sys/kernel/debug/tracing/trace | grep usleep
           usleep-405   [004] d... 2745423.547822: : 101
           usleep-655   [006] d... 2745434.122814: : 102
           usleep-904   [006] d... 2745439.916264: : 103
           usleep-1537  [003] d... 2745538.053737: : 104

Error case:
 # ./perf record -e './test_bpf_map_3.c/maps:channel.value[10...1000]=104/' usleep 99
 event syntax error: '..annel.value[10...1000]=104/'
                                   \___ Index too large
 Hint:	Valid config terms:
      	maps:[<arraymap>].value<indices>=[value]
      	maps:[<eventmap>].event<indices>=[event]

      	where <indices> is something like [0,3...5] or [all]
      	(add -v to see detail)
 Run 'perf list' for a list of valid events

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

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

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/parse-events.c |  5 ++-
 tools/perf/util/parse-events.l | 13 ++++++-
 tools/perf/util/parse-events.y | 85 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index af3d657..abdf551 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -660,9 +660,10 @@ parse_events_config_bpf(struct parse_events_evlist *data,
 						 sizeof(errbuf));
 			data->error->help = strdup(
 "Hint:\tValid config terms:\n"
-"     \tmaps:[<arraymap>].value=[value]\n"
-"     \tmaps:[<eventmap>].event=[event]\n"
+"     \tmaps:[<arraymap>].value<indices>=[value]\n"
+"     \tmaps:[<eventmap>].event<indices>=[event]\n"
 "\n"
+"     \twhere <indices> is something like [0,3...5] or [all]\n"
 "     \t(add -v to see detail)");
 			data->error->str = strdup(errbuf);
 			if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 4387728..8bb3437 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -9,8 +9,8 @@
 %{
 #include <errno.h>
 #include "../perf.h"
-#include "parse-events-bison.h"
 #include "parse-events.h"
+#include "parse-events-bison.h"
 
 char *parse_events_get_text(yyscan_t yyscanner);
 YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
@@ -111,6 +111,7 @@ do {							\
 %x mem
 %s config
 %x event
+%x array
 
 group		[^,{}/]*[{][^}]*[}][^,{}/]*
 event_pmu	[^,{}/]+[/][^/]*[/][^,{}/]*
@@ -176,6 +177,14 @@ modifier_bp	[rwx]{1,3}
 
 }
 
+<array>{
+"]"			{ BEGIN(config); return ']'; }
+{num_dec}		{ return value(yyscanner, 10); }
+{num_hex}		{ return value(yyscanner, 16); }
+,			{ return ','; }
+"\.\.\."		{ return PE_ARRAY_RANGE; }
+}
+
 <config>{
 	/*
 	 * Please update parse_events_formats_error_string any time
@@ -196,6 +205,8 @@ no-inherit		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
 ,			{ return ','; }
 "/"			{ BEGIN(INITIAL); return '/'; }
 {name_minus}		{ return str(yyscanner, PE_NAME); }
+\[all\]			{ return PE_ARRAY_ALL; }
+"["			{ BEGIN(array); return '['; }
 }
 
 <mem>{
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index c3cbd7a..7e93b9f 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -48,6 +48,7 @@ static inc_group_count(struct list_head *list,
 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
 %token PE_ERROR
 %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
+%token PE_ARRAY_ALL PE_ARRAY_RANGE
 %type <num> PE_VALUE
 %type <num> PE_VALUE_SYM_HW
 %type <num> PE_VALUE_SYM_SW
@@ -84,6 +85,9 @@ static inc_group_count(struct list_head *list,
 %type <head> group_def
 %type <head> group
 %type <head> groups
+%type <array> array
+%type <array> array_term
+%type <array> array_terms
 
 %union
 {
@@ -95,6 +99,7 @@ static inc_group_count(struct list_head *list,
 		char *sys;
 		char *event;
 	} tracepoint_name;
+	struct parse_events_array array;
 }
 %%
 
@@ -601,6 +606,86 @@ PE_TERM
 	ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL));
 	$$ = term;
 }
+|
+PE_NAME array '=' PE_NAME
+{
+	struct parse_events_term *term;
+	int i;
+
+	ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
+					$1, $4, &@1, &@4));
+
+	term->array = $2;
+	$$ = term;
+}
+|
+PE_NAME array '=' PE_VALUE
+{
+	struct parse_events_term *term;
+
+	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+					$1, $4, &@1, &@4));
+	term->array = $2;
+	$$ = term;
+}
+
+array:
+'[' array_terms ']'
+{
+	$$ = $2;
+}
+|
+PE_ARRAY_ALL
+{
+	$$.nr_ranges = 0;
+	$$.ranges = NULL;
+}
+
+array_terms:
+array_terms ',' array_term
+{
+	struct parse_events_array new_array;
+
+	new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges;
+	new_array.ranges = malloc(sizeof(new_array.ranges[0]) *
+				  new_array.nr_ranges);
+	ABORT_ON(!new_array.ranges);
+	memcpy(&new_array.ranges[0], $1.ranges,
+	       $1.nr_ranges * sizeof(new_array.ranges[0]));
+	memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges,
+	       $3.nr_ranges * sizeof(new_array.ranges[0]));
+	free($1.ranges);
+	free($3.ranges);
+	$$ = new_array;
+}
+|
+array_term
+
+array_term:
+PE_VALUE
+{
+	struct parse_events_array array;
+
+	array.nr_ranges = 1;
+	array.ranges = malloc(sizeof(array.ranges[0]));
+	ABORT_ON(!array.ranges);
+	array.ranges[0].start = $1;
+	array.ranges[0].length = 1;
+	$$ = array;
+}
+|
+PE_VALUE PE_ARRAY_RANGE PE_VALUE
+{
+	struct parse_events_array array;
+
+	ABORT_ON($3 < $1);
+	array.nr_ranges = 1;
+	array.ranges = malloc(sizeof(array.ranges[0]));
+	ABORT_ON(!array.ranges);
+	array.ranges[0].start = $1;
+	array.ranges[0].length = $3 - $1 + 1;
+	$$ = array;
+}
 
 sep_dc: ':' |
 
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1289512 — Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2015-12-11 13:20 +0100
SubjectRe: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qEuQ2-486-11@gated-at.bofh.it>
In reply to#1286162
Em Tue, Dec 08, 2015 at 02:25:37AM +0000, Wang Nan escreveu:
> This patch introduce a new syntax to perf event parser:
> 
>  # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...

Is the above example valid? Wouldn't this be "maps:mymap.value" ?

> 
> By utilizing the basic facilities in bpf-loader.c which allow setting
> different slots in a BPF map separately, the newly introduced syntax
> allows perf to control specific elements in a BPF map.
> 
> Test result:
> 
>  # cat ./test_bpf_map_3.c
>  /************************ BEGIN **************************/
>  #define SEC(NAME) __attribute__((section(NAME), used))
>  enum bpf_map_type {
>      BPF_MAP_TYPE_ARRAY = 2,
>  };
>  struct bpf_map_def {
>      unsigned int type;
>      unsigned int key_size;
>      unsigned int value_size;
>      unsigned int max_entries;
>  };
>  static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
>      (void *)1;
>  static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>      (void *)6;

Can you explain the above a bit more? What are the magic 1 and 6 values?

>  struct bpf_map_def SEC("maps") channel = {
>      .type = BPF_MAP_TYPE_ARRAY,
>      .key_size = sizeof(int),
>      .value_size = sizeof(unsigned char),
>      .max_entries = 100,
>  };

>  SEC("func=hrtimer_nanosleep rqtp->tv_nsec")
>  int func(void *ctx, int err, long nsec)
>  {
>      char fmt[] = "%ld\n";
>      long usec = nsec * 0x10624dd3 >> 38; // nsec / 1000
>      int key = (int)usec;
>      unsigned char *pval = map_lookup_elem(&channel, &key);

So that "mymap.value" name doesn't needs to be specified here?

> 
>      if (!pval)
>          return 0;
>      bpf_trace_printk(fmt, sizeof(fmt), (unsigned char)*pval);
>      return 0;
>  }
>  char _license[] SEC("license") = "GPL";
>  int _version SEC("version") = LINUX_VERSION_CODE;
>  /************************* END ***************************/
> 
> Normal case:
>  # echo "" > /sys/kernel/debug/tracing/trace
>  # ./perf record -e './test_bpf_map_3.c/maps:channel.value[0,1,2,3...5]=101/' usleep 2
>  [ perf record: Woken up 1 times to write data ]
>  [ perf record: Captured and wrote 0.012 MB perf.data ]
>  # cat /sys/kernel/debug/tracing/trace | grep usleep
>            usleep-405   [004] d... 2745423.547822: : 101
>  # ./perf record -e './test_bpf_map_3.c/maps:channel.value[0...9,20...29]=102,maps:channel.value[10...19]=103/' usleep 3
>  [ perf record: Woken up 1 times to write data ]
>  [ perf record: Captured and wrote 0.012 MB perf.data ]
>  # ./perf record -e './test_bpf_map_3.c/maps:channel.value[0...9,20...29]=102,maps:channel.value[10...19]=103/' usleep 15
>  [ perf record: Woken up 1 times to write data ]
>  [ perf record: Captured and wrote 0.012 MB perf.data ]
>  # cat /sys/kernel/debug/tracing/trace | grep usleep
>            usleep-405   [004] d... 2745423.547822: : 101
>            usleep-655   [006] d... 2745434.122814: : 102
>            usleep-904   [006] d... 2745439.916264: : 103
>  # ./perf record -e './test_bpf_map_3.c/maps:channel.value[all]=104/' usleep 99
>  # cat /sys/kernel/debug/tracing/trace | grep usleep
>            usleep-405   [004] d... 2745423.547822: : 101
>            usleep-655   [006] d... 2745434.122814: : 102
>            usleep-904   [006] d... 2745439.916264: : 103
>            usleep-1537  [003] d... 2745538.053737: : 104
> 
> Error case:
>  # ./perf record -e './test_bpf_map_3.c/maps:channel.value[10...1000]=104/' usleep 99
>  event syntax error: '..annel.value[10...1000]=104/'
>                                    \___ Index too large
>  Hint:	Valid config terms:
>       	maps:[<arraymap>].value<indices>=[value]
>       	maps:[<eventmap>].event<indices>=[event]
> 
>       	where <indices> is something like [0,3...5] or [all]
>       	(add -v to see detail)
>  Run 'perf list' for a list of valid events
> 
>   Usage: perf record [<options>] [<command>]
>      or: perf record [<options>] -- <command> [<options>]
> 
>      -e, --event <event>   event selector. use 'perf list' to list available events
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Zefan Li <lizefan@huawei.com>
> Cc: pi3orama@163.com
> ---
>  tools/perf/util/parse-events.c |  5 ++-
>  tools/perf/util/parse-events.l | 13 ++++++-
>  tools/perf/util/parse-events.y | 85 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 100 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
> index af3d657..abdf551 100644
> --- a/tools/perf/util/parse-events.c
> +++ b/tools/perf/util/parse-events.c
> @@ -660,9 +660,10 @@ parse_events_config_bpf(struct parse_events_evlist *data,
>  						 sizeof(errbuf));
>  			data->error->help = strdup(
>  "Hint:\tValid config terms:\n"
> -"     \tmaps:[<arraymap>].value=[value]\n"
> -"     \tmaps:[<eventmap>].event=[event]\n"
> +"     \tmaps:[<arraymap>].value<indices>=[value]\n"
> +"     \tmaps:[<eventmap>].event<indices>=[event]\n"
>  "\n"
> +"     \twhere <indices> is something like [0,3...5] or [all]\n"
>  "     \t(add -v to see detail)");
>  			data->error->str = strdup(errbuf);
>  			if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
> diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
> index 4387728..8bb3437 100644
> --- a/tools/perf/util/parse-events.l
> +++ b/tools/perf/util/parse-events.l
> @@ -9,8 +9,8 @@
>  %{
>  #include <errno.h>
>  #include "../perf.h"
> -#include "parse-events-bison.h"
>  #include "parse-events.h"
> +#include "parse-events-bison.h"
>  
>  char *parse_events_get_text(yyscan_t yyscanner);
>  YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
> @@ -111,6 +111,7 @@ do {							\
>  %x mem
>  %s config
>  %x event
> +%x array
>  
>  group		[^,{}/]*[{][^}]*[}][^,{}/]*
>  event_pmu	[^,{}/]+[/][^/]*[/][^,{}/]*
> @@ -176,6 +177,14 @@ modifier_bp	[rwx]{1,3}
>  
>  }
>  
> +<array>{
> +"]"			{ BEGIN(config); return ']'; }
> +{num_dec}		{ return value(yyscanner, 10); }
> +{num_hex}		{ return value(yyscanner, 16); }
> +,			{ return ','; }
> +"\.\.\."		{ return PE_ARRAY_RANGE; }
> +}
> +
>  <config>{
>  	/*
>  	 * Please update parse_events_formats_error_string any time
> @@ -196,6 +205,8 @@ no-inherit		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
>  ,			{ return ','; }
>  "/"			{ BEGIN(INITIAL); return '/'; }
>  {name_minus}		{ return str(yyscanner, PE_NAME); }
> +\[all\]			{ return PE_ARRAY_ALL; }
> +"["			{ BEGIN(array); return '['; }
>  }
>  
>  <mem>{
> diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
> index c3cbd7a..7e93b9f 100644
> --- a/tools/perf/util/parse-events.y
> +++ b/tools/perf/util/parse-events.y
> @@ -48,6 +48,7 @@ static inc_group_count(struct list_head *list,
>  %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
>  %token PE_ERROR
>  %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
> +%token PE_ARRAY_ALL PE_ARRAY_RANGE
>  %type <num> PE_VALUE
>  %type <num> PE_VALUE_SYM_HW
>  %type <num> PE_VALUE_SYM_SW
> @@ -84,6 +85,9 @@ static inc_group_count(struct list_head *list,
>  %type <head> group_def
>  %type <head> group
>  %type <head> groups
> +%type <array> array
> +%type <array> array_term
> +%type <array> array_terms
>  
>  %union
>  {
> @@ -95,6 +99,7 @@ static inc_group_count(struct list_head *list,
>  		char *sys;
>  		char *event;
>  	} tracepoint_name;
> +	struct parse_events_array array;
>  }
>  %%
>  
> @@ -601,6 +606,86 @@ PE_TERM
>  	ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL));
>  	$$ = term;
>  }
> +|
> +PE_NAME array '=' PE_NAME
> +{
> +	struct parse_events_term *term;
> +	int i;
> +
> +	ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
> +					$1, $4, &@1, &@4));
> +
> +	term->array = $2;
> +	$$ = term;
> +}
> +|
> +PE_NAME array '=' PE_VALUE
> +{
> +	struct parse_events_term *term;
> +
> +	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
> +					$1, $4, &@1, &@4));
> +	term->array = $2;
> +	$$ = term;
> +}
> +
> +array:
> +'[' array_terms ']'
> +{
> +	$$ = $2;
> +}
> +|
> +PE_ARRAY_ALL
> +{
> +	$$.nr_ranges = 0;
> +	$$.ranges = NULL;
> +}
> +
> +array_terms:
> +array_terms ',' array_term
> +{
> +	struct parse_events_array new_array;
> +
> +	new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges;
> +	new_array.ranges = malloc(sizeof(new_array.ranges[0]) *
> +				  new_array.nr_ranges);
> +	ABORT_ON(!new_array.ranges);
> +	memcpy(&new_array.ranges[0], $1.ranges,
> +	       $1.nr_ranges * sizeof(new_array.ranges[0]));
> +	memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges,
> +	       $3.nr_ranges * sizeof(new_array.ranges[0]));
> +	free($1.ranges);
> +	free($3.ranges);
> +	$$ = new_array;
> +}
> +|
> +array_term
> +
> +array_term:
> +PE_VALUE
> +{
> +	struct parse_events_array array;
> +
> +	array.nr_ranges = 1;
> +	array.ranges = malloc(sizeof(array.ranges[0]));
> +	ABORT_ON(!array.ranges);
> +	array.ranges[0].start = $1;
> +	array.ranges[0].length = 1;
> +	$$ = array;
> +}
> +|
> +PE_VALUE PE_ARRAY_RANGE PE_VALUE
> +{
> +	struct parse_events_array array;
> +
> +	ABORT_ON($3 < $1);
> +	array.nr_ranges = 1;
> +	array.ranges = malloc(sizeof(array.ranges[0]));
> +	ABORT_ON(!array.ranges);
> +	array.ranges[0].start = $1;
> +	array.ranges[0].length = $3 - $1 + 1;
> +	$$ = array;
> +}
>  
>  sep_dc: ':' |
>  
> -- 
> 1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1289515 — Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2015-12-11 13:20 +0100
SubjectRe: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qEuQ3-486-31@gated-at.bofh.it>
In reply to#1289512
Em Fri, Dec 11, 2015 at 09:11:45AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Tue, Dec 08, 2015 at 02:25:37AM +0000, Wang Nan escreveu:
> > This patch introduce a new syntax to perf event parser:
> > 
> >  # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...
> 
> Is the above example valid? Wouldn't this be "maps:mymap.value" ?
> 
> > 
> > By utilizing the basic facilities in bpf-loader.c which allow setting
> > different slots in a BPF map separately, the newly introduced syntax
> > allows perf to control specific elements in a BPF map.
> > 
> > Test result:
> > 
> >  # cat ./test_bpf_map_3.c
> >  /************************ BEGIN **************************/
> >  #define SEC(NAME) __attribute__((section(NAME), used))
> >  enum bpf_map_type {
> >      BPF_MAP_TYPE_ARRAY = 2,
> >  };
> >  struct bpf_map_def {
> >      unsigned int type;
> >      unsigned int key_size;
> >      unsigned int value_size;
> >      unsigned int max_entries;
> >  };
> >  static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
> >      (void *)1;
> >  static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
> >      (void *)6;
> 
> Can you explain the above a bit more? What are the magic 1 and 6 values?

So, from another patch:

 static u64 (*bpf_ktime_get_ns)(void) =
     (void *)5;
 static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
     (void *)6;
 static int (*bpf_get_smp_processor_id)(void) =
     (void *)8;
 static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
void *, unsigned long) =
     (void *)23;

Where can I get this magical mistery table? Could this be hidden away in
some .h file automagically included in bpf scriptlets so that n00bies
like me don't have to be wtf'ing?

- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1289528 — Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2015-12-11 13:50 +0100
SubjectRe: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qEvj4-4o4-9@gated-at.bofh.it>
In reply to#1289515
Em Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama escreveu:
> 
> 
> 发自我的 iPhone
> 
> > 在 2015年12月11日,下午8:15,Arnaldo Carvalho de Melo <acme@kernel.org> 写道:
> > 
> > Em Fri, Dec 11, 2015 at 09:11:45AM -0300, Arnaldo Carvalho de Melo escreveu:
> >> Em Tue, Dec 08, 2015 at 02:25:37AM +0000, Wang Nan escreveu:
> >>> This patch introduce a new syntax to perf event parser:
> >>> 
> >>> # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...
> >> 
> >> Is the above example valid? Wouldn't this be "maps:mymap.value" ?
> >> 
> >>> 
> >>> By utilizing the basic facilities in bpf-loader.c which allow setting
> >>> different slots in a BPF map separately, the newly introduced syntax
> >>> allows perf to control specific elements in a BPF map.
> >>> 
> >>> Test result:
> >>> 
> >>> # cat ./test_bpf_map_3.c
> >>> /************************ BEGIN **************************/
> >>> #define SEC(NAME) __attribute__((section(NAME), used))
> >>> enum bpf_map_type {
> >>>     BPF_MAP_TYPE_ARRAY = 2,
> >>> };
> >>> struct bpf_map_def {
> >>>     unsigned int type;
> >>>     unsigned int key_size;
> >>>     unsigned int value_size;
> >>>     unsigned int max_entries;
> >>> };
> >>> static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
> >>>     (void *)1;
> >>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
> >>>     (void *)6;
> >> 
> >> Can you explain the above a bit more? What are the magic 1 and 6 values?
> > 
> > So, from another patch:
> > 
> > static u64 (*bpf_ktime_get_ns)(void) =
> >     (void *)5;
> > static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
> >     (void *)6;
> > static int (*bpf_get_smp_processor_id)(void) =
> >     (void *)8;
> > static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
> > void *, unsigned long) =
> >     (void *)23;
> > 
> > Where can I get this magical mistery table? Could this be hidden away in
> > some .h file automagically included in bpf scriptlets so that n00bies
> > like me don't have to be wtf'ing?
> > 
> 
> They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
> headers. Directly include them causes many error for llvm. Also, the function
> prototypes are BPF specific and can't included in Linux source. We should have
> a place holds those indices and prototypes together.

Sure, just please don't assume whoever is reading your patches has this
background, provide comments above such places, so that reviewing gets
facilitated.

I eventually figured this is some sort of trampoline to access kernel
functions:

/* integer value in 'imm' field of BPF_CALL instruction selects which
 * helper function eBPF program intends to call
 */
enum bpf_func_id {
        BPF_FUNC_unspec,
        BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
        BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
        BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
        BPF_FUNC_probe_read,      /* int bpf_probe_read(void *dst, int size, void *src) */


But if you had just:

/*
 * See enum_bpf_func_id in ./include/uapi/linux/bpf.h
 */

That would've helped.

- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1289543 — Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

Frompi3orama <pi3orama@163.com>
Date2015-12-11 14:00 +0100
SubjectRe: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qEvsL-4sJ-35@gated-at.bofh.it>
In reply to#1289528

发自我的 iPhone

> 在 2015年12月11日,下午8:47,Arnaldo Carvalho de Melo <acme@kernel.org> 写道:
> 
> Em Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama escreveu:
>> 
>> 
>> 发自我的 iPhone
>> 
>>> 在 2015年12月11日,下午8:15,Arnaldo Carvalho de Melo <acme@kernel.org> 写道:
>>> 
>>> Em Fri, Dec 11, 2015 at 09:11:45AM -0300, Arnaldo Carvalho de Melo escreveu:
>>>> Em Tue, Dec 08, 2015 at 02:25:37AM +0000, Wang Nan escreveu:
>>>>> This patch introduce a new syntax to perf event parser:
>>>>> 
>>>>> # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...
>>>> 
>>>> Is the above example valid? Wouldn't this be "maps:mymap.value" ?
>>>> 
>>>>> 
>>>>> By utilizing the basic facilities in bpf-loader.c which allow setting
>>>>> different slots in a BPF map separately, the newly introduced syntax
>>>>> allows perf to control specific elements in a BPF map.
>>>>> 
>>>>> Test result:
>>>>> 
>>>>> # cat ./test_bpf_map_3.c
>>>>> /************************ BEGIN **************************/
>>>>> #define SEC(NAME) __attribute__((section(NAME), used))
>>>>> enum bpf_map_type {
>>>>>    BPF_MAP_TYPE_ARRAY = 2,
>>>>> };
>>>>> struct bpf_map_def {
>>>>>    unsigned int type;
>>>>>    unsigned int key_size;
>>>>>    unsigned int value_size;
>>>>>    unsigned int max_entries;
>>>>> };
>>>>> static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
>>>>>    (void *)1;
>>>>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>>>>>    (void *)6;
>>>> 
>>>> Can you explain the above a bit more? What are the magic 1 and 6 values?
>>> 
>>> So, from another patch:
>>> 
>>> static u64 (*bpf_ktime_get_ns)(void) =
>>>    (void *)5;
>>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>>>    (void *)6;
>>> static int (*bpf_get_smp_processor_id)(void) =
>>>    (void *)8;
>>> static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
>>> void *, unsigned long) =
>>>    (void *)23;
>>> 
>>> Where can I get this magical mistery table? Could this be hidden away in
>>> some .h file automagically included in bpf scriptlets so that n00bies
>>> like me don't have to be wtf'ing?
>> 
>> They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
>> headers. Directly include them causes many error for llvm. Also, the function
>> prototypes are BPF specific and can't included in Linux source. We should have
>> a place holds those indices and prototypes together.
> 
> Sure, just please don't assume whoever is reading your patches has this
> background, provide comments above such places, so that reviewing gets
> facilitated.
> 
> I eventually figured this is some sort of trampoline to access kernel
> functions:
> 
> /* integer value in 'imm' field of BPF_CALL instruction selects which
> * helper function eBPF program intends to call
> */
> enum bpf_func_id {
>        BPF_FUNC_unspec,
>        BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
>        BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
>        BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
>        BPF_FUNC_probe_read,      /* int bpf_probe_read(void *dst, int size, void *src) */
> 
> 
> But if you had just:
> 
> /*
> * See enum_bpf_func_id in ./include/uapi/linux/bpf.h
> */
> 
> That would've helped.
> 

Thank you, but I think this is a good chance to setup the policy about the header
files for BPF. I suggested to put BPF specific headers into Linux kernel include dir,
but we must find a way to avoid Linux includes them. Another useful structure is
pt_regs, however which is not as important as before because we have prologue
now.

I'd like to have a try next week.

Thank you.

> - Arnaldo

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1289534 — Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

Frompi3orama <pi3orama@163.com>
Date2015-12-11 13:50 +0100
SubjectRe: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qEvj4-4o4-11@gated-at.bofh.it>
In reply to#1289515

发自我的 iPhone

> 在 2015年12月11日,下午8:15,Arnaldo Carvalho de Melo <acme@kernel.org> 写道:
> 
> Em Fri, Dec 11, 2015 at 09:11:45AM -0300, Arnaldo Carvalho de Melo escreveu:
>> Em Tue, Dec 08, 2015 at 02:25:37AM +0000, Wang Nan escreveu:
>>> This patch introduce a new syntax to perf event parser:
>>> 
>>> # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...
>> 
>> Is the above example valid? Wouldn't this be "maps:mymap.value" ?
>> 
>>> 
>>> By utilizing the basic facilities in bpf-loader.c which allow setting
>>> different slots in a BPF map separately, the newly introduced syntax
>>> allows perf to control specific elements in a BPF map.
>>> 
>>> Test result:
>>> 
>>> # cat ./test_bpf_map_3.c
>>> /************************ BEGIN **************************/
>>> #define SEC(NAME) __attribute__((section(NAME), used))
>>> enum bpf_map_type {
>>>     BPF_MAP_TYPE_ARRAY = 2,
>>> };
>>> struct bpf_map_def {
>>>     unsigned int type;
>>>     unsigned int key_size;
>>>     unsigned int value_size;
>>>     unsigned int max_entries;
>>> };
>>> static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
>>>     (void *)1;
>>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>>>     (void *)6;
>> 
>> Can you explain the above a bit more? What are the magic 1 and 6 values?
> 
> So, from another patch:
> 
> static u64 (*bpf_ktime_get_ns)(void) =
>     (void *)5;
> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>     (void *)6;
> static int (*bpf_get_smp_processor_id)(void) =
>     (void *)8;
> static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
> void *, unsigned long) =
>     (void *)23;
> 
> Where can I get this magical mistery table? Could this be hidden away in
> some .h file automagically included in bpf scriptlets so that n00bies
> like me don't have to be wtf'ing?
> 

They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
headers. Directly include them causes many error for llvm. Also, the function
prototypes are BPF specific and can't included in Linux source. We should have
a place holds those indices and prototypes together.

> - Arnaldo

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1289812 — Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

FromAlexei Starovoitov <alexei.starovoitov@gmail.com>
Date2015-12-11 19:30 +0100
SubjectRe: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qEAC5-862-5@gated-at.bofh.it>
In reply to#1289534
On Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama wrote:
> > static u64 (*bpf_ktime_get_ns)(void) =
> >     (void *)5;
> > static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
> >     (void *)6;
> > static int (*bpf_get_smp_processor_id)(void) =
> >     (void *)8;
> > static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
> > void *, unsigned long) =
> >     (void *)23;
> > 
> > Where can I get this magical mistery table? Could this be hidden away in
> > some .h file automagically included in bpf scriptlets so that n00bies
> > like me don't have to be wtf'ing?
> > 
> 
> They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
> headers. Directly include them causes many error for llvm. Also, the function
> prototypes are BPF specific and can't included in Linux source. We should have
> a place holds those indices and prototypes together.

wait, what kind of errors?
they are in uapi, so gets installed into /usr/include eventually
and I haven't seen any erros either with gcc or clang.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1290815 — Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

From"Wangnan (F)" <wangnan0@huawei.com>
Date2015-12-14 04:30 +0100
SubjectRe: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qFrZM-we-11@gated-at.bofh.it>
In reply to#1289812

On 2015/12/12 2:21, Alexei Starovoitov wrote:
> On Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama wrote:
>>> static u64 (*bpf_ktime_get_ns)(void) =
>>>      (void *)5;
>>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>>>      (void *)6;
>>> static int (*bpf_get_smp_processor_id)(void) =
>>>      (void *)8;
>>> static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
>>> void *, unsigned long) =
>>>      (void *)23;
>>>
>>> Where can I get this magical mistery table? Could this be hidden away in
>>> some .h file automagically included in bpf scriptlets so that n00bies
>>> like me don't have to be wtf'ing?
>>>
>> They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
>> headers. Directly include them causes many error for llvm. Also, the function
>> prototypes are BPF specific and can't included in Linux source. We should have
>> a place holds those indices and prototypes together.
> wait, what kind of errors?
> they are in uapi, so gets installed into /usr/include eventually
> and I haven't seen any erros either with gcc or clang.
>
Sorry. I saw error because I use

#include <linux/bpf.h>

It is okay if I use

#include <uapi/linux/bpf.h>

Thank you.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1290834 — Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

FromAlexei Starovoitov <alexei.starovoitov@gmail.com>
Date2015-12-14 05:30 +0100
SubjectRe: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qFsVP-17V-5@gated-at.bofh.it>
In reply to#1290815
On Mon, Dec 14, 2015 at 11:27:36AM +0800, Wangnan (F) wrote:
> 
> 
> On 2015/12/12 2:21, Alexei Starovoitov wrote:
> >On Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama wrote:
> >>>static u64 (*bpf_ktime_get_ns)(void) =
> >>>     (void *)5;
> >>>static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
> >>>     (void *)6;
> >>>static int (*bpf_get_smp_processor_id)(void) =
> >>>     (void *)8;
> >>>static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
> >>>void *, unsigned long) =
> >>>     (void *)23;
> >>>
> >>>Where can I get this magical mistery table? Could this be hidden away in
> >>>some .h file automagically included in bpf scriptlets so that n00bies
> >>>like me don't have to be wtf'ing?
> >>>
> >>They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
> >>headers. Directly include them causes many error for llvm. Also, the function
> >>prototypes are BPF specific and can't included in Linux source. We should have
> >>a place holds those indices and prototypes together.
> >wait, what kind of errors?
> >they are in uapi, so gets installed into /usr/include eventually
> >and I haven't seen any erros either with gcc or clang.
> >
> Sorry. I saw error because I use
> 
> #include <linux/bpf.h>
> 
> It is okay if I use
> 
> #include <uapi/linux/bpf.h>

then let's use that instead of copy-paste. thanks

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1290845 — Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

From"Wangnan (F)" <wangnan0@huawei.com>
Date2015-12-14 05:50 +0100
SubjectRe: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qFtfc-1fM-9@gated-at.bofh.it>
In reply to#1290834

On 2015/12/14 12:28, Alexei Starovoitov wrote:
> On Mon, Dec 14, 2015 at 11:27:36AM +0800, Wangnan (F) wrote:
>>
>> On 2015/12/12 2:21, Alexei Starovoitov wrote:
>>> On Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama wrote:
>>>>> static u64 (*bpf_ktime_get_ns)(void) =
>>>>>      (void *)5;
>>>>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>>>>>      (void *)6;
>>>>> static int (*bpf_get_smp_processor_id)(void) =
>>>>>      (void *)8;
>>>>> static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
>>>>> void *, unsigned long) =
>>>>>      (void *)23;
>>>>>
>>>>> Where can I get this magical mistery table? Could this be hidden away in
>>>>> some .h file automagically included in bpf scriptlets so that n00bies
>>>>> like me don't have to be wtf'ing?
>>>>>
>>>> They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
>>>> headers. Directly include them causes many error for llvm. Also, the function
>>>> prototypes are BPF specific and can't included in Linux source. We should have
>>>> a place holds those indices and prototypes together.
>>> wait, what kind of errors?
>>> they are in uapi, so gets installed into /usr/include eventually
>>> and I haven't seen any erros either with gcc or clang.
>>>
>> Sorry. I saw error because I use
>>
>> #include <linux/bpf.h>
>>
>> It is okay if I use
>>
>> #include <uapi/linux/bpf.h>
> then let's use that instead of copy-paste. thanks

And what do you think about the BPF function prototype? Should we put them
into kernel headers? What about::

diff --git a/include/uapi/linux/bpf_functions.h 
b/include/uapi/linux/bpf_functions.h
new file mode 100644
index 0000000..3a562d4
--- /dev/null
+++ b/include/uapi/linux/bpf_functions.h
@@ -0,0 +1,2 @@
+DEFINE_BPF_FUNC(void *, map_lookup_elem, void *, void *)
+DEFINE_BPF_FUNC(int, map_update_elem, void *, void *, void *, int)
[SNIP]
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 9ea2d22..2f2f05f 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -133,143 +133,23 @@ union bpf_attr {
         };
  } __attribute__((aligned(8)));

+#define DEFINE_BPF_FUNC(rettype, name, arglist...) BPF_FUNC_##name
+
+enum bpf_func_id {
+BPF_FUNC_unspec,
+#include "bpf_functions.h"
+__BPF_FUNC_MAX_ID,
+};
+
+#ifdef __BPF_SOURCE__
+#undef DEFINE_BPF_FUNC
+#define DEFINE_BPF_FUNC(rettype, name, arglist...)     static rettype 
(*name)(arglist) = (void *)BPF_FUNC_##name
+#include "bpf_functions.h"
+#endif
  /* integer value in 'imm' field of BPF_CALL instruction selects which 
helper
   * function eBPF program intends to call
   */
  enum bpf_func_id {
-       BPF_FUNC_unspec,
[SNIP]

And when compiling BPF source file we add a __BPF_SOURCE__ directive?

Thank you.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1290861 — Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps

FromAlexei Starovoitov <alexei.starovoitov@gmail.com>
Date2015-12-14 07:00 +0100
SubjectRe: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps
Message-ID<qFukW-1Wg-7@gated-at.bofh.it>
In reply to#1290845
On Mon, Dec 14, 2015 at 12:39:40PM +0800, Wangnan (F) wrote:
> 
> And what do you think about the BPF function prototype? Should we put them
> into kernel headers? What about::
> +#define DEFINE_BPF_FUNC(rettype, name, arglist...)     static rettype
> (*name)(arglist) = (void *)BPF_FUNC_##name

tldr: let's keep it as a part of user headers until better
solution found.

frankly
static void *(*bpf_map_lookup_elem)(void *map, void *key) =
        (void *) BPF_FUNC_map_lookup_elem;
was llvm hack that I thought will be fixed quickly.
That was the easiest way to make C/llvm/bpf_loader to agree on
passing 'bpf_call #num' insn into the kernel.
It works, but it works only with -O2 and higher.
At lower optimization levels llvm generates load of constant
into register and indirect call by register, so that's not suitable
as clean api. bcc with clang::rewriter can solve it, but we don't
want to always depend on that, so currently it's a status quo.
Don't mess with what ain't broken.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286163 — [PATCH v4 13/16] perf tools: Always give options even it not compiled

FromWang Nan <wangnan0@huawei.com>
Date2015-12-08 03:30 +0100
Subject[PATCH v4 13/16] perf tools: Always give options even it not compiled
Message-ID<qDgcq-4Bz-29@gated-at.bofh.it>
In reply to#1286157
This patch keeps options of perf builtins same in all conditions. If
one option is disabled because of compiling options, users should be
notified.

Masami suggested another implementation in [1] that, by adding a
OPTION_NEXT_DEPENDS option before those options in the 'struct option'
array, options parser knows an option is disabled. However, in some
cases this array is reordered (options__order()). In addition, in
parse-option.c that array is const, so we can't simply merge
information in decorator option into the affacted option.

This patch chooses a simpler implementation that, introducing a
set_option_nobuild() function and two option parsing flags. Builtins
with such options should call set_option_nobuild() before option
parsing. The complexity of this patch is because we want some of options
can be skipped safely. In this case their arguments should also be
consumed.

Options in 'perf record' and 'perf probe' are fixed in this patch.

[1] http://lkml.kernel.org/g/50399556C9727B4D88A595C8584AAB3752627CD4@GSjpTKYDCembx32.service.hitachi.net

Test result:

Normal case:

# ./perf probe --vmlinux /tmp/vmlinux sys_write
Added new event:
  probe:sys_write      (on sys_write)

You can now use it in all perf tools, such as:

	perf record -e probe:sys_write -aR sleep 1


Build with NO_DWARF=1:

# ./perf probe -L sys_write
  Error: switch `L' is not built because NO_DWARF=1

 Usage: perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]
    or: perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]
    or: perf probe [<options>] --del '[GROUP:]EVENT' ...
    or: perf probe --list [GROUP:]EVENT ...
    or: perf probe [<options>] --funcs

    -L, --line <FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]>
                          Show source code lines.
                          (not build because NO_DWARF=1)

# ./perf probe -k /tmp/vmlinux sys_write
  Warning: switch `k' is not built because NO_DWARF=1
Added new event:
  probe:sys_write      (on sys_write)

You can now use it in all perf tools, such as:

	perf record -e probe:sys_write -aR sleep 1

# ./perf probe --vmlinux /tmp/vmlinux sys_write
  Warning: option `vmlinux' is not built because NO_DWARF=1
Added new event:
[SNIP]

# ./perf probe -l
 Usage: perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]
    or: perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]
...
    -k, --vmlinux <file>  vmlinux pathname
                          (not build because NO_DWARF=1)
    -L, --line <FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]>
                          Show source code lines.
                          (not build because NO_DWARF=1)
...
    -V, --vars <FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT>
                          Show accessible variables on PROBEDEF
                          (not build because NO_DWARF=1)
        --externs         Show external variables too (with --vars only)
                          (not build because NO_DWARF=1)
        --no-inlines      Don't search inlined functions
                          (not build because NO_DWARF=1)
        --range           Show variables location range in scope (with --vars only)
                          (not build because NO_DWARF=1)

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/builtin-probe.c      |  15 +++++-
 tools/perf/builtin-record.c     |   9 +++-
 tools/perf/util/parse-options.c | 113 ++++++++++++++++++++++++++++++++++++----
 tools/perf/util/parse-options.h |   5 ++
 4 files changed, 129 insertions(+), 13 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 132afc9..dbe2ea5 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -249,6 +249,9 @@ static int opt_show_vars(const struct option *opt,
 
 	return ret;
 }
+#else
+# define opt_show_lines NULL
+# define opt_show_vars NULL
 #endif
 static int opt_add_probe_event(const struct option *opt,
 			      const char *str, int unset __maybe_unused)
@@ -473,7 +476,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 		opt_add_probe_event),
 	OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
 		    " with existing name"),
-#ifdef HAVE_DWARF_SUPPORT
 	OPT_CALLBACK('L', "line", NULL,
 		     "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
 		     "Show source code lines.", opt_show_lines),
@@ -490,7 +492,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 		   "directory", "path to kernel source"),
 	OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
 		"Don't search inlined functions"),
-#endif
 	OPT__DRY_RUN(&probe_event_dry_run),
 	OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
 		 "Set how many probe points can be found for a probe."),
@@ -521,6 +522,16 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 #ifdef HAVE_DWARF_SUPPORT
 	set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
 	set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
+#else
+# define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_DWARF=1", c)
+	set_nobuild('L', "line", false);
+	set_nobuild('V', "vars", false);
+	set_nobuild('\0', "externs", false);
+	set_nobuild('\0', "range", false);
+	set_nobuild('k', "vmlinux", true);
+	set_nobuild('s', "source", true);
+	set_nobuild('\0', "no-inlines", true);
+# undef set_nobuild
 #endif
 	set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE);
 
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8479821..11bf32d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1124,12 +1124,10 @@ struct option __record_options[] = {
 			"per thread proc mmap processing timeout in ms"),
 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
 		    "Record context switch events"),
-#ifdef HAVE_LIBBPF_SUPPORT
 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
 		   "clang binary to use for compiling BPF scriptlets"),
 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
 		   "options passed to clang when compiling BPF scriptlets"),
-#endif
 	OPT_END()
 };
 
@@ -1141,6 +1139,13 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	struct record *rec = &record;
 	char errbuf[BUFSIZ];
 
+#ifndef HAVE_LIBBPF_SUPPORT
+# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
+	set_nobuild('\0', "clang-path", true);
+	set_nobuild('\0', "clang-opt", true);
+# undef set_nobuild
+#endif
+
 	rec->evlist = perf_evlist__new();
 	if (rec->evlist == NULL)
 		return -ENOMEM;
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 9fca092..105e357 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -18,20 +18,34 @@ static int opterror(const struct option *opt, const char *reason, int flags)
 	return error("option `%s' %s", opt->long_name, reason);
 }
 
+static void optwarning(const struct option *opt, const char *reason, int flags)
+{
+	if (flags & OPT_SHORT)
+		warning("switch `%c' %s", opt->short_name, reason);
+	else if (flags & OPT_UNSET)
+		warning("option `no-%s' %s", opt->long_name, reason);
+	else
+		warning("option `%s' %s", opt->long_name, reason);
+}
+
 static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
 		   int flags, const char **arg)
 {
+	const char *res;
+
 	if (p->opt) {
-		*arg = p->opt;
+		res = p->opt;
 		p->opt = NULL;
 	} else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
 		    **(p->argv + 1) == '-')) {
-		*arg = (const char *)opt->defval;
+		res = (const char *)opt->defval;
 	} else if (p->argc > 1) {
 		p->argc--;
-		*arg = *++p->argv;
+		res = *++p->argv;
 	} else
 		return opterror(opt, "requires a value", flags);
+	if (arg)
+		*arg = res;
 	return 0;
 }
 
@@ -91,6 +105,59 @@ static int get_value(struct parse_opt_ctx_t *p,
 		}
 	}
 
+	if (opt->flags & PARSE_OPT_NOBUILD) {
+		char reason[128];
+		bool noarg = false;
+
+		err = snprintf(reason, sizeof(reason),
+				"is not built because %s",
+				opt->build_opt);
+		reason[sizeof(reason) - 1] = '\0';
+
+		if (err < 0)
+			strncpy(reason, "is not built", sizeof(reason));
+
+		if (!(opt->flags & PARSE_OPT_CANSKIP))
+			return opterror(opt, reason, flags);
+
+		err = 0;
+		if (unset)
+			noarg = true;
+		if (opt->flags & PARSE_OPT_NOARG)
+			noarg = true;
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+			noarg = true;
+
+		switch (opt->type) {
+		case OPTION_BOOLEAN:
+		case OPTION_INCR:
+		case OPTION_BIT:
+		case OPTION_SET_UINT:
+		case OPTION_SET_PTR:
+		case OPTION_END:
+		case OPTION_ARGUMENT:
+		case OPTION_GROUP:
+			noarg = true;
+			break;
+		case OPTION_CALLBACK:
+		case OPTION_STRING:
+		case OPTION_INTEGER:
+		case OPTION_UINTEGER:
+		case OPTION_LONG:
+		case OPTION_U64:
+		default:
+			break;
+		}
+
+		if (!noarg)
+			err = get_arg(p, opt, flags, NULL);
+		if (err)
+			return err;
+
+		optwarning(opt, reason, flags);
+		return 0;
+	}
+
 	switch (opt->type) {
 	case OPTION_BIT:
 		if (unset)
@@ -647,6 +714,10 @@ static void print_option_help(const struct option *opts, int full)
 		pad = USAGE_OPTS_WIDTH;
 	}
 	fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
+	if (opts->flags & PARSE_OPT_NOBUILD)
+		fprintf(stderr, "%*s(not build because %s)\n",
+			USAGE_OPTS_WIDTH + USAGE_GAP, "",
+			opts->build_opt);
 }
 
 static int option__cmp(const void *va, const void *vb)
@@ -853,15 +924,39 @@ int parse_opt_verbosity_cb(const struct option *opt,
 	return 0;
 }
 
-void set_option_flag(struct option *opts, int shortopt, const char *longopt,
-		     int flag)
+static struct option *
+find_option(struct option *opts, int shortopt, const char *longopt)
 {
 	for (; opts->type != OPTION_END; opts++) {
 		if ((shortopt && opts->short_name == shortopt) ||
 		    (opts->long_name && longopt &&
-		     !strcmp(opts->long_name, longopt))) {
-			opts->flags |= flag;
-			break;
-		}
+		     !strcmp(opts->long_name, longopt)))
+			return opts;
 	}
+	return NULL;
+}
+
+void set_option_flag(struct option *opts, int shortopt, const char *longopt,
+		     int flag)
+{
+	struct option *opt = find_option(opts, shortopt, longopt);
+
+	if (opt)
+		opt->flags |= flag;
+	return;
+}
+
+void set_option_nobuild(struct option *opts, int shortopt,
+			const char *longopt,
+			const char *build_opt,
+			bool can_skip)
+{
+	struct option *opt = find_option(opts, shortopt, longopt);
+
+	if (!opt)
+		return;
+
+	opt->flags |= PARSE_OPT_NOBUILD;
+	opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0;
+	opt->build_opt = build_opt;
 }
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index a8e407b..2cac2aa 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -41,6 +41,8 @@ enum parse_opt_option_flags {
 	PARSE_OPT_DISABLED = 32,
 	PARSE_OPT_EXCLUSIVE = 64,
 	PARSE_OPT_NOEMPTY  = 128,
+	PARSE_OPT_NOBUILD  = 256,
+	PARSE_OPT_CANSKIP  = 512,
 };
 
 struct option;
@@ -96,6 +98,7 @@ struct option {
 	void *value;
 	const char *argh;
 	const char *help;
+	const char *build_opt;
 
 	int flags;
 	parse_opt_cb *callback;
@@ -226,4 +229,6 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
 extern const char *parse_options_fix_filename(const char *prefix, const char *file);
 
 void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
+void set_option_nobuild(struct option *opts, int shortopt, const char *longopt,
+			const char *build_opt, bool can_skip);
 #endif /* __PERF_PARSE_OPTIONS_H */
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1289532 — Re: [PATCH v4 13/16] perf tools: Always give options even it not compiled

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2015-12-11 13:50 +0100
SubjectRe: [PATCH v4 13/16] perf tools: Always give options even it not compiled
Message-ID<qEvj4-4o4-19@gated-at.bofh.it>
In reply to#1286163
Em Tue, Dec 08, 2015 at 02:25:41AM +0000, Wang Nan escreveu:
> This patch keeps options of perf builtins same in all conditions. If
> one option is disabled because of compiling options, users should be
> notified.
> 
> Masami suggested another implementation in [1] that, by adding a
> OPTION_NEXT_DEPENDS option before those options in the 'struct option'
> array, options parser knows an option is disabled. However, in some
> cases this array is reordered (options__order()). In addition, in
> parse-option.c that array is const, so we can't simply merge
> information in decorator option into the affacted option.
> 
> This patch chooses a simpler implementation that, introducing a
> set_option_nobuild() function and two option parsing flags. Builtins
> with such options should call set_option_nobuild() before option
> parsing. The complexity of this patch is because we want some of options
> can be skipped safely. In this case their arguments should also be
> consumed.
> 
> Options in 'perf record' and 'perf probe' are fixed in this patch.
> 
> [1] http://lkml.kernel.org/g/50399556C9727B4D88A595C8584AAB3752627CD4@GSjpTKYDCembx32.service.hitachi.net
> 
> Test result:
> 
> Normal case:
> 
> # ./perf probe --vmlinux /tmp/vmlinux sys_write
> Added new event:
>   probe:sys_write      (on sys_write)
> 
> You can now use it in all perf tools, such as:
> 
> 	perf record -e probe:sys_write -aR sleep 1
> 
> 
> Build with NO_DWARF=1:
> 
> # ./perf probe -L sys_write
>   Error: switch `L' is not built because NO_DWARF=1

This should be:

  Error: switch `L' is not built-in because NO_DWARF=1

But it would be better as:

  Error: switch `L' is not available because NO_DWARF=1

What makes this an error is the fact that this option doesn't have that
CAN_SKIP flag, right? I.e. this SKIP flag determines the error/warning
message, for errors this should be "... is not available ..." for
warnings it should instead be "... is being ignored ...".

>  Usage: perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]
>     or: perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]
>     or: perf probe [<options>] --del '[GROUP:]EVENT' ...
>     or: perf probe --list [GROUP:]EVENT ...
>     or: perf probe [<options>] --funcs
> 
>     -L, --line <FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]>
>                           Show source code lines.
>                           (not build because NO_DWARF=1)
> 
> # ./perf probe -k /tmp/vmlinux sys_write
>   Warning: switch `k' is not built because NO_DWARF=1
> Added new event:
>   probe:sys_write      (on sys_write)
> 
> You can now use it in all perf tools, such as:
> 
> 	perf record -e probe:sys_write -aR sleep 1
> 
> # ./perf probe --vmlinux /tmp/vmlinux sys_write
>   Warning: option `vmlinux' is not built because NO_DWARF=1
> Added new event:
> [SNIP]
> 
> # ./perf probe -l
>  Usage: perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]
>     or: perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]
> ...
>     -k, --vmlinux <file>  vmlinux pathname
>                           (not build because NO_DWARF=1)
>     -L, --line <FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]>
>                           Show source code lines.
>                           (not build because NO_DWARF=1)
> ...
>     -V, --vars <FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT>
>                           Show accessible variables on PROBEDEF
>                           (not build because NO_DWARF=1)
>         --externs         Show external variables too (with --vars only)
>                           (not build because NO_DWARF=1)
>         --no-inlines      Don't search inlined functions
>                           (not build because NO_DWARF=1)
>         --range           Show variables location range in scope (with --vars only)
>                           (not build because NO_DWARF=1)
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Zefan Li <lizefan@huawei.com>
> Cc: pi3orama@163.com
> ---
>  tools/perf/builtin-probe.c      |  15 +++++-
>  tools/perf/builtin-record.c     |   9 +++-
>  tools/perf/util/parse-options.c | 113 ++++++++++++++++++++++++++++++++++++----
>  tools/perf/util/parse-options.h |   5 ++
>  4 files changed, 129 insertions(+), 13 deletions(-)
> 
> diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
> index 132afc9..dbe2ea5 100644
> --- a/tools/perf/builtin-probe.c
> +++ b/tools/perf/builtin-probe.c
> @@ -249,6 +249,9 @@ static int opt_show_vars(const struct option *opt,
>  
>  	return ret;
>  }
> +#else
> +# define opt_show_lines NULL
> +# define opt_show_vars NULL
>  #endif
>  static int opt_add_probe_event(const struct option *opt,
>  			      const char *str, int unset __maybe_unused)
> @@ -473,7 +476,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
>  		opt_add_probe_event),
>  	OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
>  		    " with existing name"),
> -#ifdef HAVE_DWARF_SUPPORT
>  	OPT_CALLBACK('L', "line", NULL,
>  		     "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
>  		     "Show source code lines.", opt_show_lines),
> @@ -490,7 +492,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
>  		   "directory", "path to kernel source"),
>  	OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
>  		"Don't search inlined functions"),
> -#endif
>  	OPT__DRY_RUN(&probe_event_dry_run),
>  	OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
>  		 "Set how many probe points can be found for a probe."),
> @@ -521,6 +522,16 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
>  #ifdef HAVE_DWARF_SUPPORT
>  	set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
>  	set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
> +#else
> +# define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_DWARF=1", c)
> +	set_nobuild('L', "line", false);
> +	set_nobuild('V', "vars", false);
> +	set_nobuild('\0', "externs", false);
> +	set_nobuild('\0', "range", false);
> +	set_nobuild('k', "vmlinux", true);
> +	set_nobuild('s', "source", true);
> +	set_nobuild('\0', "no-inlines", true);
> +# undef set_nobuild
>  #endif
>  	set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE);
>  
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 8479821..11bf32d 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -1124,12 +1124,10 @@ struct option __record_options[] = {
>  			"per thread proc mmap processing timeout in ms"),
>  	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
>  		    "Record context switch events"),
> -#ifdef HAVE_LIBBPF_SUPPORT
>  	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
>  		   "clang binary to use for compiling BPF scriptlets"),
>  	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
>  		   "options passed to clang when compiling BPF scriptlets"),
> -#endif
>  	OPT_END()
>  };
>  
> @@ -1141,6 +1139,13 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
>  	struct record *rec = &record;
>  	char errbuf[BUFSIZ];
>  
> +#ifndef HAVE_LIBBPF_SUPPORT
> +# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
> +	set_nobuild('\0', "clang-path", true);
> +	set_nobuild('\0', "clang-opt", true);
> +# undef set_nobuild
> +#endif
> +
>  	rec->evlist = perf_evlist__new();
>  	if (rec->evlist == NULL)
>  		return -ENOMEM;
> diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
> index 9fca092..105e357 100644
> --- a/tools/perf/util/parse-options.c
> +++ b/tools/perf/util/parse-options.c
> @@ -18,20 +18,34 @@ static int opterror(const struct option *opt, const char *reason, int flags)
>  	return error("option `%s' %s", opt->long_name, reason);
>  }
>  
> +static void optwarning(const struct option *opt, const char *reason, int flags)
> +{
> +	if (flags & OPT_SHORT)
> +		warning("switch `%c' %s", opt->short_name, reason);
> +	else if (flags & OPT_UNSET)
> +		warning("option `no-%s' %s", opt->long_name, reason);
> +	else
> +		warning("option `%s' %s", opt->long_name, reason);
> +}
> +
>  static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
>  		   int flags, const char **arg)
>  {
> +	const char *res;
> +
>  	if (p->opt) {
> -		*arg = p->opt;
> +		res = p->opt;
>  		p->opt = NULL;
>  	} else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
>  		    **(p->argv + 1) == '-')) {
> -		*arg = (const char *)opt->defval;
> +		res = (const char *)opt->defval;
>  	} else if (p->argc > 1) {
>  		p->argc--;
> -		*arg = *++p->argv;
> +		res = *++p->argv;
>  	} else
>  		return opterror(opt, "requires a value", flags);
> +	if (arg)
> +		*arg = res;
>  	return 0;
>  }
>  
> @@ -91,6 +105,59 @@ static int get_value(struct parse_opt_ctx_t *p,
>  		}
>  	}
>  
> +	if (opt->flags & PARSE_OPT_NOBUILD) {
> +		char reason[128];
> +		bool noarg = false;
> +
> +		err = snprintf(reason, sizeof(reason),
> +				"is not built because %s",
> +				opt->build_opt);
> +		reason[sizeof(reason) - 1] = '\0';
> +
> +		if (err < 0)
> +			strncpy(reason, "is not built", sizeof(reason));
> +
> +		if (!(opt->flags & PARSE_OPT_CANSKIP))
> +			return opterror(opt, reason, flags);
> +
> +		err = 0;
> +		if (unset)
> +			noarg = true;
> +		if (opt->flags & PARSE_OPT_NOARG)
> +			noarg = true;
> +		if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
> +			noarg = true;
> +
> +		switch (opt->type) {
> +		case OPTION_BOOLEAN:
> +		case OPTION_INCR:
> +		case OPTION_BIT:
> +		case OPTION_SET_UINT:
> +		case OPTION_SET_PTR:
> +		case OPTION_END:
> +		case OPTION_ARGUMENT:
> +		case OPTION_GROUP:
> +			noarg = true;
> +			break;
> +		case OPTION_CALLBACK:
> +		case OPTION_STRING:
> +		case OPTION_INTEGER:
> +		case OPTION_UINTEGER:
> +		case OPTION_LONG:
> +		case OPTION_U64:
> +		default:
> +			break;
> +		}
> +
> +		if (!noarg)
> +			err = get_arg(p, opt, flags, NULL);
> +		if (err)
> +			return err;
> +
> +		optwarning(opt, reason, flags);
> +		return 0;
> +	}
> +
>  	switch (opt->type) {
>  	case OPTION_BIT:
>  		if (unset)
> @@ -647,6 +714,10 @@ static void print_option_help(const struct option *opts, int full)
>  		pad = USAGE_OPTS_WIDTH;
>  	}
>  	fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
> +	if (opts->flags & PARSE_OPT_NOBUILD)
> +		fprintf(stderr, "%*s(not build because %s)\n",
> +			USAGE_OPTS_WIDTH + USAGE_GAP, "",
> +			opts->build_opt);
>  }
>  
>  static int option__cmp(const void *va, const void *vb)
> @@ -853,15 +924,39 @@ int parse_opt_verbosity_cb(const struct option *opt,
>  	return 0;
>  }
>  
> -void set_option_flag(struct option *opts, int shortopt, const char *longopt,
> -		     int flag)
> +static struct option *
> +find_option(struct option *opts, int shortopt, const char *longopt)
>  {
>  	for (; opts->type != OPTION_END; opts++) {
>  		if ((shortopt && opts->short_name == shortopt) ||
>  		    (opts->long_name && longopt &&
> -		     !strcmp(opts->long_name, longopt))) {
> -			opts->flags |= flag;
> -			break;
> -		}
> +		     !strcmp(opts->long_name, longopt)))
> +			return opts;
>  	}
> +	return NULL;
> +}
> +
> +void set_option_flag(struct option *opts, int shortopt, const char *longopt,
> +		     int flag)
> +{
> +	struct option *opt = find_option(opts, shortopt, longopt);
> +
> +	if (opt)
> +		opt->flags |= flag;
> +	return;
> +}
> +
> +void set_option_nobuild(struct option *opts, int shortopt,
> +			const char *longopt,
> +			const char *build_opt,
> +			bool can_skip)
> +{
> +	struct option *opt = find_option(opts, shortopt, longopt);
> +
> +	if (!opt)
> +		return;
> +
> +	opt->flags |= PARSE_OPT_NOBUILD;
> +	opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0;
> +	opt->build_opt = build_opt;
>  }
> diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
> index a8e407b..2cac2aa 100644
> --- a/tools/perf/util/parse-options.h
> +++ b/tools/perf/util/parse-options.h
> @@ -41,6 +41,8 @@ enum parse_opt_option_flags {
>  	PARSE_OPT_DISABLED = 32,
>  	PARSE_OPT_EXCLUSIVE = 64,
>  	PARSE_OPT_NOEMPTY  = 128,
> +	PARSE_OPT_NOBUILD  = 256,
> +	PARSE_OPT_CANSKIP  = 512,
>  };
>  
>  struct option;
> @@ -96,6 +98,7 @@ struct option {
>  	void *value;
>  	const char *argh;
>  	const char *help;
> +	const char *build_opt;
>  
>  	int flags;
>  	parse_opt_cb *callback;
> @@ -226,4 +229,6 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
>  extern const char *parse_options_fix_filename(const char *prefix, const char *file);
>  
>  void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
> +void set_option_nobuild(struct option *opts, int shortopt, const char *longopt,
> +			const char *build_opt, bool can_skip);
>  #endif /* __PERF_PARSE_OPTIONS_H */
> -- 
> 1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286164 — [PATCH v4 15/16] perf script: Add support for PERF_TYPE_BREAKPOINT

FromWang Nan <wangnan0@huawei.com>
Date2015-12-08 03:40 +0100
Subject[PATCH v4 15/16] perf script: Add support for PERF_TYPE_BREAKPOINT
Message-ID<qDgm5-4Et-1@gated-at.bofh.it>
In reply to#1286157
Useful for getting stack traces for hardware breakpoint events.

Test result:

Before this patch:
 # ~/perf record -g -e mem:0x600980 ./sample
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.011 MB perf.data (12 samples) ]

 # ~/perf script

 # ~/perf script -F comm,tid,pid,time,event,ip,sym,dso
 sample 22520/22520 97457.836294: mem:0x600980:
                   5a4ad8 __clear_user (/lib/modules/4.3.0-rc4+/build/vmlinux)
 ...
                   3f41ba sys_execve (/lib/modules/4.3.0-rc4+/build/vmlinux)
                   979395 return_from_execve (/lib/modules/4.3.0-rc4+/build/vmlinux)
             7f1b59719cf7 [unknown] ([unknown])

 sample 22520/22520 97457.836648: mem:0x600980:
                      532 main (/home/w00229757/DataBreakpoints/sample)
                    21bd5 __libc_start_main (/tmp/oxygen_root-root/lib64/libc-2.18.so)
 ...

After this patch:
 # ~/perf script
 sample 22520 97457.836294: mem:0x600980:
                   5a4ad8 __clear_user (/lib/modules/4.3.0-rc4+/build/vmlinux)
 ...
                   3f41ba sys_execve (/lib/modules/4.3.0-rc4+/build/vmlinux)
                   979395 return_from_execve (/lib/modules/4.3.0-rc4+/build/vmlinux)
             7f1b59719cf7 [unknown] ([unknown])

 sample 22520 97457.836648: mem:0x600980:
                      532 main (/home/w00229757/DataBreakpoints/sample)
                    21bd5 __libc_start_main (/tmp/oxygen_root-root/lib64/libc-2.18.so)

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/builtin-script.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 3c3f8d0..d259e9a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -130,6 +130,18 @@ static struct {
 
 		.invalid_fields = PERF_OUTPUT_TRACE,
 	},
+
+	[PERF_TYPE_BREAKPOINT] = {
+		.user_set = false,
+
+		.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
+			      PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
+			      PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+			      PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
+			      PERF_OUTPUT_PERIOD,
+
+		.invalid_fields = PERF_OUTPUT_TRACE,
+	},
 };
 
 static bool output_set_by_user(void)
@@ -1129,6 +1141,8 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
 			type = PERF_TYPE_TRACEPOINT;
 		else if (!strcmp(str, "raw"))
 			type = PERF_TYPE_RAW;
+		else if (!strcmp(str, "break"))
+			type = PERF_TYPE_BREAKPOINT;
 		else {
 			fprintf(stderr, "Invalid event type in field string.\n");
 			rc = -EINVAL;
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.kernel


csiph-web