From patchwork Wed Jul 13 10:44:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Nan X-Patchwork-Id: 71909 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp934365qga; Wed, 13 Jul 2016 03:45:38 -0700 (PDT) X-Received: by 10.98.111.138 with SMTP id k132mr2246089pfc.105.1468406734919; Wed, 13 Jul 2016 03:45:34 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id pc3si4374508pac.129.2016.07.13.03.45.34; Wed, 13 Jul 2016 03:45:34 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932084AbcGMKpL (ORCPT + 30 others); Wed, 13 Jul 2016 06:45:11 -0400 Received: from szxga02-in.huawei.com ([119.145.14.65]:34272 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753110AbcGMKpB (ORCPT ); Wed, 13 Jul 2016 06:45:01 -0400 Received: from 172.24.1.36 (EHLO szxeml425-hub.china.huawei.com) ([172.24.1.36]) by szxrg02-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id DKD56460; Wed, 13 Jul 2016 18:44:24 +0800 (CST) Received: from linux-4hy3.site (10.107.193.248) by szxeml425-hub.china.huawei.com (10.82.67.180) with Microsoft SMTP Server id 14.3.235.1; Wed, 13 Jul 2016 18:44:13 +0800 From: Wang Nan To: CC: , , , Wang Nan , Arnaldo Carvalho de Melo , Alexei Starovoitov , Jiri Olsa Subject: [PATCH 5/5] perf bpf: Support BPF program attach to tracepoints Date: Wed, 13 Jul 2016 10:44:05 +0000 Message-ID: <1468406646-21642-6-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1468406646-21642-1-git-send-email-wangnan0@huawei.com> References: <1468406646-21642-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.107.193.248] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020205.57861B88.024A, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: decebea75b9a75a3bd22aa548d001ea6 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org To support commit 98b5c2c65c29 ("perf, bpf: allow bpf programs attach to tracepoints"), this patch allows BPF script select tracepoints in their section name. Example: # cat test_tracepoint.c /*********************************************/ #include #define SEC(NAME) __attribute__((section(NAME), used)) SEC("raw_syscalls:sys_enter") int func(void *ctx) { /* * /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/format: * ... * field:long id; offset:8; size:8; signed:1; * ... * ctx + 8 select 'id' */ u64 id = *((u64 *)(ctx + 8)); if (id == 1) return 1; return 0; } SEC("_write=sys_write") int _write(void *ctx) { return 1; } char _license[] SEC("license") = "GPL"; int _version SEC("version") = LINUX_VERSION_CODE; /*********************************************/ # perf record -e ./test_tracepoint.c dd if=/dev/zero of=/dev/null count=5 5+0 records in 5+0 records out 2560 bytes (2.6 kB) copied, 6.2281e-05 s, 41.1 MB/s [ perf record: Woken up 1 times to write data ] # perf script dd 13436 [005] 1596.490869: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, 7ffe82470d60, ffffffffffffe020, fffff dd 13436 [005] 1596.490871: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490873: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f dd 13436 [005] 1596.490874: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490876: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f dd 13436 [005] 1596.490876: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490878: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f dd 13436 [005] 1596.490879: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490881: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f dd 13436 [005] 1596.490882: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490900: raw_syscalls:sys_enter: NR 1 (2, 7ffe8246e640, 1f, 40acb8, 7f44bac74700, 7f44baa4fba dd 13436 [005] 1596.490901: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490917: raw_syscalls:sys_enter: NR 1 (2, 7ffe8246e640, 1a, fffffffa, 7f44bac74700, 7f44baa4f dd 13436 [005] 1596.490918: perf_bpf_probe:_write: (ffffffff812351e0) dd 13436 [005] 1596.490932: raw_syscalls:sys_enter: NR 1 (2, 7ffe8246e640, 1a, fffffff9, 7f44bac74700, 7f44baa4f dd 13436 [005] 1596.490933: perf_bpf_probe:_write: (ffffffff812351e0) Signed-off-by: Wang Nan Cc: Arnaldo Carvalho de Melo Cc: Alexei Starovoitov Cc: Li Zefan Cc: Jiri Olsa --- tools/perf/util/bpf-loader.c | 65 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 5 deletions(-) -- 1.8.3.4 diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index f227014..1f12e4e 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -37,6 +37,9 @@ DEFINE_PRINT_FN(info, 1) DEFINE_PRINT_FN(debug, 1) struct bpf_prog_priv { + bool is_tp; + char *sys_name; + char *evt_name; struct perf_probe_event pev; bool need_prologue; struct bpf_insn *insns_buf; @@ -118,6 +121,8 @@ clear_prog_priv(struct bpf_program *prog __maybe_unused, cleanup_perf_probe_events(&priv->pev, 1); zfree(&priv->insns_buf); zfree(&priv->type_mapping); + zfree(&priv->sys_name); + zfree(&priv->evt_name); free(priv); } @@ -269,7 +274,8 @@ nextline: } static int -parse_prog_config(const char *config_str, struct perf_probe_event *pev) +parse_prog_config(const char *config_str, const char **p_main_str, + bool *is_tp, struct perf_probe_event *pev) { int err; const char *main_str = parse_prog_config_kvpair(config_str, pev); @@ -277,6 +283,22 @@ parse_prog_config(const char *config_str, struct perf_probe_event *pev) if (IS_ERR(main_str)) return PTR_ERR(main_str); + *p_main_str = main_str; + if (!strchr(main_str, '=')) { + /* Is a tracepoint event? */ + const char *s = strchr(main_str, ':'); + + if (!s) { + pr_debug("bpf: '%s' is not a valid tracepoint\n", + config_str); + return -BPF_LOADER_ERRNO__CONFIG; + } + + *is_tp = true; + return 0; + } + + *is_tp = false; err = parse_perf_probe_command(main_str, pev); if (err < 0) { pr_debug("bpf: '%s' is not a valid config string\n", @@ -292,7 +314,8 @@ config_bpf_program(struct bpf_program *prog) { struct perf_probe_event *pev = NULL; struct bpf_prog_priv *priv = NULL; - const char *config_str; + const char *config_str, *main_str; + bool is_tp = false; int err; /* Initialize per-program probing setting */ @@ -313,10 +336,19 @@ config_bpf_program(struct bpf_program *prog) pev = &priv->pev; pr_debug("bpf: config program '%s'\n", config_str); - err = parse_prog_config(config_str, pev); + err = parse_prog_config(config_str, &main_str, &is_tp, pev); if (err) goto errout; + if (is_tp) { + char *s = strchr(main_str, ':'); + + priv->is_tp = true; + priv->sys_name = strndup(main_str, s - main_str); + priv->evt_name = strdup(s + 1); + goto set_priv; + } + if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) { pr_debug("bpf: '%s': group for event is set and not '%s'.\n", config_str, PERF_BPF_PROBE_GROUP); @@ -339,6 +371,7 @@ config_bpf_program(struct bpf_program *prog) } pr_debug("bpf: config '%s' is ok\n", config_str); +set_priv: err = bpf_program__set_priv(prog, priv, clear_prog_priv); if (err) { pr_debug("Failed to set priv for program '%s'\n", config_str); @@ -387,7 +420,7 @@ preproc_gen_prologue(struct bpf_program *prog, int n, size_t prologue_cnt = 0; int i, err; - if (IS_ERR(priv) || !priv) + if (IS_ERR(priv) || !priv || priv->is_tp) goto errout; pev = &priv->pev; @@ -544,6 +577,11 @@ static int hook_load_preprocessor(struct bpf_program *prog) return -BPF_LOADER_ERRNO__INTERNAL; } + if (priv->is_tp) { + priv->need_prologue = false; + return 0; + } + pev = &priv->pev; for (i = 0; i < pev->ntevs; i++) { struct probe_trace_event *tev = &pev->tevs[i]; @@ -610,6 +648,13 @@ int bpf__probe(struct bpf_object *obj) err = PTR_ERR(priv); goto out; } + + if (priv->is_tp) { + bpf_program__set_tracepoint(prog); + continue; + } + + bpf_program__set_kprobe(prog); pev = &priv->pev; err = convert_perf_probe_events(pev, 1); @@ -650,7 +695,7 @@ int bpf__unprobe(struct bpf_object *obj) struct bpf_prog_priv *priv = bpf_program__priv(prog); int i; - if (IS_ERR(priv) || !priv) + if (IS_ERR(priv) || !priv || priv->is_tp) continue; for (i = 0; i < priv->pev.ntevs; i++) { @@ -711,6 +756,16 @@ int bpf__foreach_event(struct bpf_object *obj, return -BPF_LOADER_ERRNO__INTERNAL; } + if (priv->is_tp) { + fd = bpf_program__fd(prog); + err = (*func)(priv->sys_name, priv->evt_name, fd, arg); + if (err) { + pr_debug("bpf: tracepoint call back failed, stop iterate\n"); + return err; + } + continue; + } + pev = &priv->pev; for (i = 0; i < pev->ntevs; i++) { tev = &pev->tevs[i];