Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754584AbbLKMLv (ORCPT ); Fri, 11 Dec 2015 07:11:51 -0500 Received: from mail.kernel.org ([198.145.29.136]:46394 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751937AbbLKMLu (ORCPT ); Fri, 11 Dec 2015 07:11:50 -0500 Date: Fri, 11 Dec 2015 09:11:45 -0300 From: Arnaldo Carvalho de Melo To: Wang Nan Cc: namhyung@kernel.org, linux-kernel@vger.kernel.org, pi3orama@163.com, mingo@kernel.org, lizefan@huawei.com, Alexei Starovoitov , Masami Hiramatsu Subject: Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps Message-ID: <20151211121145.GP17996@kernel.org> References: <1449541544-67621-1-git-send-email-wangnan0@huawei.com> <1449541544-67621-10-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1449541544-67621-10-git-send-email-wangnan0@huawei.com> X-Url: http://acmel.wordpress.com User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9751 Lines: 301 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:[].value=[value] > maps:[].event=[event] > > where 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 [] [] > or: perf record [] -- [] > > -e, --event event selector. use 'perf list' to list available events > > Signed-off-by: Wang Nan > Cc: Alexei Starovoitov > Cc: Arnaldo Carvalho de Melo > Cc: Masami Hiramatsu > Cc: Namhyung Kim > Cc: Zefan Li > 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:[].value=[value]\n" > -" \tmaps:[].event=[event]\n" > +" \tmaps:[].value=[value]\n" > +" \tmaps:[].event=[event]\n" > "\n" > +" \twhere 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 > #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} > > } > > +{ > +"]" { BEGIN(config); return ']'; } > +{num_dec} { return value(yyscanner, 10); } > +{num_hex} { return value(yyscanner, 16); } > +, { return ','; } > +"\.\.\." { return PE_ARRAY_RANGE; } > +} > + > { > /* > * 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 '['; } > } > > { > 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 PE_VALUE > %type PE_VALUE_SYM_HW > %type PE_VALUE_SYM_SW > @@ -84,6 +85,9 @@ static inc_group_count(struct list_head *list, > %type group_def > %type group > %type groups > +%type array > +%type array_term > +%type 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/