From patchwork Sat Oct 17 10:48:30 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Nan X-Patchwork-Id: 55156 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lf0-f71.google.com (mail-lf0-f71.google.com [209.85.215.71]) by patches.linaro.org (Postfix) with ESMTPS id D54B1230A1 for ; Sat, 17 Oct 2015 10:50:14 +0000 (UTC) Received: by lfaz124 with SMTP id z124sf25791870lfa.0 for ; Sat, 17 Oct 2015 03:50:13 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-type:sender:precedence :list-id:x-original-sender:x-original-authentication-results :mailing-list:list-post:list-help:list-archive:list-unsubscribe; bh=8NyRe4yPbidO6E+6T3ec7JF7kKTBSGMa57iv0n3tBmQ=; b=bdYnDzHTc6FXgjom+oDpIT8G5yafO6UTPZ9Q5ADRMUPYzs/HtaNb4zwFbzih0f4ZY2 kdz5rr7LGhyyBQwjh8vNr9JMtTuNpobdzeRSEAVts+AoTjy7TB+1WtWulQwLGoduMX4O Td6JwpwLTw8xVd1f8fRS+uCP8Hyl7nZu/TIOjEMO3mraLuxWAjXAngcEMGuEzEr+elOT sWckQsd5XQtwGryWPlq3SR+pWGXiy+mYiDBFEk/arnpXPt9YMv1csg/MjHX0ncg4j9hx W0Q/lACoWMQOkAnJmRiIeC0Ic77tpKXnfVFqGTpc7sGbbX1w5hNBmMvvZ3/gE+5oHJFB KS5A== X-Gm-Message-State: ALoCoQnjsKEbY0h2LkJKIDU+2HMx0PxUtTil0zy9XO/PJR6bcs4gfSSFzZMcV4gduGWN5zvKCfFY X-Received: by 10.194.71.107 with SMTP id t11mr1509358wju.6.1445079013815; Sat, 17 Oct 2015 03:50:13 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.26.140 with SMTP id a134ls434561lfa.30.gmail; Sat, 17 Oct 2015 03:50:13 -0700 (PDT) X-Received: by 10.25.43.9 with SMTP id r9mr6854045lfr.45.1445079013639; Sat, 17 Oct 2015 03:50:13 -0700 (PDT) Received: from mail-lf0-f47.google.com (mail-lf0-f47.google.com. [209.85.215.47]) by mx.google.com with ESMTPS id m8si15801041lbs.23.2015.10.17.03.50.13 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 17 Oct 2015 03:50:13 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.47 as permitted sender) client-ip=209.85.215.47; Received: by lfaz124 with SMTP id z124so89219400lfa.1 for ; Sat, 17 Oct 2015 03:50:13 -0700 (PDT) X-Received: by 10.25.20.24 with SMTP id k24mr6260474lfi.117.1445079013311; Sat, 17 Oct 2015 03:50:13 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp436461lbq; Sat, 17 Oct 2015 03:50:12 -0700 (PDT) X-Received: by 10.68.197.226 with SMTP id ix2mr15785099pbc.42.1445079011789; Sat, 17 Oct 2015 03:50:11 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ms6si36091549pbb.247.2015.10.17.03.50.11; Sat, 17 Oct 2015 03:50:11 -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; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752880AbbJQKuE (ORCPT + 30 others); Sat, 17 Oct 2015 06:50:04 -0400 Received: from szxga01-in.huawei.com ([58.251.152.64]:7845 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751551AbbJQKtU (ORCPT ); Sat, 17 Oct 2015 06:49:20 -0400 Received: from 172.24.1.50 (EHLO szxeml428-hub.china.huawei.com) ([172.24.1.50]) by szxrg01-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id CWX99311; Sat, 17 Oct 2015 18:48:55 +0800 (CST) Received: from linux-4hy3.site (10.107.193.248) by szxeml428-hub.china.huawei.com (10.82.67.183) with Microsoft SMTP Server id 14.3.235.1; Sat, 17 Oct 2015 18:48:47 +0800 From: Wang Nan To: , , CC: , , , , , , , , , , , , Wang Nan , Arnaldo Carvalho de Melo Subject: [RFC PATCH 7/7] perf tools: Enable passing event to BPF object Date: Sat, 17 Oct 2015 10:48:30 +0000 Message-ID: <1445078910-73699-8-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1445078910-73699-1-git-send-email-wangnan0@huawei.com> References: <1445078910-73699-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.107.193.248] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: wangnan0@huawei.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.47 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , 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) in following way: ===== BPF program bpf_program.c ===== struct bpf_map_def SEC("maps") pmu_map = { .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, .key_size = sizeof(int), .value_size = sizeof(u32), .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; } ===== cmdline ===== # echo "" > /sys/kernel/debug/tracing/trace # perf record -e evt=cycles/period=0x7fffffffffffffff/ \ -e bpf_program.c/maps.pmu_map.event[all]=evt/ -a ls # cat /sys/kernel/debug/tracing/trace | grep ls ls-3363 [003] d... 75475.056190: : sys_write: pmu=3961415 ls-3363 [003] dN.. 75475.056212: : sys_write_return: pmu=4051390 ls-3363 [003] d... 75475.056216: : sys_write: pmu=4065447 ls-3363 [003] dN.. 75475.056227: : sys_write_return: pmu=4109760 ls-3363 [003] d... 75475.056230: : sys_write: pmu=4120776 ls-3363 [003] dN.. 75475.056245: : sys_write_return: pmu=4178441 ... # perf report --stdio Error: The perf.data file has no samples! Where, setting period of cycles Set a very large value to period of cycles event because we want to use this event as a counter only, don't need sampling. Signed-off-by: Wang Nan Signed-off-by: He Kuang Cc: Arnaldo Carvalho de Melo Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: David Ahern Cc: He Kuang Cc: Jiri Olsa Cc: Kaixu Xia Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/n/ebpf-2mjd96mowgzslkj8jrwbnwg7@git.kernel.org --- tools/perf/util/bpf-loader.c | 106 +++++++++++++++++++++++++++++++++++++++++ tools/perf/util/parse-events.c | 2 +- 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 023fc12..e185fb6 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -643,6 +643,7 @@ enum bpf_map_priv_key_type { enum bpf_map_priv_value_type { BPF_MAP_PRIV_VAL_VALUE, + BPF_MAP_PRIV_VAL_EVSEL, }; struct bpf_map_priv { @@ -660,6 +661,7 @@ struct bpf_map_priv { enum bpf_map_priv_value_type type; union { u64 val; + struct perf_evsel *evsel; }; } value; }; @@ -715,6 +717,7 @@ bpf_map_config_foreach_key(struct bpf_map *map, switch (def.type) { case BPF_MAP_TYPE_ARRAY: + case BPF_MAP_TYPE_PERF_EVENT_ARRAY: switch (priv->key.type) { case BPF_MAP_PRIV_KEY_ALL: for (i = 0; i < def.max_entries; i++) { @@ -838,6 +841,69 @@ bpf__config_obj_map_value(struct bpf_map *map, return -EINVAL; } +static int +bpf__config_obj_map_array_event(struct bpf_map *map, + struct parse_events_term *term, + struct perf_evlist *evlist) +{ + struct bpf_map_priv *priv; + struct perf_evsel *evsel; + struct bpf_map_def def; + 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 -EINVAL; + } + + err = bpf_map__get_def(map, &def); + if (err) { + pr_debug("Unable to get map definition from '%s'\n", + map_name); + return -EINVAL; + } + + /* + * 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 -EINVAL; + } + + priv = zalloc(sizeof(*priv)); + if (!priv) { + pr_debug("No enough memory for map private\n"); + return -ENOMEM; + } + + err = bpf_map_priv_setkey(priv, term, map_name); + if (err) + return err; + + priv->value.type = BPF_MAP_PRIV_VAL_EVSEL; + priv->value.evsel = evsel; + return bpf_map__set_private(map, priv, bpf_map_priv__clear); +} + +static int +bpf__config_obj_map_event(struct bpf_map *map, + struct parse_events_term *term, + struct perf_evlist *evlist) +{ + if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) + return bpf__config_obj_map_array_event(map, term, evlist); + + pr_debug("ERROR: wrong value type\n"); + return -EINVAL; +} + struct bpf_config_map_func { const char *config_opt; int (*config_func)(struct bpf_map *, struct parse_events_term *, @@ -846,6 +912,7 @@ struct bpf_config_map_func { struct bpf_config_map_func bpf_config_map_funcs[] = { {"value", bpf__config_obj_map_value}, + {"event", bpf__config_obj_map_event}, }; static int @@ -964,6 +1031,40 @@ bpf__apply_config_value_for_key(int map_fd, void *pkey, } static int +bpf__apply_config_evsel_for_key(const char *name, int map_fd, void *pkey, + struct perf_evsel *evsel) +{ + struct xyarray *xy = evsel->fd; + unsigned int key, events; + int *evt_fd; + int err; + + if (!xy) { + pr_debug("ERROR: evsel not ready for map %s\n", name); + return -EINVAL; + } + + if (xy->row_size / xy->entry_size != 1) { + pr_debug("ERROR: Dimension of target event is incorrect for map %s\n", + name); + return -EINVAL; + } + + 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 -E2BIG; + } + 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 bpf__apply_config_map_for_key(const char *name, int map_fd, struct bpf_map_def *pdef __maybe_unused, struct bpf_map_priv *priv, @@ -977,6 +1078,10 @@ bpf__apply_config_map_for_key(const char *name, int map_fd, pdef->value_size, priv->value.val); break; + case BPF_MAP_PRIV_VAL_EVSEL: + err = bpf__apply_config_evsel_for_key(name, map_fd, pkey, + priv->value.evsel); + break; default: pr_debug("ERROR: unknown value type for '%s'\n", name); err = -EINVAL; @@ -1081,6 +1186,7 @@ int bpf__strerror_apply_config(int err, char *buf, size_t size) { bpf__strerror_head(err, buf, size); bpf__strerror_entry(EINVAL, "Invalid option for map, add -v to see detail"); + bpf__strerror_entry(E2BIG, "Array index too big, add -v to see detail"); bpf__strerror_end(buf, size); return 0; } diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index a2af5a8..ae973cd 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -654,7 +654,7 @@ parse_events_config_bpf(struct parse_events_evlist *data, err, errbuf, sizeof(errbuf)); data->error->help = strdup( "Hint:\tValid config term:\n" -" \tmaps..value\n" +" \tmaps..[value|event]\n" "\n" " \twhere is something like [0,3-4]\n" " \t(add -v to see detail)");