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


Groups > linux.kernel > #1316351 > unrolled thread

[GIT PULL 00/54] perf tools: Bugfix, BPF improvements and overwrite ring buffer support

Started byWang Nan <wangnan0@huawei.com>
First post2016-01-25 11:00 +0100
Last post2016-01-26 15:20 +0100
Articles 20 on this page of 65 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [GIT PULL 00/54] perf tools: Bugfix, BPF improvements and overwrite ring buffer support Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 16/54] perf tools: Introduce bpf-output event Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 20/54] perf core: Prepare writing into ring buffer from end Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 33/54] perf record: Add '--timestamp-filename' option to append timestamp to output filename Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 25/54] perf tools: Print write_backward value in perf_event_attr__fprintf Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 03/54] tools build: Allow subprojects select all feature checkers Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 28/54] perf record: Extract synthesize code to record__synthesize() Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 23/54] perf tools: Introduce API to pause ring buffer Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 39/54] perf record: Ensure return non-zero rc when mmap fail Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 14/54] perf tools: Support setting different slots in a BPF map separately Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 19/54] perf core: Set event's default overflow_handler Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 06/54] perf test: Check environment before start real BPF test Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 13/54] perf tools: Support perf event alias name Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:00 +0100
    [PATCH 42/54] perf tools: Automatically add new channel according to evlist Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 40/54] perf record: Prevent reading invalid data in record__mmap_read Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 24/54] perf tools: Only validate is_pos for tracking evsels Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 36/54] perf record: Disable buildid cache options by default in switch output mode Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 26/54] perf tools: Move timestamp creation to util Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 38/54] perf record: Generate tracking events for process forked by perf Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 32/54] perf record: Use OPT_BOOLEAN_SET for buildid cache related options Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 34/54] perf record: Split output into multiple files via '--switch-output' Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 30/54] perf record: Turns auxtrace_snapshot_enable into 3 states Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 35/54] perf record: Force enable --timestamp-filename when --switch-output is provided Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 49/54] perf tools: Set write_backward attribut bit for overwrite events Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 45/54] perf record: Don't read from and poll overwrite channel Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 15/54] perf tools: Enable indices setting syntax for BPF maps Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 22/54] perf core: Reduce perf event output overhead by new overflow handler Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 50/54] perf record: Toggle overwrite ring buffer for reading Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
      Re: [PATCH 50/54] perf record: Toggle overwrite ring buffer for reading "Wangnan (F)" <wangnan0@huawei.com> - 2016-01-26 09:30 +0100
    [PATCH 37/54] perf record: Re-synthesize tracking events after output switching Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 17/54] perf data: Support converting data from bpf_perf_event_output() Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 31/54] perf record: Introduce record__finish_output() to finish a perf.data Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 29/54] perf tools: Add perf_data_file__switch() helper Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 54/54] perf tools: Don't warn about out of order event if write_backward is used Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 27/54] perf tools: Make ordered_events reusable Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 11/54] perf record: Apply config to BPF objects before recording Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:10 +0100
    [PATCH 18/54] perf core: Introduce new ioctl options to pause and resume ring buffer Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 12/54] perf tools: Enable passing event to BPF object Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 52/54] perf record: Read from backward ring buffer Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 47/54] perf tools: Detect avalibility of write_backward Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 10/54] perf tools: Enable BPF object configure syntax Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 41/54] perf tools: Add evlist channel helpers Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 01/54] perf test: Add libbpf relocation checker Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
      Re: [PATCH 01/54] perf test: Add libbpf relocation checker Arnaldo Carvalho de Melo <acme@redhat.com> - 2016-01-26 16:00 +0100
        Re: [PATCH 01/54] perf test: Add libbpf relocation checker Arnaldo Carvalho de Melo <acme@redhat.com> - 2016-01-26 16:10 +0100
    [PATCH 08/54] perf test: Improve bp_signal Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 44/54] perf tools: Squash overwrite setting into channel Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 05/54] perf build: Use feature dump file for build-test Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
      Re: [PATCH 05/54] perf build: Use feature dump file for build-test Arnaldo Carvalho de Melo <acme@redhat.com> - 2016-01-26 18:00 +0100
        Re: [PATCH 05/54] perf build: Use feature dump file for build-test "Wangnan (F)" <wangnan0@huawei.com> - 2016-01-27 03:40 +0100
          Re: [PATCH 05/54] perf build: Use feature dump file for build-test Arnaldo Carvalho de Melo <acme@redhat.com> - 2016-01-27 15:00 +0100
        [PATCH] tools build: Check basic headers for test-compile feature checker Wang Nan <wangnan0@huawei.com> - 2016-01-27 12:30 +0100
          Re: [PATCH] tools build: Check basic headers for test-compile  feature checker Jiri Olsa <jolsa@redhat.com> - 2016-01-27 14:30 +0100
            Re: [PATCH] tools build: Check basic headers for test-compile  feature checker Arnaldo Carvalho de Melo <acme@redhat.com> - 2016-01-27 15:00 +0100
    [PATCH 51/54] perf record: Rename variable to make code clear Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 09/54] perf tools: Add API to config maps in bpf object Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 48/54] perf tools: Enable overwrite settings Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 02/54] perf bpf: Check relocation target section Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 21/54] perf core: Add backward attribute to perf event Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 04/54] perf build: Select all feature checkers for feature-dump Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 43/54] perf tools: Operate multiple channels Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 46/54] perf record: Don't poll on overwrite channel Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [PATCH 07/54] perf tools: Fix symbols searching for offline module in buildid-cache Wang Nan <wangnan0@huawei.com> - 2016-01-25 11:20 +0100
    [offlist] Re: [GIT PULL 00/54] perf tools: Bugfix, BPF improvements  and overwrite ring buffer support "Wangnan (F)" <wangnan0@huawei.com> - 2016-01-26 10:20 +0100
      Re: [offlist] Re: [GIT PULL 00/54] perf tools: Bugfix, BPF  improvements and overwrite ring buffer support Arnaldo Carvalho de Melo <acme@redhat.com> - 2016-01-26 15:20 +0100

Page 3 of 4 — ← Prev page 1 2 [3] 4  Next page →


#1316421 — [PATCH 10/54] perf tools: Enable BPF object configure syntax

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 10/54] perf tools: Enable BPF object configure syntax
Message-ID<qUMpA-2q9-27@gated-at.bofh.it>
In reply to#1316351
This patch adds the final step for BPF map configuration. A new syntax
is appended into parser so user can config BPF objects through '/' '/'
enclosed config terms.

After this patch, following syntax is available:

 # perf record -e ./test_bpf_map_1.c/maps:channel.value=10/ ...

It would takes effect after appling following commits.

Test result:

 # cat ./test_bpf_map_1.c
 /************************ BEGIN **************************/
 #include <uapi/linux/bpf.h>
 #define SEC(NAME) __attribute__((section(NAME), used))
 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 *)BPF_FUNC_map_lookup_elem;
 static int (*trace_printk)(const char *fmt, int fmt_size, ...) =
     (void *)BPF_FUNC_trace_printk;
 struct bpf_map_def SEC("maps") channel = {
     .type = BPF_MAP_TYPE_ARRAY,
     .key_size = sizeof(int),
     .value_size = sizeof(int),
     .max_entries = 1,
 };
 SEC("func=sys_nanosleep")
 int func(void *ctx)
 {
     int key = 0;
     char fmt[] = "%d\n";
     int *pval = map_lookup_elem(&channel, &key);
     if (!pval)
         return 0;
     trace_printk(fmt, sizeof(fmt), *pval);
     return 0;
 }
 char _license[] SEC("license") = "GPL";
 int _version SEC("version") = LINUX_VERSION_CODE;
 /************************* END ***************************/

 - Normal case:
 # ./perf record -e './test_bpf_map_1.c/maps:channel.value=10/' usleep 10
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 0.012 MB perf.data ]

 - Error case:

 # ./perf record -e './test_bpf_map_1.c/maps:channel.value/' usleep 10
 event syntax error: '..ps:channel:value/'
                                   \___ Config value not set (lost '=')
 Hint:	Valid config term:
      	maps:[<arraymap>]:value=[value]
	     	(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

 # ./perf record -e './test_bpf_map_1.c/xmaps:channel.value=10/' usleep 10
 event syntax error: '..pf_map_1.c/xmaps:channel.value=10/'
                                   \___ Invalid object config option
 [SNIP]

 # ./perf record -e './test_bpf_map_1.c/maps:xchannel.value=10/' usleep 10
 event syntax error: '..p_1.c/maps:xchannel.value=10/'
                                   \___ Target map not exist
 [SNIP]

 # ./perf record -e './test_bpf_map_1.c/maps:channel.xvalue=10/' usleep 10
 event syntax error: '..ps:channel.xvalue=10/'
                                   \___ Invalid object maps config option
 [SNIP]

 # ./perf record -e './test_bpf_map_1.c/maps:channel.value=x10/' usleep 10
 event syntax error: '..nnel.value=x10/'
                                   \___ Incorrect value type for map
 [SNIP]

 Change BPF_MAP_TYPE_ARRAY to '1':

 # ./perf record -e './test_bpf_map_1.c/maps:channel.value=10/' usleep 10
 event syntax error: '..ps:channel.value=10/'
                                   \___ Can't use this config term to this type of map

 Hint:	Valid config term:
     	maps:[<arraymap>].value=[value]
     	(add -v to see detail)

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
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 | 56 +++++++++++++++++++++++++++++++++++++++---
 tools/perf/util/parse-events.h |  3 ++-
 tools/perf/util/parse-events.l |  2 +-
 tools/perf/util/parse-events.y | 23 ++++++++++++++---
 4 files changed, 75 insertions(+), 9 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4f7b0ef..1c2dc5d 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -628,17 +628,64 @@ errout:
 	return err;
 }
 
+static int
+parse_events_config_bpf(struct parse_events_evlist *data,
+		       struct bpf_object *obj,
+		       struct list_head *head_config)
+{
+	struct parse_events_term *term;
+	int error_pos;
+
+	if (!head_config || list_empty(head_config))
+		return 0;
+
+	list_for_each_entry(term, head_config, list) {
+		char errbuf[BUFSIZ];
+		int err;
+
+		if (term->type_term != PARSE_EVENTS__TERM_TYPE_USER) {
+			snprintf(errbuf, sizeof(errbuf),
+				 "Invalid config term for BPF object");
+			errbuf[BUFSIZ - 1] = '\0';
+
+			data->error->idx = term->err_term;
+			data->error->str = strdup(errbuf);
+			return -EINVAL;
+		}
+
+		err = bpf__config_obj(obj, term, NULL, &error_pos);
+		if (err) {
+			bpf__strerror_config_obj(obj, term, NULL,
+						 &error_pos, err, errbuf,
+						 sizeof(errbuf));
+			data->error->help = strdup(
+"Hint:\tValid config term:\n"
+"     \tmaps:[<arraymap>].value=[value]\n"
+"     \t(add -v to see detail)");
+			data->error->str = strdup(errbuf);
+			if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
+				data->error->idx = term->err_val;
+			else
+				data->error->idx = term->err_term + error_pos;
+			return err;
+		}
+	}
+	return 0;
+
+}
+
 int parse_events_load_bpf(struct parse_events_evlist *data,
 			  struct list_head *list,
 			  char *bpf_file_name,
-			  bool source)
+			  bool source,
+			  struct list_head *head_config)
 {
 	struct bpf_object *obj;
+	int err;
 
 	obj = bpf__prepare_load(bpf_file_name, source);
 	if (IS_ERR(obj)) {
 		char errbuf[BUFSIZ];
-		int err;
 
 		err = PTR_ERR(obj);
 
@@ -656,7 +703,10 @@ int parse_events_load_bpf(struct parse_events_evlist *data,
 		return err;
 	}
 
-	return parse_events_load_bpf_obj(data, list, obj);
+	err = parse_events_load_bpf_obj(data, list, obj);
+	if (err)
+		return err;
+	return parse_events_config_bpf(data, obj, head_config);
 }
 
 static int
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index f1a6db1..84694f3 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -126,7 +126,8 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
 int parse_events_load_bpf(struct parse_events_evlist *data,
 			  struct list_head *list,
 			  char *bpf_file_name,
-			  bool source);
+			  bool source,
+			  struct list_head *head_config);
 /* Provide this function for perf test */
 struct bpf_object;
 int parse_events_load_bpf_obj(struct parse_events_evlist *data,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 58c5831..4387728 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -122,7 +122,7 @@ num_dec		[0-9]+
 num_hex		0x[a-fA-F0-9]+
 num_raw_hex	[a-fA-F0-9]+
 name		[a-zA-Z_*?][a-zA-Z0-9_*?.]*
-name_minus	[a-zA-Z_*?][a-zA-Z0-9\-_*?.]*
+name_minus	[a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
 /* If you add a modifier you need to update check_modifier() */
 modifier_event	[ukhpPGHSDI]+
 modifier_bp	[rwx]{1,3}
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index ad37996..8992d16 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -64,6 +64,7 @@ static inc_group_count(struct list_head *list,
 %type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
 %type <num> value_sym
 %type <head> event_config
+%type <head> event_bpf_config
 %type <term> event_term
 %type <head> event_pmu
 %type <head> event_legacy_symbol
@@ -455,27 +456,41 @@ PE_RAW
 }
 
 event_bpf_file:
-PE_BPF_OBJECT
+PE_BPF_OBJECT event_bpf_config
 {
 	struct parse_events_evlist *data = _data;
 	struct parse_events_error *error = data->error;
 	struct list_head *list;
 
 	ALLOC_LIST(list);
-	ABORT_ON(parse_events_load_bpf(data, list, $1, false));
+	ABORT_ON(parse_events_load_bpf(data, list, $1, false, $2));
+	if ($2)
+		parse_events__free_terms($2);
 	$$ = list;
 }
 |
-PE_BPF_SOURCE
+PE_BPF_SOURCE event_bpf_config
 {
 	struct parse_events_evlist *data = _data;
 	struct list_head *list;
 
 	ALLOC_LIST(list);
-	ABORT_ON(parse_events_load_bpf(data, list, $1, true));
+	ABORT_ON(parse_events_load_bpf(data, list, $1, true, $2));
+	if ($2)
+		parse_events__free_terms($2);
 	$$ = list;
 }
 
+event_bpf_config:
+'/' event_config '/'
+{
+	$$ = $2;
+}
+|
+{
+	$$ = NULL;
+}
+
 start_terms: event_config
 {
 	struct parse_events_terms *data = _data;
-- 
1.8.3.4

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


#1316422 — [PATCH 41/54] perf tools: Add evlist channel helpers

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 41/54] perf tools: Add evlist channel helpers
Message-ID<qUMpA-2q9-31@gated-at.bofh.it>
In reply to#1316351
In this commit sereval helpers are introduced to support the principle
of channel. Channels hold different groups of evsels which configured
differently. It will be used for overwritable evsels, which allows perf
record some events continuously while capture snapshot for other events
when something happen. Tracking events (mmap, mmap2, fork, exit ...)
are another possible events worth to be put into a separated channel.

Channels are represented by an array with channel flags. Each channel
contains evlist->nr_mmaps mmaps. Channels are configured before
perf_evlist__mmap_ex(). During that function nr_mmaps mmaps for each
channel are allocated together as a big array.
perf_evlist__channel_idx() converts index in the big array and the
channel number. For API functions which accept idx, _ex() versions are
introduced to accept selecting an mmap from a channel.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
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/builtin-record.c |   6 ++
 tools/perf/util/evlist.c    | 132 ++++++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/evlist.h    |  58 +++++++++++++++++++
 3 files changed, 190 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0a4f3ec..2d9e6c6 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -356,6 +356,12 @@ try_again:
 		goto out;
 	}
 
+	perf_evlist__channel_reset(evlist);
+	rc = perf_evlist__channel_add(evlist, 0, true);
+	if (rc < 0)
+		goto out;
+	rc = 0;
+
 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
 				 opts->auxtrace_mmap_pages,
 				 opts->auxtrace_snapshot_mode) < 0) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index c80aad1..c565563 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -679,14 +679,51 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
 	return NULL;
 }
 
-union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
+int perf_evlist__channel_idx(struct perf_evlist *evlist,
+			     int *p_channel, int *p_idx)
+{
+	int channel = *p_channel;
+	int _idx = *p_idx;
+
+	if (_idx < 0)
+		return -EINVAL;
+	/*
+	 * Negative channel means caller explicitly use real index.
+	 */
+	if (channel < 0) {
+		channel = perf_evlist__idx_channel(evlist, _idx);
+		_idx = _idx % evlist->nr_mmaps;
+	}
+	if (channel < 0)
+		return channel;
+	if (channel >= PERF_EVLIST__NR_CHANNELS)
+		return -E2BIG;
+	if (_idx >= evlist->nr_mmaps)
+		return -E2BIG;
+
+	*p_channel = channel;
+	*p_idx = evlist->nr_mmaps * channel + _idx;
+	return 0;
+}
+
+union perf_event *perf_evlist__mmap_read_ex(struct perf_evlist *evlist,
+					    int channel, int idx)
 {
+	int err = perf_evlist__channel_idx(evlist, &channel, &idx);
 	struct perf_mmap *md = &evlist->mmap[idx];
 	u64 head;
-	u64 old = md->prev;
-	unsigned char *data = md->base + page_size;
+	u64 old;
+	unsigned char *data;
 	union perf_event *event = NULL;
 
+	if (err || !perf_evlist__channel_is_enabled(evlist, channel)) {
+		pr_err("ERROR: invalid mmap index: channel %d, idx: %d\n",
+		       channel, idx);
+		return NULL;
+	}
+	old = md->prev;
+	data = md->base + page_size;
+
 	/*
 	 * Check if event was unmapped due to a POLLHUP/POLLERR.
 	 */
@@ -748,6 +785,11 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
 	return event;
 }
 
+union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
+{
+	return perf_evlist__mmap_read_ex(evlist, -1, idx);
+}
+
 static bool perf_mmap__empty(struct perf_mmap *md)
 {
 	return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
@@ -766,10 +808,18 @@ static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
 		__perf_evlist__munmap(evlist, idx);
 }
 
-void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
+void perf_evlist__mmap_consume_ex(struct perf_evlist *evlist,
+				  int channel, int idx)
 {
+	int err = perf_evlist__channel_idx(evlist, &channel, &idx);
 	struct perf_mmap *md = &evlist->mmap[idx];
 
+	if (err || !perf_evlist__channel_is_enabled(evlist, channel)) {
+		pr_err("ERROR: invalid mmap index: channel %d, idx: %d\n",
+		       channel, idx);
+		return;
+	}
+
 	if (!evlist->overwrite) {
 		u64 old = md->prev;
 
@@ -780,6 +830,11 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
 		perf_evlist__mmap_put(evlist, idx);
 }
 
+void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
+{
+	perf_evlist__mmap_consume_ex(evlist, -1, idx);
+}
+
 int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused,
 			       struct auxtrace_mmap_params *mp __maybe_unused,
 			       void *userpg __maybe_unused,
@@ -825,7 +880,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
 	if (evlist->mmap == NULL)
 		return;
 
-	for (i = 0; i < evlist->nr_mmaps; i++)
+	for (i = 0; i < perf_evlist__mmap_nr(evlist); i++)
 		__perf_evlist__munmap(evlist, i);
 
 	zfree(&evlist->mmap);
@@ -833,10 +888,17 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
 
 static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
 {
+	int total_mmaps;
+
 	evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
 	if (cpu_map__empty(evlist->cpus))
 		evlist->nr_mmaps = thread_map__nr(evlist->threads);
-	evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
+
+	total_mmaps = perf_evlist__mmap_nr(evlist);
+	if (!total_mmaps)
+		return -EINVAL;
+
+	evlist->mmap = zalloc(total_mmaps * sizeof(struct perf_mmap));
 	return evlist->mmap != NULL ? 0 : -ENOMEM;
 }
 
@@ -1137,6 +1199,12 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 		      bool overwrite)
 {
+	int err;
+
+	perf_evlist__channel_reset(evlist);
+	err = perf_evlist__channel_add(evlist, 0, true);
+	if (err < 0)
+		return err;
 	return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
 }
 
@@ -1746,3 +1814,55 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
 
 	return NULL;
 }
+
+int perf_evlist__channel_nr(struct perf_evlist *evlist)
+{
+	int i;
+
+	for (i = PERF_EVLIST__NR_CHANNELS - 1; i >= 0; i--) {
+		unsigned long flags = evlist->channel_flags[i];
+
+		if (flags & PERF_EVLIST__CHANNEL_ENABLED)
+			return i + 1;
+	}
+	return 0;
+}
+
+int perf_evlist__mmap_nr(struct perf_evlist *evlist)
+{
+	return evlist->nr_mmaps * perf_evlist__channel_nr(evlist);
+}
+
+void perf_evlist__channel_reset(struct perf_evlist *evlist)
+{
+	int i;
+
+	BUG_ON(evlist->mmap);
+
+	for (i = 0; i < PERF_EVLIST__NR_CHANNELS; i++)
+		evlist->channel_flags[i] = 0;
+}
+
+int perf_evlist__channel_add(struct perf_evlist *evlist,
+			     unsigned long flag,
+			     bool is_default)
+{
+	int n = perf_evlist__channel_nr(evlist);
+	unsigned long *flags = evlist->channel_flags;
+
+	BUG_ON(evlist->mmap);
+
+	if (n >= PERF_EVLIST__NR_CHANNELS) {
+		pr_debug("ERROR: too many channels. Increase PERF_EVLIST__NR_CHANNELS\n");
+		return -ENOSPC;
+	}
+
+	if (is_default) {
+		memmove(&flags[1], &flags[0],
+			sizeof(evlist->channel_flags) -
+			sizeof(evlist->channel_flags[0]));
+		n = 0;
+	}
+	flags[n] = flag | PERF_EVLIST__CHANNEL_ENABLED;
+	return n;
+}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index a0d1522..1812652 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -20,6 +20,11 @@ struct record_opts;
 #define PERF_EVLIST__HLIST_BITS 8
 #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
 
+#define PERF_EVLIST__NR_CHANNELS	1
+enum perf_evlist_mmap_flag {
+	PERF_EVLIST__CHANNEL_ENABLED	= 1,
+};
+
 /**
  * struct perf_mmap - perf's ring buffer mmap details
  *
@@ -52,6 +57,7 @@ struct perf_evlist {
 		pid_t	pid;
 	} workload;
 	struct fdarray	 pollfd;
+	unsigned long channel_flags[PERF_EVLIST__NR_CHANNELS];
 	struct perf_mmap *mmap;
 	struct thread_map *threads;
 	struct cpu_map	  *cpus;
@@ -116,9 +122,61 @@ struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
 
 struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
 
+union perf_event *perf_evlist__mmap_read_ex(struct perf_evlist *evlist,
+					    int channel, int idx);
 union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
 
+void perf_evlist__mmap_consume_ex(struct perf_evlist *evlist,
+				  int channel, int idx);
 void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
+int perf_evlist__mmap_nr(struct perf_evlist *evlist);
+
+int perf_evlist__channel_nr(struct perf_evlist *evlist);
+void perf_evlist__channel_reset(struct perf_evlist *evlist);
+int perf_evlist__channel_add(struct perf_evlist *evlist,
+			     unsigned long flag,
+			     bool is_default);
+
+static inline bool
+__perf_evlist__channel_check(struct perf_evlist *evlist, int channel,
+			     enum perf_evlist_mmap_flag bits)
+{
+	if (channel >= PERF_EVLIST__NR_CHANNELS)
+		return false;
+
+	return (evlist->channel_flags[channel] & bits) ? true : false;
+}
+#define perf_evlist__channel_check(e, c, b) \
+		__perf_evlist__channel_check(e, c, PERF_EVLIST__CHANNEL_##b)
+
+static inline bool
+perf_evlist__channel_is_enabled(struct perf_evlist *evlist, int channel)
+{
+	return perf_evlist__channel_check(evlist, channel, ENABLED);
+}
+
+static inline int
+perf_evlist__idx_channel(struct perf_evlist *evlist, int idx)
+{
+	int channel = idx / evlist->nr_mmaps;
+
+	if (channel >= PERF_EVLIST__NR_CHANNELS)
+		return -E2BIG;
+	return channel;
+}
+
+int perf_evlist__channel_idx(struct perf_evlist *evlist,
+			     int *p_channel, int *p_idx);
+
+static inline struct perf_mmap *
+perf_evlist__get_mmap(struct perf_evlist *evlist,
+		      int channel, int idx)
+{
+	if (perf_evlist__channel_idx(evlist, &channel, &idx))
+		return NULL;
+
+	return &evlist->mmap[idx];
+}
 
 int perf_evlist__open(struct perf_evlist *evlist);
 void perf_evlist__close(struct perf_evlist *evlist);
-- 
1.8.3.4

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


#1316424 — [PATCH 01/54] perf test: Add libbpf relocation checker

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 01/54] perf test: Add libbpf relocation checker
Message-ID<qUMpA-2q9-33@gated-at.bofh.it>
In reply to#1316351
There's a bug in LLVM that it can generate unneeded relocation
information. See [1] and [2]. Libbpf should check the target section
of a relocation symbol.

This patch adds a testcase which reference a global variable (BPF
doesn't support global variable). Before fixing libbpf, the new test
case can be loaded into kernel, the global variable acts like the first
map. It is incorrect.

Result:
 # ~/perf test BPF
 37: Test BPF filter                                          :
 37.1: Test basic BPF filtering                               : Ok
 37.2: Test BPF prologue generation                           : Ok
 37.3: Test BPF relocation checker                            : FAILED!

 # ~/perf test -v BPF
 ...
 libbpf: loading object '[bpf_relocation_test]' from buffer
 libbpf: section .strtab, size 126, link 0, flags 0, type=3
 libbpf: section .text, size 0, link 0, flags 6, type=1
 libbpf: section .data, size 0, link 0, flags 3, type=1
 libbpf: section .bss, size 0, link 0, flags 3, type=8
 libbpf: section func=sys_write, size 104, link 0, flags 6, type=1
 libbpf: found program func=sys_write
 libbpf: section .relfunc=sys_write, size 16, link 10, flags 0, type=9
 libbpf: section maps, size 16, link 0, flags 3, type=1
 libbpf: maps in [bpf_relocation_test]: 16 bytes
 libbpf: section license, size 4, link 0, flags 3, type=1
 libbpf: license of [bpf_relocation_test] is GPL
 libbpf: section version, size 4, link 0, flags 3, type=1
 libbpf: kernel version of [bpf_relocation_test] is 40400
 libbpf: section .symtab, size 144, link 1, flags 0, type=2
 libbpf: map 0 is "my_table"
 libbpf: collecting relocating info for: 'func=sys_write'
 libbpf: relocation: insn_idx=7
 Success unexpectedly: libbpf error when dealing with relocation
 test child finished with -1
 ---- end ----
 Test BPF filter subtest 2: FAILED!

[1] https://llvm.org/bugs/show_bug.cgi?id=26243
[2] https://patchwork.ozlabs.org/patch/571385/

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Li Zefan <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/Makefile.perf                      |  2 +-
 tools/perf/tests/.gitignore                   |  1 +
 tools/perf/tests/Build                        |  9 ++++-
 tools/perf/tests/bpf-script-test-relocation.c | 50 +++++++++++++++++++++++++++
 tools/perf/tests/bpf.c                        | 26 +++++++++++---
 tools/perf/tests/llvm.c                       | 17 ++++++---
 tools/perf/tests/llvm.h                       |  5 ++-
 7 files changed, 98 insertions(+), 12 deletions(-)
 create mode 100644 tools/perf/tests/bpf-script-test-relocation.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 5d34815..97ce869 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -618,7 +618,7 @@ clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean
 	$(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
 	$(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
 		$(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \
-		$(OUTPUT)tests/llvm-src-{base,kbuild,prologue}.c
+		$(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c
 	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
 	$(python-clean)
 
diff --git a/tools/perf/tests/.gitignore b/tools/perf/tests/.gitignore
index bf016c4..8cc30e7 100644
--- a/tools/perf/tests/.gitignore
+++ b/tools/perf/tests/.gitignore
@@ -1,3 +1,4 @@
 llvm-src-base.c
 llvm-src-kbuild.c
 llvm-src-prologue.c
+llvm-src-relocation.c
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 614899b..1ba628e 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -31,7 +31,7 @@ perf-y += sample-parsing.o
 perf-y += parse-no-sample-id-all.o
 perf-y += kmod-path.o
 perf-y += thread-map.o
-perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o
+perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o llvm-src-relocation.o
 perf-y += bpf.o
 perf-y += topology.o
 perf-y += cpumap.o
@@ -59,6 +59,13 @@ $(OUTPUT)tests/llvm-src-prologue.c: tests/bpf-script-test-prologue.c tests/Build
 	$(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
 	$(Q)echo ';' >> $@
 
+$(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/Build
+	$(call rule_mkdir)
+	$(Q)echo '#include <tests/llvm.h>' > $@
+	$(Q)echo 'const char test_llvm__bpf_test_relocation[] =' >> $@
+	$(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
+	$(Q)echo ';' >> $@
+
 ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
 perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
 endif
diff --git a/tools/perf/tests/bpf-script-test-relocation.c b/tools/perf/tests/bpf-script-test-relocation.c
new file mode 100644
index 0000000..93af774
--- /dev/null
+++ b/tools/perf/tests/bpf-script-test-relocation.c
@@ -0,0 +1,50 @@
+/*
+ * bpf-script-test-relocation.c
+ * Test BPF loader checking relocation
+ */
+#ifndef LINUX_VERSION_CODE
+# error Need LINUX_VERSION_CODE
+# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
+#endif
+#define BPF_ANY 0
+#define BPF_MAP_TYPE_ARRAY 2
+#define BPF_FUNC_map_lookup_elem 1
+#define BPF_FUNC_map_update_elem 2
+
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+	(void *) BPF_FUNC_map_lookup_elem;
+static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
+	(void *) BPF_FUNC_map_update_elem;
+
+struct bpf_map_def {
+	unsigned int type;
+	unsigned int key_size;
+	unsigned int value_size;
+	unsigned int max_entries;
+};
+
+#define SEC(NAME) __attribute__((section(NAME), used))
+struct bpf_map_def SEC("maps") my_table = {
+	.type = BPF_MAP_TYPE_ARRAY,
+	.key_size = sizeof(int),
+	.value_size = sizeof(int),
+	.max_entries = 1,
+};
+
+int this_is_a_global_val;
+
+SEC("func=sys_write")
+int bpf_func__sys_write(void *ctx)
+{
+	int key = 0;
+	int value = 0;
+
+	/*
+	 * Incorrect relocation. Should not allow this program be
+	 * loaded into kernel.
+	 */
+	bpf_map_update_elem(&this_is_a_global_val, &key, &value, 0);
+	return 0;
+}
+char _license[] SEC("license") = "GPL";
+int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 33689a0..952ca99 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -71,6 +71,15 @@ static struct {
 		(NR_ITERS + 1) / 4,
 	},
 #endif
+	{
+		LLVM_TESTCASE_BPF_RELOCATION,
+		"Test BPF relocation checker",
+		"[bpf_relocation_test]",
+		"fix 'perf test LLVM' first",
+		"libbpf error when dealing with relocation",
+		NULL,
+		0,
+	},
 };
 
 static int do_test(struct bpf_object *obj, int (*func)(void),
@@ -190,7 +199,7 @@ static int __test__bpf(int idx)
 
 	ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
 				       bpf_testcase_table[idx].prog_id,
-				       true);
+				       true, NULL);
 	if (ret != TEST_OK || !obj_buf || !obj_buf_sz) {
 		pr_debug("Unable to get BPF object, %s\n",
 			 bpf_testcase_table[idx].msg_compile_fail);
@@ -202,14 +211,21 @@ static int __test__bpf(int idx)
 
 	obj = prepare_bpf(obj_buf, obj_buf_sz,
 			  bpf_testcase_table[idx].name);
-	if (!obj) {
+	if ((!!bpf_testcase_table[idx].target_func) != (!!obj)) {
+		if (!obj)
+			pr_debug("Fail to load BPF object: %s\n",
+				 bpf_testcase_table[idx].msg_load_fail);
+		else
+			pr_debug("Success unexpectedly: %s\n",
+				 bpf_testcase_table[idx].msg_load_fail);
 		ret = TEST_FAIL;
 		goto out;
 	}
 
-	ret = do_test(obj,
-		      bpf_testcase_table[idx].target_func,
-		      bpf_testcase_table[idx].expect_result);
+	if (obj)
+		ret = do_test(obj,
+			      bpf_testcase_table[idx].target_func,
+			      bpf_testcase_table[idx].expect_result);
 out:
 	bpf__clear();
 	return ret;
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index 06f45c1..70edcdf 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -35,6 +35,7 @@ static int test__bpf_parsing(void *obj_buf __maybe_unused,
 static struct {
 	const char *source;
 	const char *desc;
+	bool should_load_fail;
 } bpf_source_table[__LLVM_TESTCASE_MAX] = {
 	[LLVM_TESTCASE_BASE] = {
 		.source = test_llvm__bpf_base_prog,
@@ -48,14 +49,19 @@ static struct {
 		.source = test_llvm__bpf_test_prologue_prog,
 		.desc = "Compile source for BPF prologue generation test",
 	},
+	[LLVM_TESTCASE_BPF_RELOCATION] = {
+		.source = test_llvm__bpf_test_relocation,
+		.desc = "Compile source for BPF relocation test",
+		.should_load_fail = true,
+	},
 };
 
-
 int
 test_llvm__fetch_bpf_obj(void **p_obj_buf,
 			 size_t *p_obj_buf_sz,
 			 enum test_llvm__testcase idx,
-			 bool force)
+			 bool force,
+			 bool *should_load_fail)
 {
 	const char *source;
 	const char *desc;
@@ -68,6 +74,8 @@ test_llvm__fetch_bpf_obj(void **p_obj_buf,
 
 	source = bpf_source_table[idx].source;
 	desc = bpf_source_table[idx].desc;
+	if (should_load_fail)
+		*should_load_fail = bpf_source_table[idx].should_load_fail;
 
 	perf_config(perf_config_cb, NULL);
 
@@ -136,14 +144,15 @@ int test__llvm(int subtest)
 	int ret;
 	void *obj_buf = NULL;
 	size_t obj_buf_sz = 0;
+	bool should_load_fail = false;
 
 	if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
 		return TEST_FAIL;
 
 	ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
-				       subtest, false);
+				       subtest, false, &should_load_fail);
 
-	if (ret == TEST_OK) {
+	if (ret == TEST_OK && !should_load_fail) {
 		ret = test__bpf_parsing(obj_buf, obj_buf_sz);
 		if (ret != TEST_OK) {
 			pr_debug("Failed to parse test case '%s'\n",
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index 5150b4d..0eaa604 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -7,14 +7,17 @@
 extern const char test_llvm__bpf_base_prog[];
 extern const char test_llvm__bpf_test_kbuild_prog[];
 extern const char test_llvm__bpf_test_prologue_prog[];
+extern const char test_llvm__bpf_test_relocation[];
 
 enum test_llvm__testcase {
 	LLVM_TESTCASE_BASE,
 	LLVM_TESTCASE_KBUILD,
 	LLVM_TESTCASE_BPF_PROLOGUE,
+	LLVM_TESTCASE_BPF_RELOCATION,
 	__LLVM_TESTCASE_MAX,
 };
 
 int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
-			     enum test_llvm__testcase index, bool force);
+			     enum test_llvm__testcase index, bool force,
+			     bool *should_load_fail);
 #endif
-- 
1.8.3.4

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


#1318018 — Re: [PATCH 01/54] perf test: Add libbpf relocation checker

FromArnaldo Carvalho de Melo <acme@redhat.com>
Date2016-01-26 16:00 +0100
SubjectRe: [PATCH 01/54] perf test: Add libbpf relocation checker
Message-ID<qVdg7-5z6-33@gated-at.bofh.it>
In reply to#1316424
Em Mon, Jan 25, 2016 at 09:55:48AM +0000, Wang Nan escreveu:
> There's a bug in LLVM that it can generate unneeded relocation
> information. See [1] and [2]. Libbpf should check the target section
> of a relocation symbol.
> 
> This patch adds a testcase which reference a global variable (BPF
> doesn't support global variable). Before fixing libbpf, the new test
> case can be loaded into kernel, the global variable acts like the first
> map. It is incorrect.
> 
> Result:
>  # ~/perf test BPF
>  37: Test BPF filter                                          :
>  37.1: Test basic BPF filtering                               : Ok
>  37.2: Test BPF prologue generation                           : Ok
>  37.3: Test BPF relocation checker                            : FAILED!
> 
>  # ~/perf test -v BPF
>  ...
>  libbpf: loading object '[bpf_relocation_test]' from buffer
>  libbpf: section .strtab, size 126, link 0, flags 0, type=3
>  libbpf: section .text, size 0, link 0, flags 6, type=1
>  libbpf: section .data, size 0, link 0, flags 3, type=1
>  libbpf: section .bss, size 0, link 0, flags 3, type=8
>  libbpf: section func=sys_write, size 104, link 0, flags 6, type=1
>  libbpf: found program func=sys_write
>  libbpf: section .relfunc=sys_write, size 16, link 10, flags 0, type=9
>  libbpf: section maps, size 16, link 0, flags 3, type=1
>  libbpf: maps in [bpf_relocation_test]: 16 bytes
>  libbpf: section license, size 4, link 0, flags 3, type=1
>  libbpf: license of [bpf_relocation_test] is GPL
>  libbpf: section version, size 4, link 0, flags 3, type=1
>  libbpf: kernel version of [bpf_relocation_test] is 40400
>  libbpf: section .symtab, size 144, link 1, flags 0, type=2
>  libbpf: map 0 is "my_table"
>  libbpf: collecting relocating info for: 'func=sys_write'
>  libbpf: relocation: insn_idx=7
>  Success unexpectedly: libbpf error when dealing with relocation

"Success unexpectedly?" Reading the code to try to grok this message...


- Arnaldo

>  test child finished with -1
>  ---- end ----
>  Test BPF filter subtest 2: FAILED!
> 
> [1] https://llvm.org/bugs/show_bug.cgi?id=26243
> [2] https://patchwork.ozlabs.org/patch/571385/
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Li Zefan <lizefan@huawei.com>
> Cc: pi3orama@163.com
> ---
>  tools/perf/Makefile.perf                      |  2 +-
>  tools/perf/tests/.gitignore                   |  1 +
>  tools/perf/tests/Build                        |  9 ++++-
>  tools/perf/tests/bpf-script-test-relocation.c | 50 +++++++++++++++++++++++++++
>  tools/perf/tests/bpf.c                        | 26 +++++++++++---
>  tools/perf/tests/llvm.c                       | 17 ++++++---
>  tools/perf/tests/llvm.h                       |  5 ++-
>  7 files changed, 98 insertions(+), 12 deletions(-)
>  create mode 100644 tools/perf/tests/bpf-script-test-relocation.c
> 
> diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
> index 5d34815..97ce869 100644
> --- a/tools/perf/Makefile.perf
> +++ b/tools/perf/Makefile.perf
> @@ -618,7 +618,7 @@ clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean
>  	$(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
>  	$(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
>  		$(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \
> -		$(OUTPUT)tests/llvm-src-{base,kbuild,prologue}.c
> +		$(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c
>  	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
>  	$(python-clean)
>  
> diff --git a/tools/perf/tests/.gitignore b/tools/perf/tests/.gitignore
> index bf016c4..8cc30e7 100644
> --- a/tools/perf/tests/.gitignore
> +++ b/tools/perf/tests/.gitignore
> @@ -1,3 +1,4 @@
>  llvm-src-base.c
>  llvm-src-kbuild.c
>  llvm-src-prologue.c
> +llvm-src-relocation.c
> diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
> index 614899b..1ba628e 100644
> --- a/tools/perf/tests/Build
> +++ b/tools/perf/tests/Build
> @@ -31,7 +31,7 @@ perf-y += sample-parsing.o
>  perf-y += parse-no-sample-id-all.o
>  perf-y += kmod-path.o
>  perf-y += thread-map.o
> -perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o
> +perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o llvm-src-relocation.o
>  perf-y += bpf.o
>  perf-y += topology.o
>  perf-y += cpumap.o
> @@ -59,6 +59,13 @@ $(OUTPUT)tests/llvm-src-prologue.c: tests/bpf-script-test-prologue.c tests/Build
>  	$(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
>  	$(Q)echo ';' >> $@
>  
> +$(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/Build
> +	$(call rule_mkdir)
> +	$(Q)echo '#include <tests/llvm.h>' > $@
> +	$(Q)echo 'const char test_llvm__bpf_test_relocation[] =' >> $@
> +	$(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
> +	$(Q)echo ';' >> $@
> +
>  ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
>  perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
>  endif
> diff --git a/tools/perf/tests/bpf-script-test-relocation.c b/tools/perf/tests/bpf-script-test-relocation.c
> new file mode 100644
> index 0000000..93af774
> --- /dev/null
> +++ b/tools/perf/tests/bpf-script-test-relocation.c
> @@ -0,0 +1,50 @@
> +/*
> + * bpf-script-test-relocation.c
> + * Test BPF loader checking relocation
> + */
> +#ifndef LINUX_VERSION_CODE
> +# error Need LINUX_VERSION_CODE
> +# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
> +#endif
> +#define BPF_ANY 0
> +#define BPF_MAP_TYPE_ARRAY 2
> +#define BPF_FUNC_map_lookup_elem 1
> +#define BPF_FUNC_map_update_elem 2
> +
> +static void *(*bpf_map_lookup_elem)(void *map, void *key) =
> +	(void *) BPF_FUNC_map_lookup_elem;
> +static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
> +	(void *) BPF_FUNC_map_update_elem;
> +
> +struct bpf_map_def {
> +	unsigned int type;
> +	unsigned int key_size;
> +	unsigned int value_size;
> +	unsigned int max_entries;
> +};
> +
> +#define SEC(NAME) __attribute__((section(NAME), used))
> +struct bpf_map_def SEC("maps") my_table = {
> +	.type = BPF_MAP_TYPE_ARRAY,
> +	.key_size = sizeof(int),
> +	.value_size = sizeof(int),
> +	.max_entries = 1,
> +};
> +
> +int this_is_a_global_val;
> +
> +SEC("func=sys_write")
> +int bpf_func__sys_write(void *ctx)
> +{
> +	int key = 0;
> +	int value = 0;
> +
> +	/*
> +	 * Incorrect relocation. Should not allow this program be
> +	 * loaded into kernel.
> +	 */
> +	bpf_map_update_elem(&this_is_a_global_val, &key, &value, 0);
> +	return 0;
> +}
> +char _license[] SEC("license") = "GPL";
> +int _version SEC("version") = LINUX_VERSION_CODE;
> diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
> index 33689a0..952ca99 100644
> --- a/tools/perf/tests/bpf.c
> +++ b/tools/perf/tests/bpf.c
> @@ -71,6 +71,15 @@ static struct {
>  		(NR_ITERS + 1) / 4,
>  	},
>  #endif
> +	{
> +		LLVM_TESTCASE_BPF_RELOCATION,
> +		"Test BPF relocation checker",
> +		"[bpf_relocation_test]",
> +		"fix 'perf test LLVM' first",
> +		"libbpf error when dealing with relocation",
> +		NULL,
> +		0,
> +	},
>  };
>  
>  static int do_test(struct bpf_object *obj, int (*func)(void),
> @@ -190,7 +199,7 @@ static int __test__bpf(int idx)
>  
>  	ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
>  				       bpf_testcase_table[idx].prog_id,
> -				       true);
> +				       true, NULL);
>  	if (ret != TEST_OK || !obj_buf || !obj_buf_sz) {
>  		pr_debug("Unable to get BPF object, %s\n",
>  			 bpf_testcase_table[idx].msg_compile_fail);
> @@ -202,14 +211,21 @@ static int __test__bpf(int idx)
>  
>  	obj = prepare_bpf(obj_buf, obj_buf_sz,
>  			  bpf_testcase_table[idx].name);
> -	if (!obj) {
> +	if ((!!bpf_testcase_table[idx].target_func) != (!!obj)) {
> +		if (!obj)
> +			pr_debug("Fail to load BPF object: %s\n",
> +				 bpf_testcase_table[idx].msg_load_fail);
> +		else
> +			pr_debug("Success unexpectedly: %s\n",
> +				 bpf_testcase_table[idx].msg_load_fail);
>  		ret = TEST_FAIL;
>  		goto out;
>  	}
>  
> -	ret = do_test(obj,
> -		      bpf_testcase_table[idx].target_func,
> -		      bpf_testcase_table[idx].expect_result);
> +	if (obj)
> +		ret = do_test(obj,
> +			      bpf_testcase_table[idx].target_func,
> +			      bpf_testcase_table[idx].expect_result);
>  out:
>  	bpf__clear();
>  	return ret;
> diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
> index 06f45c1..70edcdf 100644
> --- a/tools/perf/tests/llvm.c
> +++ b/tools/perf/tests/llvm.c
> @@ -35,6 +35,7 @@ static int test__bpf_parsing(void *obj_buf __maybe_unused,
>  static struct {
>  	const char *source;
>  	const char *desc;
> +	bool should_load_fail;
>  } bpf_source_table[__LLVM_TESTCASE_MAX] = {
>  	[LLVM_TESTCASE_BASE] = {
>  		.source = test_llvm__bpf_base_prog,
> @@ -48,14 +49,19 @@ static struct {
>  		.source = test_llvm__bpf_test_prologue_prog,
>  		.desc = "Compile source for BPF prologue generation test",
>  	},
> +	[LLVM_TESTCASE_BPF_RELOCATION] = {
> +		.source = test_llvm__bpf_test_relocation,
> +		.desc = "Compile source for BPF relocation test",
> +		.should_load_fail = true,
> +	},
>  };
>  
> -
>  int
>  test_llvm__fetch_bpf_obj(void **p_obj_buf,
>  			 size_t *p_obj_buf_sz,
>  			 enum test_llvm__testcase idx,
> -			 bool force)
> +			 bool force,
> +			 bool *should_load_fail)
>  {
>  	const char *source;
>  	const char *desc;
> @@ -68,6 +74,8 @@ test_llvm__fetch_bpf_obj(void **p_obj_buf,
>  
>  	source = bpf_source_table[idx].source;
>  	desc = bpf_source_table[idx].desc;
> +	if (should_load_fail)
> +		*should_load_fail = bpf_source_table[idx].should_load_fail;
>  
>  	perf_config(perf_config_cb, NULL);
>  
> @@ -136,14 +144,15 @@ int test__llvm(int subtest)
>  	int ret;
>  	void *obj_buf = NULL;
>  	size_t obj_buf_sz = 0;
> +	bool should_load_fail = false;
>  
>  	if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
>  		return TEST_FAIL;
>  
>  	ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
> -				       subtest, false);
> +				       subtest, false, &should_load_fail);
>  
> -	if (ret == TEST_OK) {
> +	if (ret == TEST_OK && !should_load_fail) {
>  		ret = test__bpf_parsing(obj_buf, obj_buf_sz);
>  		if (ret != TEST_OK) {
>  			pr_debug("Failed to parse test case '%s'\n",
> diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
> index 5150b4d..0eaa604 100644
> --- a/tools/perf/tests/llvm.h
> +++ b/tools/perf/tests/llvm.h
> @@ -7,14 +7,17 @@
>  extern const char test_llvm__bpf_base_prog[];
>  extern const char test_llvm__bpf_test_kbuild_prog[];
>  extern const char test_llvm__bpf_test_prologue_prog[];
> +extern const char test_llvm__bpf_test_relocation[];
>  
>  enum test_llvm__testcase {
>  	LLVM_TESTCASE_BASE,
>  	LLVM_TESTCASE_KBUILD,
>  	LLVM_TESTCASE_BPF_PROLOGUE,
> +	LLVM_TESTCASE_BPF_RELOCATION,
>  	__LLVM_TESTCASE_MAX,
>  };
>  
>  int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
> -			     enum test_llvm__testcase index, bool force);
> +			     enum test_llvm__testcase index, bool force,
> +			     bool *should_load_fail);
>  #endif
> -- 
> 1.8.3.4

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


#1318034 — Re: [PATCH 01/54] perf test: Add libbpf relocation checker

FromArnaldo Carvalho de Melo <acme@redhat.com>
Date2016-01-26 16:10 +0100
SubjectRe: [PATCH 01/54] perf test: Add libbpf relocation checker
Message-ID<qVdpN-5RZ-39@gated-at.bofh.it>
In reply to#1318018
Em Tue, Jan 26, 2016 at 12:58:50PM -0200, Arnaldo Carvalho de Melo escreveu:
> Em Mon, Jan 25, 2016 at 09:55:48AM +0000, Wang Nan escreveu:
> > There's a bug in LLVM that it can generate unneeded relocation
> > information. See [1] and [2]. Libbpf should check the target section
> > of a relocation symbol.
> > 
> > This patch adds a testcase which reference a global variable (BPF
> > doesn't support global variable). Before fixing libbpf, the new test
> > case can be loaded into kernel, the global variable acts like the first
> > map. It is incorrect.
> > 
> > Result:
> >  # ~/perf test BPF
> >  37: Test BPF filter                                          :
> >  37.1: Test basic BPF filtering                               : Ok
> >  37.2: Test BPF prologue generation                           : Ok
> >  37.3: Test BPF relocation checker                            : FAILED!
> > 
> >  # ~/perf test -v BPF
> >  ...
> >  libbpf: loading object '[bpf_relocation_test]' from buffer
> >  libbpf: section .strtab, size 126, link 0, flags 0, type=3
> >  libbpf: section .text, size 0, link 0, flags 6, type=1
> >  libbpf: section .data, size 0, link 0, flags 3, type=1
> >  libbpf: section .bss, size 0, link 0, flags 3, type=8
> >  libbpf: section func=sys_write, size 104, link 0, flags 6, type=1
> >  libbpf: found program func=sys_write
> >  libbpf: section .relfunc=sys_write, size 16, link 10, flags 0, type=9
> >  libbpf: section maps, size 16, link 0, flags 3, type=1
> >  libbpf: maps in [bpf_relocation_test]: 16 bytes
> >  libbpf: section license, size 4, link 0, flags 3, type=1
> >  libbpf: license of [bpf_relocation_test] is GPL
> >  libbpf: section version, size 4, link 0, flags 3, type=1
> >  libbpf: kernel version of [bpf_relocation_test] is 40400
> >  libbpf: section .symtab, size 144, link 1, flags 0, type=2
> >  libbpf: map 0 is "my_table"
> >  libbpf: collecting relocating info for: 'func=sys_write'
> >  libbpf: relocation: insn_idx=7
> >  Success unexpectedly: libbpf error when dealing with relocation
> 
> "Success unexpectedly?" Reading the code to try to grok this message...

        obj = prepare_bpf(obj_buf, obj_buf_sz,
                          bpf_testcase_table[idx].name);
        if ((!!bpf_testcase_table[idx].target_func) != (!!obj)) {
                if (!obj)
                        pr_debug("Fail to load BPF object: %s\n",
                                 bpf_testcase_table[idx].msg_load_fail);
                else
                        pr_debug("Success unexpectedly: %s\n",
                                 bpf_testcase_table[idx].msg_load_fail);
                ret = TEST_FAIL;
                goto out;
        }


Ok, so in this case you have target_func == NULL, and you managed to
prepare the bpf object, that shouldn't been the case, i.e. prepare_obj
should've returned NULL.

Perhaps replace that "Success unexpectedly"  with "Unexpected sucess,
this script is invalid, should've been marked as such by function
libbpf_foo()"?

Now to apply the follow up patch to see how that will make this test
work as expected...

- Arnaldo

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


#1316426 — [PATCH 08/54] perf test: Improve bp_signal

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 08/54] perf test: Improve bp_signal
Message-ID<qUMpB-2q9-39@gated-at.bofh.it>
In reply to#1316351
Will Deacon [1] has some question on patch [2]. This patch improves
test__bp_signal so we can test:

 1. A watchpoint and a breakpoint that fire on the same instruction
 2. Nested signals

Test result:

 On x86_64 and ARM64 (result are similar with patch [2] on ARM64):

 # ./perf test -v signal
 17: Test breakpoint overflow signal handler                  :
 --- start ---
 test child forked, pid 10213
 count1 1, count2 3, count3 2, overflow 3, overflows_2 3
 test child finished with 0
 ---- end ----
 Test breakpoint overflow signal handler: Ok

So at least 2 cases Will doubted are handled correctly.

[1] http://lkml.kernel.org/g/20160104165535.GI1616@arm.com
[2] http://lkml.kernel.org/g/1450921362-198371-1-git-send-email-wangnan0@huawei.com

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/bp_signal.c | 140 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 118 insertions(+), 22 deletions(-)

diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c
index fb80c9e..1d1bb48 100644
--- a/tools/perf/tests/bp_signal.c
+++ b/tools/perf/tests/bp_signal.c
@@ -29,14 +29,59 @@
 
 static int fd1;
 static int fd2;
+static int fd3;
 static int overflows;
+static int overflows_2;
+
+volatile long the_var;
+
+
+/*
+ * Use ASM to ensure watchpoint and breakpoint can be triggered
+ * at one instruction.
+ */
+#if defined (__x86_64__)
+extern void __test_function(volatile long *ptr);
+asm (
+	".globl __test_function\n"
+	"__test_function:\n"
+	"incq (%rdi)\n"
+	"ret\n");
+#elif defined (__aarch64__)
+extern void __test_function(volatile long *ptr);
+asm (
+	".globl __test_function\n"
+	"__test_function:\n"
+	"str x30, [x0]\n"
+	"ret\n");
+
+#else
+static void __test_function(volatile long *ptr)
+{
+	*ptr = 0x1234;
+}
+#endif
 
 __attribute__ ((noinline))
 static int test_function(void)
 {
+	__test_function(&the_var);
+	the_var++;
 	return time(NULL);
 }
 
+static void sig_handler_2(int signum __maybe_unused,
+			  siginfo_t *oh __maybe_unused,
+			  void *uc __maybe_unused)
+{
+	overflows_2++;
+	if (overflows_2 > 10) {
+		ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
+		ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
+		ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
+	}
+}
+
 static void sig_handler(int signum __maybe_unused,
 			siginfo_t *oh __maybe_unused,
 			void *uc __maybe_unused)
@@ -54,10 +99,11 @@ static void sig_handler(int signum __maybe_unused,
 		 */
 		ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
 		ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
+		ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
 	}
 }
 
-static int bp_event(void *fn, int setup_signal)
+static int __event(bool is_x, void *addr, int signal)
 {
 	struct perf_event_attr pe;
 	int fd;
@@ -67,8 +113,8 @@ static int bp_event(void *fn, int setup_signal)
 	pe.size = sizeof(struct perf_event_attr);
 
 	pe.config = 0;
-	pe.bp_type = HW_BREAKPOINT_X;
-	pe.bp_addr = (unsigned long) fn;
+	pe.bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
+	pe.bp_addr = (unsigned long) addr;
 	pe.bp_len = sizeof(long);
 
 	pe.sample_period = 1;
@@ -86,17 +132,25 @@ static int bp_event(void *fn, int setup_signal)
 		return TEST_FAIL;
 	}
 
-	if (setup_signal) {
-		fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
-		fcntl(fd, F_SETSIG, SIGIO);
-		fcntl(fd, F_SETOWN, getpid());
-	}
+	fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
+	fcntl(fd, F_SETSIG, signal);
+	fcntl(fd, F_SETOWN, getpid());
 
 	ioctl(fd, PERF_EVENT_IOC_RESET, 0);
 
 	return fd;
 }
 
+static int bp_event(void *addr, int signal)
+{
+	return __event(true, addr, signal);
+}
+
+static int wp_event(void *addr, int signal)
+{
+	return __event(false, addr, signal);
+}
+
 static long long bp_count(int fd)
 {
 	long long count;
@@ -114,7 +168,7 @@ static long long bp_count(int fd)
 int test__bp_signal(int subtest __maybe_unused)
 {
 	struct sigaction sa;
-	long long count1, count2;
+	long long count1, count2, count3;
 
 	/* setup SIGIO signal handler */
 	memset(&sa, 0, sizeof(struct sigaction));
@@ -126,21 +180,52 @@ int test__bp_signal(int subtest __maybe_unused)
 		return TEST_FAIL;
 	}
 
+	sa.sa_sigaction = (void *) sig_handler_2;
+	if (sigaction(SIGUSR1, &sa, NULL) < 0) {
+		pr_debug("failed setting up signal handler 2\n");
+		return TEST_FAIL;
+	}
+
 	/*
 	 * We create following events:
 	 *
-	 * fd1 - breakpoint event on test_function with SIGIO
+	 * fd1 - breakpoint event on __test_function with SIGIO
 	 *       signal configured. We should get signal
 	 *       notification each time the breakpoint is hit
 	 *
-	 * fd2 - breakpoint event on sig_handler without SIGIO
+	 * fd2 - breakpoint event on sig_handler with SIGUSR1
+	 *       configured. We should get SIGUSR1 each time when
+	 *       breakpoint is hit
+	 *
+	 * fd3 - watchpoint event on __test_function with SIGIO
 	 *       configured.
 	 *
 	 * Following processing should happen:
-	 *   - execute test_function
-	 *   - fd1 event breakpoint hit -> count1 == 1
-	 *   - SIGIO is delivered       -> overflows == 1
-	 *   - fd2 event breakpoint hit -> count2 == 1
+	 *   Exec:               Action:                       Result:
+	 *   incq (%rdi)       - fd1 event breakpoint hit   -> count1 == 1
+	 *                     - SIGIO is delivered
+	 *   sig_handler       - fd2 event breakpoint hit   -> count2 == 1
+	 *                     - SIGUSR1 is delivered
+	 *   sig_handler_2                                  -> overflows_2 == 1  (nested signal)
+	 *   sys_rt_sigreturn  - return from sig_handler_2
+	 *   overflows++                                    -> overflows = 1
+	 *   sys_rt_sigreturn  - return from sig_handler
+	 *   incq (%rdi)       - fd3 event watchpoint hit   -> count3 == 1       (wp and bp in one insn)
+	 *                     - SIGIO is delivered
+	 *   sig_handler       - fd2 event breakpoint hit   -> count2 == 2
+	 *                     - SIGUSR1 is delivered
+	 *   sig_handler_2                                  -> overflows_2 == 2  (nested signal)
+	 *   sys_rt_sigreturn  - return from sig_handler_2
+	 *   overflows++                                    -> overflows = 2
+	 *   sys_rt_sigreturn  - return from sig_handler
+	 *   the_var++         - fd3 event watchpoint hit   -> count3 == 2       (standalone watchpoint)
+	 *                     - SIGIO is delivered
+	 *   sig_handler       - fd2 event breakpoint hit   -> count2 == 3
+	 *                     - SIGUSR1 is delivered
+	 *   sig_handler_2                                  -> overflows_2 == 3  (nested signal)
+	 *   sys_rt_sigreturn  - return from sig_handler_2
+	 *   overflows++                                    -> overflows == 3
+	 *   sys_rt_sigreturn  - return from sig_handler
 	 *
 	 * The test case check following error conditions:
 	 * - we get stuck in signal handler because of debug
@@ -152,11 +237,13 @@ int test__bp_signal(int subtest __maybe_unused)
 	 *
 	 */
 
-	fd1 = bp_event(test_function, 1);
-	fd2 = bp_event(sig_handler, 0);
+	fd1 = bp_event(__test_function, SIGIO);
+	fd2 = bp_event(sig_handler, SIGUSR1);
+	fd3 = wp_event((void *)&the_var, SIGIO);
 
 	ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
 	ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
+	ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);
 
 	/*
 	 * Kick off the test by trigering 'fd1'
@@ -166,15 +253,18 @@ int test__bp_signal(int subtest __maybe_unused)
 
 	ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
 	ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
+	ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
 
 	count1 = bp_count(fd1);
 	count2 = bp_count(fd2);
+	count3 = bp_count(fd3);
 
 	close(fd1);
 	close(fd2);
+	close(fd3);
 
-	pr_debug("count1 %lld, count2 %lld, overflow %d\n",
-		 count1, count2, overflows);
+	pr_debug("count1 %lld, count2 %lld, count3 %lld, overflow %d, overflows_2 %d\n",
+		 count1, count2, count3, overflows, overflows_2);
 
 	if (count1 != 1) {
 		if (count1 == 11)
@@ -183,12 +273,18 @@ int test__bp_signal(int subtest __maybe_unused)
 			pr_debug("failed: wrong count for bp1%lld\n", count1);
 	}
 
-	if (overflows != 1)
+	if (overflows != 3)
 		pr_debug("failed: wrong overflow hit\n");
 
-	if (count2 != 1)
+	if (overflows_2 != 3)
+		pr_debug("failed: wrong overflow_2 hit\n");
+
+	if (count2 != 3)
 		pr_debug("failed: wrong count for bp2\n");
 
-	return count1 == 1 && overflows == 1 && count2 == 1 ?
+	if (count3 != 2)
+		pr_debug("failed: wrong count for bp3\n");
+
+	return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
 		TEST_OK : TEST_FAIL;
 }
-- 
1.8.3.4

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


#1316427 — [PATCH 44/54] perf tools: Squash overwrite setting into channel

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 44/54] perf tools: Squash overwrite setting into channel
Message-ID<qUMpB-2q9-41@gated-at.bofh.it>
In reply to#1316351
Make 'overwrite' a channel configuration other than a evlist global
option. With this setting an evlist can have two channels, one is
normal channel, another is overwritable channel.
perf_evlist__channel_for_evsel() ensures events with 'overwrite'
configuration inserted to overwritable channel.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
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/builtin-record.c |  2 +-
 tools/perf/util/evlist.c    | 42 +++++++++++++++++++++++++++---------------
 tools/perf/util/evlist.h    |  5 ++---
 tools/perf/util/evsel.h     |  1 +
 4 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a471ca6..53bfe55 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -357,7 +357,7 @@ try_again:
 	}
 
 	perf_evlist__channel_reset(evlist);
-	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
+	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages,
 				 opts->auxtrace_mmap_pages,
 				 opts->auxtrace_snapshot_mode) < 0) {
 		if (errno == EPERM) {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a363466..d728d82 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -731,7 +731,7 @@ union perf_event *perf_evlist__mmap_read_ex(struct perf_evlist *evlist,
 		return NULL;
 
 	head = perf_mmap__read_head(md);
-	if (evlist->overwrite) {
+	if (perf_evlist__channel_check(evlist, channel, RDONLY)) {
 		/*
 		 * If we're further behind than half the buffer, there's a chance
 		 * the writer will bite our tail and mess up the samples under us.
@@ -820,7 +820,7 @@ void perf_evlist__mmap_consume_ex(struct perf_evlist *evlist,
 		return;
 	}
 
-	if (!evlist->overwrite) {
+	if (!perf_evlist__channel_check(evlist, channel, RDONLY)) {
 		u64 old = md->prev;
 
 		perf_mmap__write_tail(md, old);
@@ -918,7 +918,6 @@ static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
 }
 
 struct mmap_params {
-	int prot;
 	int mask;
 	struct auxtrace_mmap_params auxtrace_mp;
 };
@@ -926,6 +925,15 @@ struct mmap_params {
 static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
 			       struct mmap_params *mp, int fd)
 {
+	int channel = perf_evlist__idx_channel(evlist, idx);
+	int prot = PROT_READ;
+
+	if (channel < 0)
+		return -1;
+
+	if (!perf_evlist__channel_check(evlist, channel, RDONLY))
+		prot |= PROT_WRITE;
+
 	/*
 	 * The last one will be done at perf_evlist__mmap_consume(), so that we
 	 * make sure we don't prevent tools from consuming every last event in
@@ -942,7 +950,7 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
 	atomic_set(&evlist->mmap[idx].refcnt, 2);
 	evlist->mmap[idx].prev = 0;
 	evlist->mmap[idx].mask = mp->mask;
-	evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
+	evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
 				      MAP_SHARED, fd, 0);
 	if (evlist->mmap[idx].base == MAP_FAILED) {
 		pr_debug2("failed to mmap perf event ring buffer, error %d\n",
@@ -959,9 +967,13 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
 }
 
 static unsigned long
-perf_evlist__channel_for_evsel(struct perf_evsel *evsel __maybe_unused)
+perf_evlist__channel_for_evsel(struct perf_evsel *evsel)
 {
-	return 0;
+	unsigned long flag = 0;
+
+	if (evsel->overwrite)
+		flag |= PERF_EVLIST__CHANNEL_RDONLY;
+	return flag;
 }
 
 static int
@@ -1211,11 +1223,10 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
  * perf_evlist__mmap_ex - Create mmaps to receive events.
  * @evlist: list of events
  * @pages: map length in pages
- * @overwrite: overwrite older events?
  * @auxtrace_pages - auxtrace map length in pages
  * @auxtrace_overwrite - overwrite older auxtrace data?
  *
- * If @overwrite is %false the user needs to signal event consumption using
+ * For writable channel, the user needs to signal event consumption using
  * perf_mmap__write_tail().  Using perf_evlist__mmap_read() does this
  * automatically.
  *
@@ -1225,16 +1236,13 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
  * Return: %0 on success, negative error code otherwise.
  */
 int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
-			 bool overwrite, unsigned int auxtrace_pages,
-			 bool auxtrace_overwrite)
+			 unsigned int auxtrace_pages, bool auxtrace_overwrite)
 {
 	int err;
 	struct perf_evsel *evsel;
 	const struct cpu_map *cpus = evlist->cpus;
 	const struct thread_map *threads = evlist->threads;
-	struct mmap_params mp = {
-		.prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
-	};
+	struct mmap_params mp;
 
 	err = perf_evlist__channel_complete(evlist);
 	if (err)
@@ -1246,7 +1254,6 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
 	if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
 		return -ENOMEM;
 
-	evlist->overwrite = overwrite;
 	evlist->mmap_len = perf_evlist__mmap_size(pages);
 	pr_debug("mmap size %zuB\n", evlist->mmap_len);
 	mp.mask = evlist->mmap_len - page_size - 1;
@@ -1270,8 +1277,13 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 		      bool overwrite)
 {
+	struct perf_evsel *evsel;
+
 	perf_evlist__channel_reset(evlist);
-	return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
+	evlist__for_each(evlist, evsel)
+		evsel->overwrite = overwrite;
+
+	return perf_evlist__mmap_ex(evlist, pages, 0, false);
 }
 
 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index b652587..21a8b85 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -23,6 +23,7 @@ struct record_opts;
 #define PERF_EVLIST__NR_CHANNELS	2
 enum perf_evlist_mmap_flag {
 	PERF_EVLIST__CHANNEL_ENABLED	= 1,
+	PERF_EVLIST__CHANNEL_RDONLY	= 2,
 };
 
 /**
@@ -45,7 +46,6 @@ struct perf_evlist {
 	int		 nr_entries;
 	int		 nr_groups;
 	int		 nr_mmaps;
-	bool		 overwrite;
 	bool		 enabled;
 	bool		 has_user_cpus;
 	size_t		 mmap_len;
@@ -203,8 +203,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt,
 				  int unset);
 
 int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
-			 bool overwrite, unsigned int auxtrace_pages,
-			 bool auxtrace_overwrite);
+			 unsigned int auxtrace_pages, bool auxtrace_overwrite);
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 		      bool overwrite);
 void perf_evlist__munmap(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d5ae7ba..f5c7433 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -115,6 +115,7 @@ struct perf_evsel {
 	bool			tracking;
 	bool			per_pkg;
 	bool			precise_max;
+	bool			overwrite;
 	/* parse modifier helper */
 	int			exclude_GH;
 	int			nr_members;
-- 
1.8.3.4

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


#1316428 — [PATCH 05/54] perf build: Use feature dump file for build-test

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 05/54] perf build: Use feature dump file for build-test
Message-ID<qUMpB-2q9-43@gated-at.bofh.it>
In reply to#1316351
To prevent feature check run too many times, this patch utilizes
previous introduced feature-dump make target and FEATURES_DUMP
variable, makes sure the feature checkers run only once when doing
build-test for normal test cases.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/tests/make | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index f918015..b8c86bd 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -15,6 +15,7 @@ else
 PERF := .
 PERF_O := $(PERF)
 O_OPT :=
+FULL_O := $(shell readlink -f $(PERF_O) || echo $(PERF_O))
 
 ifneq ($(O),)
   FULL_O := $(shell readlink -f $(O) || echo $(O))
@@ -313,11 +314,41 @@ make_kernelsrc_tools:
 	(make -C ../../tools $(PARALLEL_OPT) $(K_O_OPT) perf) > $@ 2>&1 && \
 	test -x $(KERNEL_O)/tools/perf/perf && rm -f $@ || (cat $@ ; false)
 
+FEATURES_DUMP_FILE := $(FULL_O)/BUILD_TEST_FEATURE_DUMP
+FEATURES_DUMP_FILE_STATIC := $(FULL_O)/BUILD_TEST_FEATURE_DUMP_STATIC
+
 all: $(run) $(run_O) tarpkg make_kernelsrc make_kernelsrc_tools
 	@echo OK
+	@rm -f $(FEATURES_DUMP_FILE) $(FEATURES_DUMP_FILE_STATIC)
 
 out: $(run_O)
 	@echo OK
+	@rm -f $(FEATURES_DUMP_FILE) $(FEATURES_DUMP_FILE_STATIC)
+
+$(FEATURES_DUMP_FILE):
+	$(call clean)
+	@cmd="cd $(PERF) && make FEATURE_DUMP_COPY=$@ $(O_OPT) feature-dump"; \
+	echo "- $@: $$cmd" && echo $$cmd && \
+	( eval $$cmd ) > /dev/null 2>&1
+
+$(FEATURES_DUMP_FILE_STATIC):
+	$(call clean)
+	@cmd="cd $(PERF) && make FEATURE_DUMP_COPY=$@ $(O_OPT) LDFLAGS='-static' feature-dump"; \
+	echo "- $@: $$cmd" && echo $$cmd && \
+	( eval $$cmd ) > /dev/null 2>&1
+
+# Add feature dump dependency for run/run_O targets
+$(foreach t,$(run) $(run_O),$(eval \
+	$(t): $(if $(findstring make_static,$(t)),\
+		$(FEATURES_DUMP_FILE_STATIC),\
+		$(FEATURES_DUMP_FILE))))
+
+# Append 'FEATURES_DUMP=' option to all test cases. For example:
+# make_no_libbpf: NO_LIBBPF=1  --> NO_LIBBPF=1 FEATURES_DUMP=/a/b/BUILD_TEST_FEATURE_DUMP
+# make_static: LDFLAGS=-static --> LDFLAGS=-static FEATURES_DUMP=/a/b/BUILD_TEST_FEATURE_DUMP_STATIC
+$(foreach t,$(run),$(if $(findstring make_static,$(t)),\
+			$(eval $(t) := $($(t)) FEATURES_DUMP=$(FEATURES_DUMP_FILE_STATIC)),\
+			$(eval $(t) := $($(t)) FEATURES_DUMP=$(FEATURES_DUMP_FILE))))
 
 .PHONY: all $(run) $(run_O) tarpkg clean make_kernelsrc make_kernelsrc_tools
 endif # ifndef MK
-- 
1.8.3.4

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


#1318137 — Re: [PATCH 05/54] perf build: Use feature dump file for build-test

FromArnaldo Carvalho de Melo <acme@redhat.com>
Date2016-01-26 18:00 +0100
SubjectRe: [PATCH 05/54] perf build: Use feature dump file for build-test
Message-ID<qVf8e-6St-7@gated-at.bofh.it>
In reply to#1316428
Em Mon, Jan 25, 2016 at 09:55:52AM +0000, Wang Nan escreveu:
> To prevent feature check run too many times, this patch utilizes
> previous introduced feature-dump make target and FEATURES_DUMP
> variable, makes sure the feature checkers run only once when doing
> build-test for normal test cases.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Jiri Olsa <jolsa@kernel.org>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Namhyung Kim <namhyung@kernel.org>

So, I'm having this problem when this patch is applied.

[acme@jouet linux]$ make -C tools clean
make: Entering directory '/home/acme/git/linux/tools'
  DESCEND  power/acpi
make[1]: Entering directory '/home/acme/git/linux/tools/power/acpi'
  DESCEND  tools/acpidbg
make[2]: Entering directory '/home/acme/git/linux/tools/power/acpi/tools/acpidbg'
find ./ \( -not -type d \) \
-and \( -name '*~' -o -name '*.[oas]' \) \
-type f -print \
 | xargs rm -f
rm -f ./acpidbg
make[2]: Leaving directory '/home/acme/git/linux/tools/power/acpi/tools/acpidbg'
  DESCEND  tools/acpidump
make[2]: Entering directory '/home/acme/git/linux/tools/power/acpi/tools/acpidump'
find ./ \( -not -type d \) \
-and \( -name '*~' -o -name '*.[oas]' \) \
-type f -print \
 | xargs rm -f
rm -f ./acpidump
make[2]: Leaving directory '/home/acme/git/linux/tools/power/acpi/tools/acpidump'
  DESCEND  tools/ec
make[2]: Entering directory '/home/acme/git/linux/tools/power/acpi/tools/ec'
find ./ \( -not -type d \) \
-and \( -name '*~' -o -name '*.[oas]' \) \
-type f -print \
 | xargs rm -f
rm -f ./ec
make[2]: Leaving directory '/home/acme/git/linux/tools/power/acpi/tools/ec'
make[1]: Leaving directory '/home/acme/git/linux/tools/power/acpi'
  DESCEND  cgroup
make[1]: Entering directory '/home/acme/git/linux/tools/cgroup'
rm -f cgroup_event_listener
make[1]: Leaving directory '/home/acme/git/linux/tools/cgroup'
  DESCEND  power/cpupower
make[1]: Entering directory '/home/acme/git/linux/tools/power/cpupower'
find ./ \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
 | xargs rm -f
rm -f ./cpupower
rm -f ./libcpupower.so*
rm -rf ./po/*.gmo
rm -rf ./po/*.pot
make -C bench O=./ clean
make[2]: Entering directory '/home/acme/git/linux/tools/power/cpupower/bench'
rm -f .//*.o
rm -f .//cpufreq-bench
make[2]: Leaving directory '/home/acme/git/linux/tools/power/cpupower/bench'
make[1]: Leaving directory '/home/acme/git/linux/tools/power/cpupower'
  DESCEND  hv
make[1]: Entering directory '/home/acme/git/linux/tools/hv'
rm -f hv_kvp_daemon hv_vss_daemon hv_fcopy_daemon
make[1]: Leaving directory '/home/acme/git/linux/tools/hv'
  DESCEND  firewire
make[1]: Entering directory '/home/acme/git/linux/tools/firewire'
rm -rf *.o nosy-dump
make[1]: Leaving directory '/home/acme/git/linux/tools/firewire'
  DESCEND  lguest
make[1]: Entering directory '/home/acme/git/linux/tools/lguest'
rm -f lguest
rm -rf include
make[1]: Leaving directory '/home/acme/git/linux/tools/lguest'
  DESCEND  perf
make[1]: Entering directory '/home/acme/git/linux/tools/perf'
  CLEAN    libtraceevent
  CLEAN    libapi
  CLEAN    libsubcmd
  CLEAN    libbpf
  CLEAN    libsubcmd
  CLEAN    config
  CLEAN    core-objs
  CLEAN    core-progs
  CLEAN    core-gen
  SUBDIR   Documentation
  CLEAN    Documentation
  CLEAN    python
make[1]: Leaving directory '/home/acme/git/linux/tools/perf'
  DESCEND  testing/selftests
make[1]: Entering directory '/home/acme/git/linux/tools/testing/selftests'
for TARGET in breakpoints cpu-hotplug efivarfs exec firmware ftrace futex kcmp lib membarrier memfd memory-hotplug mount mqueue net powerpc pstore ptrace seccomp size static_keys sysctl timers user vm x86 zram; do \
	make -C $TARGET clean; \
done;
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/breakpoints'
rm -fr breakpoint_test
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/breakpoints'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/cpu-hotplug'
make[2]: Nothing to be done for 'clean'.
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/cpu-hotplug'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/efivarfs'
rm -f open-unlink create-read
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/efivarfs'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/exec'
rm -rf execveat execveat.symlink execveat.denatured script subdir subdir.moved execveat.moved xxxxx*
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/exec'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/firmware'
make[2]: Nothing to be done for 'clean'.
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/firmware'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/ftrace'
rm -rf logs/*
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/ftrace'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/futex'
for DIR in functional; do make -C $DIR clean ; done
make[3]: Entering directory '/home/acme/git/linux/tools/testing/selftests/futex/functional'
rm -f futex_wait_timeout futex_wait_wouldblock futex_requeue_pi futex_requeue_pi_signal_restart futex_requeue_pi_mismatched_ops futex_wait_uninitialized_heap futex_wait_private_mapped_file
make[3]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/futex/functional'
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/futex'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/kcmp'
rm -f kcmp_test kcmp-test-file
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/kcmp'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/lib'
make[2]: Nothing to be done for 'clean'.
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/lib'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/membarrier'
rm -f membarrier_test
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/membarrier'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/memfd'
rm -f memfd_test fuse_test
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/memfd'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/memory-hotplug'
make[2]: Nothing to be done for 'clean'.
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/memory-hotplug'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/mount'
rm -f unprivileged-remount-test
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/mount'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/mqueue'
rm -f mq_open_tests mq_perf_tests
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/mqueue'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/net'
rm -f socket psock_fanout psock_tpacket reuseport_bpf
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/net'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/powerpc'
rm -f tags
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/powerpc'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/pstore'
rm -rf logs/* *uuid
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/pstore'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/ptrace'
rm -f peeksiginfo
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/ptrace'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/seccomp'
rm -f seccomp_bpf
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/seccomp'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/size'
rm -f get_size
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/size'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/static_keys'
make[2]: Nothing to be done for 'clean'.
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/static_keys'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/sysctl'
make[2]: Nothing to be done for 'clean'.
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/sysctl'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/timers'
rm -f posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat inconsistency-check raw_skew threadtest rtctest alarmtimer-suspend valid-adjtimex adjtick change_skew skew_consistency clocksource-switch leap-a-day leapcrash set-tai set-2038
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/timers'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/user'
make[2]: Nothing to be done for 'clean'.
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/user'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/vm'
rm -f compaction_test hugepage-mmap hugepage-shm map_hugetlb mlock2-tests on-fault-limit thuge-gen transhuge-stress userfaultfd
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/vm'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/x86'
rm -f single_step_syscall_32 sysret_ss_attrs_32 syscall_nt_32 ptrace_syscall_32 entry_from_vm86_32 syscall_arg_fault_32 sigreturn_32 test_syscall_vdso_32 unwind_vdso_32 test_FCMOV_32 test_FCOMI_32 test_FISTTP_32 ldt_gdt_32 vdso_restorer_32 single_step_syscall_64 sysret_ss_attrs_64 syscall_nt_64 ptrace_syscall_64
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/x86'
make[2]: Entering directory '/home/acme/git/linux/tools/testing/selftests/zram'
rm -f err.log
make[2]: Leaving directory '/home/acme/git/linux/tools/testing/selftests/zram'
make[1]: Leaving directory '/home/acme/git/linux/tools/testing/selftests'
  DESCEND  power/x86/turbostat
make[1]: Entering directory '/home/acme/git/linux/tools/power/x86/turbostat'
make[1]: Leaving directory '/home/acme/git/linux/tools/power/x86/turbostat'
  DESCEND  spi
make[1]: Entering directory '/home/acme/git/linux/tools/spi'
rm -f spidev_test spidev_fdx
make[1]: Leaving directory '/home/acme/git/linux/tools/spi'
  DESCEND  usb
make[1]: Entering directory '/home/acme/git/linux/tools/usb'
rm -f testusb ffs-test
make[1]: Leaving directory '/home/acme/git/linux/tools/usb'
  DESCEND  virtio
make[1]: Entering directory '/home/acme/git/linux/tools/virtio'
rm -f *.o vringh_test virtio_test vhost_test/*.o vhost_test/.*.cmd \
              vhost_test/Module.symvers vhost_test/modules.order *.d
make[1]: Leaving directory '/home/acme/git/linux/tools/virtio'
  DESCEND  vm
make[1]: Entering directory '/home/acme/git/linux/tools/vm'
rm -f page-types slabinfo page_owner_sort
make -C ../lib/api clean
make[2]: Entering directory '/home/acme/git/linux/tools/lib/api'
  CLEAN    libapi
make[2]: Leaving directory '/home/acme/git/linux/tools/lib/api'
make[1]: Leaving directory '/home/acme/git/linux/tools/vm'
  DESCEND  net
make[1]: Entering directory '/home/acme/git/linux/tools/net'
rm -rf *.o bpf_jit_disasm bpf_dbg bpf_asm bpf_exp.yacc.* bpf_exp.lex.*
make[1]: Leaving directory '/home/acme/git/linux/tools/net'
  DESCEND  iio
make[1]: Entering directory '/home/acme/git/linux/tools/iio'
rm -f *.o iio_event_monitor lsiio generic_buffer
make[1]: Leaving directory '/home/acme/git/linux/tools/iio'
  DESCEND  power/x86/x86_energy_perf_policy
make[1]: Entering directory '/home/acme/git/linux/tools/power/x86/x86_energy_perf_policy'
rm -f x86_energy_perf_policy
make[1]: Leaving directory '/home/acme/git/linux/tools/power/x86/x86_energy_perf_policy'
  DESCEND  thermal/tmon
make[1]: Entering directory '/home/acme/git/linux/tools/thermal/tmon'
find . -name "*.o" | xargs rm -f
rm -f tmon
make[1]: Leaving directory '/home/acme/git/linux/tools/thermal/tmon'
  DESCEND  laptop/freefall
make[1]: Entering directory '/home/acme/git/linux/tools/laptop/freefall'
rm -f freefall
make[1]: Leaving directory '/home/acme/git/linux/tools/laptop/freefall'
  DESCEND  build
make[1]: Entering directory '/home/acme/git/linux/tools/build'
  CLEAN    fixdep
make[1]: Leaving directory '/home/acme/git/linux/tools/build'
  DESCEND  lib/bpf
make[1]: Entering directory '/home/acme/git/linux/tools/lib/bpf'
  CLEAN    libbpf
  CLEAN    core-gen
make[1]: Leaving directory '/home/acme/git/linux/tools/lib/bpf'
  DESCEND  lib/subcmd
make[1]: Entering directory '/home/acme/git/linux/tools/lib/subcmd'
  CLEAN    libsubcmd
make[1]: Leaving directory '/home/acme/git/linux/tools/lib/subcmd'
  DESCEND  lib/lockdep
make[1]: Entering directory '/home/acme/git/linux/tools/lib/lockdep'
git statusrm -f *.o *~ liblockdep.a liblockdep.so.4.4.0 *.a *liblockdep*.so*  .*.d .*.cmd
rm -f tags TAGS
make[1]: Leaving directory '/home/acme/git/linux/tools/lib/lockdep'
make: Leaving directory '/home/acme/git/linux/tools'
[acme@jouet linux]$ git status
On branch perf/core
Untracked files:
  (use "git add <file>..." to include in what will be committed)

	perf.data
	perf.data.old
	tools/perf/BUILD_TEST_FEATURE_DUMP
	tools/perf/make_no_libbpf
	tools/perf/make_no_newt

nothing added to commit but untracked files present (use "git add" to track)
[acme@jouet linux]$ rm -f tools/perf/BUILD_TEST_FEATURE_DUMP tools/perf/make_no_libbpf tools/perf/make_no_newt
[acme@jouet linux]$ perf stat make -C tools/perf build-test
make: Entering directory '/home/acme/git/linux/tools/perf'
Testing Makefile
- /home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP: cd . && make FEATURE_DUMP_COPY=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP  feature-dump
cd . && make FEATURE_DUMP_COPY=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP feature-dump
- make_doc: cd . && make -f Makefile   DESTDIR=/tmp/tmp.lLyAWJ2KUJ doc FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP
- make_no_libperl: cd . && make -f Makefile   DESTDIR=/tmp/tmp.iPREXpyGhh NO_LIBPERL=1 FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP
cd . && make -f Makefile DESTDIR=/tmp/tmp.iPREXpyGhh NO_LIBPERL=1 FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP
  BUILD:   Doing 'make -j4' parallel build
  GEN      common-cmds.h
  CC       fixdep.o
  CC       perf-read-vdso32
In file included from /usr/include/features.h:389:0,
                 from /usr/include/stdio.h:27,
                 from perf-read-vdso.c:1:
/usr/include/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory
compilation terminated.
Makefile.perf:416: recipe for target 'perf-read-vdso32' failed
make[4]: *** [perf-read-vdso32] Error 1
make[4]: *** Waiting for unfinished jobs....
  LD       fixdep-in.o
  LINK     fixdep
  PERF_VERSION = 4.4.g80fcfd7
Makefile:68: recipe for target 'all' failed
make[3]: *** [all] Error 2
  test: test -x ./perf
tests/make:274: recipe for target 'make_no_libperl' failed
make[2]: *** [make_no_libperl] Error 1
tests/make:7: recipe for target 'all' failed
make[1]: *** [all] Error 2
Makefile:81: recipe for target 'build-test' failed
make: *** [build-test] Error 2
make: Leaving directory '/home/acme/git/linux/tools/perf'

 Performance counter stats for 'make -C tools/perf build-test':

      61660.694764      task-clock (msec)         #    3.494 CPUs utilized          
            13,836      context-switches          #    0.224 K/sec                  
             3,707      cpu-migrations            #    0.060 K/sec                  
         1,151,896      page-faults               #    0.019 M/sec                  
   190,413,042,688      cycles                    #    3.088 GHz                    
   <not supported>      stalled-cycles-frontend  
   <not supported>      stalled-cycles-backend   
   206,130,087,553      instructions              #    1.08  insns per cycle        
    48,604,926,191      branches                  #  788.264 M/sec                  
       603,468,422      branch-misses             #    1.24% of all branches        

      17.647845909 seconds time elapsed

[acme@jouet linux]$ 

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


#1318570 — Re: [PATCH 05/54] perf build: Use feature dump file for build-test

From"Wangnan (F)" <wangnan0@huawei.com>
Date2016-01-27 03:40 +0100
SubjectRe: [PATCH 05/54] perf build: Use feature dump file for build-test
Message-ID<qVobw-53J-11@gated-at.bofh.it>
In reply to#1318137

On 2016/1/27 0:59, Arnaldo Carvalho de Melo wrote:
> Em Mon, Jan 25, 2016 at 09:55:52AM +0000, Wang Nan escreveu:
>> To prevent feature check run too many times, this patch utilizes
>> previous introduced feature-dump make target and FEATURES_DUMP
>> variable, makes sure the feature checkers run only once when doing
>> build-test for normal test cases.
>>
>> Signed-off-by: Wang Nan <wangnan0@huawei.com>
>> Cc: Jiri Olsa <jolsa@kernel.org>
>> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
>> Cc: Namhyung Kim <namhyung@kernel.org>
> So, I'm having this problem when this patch is applied.

[SNIP]

>
> nothing added to commit but untracked files present (use "git add" to track)
> [acme@jouet linux]$ rm -f tools/perf/BUILD_TEST_FEATURE_DUMP tools/perf/make_no_libbpf tools/perf/make_no_newt
> [acme@jouet linux]$ perf stat make -C tools/perf build-test
> make: Entering directory '/home/acme/git/linux/tools/perf'
> Testing Makefile
> - /home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP: cd . && make FEATURE_DUMP_COPY=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP  feature-dump
> cd . && make FEATURE_DUMP_COPY=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP feature-dump
> - make_doc: cd . && make -f Makefile   DESTDIR=/tmp/tmp.lLyAWJ2KUJ doc FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP
> - make_no_libperl: cd . && make -f Makefile   DESTDIR=/tmp/tmp.iPREXpyGhh NO_LIBPERL=1 FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP
> cd . && make -f Makefile DESTDIR=/tmp/tmp.iPREXpyGhh NO_LIBPERL=1 FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP
>    BUILD:   Doing 'make -j4' parallel build
>    GEN      common-cmds.h
>    CC       fixdep.o
>    CC       perf-read-vdso32
> In file included from /usr/include/features.h:389:0,
>                   from /usr/include/stdio.h:27,
>                   from perf-read-vdso.c:1:
> /usr/include/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory
> compilation terminated.
> Makefile.perf:416: recipe for target 'perf-read-vdso32' failed
> make[4]: *** [perf-read-vdso32] Error 1
> make[4]: *** Waiting for unfinished jobs....
>    LD       fixdep-in.o
>    LINK     fixdep
>    PERF_VERSION = 4.4.g80fcfd7
> Makefile:68: recipe for target 'all' failed
> make[3]: *** [all] Error 2
>    test: test -x ./perf
> tests/make:274: recipe for target 'make_no_libperl' failed
> make[2]: *** [make_no_libperl] Error 1
> tests/make:7: recipe for target 'all' failed
> make[1]: *** [all] Error 2
> Makefile:81: recipe for target 'build-test' failed
> make: *** [build-test] Error 2
> make: Leaving directory '/home/acme/git/linux/tools/perf'
>

This is the problem of test-compile-32. In 
./tools/build/feature/test-compile.c,
we check the '-m32' compiler flag but don't check include files.

Could you please have a look at your environment? Do you have 
glibc-devel-i386
installed? What's the result of

  $ gcc -m32 tools/build/feature/test-compile.c

I guess in your platform you can compile and link test-compile.c without
gnu/stubs-32.h. Then we need to improve test-compile.c to make it check 
headers
also.

Another question is why you don't meet this error before this patch. It 
seems
test-compile-32 should also pass...

Thank you.

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


#1318976 — Re: [PATCH 05/54] perf build: Use feature dump file for build-test

FromArnaldo Carvalho de Melo <acme@redhat.com>
Date2016-01-27 15:00 +0100
SubjectRe: [PATCH 05/54] perf build: Use feature dump file for build-test
Message-ID<qVyNB-4jj-25@gated-at.bofh.it>
In reply to#1318570
Em Wed, Jan 27, 2016 at 10:36:54AM +0800, Wangnan (F) escreveu:
> On 2016/1/27 0:59, Arnaldo Carvalho de Melo wrote:
> >Em Mon, Jan 25, 2016 at 09:55:52AM +0000, Wang Nan escreveu:
> >>To prevent feature check run too many times, this patch utilizes
> >>previous introduced feature-dump make target and FEATURES_DUMP
> >>variable, makes sure the feature checkers run only once when doing
> >>build-test for normal test cases.

<SNIP>

> >So, I'm having this problem when this patch is applied.
 
> [SNIP]
> 
> >nothing added to commit but untracked files present (use "git add" to track)
> >[acme@jouet linux]$ rm -f tools/perf/BUILD_TEST_FEATURE_DUMP tools/perf/make_no_libbpf tools/perf/make_no_newt
> >[acme@jouet linux]$ perf stat make -C tools/perf build-test
> >make: Entering directory '/home/acme/git/linux/tools/perf'
> >Testing Makefile
> >- /home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP: cd . && make FEATURE_DUMP_COPY=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP  feature-dump
> >cd . && make FEATURE_DUMP_COPY=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP feature-dump
> >- make_doc: cd . && make -f Makefile   DESTDIR=/tmp/tmp.lLyAWJ2KUJ doc FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP
> >- make_no_libperl: cd . && make -f Makefile   DESTDIR=/tmp/tmp.iPREXpyGhh NO_LIBPERL=1 FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP
> >cd . && make -f Makefile DESTDIR=/tmp/tmp.iPREXpyGhh NO_LIBPERL=1 FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP
> >   BUILD:   Doing 'make -j4' parallel build
> >   GEN      common-cmds.h
> >   CC       fixdep.o
> >   CC       perf-read-vdso32
> >In file included from /usr/include/features.h:389:0,
> >                  from /usr/include/stdio.h:27,
> >                  from perf-read-vdso.c:1:
> >/usr/include/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory
> >compilation terminated.
> >Makefile.perf:416: recipe for target 'perf-read-vdso32' failed
> >make[4]: *** [perf-read-vdso32] Error 1
> >make[4]: *** Waiting for unfinished jobs....
> >   LD       fixdep-in.o
> >   LINK     fixdep
> >   PERF_VERSION = 4.4.g80fcfd7
> >Makefile:68: recipe for target 'all' failed
> >make[3]: *** [all] Error 2
> >   test: test -x ./perf
> >tests/make:274: recipe for target 'make_no_libperl' failed
> >make[2]: *** [make_no_libperl] Error 1
> >tests/make:7: recipe for target 'all' failed
> >make[1]: *** [all] Error 2
> >Makefile:81: recipe for target 'build-test' failed
> >make: *** [build-test] Error 2
> >make: Leaving directory '/home/acme/git/linux/tools/perf'
 
> This is the problem of test-compile-32. In
> ./tools/build/feature/test-compile.c, we check the '-m32' compiler
> flag but don't check include files.
 
> Could you please have a look at your environment? Do you have
> glibc-devel-i386 installed? What's the result of
 
>  $ gcc -m32 tools/build/feature/test-compile.c

[acme@jouet linux]$ gcc -m32 tools/build/feature/test-compile.c 
/usr/bin/ld: cannot find crt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-redhat-linux/5.3.1/libgcc_s.so when searching for -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lc
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-redhat-linux/5.3.1/libgcc_s.so when searching for -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find crtn.o: No such file or directory
collect2: error: ld returned 1 exit status
[acme@jouet linux]$ 

But this fails, in the same fashion, on my older devel machine, with fedora 21.
 
> I guess in your platform you can compile and link test-compile.c without
> gnu/stubs-32.h. Then we need to improve test-compile.c to make it check
> headers also.

Yeah, on the old system (fedora 21 x86_64 ivy bridge) there is no stups-32.h
file anywhere, nor in the new one (fedora 23 x86_64 broadwell).
 
> Another question is why you don't meet this error before this patch.  It
> seems test-compile-32 should also pass...

What happened is that I got a new notebook, and in the new one, as you
correctly analysed, probably a file required for building that file is not
present, I'll dig deeper and try to add an informative message about
requirements to the test in question...

But the curious thing is that what I have now in my perf/core branch
passes 'make -C tools/perf build-test', its only when this specific
patch is added that it fails.

I.e. it seems that by reusing the features dump file we're triggering some
conditional compilation differently than without this reuse. I wonder if we
could try first having a mechanism that would do as before, i.e. the feature
detection, and then compare with what is passed via the FEATURES_DUMP= make
command line variable, flagging any difference, that would help us figure out
this problem...

Anyway, I'm running:

  make -C tools clean ; perf stat make -C tools/perf build-test

To recheck that it is just when this patch gets applied that the build fails.

- Arnaldo

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


#1318870 — [PATCH] tools build: Check basic headers for test-compile feature checker

FromWang Nan <wangnan0@huawei.com>
Date2016-01-27 12:30 +0100
Subject[PATCH] tools build: Check basic headers for test-compile feature checker
Message-ID<qVwsq-2JC-9@gated-at.bofh.it>
In reply to#1318137
An i386 binary can be linked correctly even without correct headers.
Which causes problem. For exmaple:

 $ mv /tmp/oxygen_root/usr/include/gnu/stubs-32.h{,.bak}
 $ make tools/perf
 Auto-detecting system features:
 ...                         dwarf: [ on  ]
 [SNIP]
   GEN      common-cmds.h
   CC       perf-read-vdso32
 In file included from /tmp/oxygen_root/usr/include/features.h:388:0,
                  from /tmp/oxygen_root/usr/include/stdio.h:27,
                  from perf-read-vdso.c:1:
 /tmp/oxygen_root/usr/include/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory
  # include <gnu/stubs-32.h>
                           ^
 compilation terminated.
 ...

In this patch we checks not only compiler and linker, but also basic
headers in test-compile test case, make it fail on a platform
lacking correct headers.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Li Zefan <lizefan@huawei.com>
---
 tools/build/feature/test-compile.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/build/feature/test-compile.c b/tools/build/feature/test-compile.c
index 31dbf45..c54e655 100644
--- a/tools/build/feature/test-compile.c
+++ b/tools/build/feature/test-compile.c
@@ -1,4 +1,6 @@
+#include <stdio.h>
 int main(void)
 {
+	printf("Hello World!\n");
 	return 0;
 }
-- 
1.8.3.4

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


#1318942 — Re: [PATCH] tools build: Check basic headers for test-compile feature checker

FromJiri Olsa <jolsa@redhat.com>
Date2016-01-27 14:30 +0100
SubjectRe: [PATCH] tools build: Check basic headers for test-compile feature checker
Message-ID<qVykA-43Z-53@gated-at.bofh.it>
In reply to#1318870
On Wed, Jan 27, 2016 at 11:22:22AM +0000, Wang Nan wrote:
> An i386 binary can be linked correctly even without correct headers.
> Which causes problem. For exmaple:
> 
>  $ mv /tmp/oxygen_root/usr/include/gnu/stubs-32.h{,.bak}
>  $ make tools/perf
>  Auto-detecting system features:
>  ...                         dwarf: [ on  ]
>  [SNIP]
>    GEN      common-cmds.h
>    CC       perf-read-vdso32
>  In file included from /tmp/oxygen_root/usr/include/features.h:388:0,
>                   from /tmp/oxygen_root/usr/include/stdio.h:27,
>                   from perf-read-vdso.c:1:
>  /tmp/oxygen_root/usr/include/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory
>   # include <gnu/stubs-32.h>
>                            ^
>  compilation terminated.
>  ...
> 
> In this patch we checks not only compiler and linker, but also basic
> headers in test-compile test case, make it fail on a platform
> lacking correct headers.
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Jiri Olsa <jolsa@kernel.org>
> Cc: Li Zefan <lizefan@huawei.com>

nice ;-)

Acked-by: Jiri Olsa <jolsa@kernel.org>

thanks,
jirka

> ---
>  tools/build/feature/test-compile.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/tools/build/feature/test-compile.c b/tools/build/feature/test-compile.c
> index 31dbf45..c54e655 100644
> --- a/tools/build/feature/test-compile.c
> +++ b/tools/build/feature/test-compile.c
> @@ -1,4 +1,6 @@
> +#include <stdio.h>
>  int main(void)
>  {
> +	printf("Hello World!\n");
>  	return 0;
>  }
> -- 
> 1.8.3.4
> 

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


#1318974 — Re: [PATCH] tools build: Check basic headers for test-compile feature checker

FromArnaldo Carvalho de Melo <acme@redhat.com>
Date2016-01-27 15:00 +0100
SubjectRe: [PATCH] tools build: Check basic headers for test-compile feature checker
Message-ID<qVyNB-4jj-21@gated-at.bofh.it>
In reply to#1318942
Em Wed, Jan 27, 2016 at 02:23:59PM +0100, Jiri Olsa escreveu:
> On Wed, Jan 27, 2016 at 11:22:22AM +0000, Wang Nan wrote:
> > An i386 binary can be linked correctly even without correct headers.
> > Which causes problem. For exmaple:
> > 
> >  $ mv /tmp/oxygen_root/usr/include/gnu/stubs-32.h{,.bak}
> >  $ make tools/perf
> >  Auto-detecting system features:
> >  ...                         dwarf: [ on  ]
> >  [SNIP]
> >    GEN      common-cmds.h
> >    CC       perf-read-vdso32
> >  In file included from /tmp/oxygen_root/usr/include/features.h:388:0,
> >                   from /tmp/oxygen_root/usr/include/stdio.h:27,
> >                   from perf-read-vdso.c:1:
> >  /tmp/oxygen_root/usr/include/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory
> >   # include <gnu/stubs-32.h>
> >                            ^
> >  compilation terminated.
> >  ...
> > 
> > In this patch we checks not only compiler and linker, but also basic
> > headers in test-compile test case, make it fail on a platform
> > lacking correct headers.
> > 
> > Signed-off-by: Wang Nan <wangnan0@huawei.com>
> > Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> > Cc: Jiri Olsa <jolsa@kernel.org>
> > Cc: Li Zefan <lizefan@huawei.com>
> 
> nice ;-)

Ok, so this one may explain that problem when reusing the features dump
file, trying applying this and then the other...
 
> Acked-by: Jiri Olsa <jolsa@kernel.org>
> 
> thanks,
> jirka
> 
> > ---
> >  tools/build/feature/test-compile.c | 2 ++
> >  1 file changed, 2 insertions(+)
> > 
> > diff --git a/tools/build/feature/test-compile.c b/tools/build/feature/test-compile.c
> > index 31dbf45..c54e655 100644
> > --- a/tools/build/feature/test-compile.c
> > +++ b/tools/build/feature/test-compile.c
> > @@ -1,4 +1,6 @@
> > +#include <stdio.h>
> >  int main(void)
> >  {
> > +	printf("Hello World!\n");
> >  	return 0;
> >  }
> > -- 
> > 1.8.3.4
> > 

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


#1316430 — [PATCH 51/54] perf record: Rename variable to make code clear

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 51/54] perf record: Rename variable to make code clear
Message-ID<qUMpB-2q9-47@gated-at.bofh.it>
In reply to#1316351
record__mmap_read() write data from ring buffer into perf.data.
'head' is maintained by kernel, points to the last writtend record.
'old' is maintained by perf, points to the record read in previous
round. record__mmap_read() saves data from 'old' to 'head' to
perf.data. The naming of variables are not easy to read. In addition,
when dealing with backward writing ring buffer, the md->prev pointer
should point to 'head' instead of the last byte it got.

Add start and end pointer to make code clear and set md->prev to 'head'
instead of the moved 'old' pointer. This patch doesn't change
behavior since:

    buf = &data[old & md->mask];
    size = head - old;
    old += size;     <--- Here, old == head

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
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/builtin-record.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 69f089f..12147ef 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -91,17 +91,18 @@ static int record__mmap_read(struct record *rec, int idx)
 	struct perf_mmap *md = &rec->evlist->mmap[idx];
 	u64 head = perf_mmap__read_head(md);
 	u64 old = md->prev;
+	u64 end = head, start = old;
 	unsigned char *data = md->base + page_size;
 	unsigned long size;
 	void *buf;
 	int rc = 0;
 
-	if (old == head)
+	if (start == end)
 		return 0;
 
 	rec->samples++;
 
-	size = head - old;
+	size = end - start;
 	if (size > (unsigned long)(md->mask) + 1) {
 		WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
 
@@ -110,10 +111,10 @@ static int record__mmap_read(struct record *rec, int idx)
 		return 0;
 	}
 
-	if ((old & md->mask) + size != (head & md->mask)) {
-		buf = &data[old & md->mask];
-		size = md->mask + 1 - (old & md->mask);
-		old += size;
+	if ((start & md->mask) + size != (end & md->mask)) {
+		buf = &data[start & md->mask];
+		size = md->mask + 1 - (start & md->mask);
+		start += size;
 
 		if (record__write(rec, buf, size) < 0) {
 			rc = -1;
@@ -121,16 +122,16 @@ static int record__mmap_read(struct record *rec, int idx)
 		}
 	}
 
-	buf = &data[old & md->mask];
-	size = head - old;
-	old += size;
+	buf = &data[start & md->mask];
+	size = end - start;
+	start += size;
 
 	if (record__write(rec, buf, size) < 0) {
 		rc = -1;
 		goto out;
 	}
 
-	md->prev = old;
+	md->prev = head;
 	perf_evlist__mmap_consume(rec->evlist, idx);
 out:
 	return rc;
-- 
1.8.3.4

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


#1316431 — [PATCH 09/54] perf tools: Add API to config maps in bpf object

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 09/54] perf tools: Add API to config maps in bpf object
Message-ID<qUMpB-2q9-49@gated-at.bofh.it>
In reply to#1316351
bpf__config_obj() is introduced as a core API to config BPF object
after loading. One configuration option of maps is introduced. After
this patch BPF object can accept configuration like:

 maps:my_map.value=1234

(maps.my_map.value looks pretty. However, there's a small but hard
to fixed problem related to flex's greedy matching. Please see [1].
Choose ':' to avoid it in a simpler way.)

This patch is more complex than the work it really does because the
consideration of extension. In designing of BPF map configuration,
following things should be considered:

 1. Array indices selection: perf should allow user setting different
    value to different slots in an array, with syntax like:
    maps:my_map.value[0,3...6]=1234;

 2. A map can be config by different config terms, each for a part
    of it. For example, set each slot to pid of a thread;

 3. Type of value: integer is not the only valid value type. Perf
    event can also be put into a map after commit 35578d7984003097af2b1e3
    (bpf: Implement function bpf_perf_event_read() that get the selected
    hardware PMU conuter);

 4. For hash table, it is possible to use string or other as key;

 5. It is possible that map configuration is unable to be setup
    during parsing. Perf event is an example.

Therefore, this patch does following:

 1. Instead of updating map element during parsing, this patch stores
    map config options in 'struct bpf_map_priv'. Following patches
    would apply those configs at proper time;

 2. Link map operations to a list so a map can have multiple config
    terms attached, so different parts can be configured separately;

 3. Make 'struct bpf_map_priv' extensible so following patches can
    add new types of keys and operations;

 4. Use bpf_config_map_funcs array to support more maps config options.

Since the patch changing event parser to parse BPF object config is
relative large, I put in another commit. Code in this patch
could be tested after applying next patch.

[1] http://lkml.kernel.org/g/564ED621.4050500@huawei.com

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: 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/bpf-loader.c | 266 +++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/bpf-loader.h |  38 +++++++
 2 files changed, 304 insertions(+)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 540a7ef..7d361aa 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -739,6 +739,251 @@ int bpf__foreach_tev(struct bpf_object *obj,
 	return 0;
 }
 
+enum bpf_map_op_type {
+	BPF_MAP_OP_SET_VALUE,
+};
+
+enum bpf_map_key_type {
+	BPF_MAP_KEY_ALL,
+};
+
+struct bpf_map_op {
+	struct list_head list;
+	enum bpf_map_op_type op_type;
+	enum bpf_map_key_type key_type;
+	union {
+		u64 value;
+	} v;
+};
+
+struct bpf_map_priv {
+	struct list_head ops_list;
+};
+
+static void
+bpf_map_op__free(struct bpf_map_op *op)
+{
+	struct list_head *list = &op->list;
+	/*
+	 * bpf_map_op__free() needs to consider following cases:
+	 *   1. When the op is created but not linked to any list:
+	 *      impossible. This only happen in bpf_map_op__alloc()
+	 *      and it would be freed directly;
+	 *   2. Normal case, when the op is linked to a list;
+	 *   3. After the op has already be removed.
+	 * Thanks to list.h, if it has removed by list_del() then
+	 * list->{next,prev} should have been set to LIST_POISON{1,2}.
+	 */
+	if ((list->next != LIST_POISON1) && (list->prev != LIST_POISON2))
+		list_del(list);
+	free(op);
+}
+
+static void
+bpf_map_priv__clear(struct bpf_map *map __maybe_unused,
+		    void *_priv)
+{
+	struct bpf_map_priv *priv = _priv;
+	struct bpf_map_op *pos, *n;
+
+	list_for_each_entry_safe(pos, n, &priv->ops_list, list)
+		bpf_map_op__free(pos);
+	free(priv);
+}
+
+static struct bpf_map_op *
+bpf_map_op__alloc(struct bpf_map *map)
+{
+	struct bpf_map_op *op;
+	struct bpf_map_priv *priv;
+	const char *map_name;
+	int err;
+
+	map_name = bpf_map__get_name(map);
+	err = bpf_map__get_private(map, (void **)&priv);
+	if (err) {
+		pr_debug("Failed to get private from map %s\n", map_name);
+		return ERR_PTR(err);
+	}
+
+	if (!priv) {
+		priv = zalloc(sizeof(*priv));
+		if (!priv) {
+			pr_debug("No enough memory to alloc map private\n");
+			return ERR_PTR(-ENOMEM);
+		}
+		INIT_LIST_HEAD(&priv->ops_list);
+
+		if (bpf_map__set_private(map, priv, bpf_map_priv__clear)) {
+			free(priv);
+			return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL);
+		}
+	}
+
+	op = zalloc(sizeof(*op));
+	if (!op) {
+		pr_debug("Failed to alloc bpf_map_op\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	op->key_type = BPF_MAP_KEY_ALL;
+	list_add_tail(&op->list, &priv->ops_list);
+	return op;
+}
+
+static int
+bpf__obj_config_map_array_value(struct bpf_map *map,
+				struct parse_events_term *term)
+{
+	struct bpf_map_def def;
+	struct bpf_map_op *op;
+	const char *map_name;
+	int err;
+
+	map_name = bpf_map__get_name(map);
+
+	err = bpf_map__get_def(map, &def);
+	if (err) {
+		pr_debug("Unable to get map definition from '%s'\n",
+			 map_name);
+		return -BPF_LOADER_ERRNO__INTERNAL;
+	}
+
+	if (def.type != BPF_MAP_TYPE_ARRAY) {
+		pr_debug("Map %s type is not BPF_MAP_TYPE_ARRAY\n",
+			 map_name);
+		return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
+	}
+	if (def.key_size < sizeof(unsigned int)) {
+		pr_debug("Map %s has incorrect key size\n", map_name);
+		return -BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE;
+	}
+	switch (def.value_size) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		break;
+	default:
+		pr_debug("Map %s has incorrect value size\n", map_name);
+		return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUESIZE;
+	}
+
+	op = bpf_map_op__alloc(map);
+	if (IS_ERR(op))
+		return PTR_ERR(op);
+	op->op_type = BPF_MAP_OP_SET_VALUE;
+	op->v.value = term->val.num;
+	return 0;
+}
+
+static int
+bpf__obj_config_map_value(struct bpf_map *map,
+			  struct parse_events_term *term,
+			  struct perf_evlist *evlist __maybe_unused)
+{
+	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_NUM)
+		return bpf__obj_config_map_array_value(map, term);
+
+	pr_debug("ERROR: wrong value type\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 *,
+			   struct perf_evlist *);
+};
+
+struct bpf_obj_config_map_func bpf_obj_config_map_funcs[] = {
+	{"value", bpf__obj_config_map_value},
+};
+
+static int
+bpf__obj_config_map(struct bpf_object *obj,
+		    struct parse_events_term *term,
+		    struct perf_evlist *evlist,
+		    int *key_scan_pos)
+{
+	/* key is "maps:<mapname>.<config opt>" */
+	char *map_name = strdup(term->config + sizeof("maps:") - 1);
+	struct bpf_map *map;
+	int err = -BPF_LOADER_ERRNO__OBJCONF_OPT;
+	char *map_opt;
+	size_t i;
+
+	if (!map_name)
+		return -ENOMEM;
+
+	map_opt = strchr(map_name, '.');
+	if (!map_opt) {
+		pr_debug("ERROR: Invalid map config: %s\n", map_name);
+		goto out;
+	}
+
+	*map_opt++ = '\0';
+	if (*map_opt == '\0') {
+		pr_debug("ERROR: Invalid map option: %s\n", term->config);
+		goto out;
+	}
+
+	map = bpf_object__get_map_by_name(obj, map_name);
+	if (!map) {
+		pr_debug("ERROR: Map %s is not exist\n", map_name);
+		err = -BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST;
+		goto out;
+	}
+
+	*key_scan_pos += map_opt - map_name;
+	for (i = 0; i < ARRAY_SIZE(bpf_obj_config_map_funcs); i++) {
+		struct bpf_obj_config_map_func *func =
+				&bpf_obj_config_map_funcs[i];
+
+		if (strcmp(map_opt, func->config_opt) == 0) {
+			err = func->config_func(map, term, evlist);
+			goto out;
+		}
+	}
+
+	pr_debug("ERROR: invalid config option '%s' for maps\n",
+		 map_opt);
+	err = -BPF_LOADER_ERRNO__OBJCONF_MAP_OPT;
+out:
+	free(map_name);
+	if (!err)
+		key_scan_pos += strlen(map_opt);
+	return err;
+}
+
+int bpf__config_obj(struct bpf_object *obj,
+		    struct parse_events_term *term,
+		    struct perf_evlist *evlist,
+		    int *error_pos)
+{
+	int key_scan_pos = 0;
+	int err;
+
+	if (!obj || !term || !term->config)
+		return -EINVAL;
+
+	if (!prefixcmp(term->config, "maps:")) {
+		key_scan_pos = sizeof("maps:") - 1;
+		err = bpf__obj_config_map(obj, term, evlist, &key_scan_pos);
+		goto out;
+	}
+	err = -BPF_LOADER_ERRNO__OBJCONF_OPT;
+out:
+	if (error_pos)
+		*error_pos = key_scan_pos;
+	return err;
+
+}
+
 #define ERRNO_OFFSET(e)		((e) - __BPF_LOADER_ERRNO__START)
 #define ERRCODE_OFFSET(c)	ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)
 #define NR_ERRNO	(__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)
@@ -753,6 +998,14 @@ static const char *bpf_loader_strerror_table[NR_ERRNO] = {
 	[ERRCODE_OFFSET(PROLOGUE)]	= "Failed to generate prologue",
 	[ERRCODE_OFFSET(PROLOGUE2BIG)]	= "Prologue too big for program",
 	[ERRCODE_OFFSET(PROLOGUEOOB)]	= "Offset out of bound for prologue",
+	[ERRCODE_OFFSET(OBJCONF_OPT)]	= "Invalid object config option",
+	[ERRCODE_OFFSET(OBJCONF_CONF)]	= "Config value not set (lost '=')",
+	[ERRCODE_OFFSET(OBJCONF_MAP_OPT)]	= "Invalid object maps config option",
+	[ERRCODE_OFFSET(OBJCONF_MAP_NOTEXIST)]	= "Target map not exist",
+	[ERRCODE_OFFSET(OBJCONF_MAP_VALUE)]	= "Incorrect value type for map",
+	[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",
 };
 
 static int
@@ -872,3 +1125,16 @@ int bpf__strerror_load(struct bpf_object *obj,
 	bpf__strerror_end(buf, size);
 	return 0;
 }
+
+int bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused,
+			     struct parse_events_term *term __maybe_unused,
+			     struct perf_evlist *evlist __maybe_unused,
+			     int *error_pos __maybe_unused, int err,
+			     char *buf, size_t size)
+{
+	bpf__strerror_head(err, buf, size);
+	bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE,
+			    "Can't use this config term to this type of 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 6fdc045..2464db9 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -10,6 +10,7 @@
 #include <string.h>
 #include <bpf/libbpf.h>
 #include "probe-event.h"
+#include "evlist.h"
 #include "debug.h"
 
 enum bpf_loader_errno {
@@ -24,10 +25,19 @@ enum bpf_loader_errno {
 	BPF_LOADER_ERRNO__PROLOGUE,	/* Failed to generate prologue */
 	BPF_LOADER_ERRNO__PROLOGUE2BIG,	/* Prologue too big for program */
 	BPF_LOADER_ERRNO__PROLOGUEOOB,	/* Offset out of bound for prologue */
+	BPF_LOADER_ERRNO__OBJCONF_OPT,	/* Invalid object config option */
+	BPF_LOADER_ERRNO__OBJCONF_CONF,	/* Config value not set (lost '=')) */
+	BPF_LOADER_ERRNO__OBJCONF_MAP_OPT,	/* Invalid object maps config option */
+	BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST,	/* Target map not exist */
+	BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE,	/* Incorrect value type for map */
+	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__END,
 };
 
 struct bpf_object;
+struct parse_events_term;
 #define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
 
 typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
@@ -53,6 +63,14 @@ int bpf__strerror_load(struct bpf_object *obj, int err,
 		       char *buf, size_t size);
 int bpf__foreach_tev(struct bpf_object *obj,
 		     bpf_prog_iter_callback_t func, void *arg);
+
+int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term,
+		    struct perf_evlist *evlist, int *error_pos);
+int bpf__strerror_config_obj(struct bpf_object *obj,
+			     struct parse_events_term *term,
+			     struct perf_evlist *evlist,
+			     int *error_pos, int err, char *buf,
+			     size_t size);
 #else
 static inline struct bpf_object *
 bpf__prepare_load(const char *filename __maybe_unused,
@@ -84,6 +102,15 @@ bpf__foreach_tev(struct bpf_object *obj __maybe_unused,
 }
 
 static inline int
+bpf__config_obj(struct bpf_object *obj __maybe_unused,
+		struct parse_events_term *term __maybe_unused,
+		struct perf_evlist *evlist __maybe_unused,
+		int *error_pos __maybe_unused)
+{
+	return 0;
+}
+
+static inline int
 __bpf_strerror(char *buf, size_t size)
 {
 	if (!size)
@@ -118,5 +145,16 @@ static inline int bpf__strerror_load(struct bpf_object *obj __maybe_unused,
 {
 	return __bpf_strerror(buf, size);
 }
+
+static inline int
+bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused,
+			 struct parse_events_term *term __maybe_unused,
+			 struct perf_evlist *evlist __maybe_unused,
+			 int *error_pos __maybe_unused,
+			 int err __maybe_unused,
+			 char *buf, size_t size)
+{
+	return __bpf_strerror(buf, size);
+}
 #endif
 #endif
-- 
1.8.3.4

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


#1316432 — [PATCH 48/54] perf tools: Enable overwrite settings

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 48/54] perf tools: Enable overwrite settings
Message-ID<qUMpB-2q9-55@gated-at.bofh.it>
In reply to#1316351
This patch allows following config terms and option:

 # perf record --overwrite ...

   Globally set following events to overwrite;

 # perf record --event cycles/overwrite/ ...
 # perf record --event cycles/no-overwrite/ ...

Set specific events to be overwrite or no-overwrite.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
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/builtin-record.c    |  1 +
 tools/perf/perf.h              |  1 +
 tools/perf/util/evsel.c        |  4 ++++
 tools/perf/util/evsel.h        |  2 ++
 tools/perf/util/parse-events.c | 14 ++++++++++++++
 tools/perf/util/parse-events.h |  4 +++-
 tools/perf/util/parse-events.l |  2 ++
 7 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 503eee9..f416296 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1271,6 +1271,7 @@ struct option __record_options[] = {
 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
 			&record.opts.no_inherit_set,
 			"child tasks do not inherit counters"),
+	OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
 		     "number of mmap data pages and AUX area tracing mmap pages",
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 00c25b1..ea7f6f5 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -58,6 +58,7 @@ struct record_opts {
 	bool	     full_auxtrace;
 	bool	     auxtrace_snapshot_mode;
 	bool	     record_switch_events;
+	bool	     overwrite;
 	unsigned int freq;
 	unsigned int mmap_pages;
 	unsigned int auxtrace_mmap_pages;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 66a47ba..d9b1f1d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -670,6 +670,9 @@ static void apply_config_terms(struct perf_evsel *evsel,
 			 */
 			attr->inherit = term->val.inherit ? 1 : 0;
 			break;
+		case PERF_EVSEL__CONFIG_TERM_OVERWRITE:
+			evsel->overwrite = term->val.overwrite ? 1 : 0;
+			break;
 		default:
 			break;
 		}
@@ -745,6 +748,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
 
 	attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
 	attr->inherit	    = !opts->no_inherit;
+	evsel->overwrite    = opts->overwrite;
 
 	perf_evsel__set_sample_bit(evsel, IP);
 	perf_evsel__set_sample_bit(evsel, TID);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index f5c7433..f987b0b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -44,6 +44,7 @@ enum {
 	PERF_EVSEL__CONFIG_TERM_CALLGRAPH,
 	PERF_EVSEL__CONFIG_TERM_STACK_USER,
 	PERF_EVSEL__CONFIG_TERM_INHERIT,
+	PERF_EVSEL__CONFIG_TERM_OVERWRITE,
 	PERF_EVSEL__CONFIG_TERM_MAX,
 };
 
@@ -57,6 +58,7 @@ struct perf_evsel_config_term {
 		char	*callgraph;
 		u64	stack_user;
 		bool	inherit;
+		bool	overwrite;
 	} val;
 };
 
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 03d18f4..c1d4f39 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -855,6 +855,12 @@ do {									   \
 	case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
 		CHECK_TYPE_VAL(NUM);
 		break;
+	case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
+		CHECK_TYPE_VAL(NUM);
+		break;
+	case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
+		CHECK_TYPE_VAL(NUM);
+		break;
 	case PARSE_EVENTS__TERM_TYPE_NAME:
 		CHECK_TYPE_VAL(STR);
 		break;
@@ -892,6 +898,8 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
 	case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
 	case PARSE_EVENTS__TERM_TYPE_INHERIT:
 	case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
+	case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
+	case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
 		return config_term_common(attr, term, err);
 	default:
 		if (err) {
@@ -961,6 +969,12 @@ do {								\
 		case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
 			ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1);
 			break;
+		case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
+			ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0);
+			break;
+		case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
+			ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1);
+			break;
 		default:
 			break;
 		}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index c34615f..29cc804 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -68,7 +68,9 @@ enum {
 	PARSE_EVENTS__TERM_TYPE_CALLGRAPH,
 	PARSE_EVENTS__TERM_TYPE_STACKSIZE,
 	PARSE_EVENTS__TERM_TYPE_NOINHERIT,
-	PARSE_EVENTS__TERM_TYPE_INHERIT
+	PARSE_EVENTS__TERM_TYPE_INHERIT,
+	PARSE_EVENTS__TERM_TYPE_NOOVERWRITE,
+	PARSE_EVENTS__TERM_TYPE_OVERWRITE,
 };
 
 struct parse_events_array {
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 27d567f..2ef6f96 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -202,6 +202,8 @@ call-graph		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
 stack-size		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
 inherit			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
 no-inherit		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
+overwrite		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }
+no-overwrite		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }
 ,			{ return ','; }
 "/"			{ BEGIN(INITIAL); return '/'; }
 {name_minus}		{ return str(yyscanner, PE_NAME); }
-- 
1.8.3.4

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


#1316433 — [PATCH 02/54] perf bpf: Check relocation target section

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 02/54] perf bpf: Check relocation target section
Message-ID<qUMpC-2q9-61@gated-at.bofh.it>
In reply to#1316351
Libbpf should check target section before doing relocation to ensure
the relocation is correct. If not, a bug in LLVM causes error. See [1].
Also, if an incorrect BPF script uses both global variable and
map, global variable whould be treated as map and be relocated
without error.

This patch saves id of map section into obj->efile and compare
target section of a relocation symbol against it during relocation.

Previous patch introduces a test case about this problem.
After this patch:

 # ~/perf test BPF
 37: Test BPF filter                                          :
 37.1: Test basic BPF filtering                               : Ok
 37.2: Test BPF prologue generation                           : Ok
 37.3: Test BPF relocation checker                            : Ok

 # perf test -v BPF
 ...
 37.3: Test BPF relocation checker                            :
 ...
 libbpf: loading object '[bpf_relocation_test]' from buffer
 libbpf: section .strtab, size 126, link 0, flags 0, type=3
 libbpf: section .text, size 0, link 0, flags 6, type=1
 libbpf: section .data, size 0, link 0, flags 3, type=1
 libbpf: section .bss, size 0, link 0, flags 3, type=8
 libbpf: section func=sys_write, size 104, link 0, flags 6, type=1
 libbpf: found program func=sys_write
 libbpf: section .relfunc=sys_write, size 16, link 10, flags 0, type=9
 libbpf: section maps, size 16, link 0, flags 3, type=1
 libbpf: maps in [bpf_relocation_test]: 16 bytes
 libbpf: section license, size 4, link 0, flags 3, type=1
 libbpf: license of [bpf_relocation_test] is GPL
 libbpf: section version, size 4, link 0, flags 3, type=1
 libbpf: kernel version of [bpf_relocation_test] is 40400
 libbpf: section .symtab, size 144, link 1, flags 0, type=2
 libbpf: map 0 is "my_table"
 libbpf: collecting relocating info for: 'func=sys_write'
 libbpf: Program 'func=sys_write' contains non-map related relo data pointing to section 65522
 bpf: failed to load buffer
 Compile BPF program failed.
 test child finished with 0
 ---- end ----
 Test BPF filter subtest 2: Ok

[1] https://llvm.org/bugs/show_bug.cgi?id=26243

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Li Zefan <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/lib/bpf/libbpf.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 8334a5a..7e543c3 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -201,6 +201,7 @@ struct bpf_object {
 			Elf_Data *data;
 		} *reloc;
 		int nr_reloc;
+		int maps_shndx;
 	} efile;
 	/*
 	 * All loaded bpf_object is linked in a list, which is
@@ -350,6 +351,7 @@ static struct bpf_object *bpf_object__new(const char *path,
 	 */
 	obj->efile.obj_buf = obj_buf;
 	obj->efile.obj_buf_sz = obj_buf_sz;
+	obj->efile.maps_shndx = -1;
 
 	obj->loaded = false;
 
@@ -529,12 +531,12 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
 }
 
 static int
-bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
+bpf_object__init_maps_name(struct bpf_object *obj)
 {
 	int i;
 	Elf_Data *symbols = obj->efile.symbols;
 
-	if (!symbols || maps_shndx < 0)
+	if (!symbols || obj->efile.maps_shndx < 0)
 		return -EINVAL;
 
 	for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
@@ -544,7 +546,7 @@ bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
 
 		if (!gelf_getsym(symbols, i, &sym))
 			continue;
-		if (sym.st_shndx != maps_shndx)
+		if (sym.st_shndx != obj->efile.maps_shndx)
 			continue;
 
 		map_name = elf_strptr(obj->efile.elf,
@@ -572,7 +574,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 	Elf *elf = obj->efile.elf;
 	GElf_Ehdr *ep = &obj->efile.ehdr;
 	Elf_Scn *scn = NULL;
-	int idx = 0, err = 0, maps_shndx = -1;
+	int idx = 0, err = 0;
 
 	/* Elf is corrupted/truncated, avoid calling elf_strptr. */
 	if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
@@ -625,7 +627,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 		else if (strcmp(name, "maps") == 0) {
 			err = bpf_object__init_maps(obj, data->d_buf,
 						    data->d_size);
-			maps_shndx = idx;
+			obj->efile.maps_shndx = idx;
 		} else if (sh.sh_type == SHT_SYMTAB) {
 			if (obj->efile.symbols) {
 				pr_warning("bpf: multiple SYMTAB in %s\n",
@@ -674,8 +676,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 		pr_warning("Corrupted ELF file: index of strtab invalid\n");
 		return LIBBPF_ERRNO__FORMAT;
 	}
-	if (maps_shndx >= 0)
-		err = bpf_object__init_maps_name(obj, maps_shndx);
+	if (obj->efile.maps_shndx >= 0)
+		err = bpf_object__init_maps_name(obj);
 out:
 	return err;
 }
@@ -697,7 +699,8 @@ bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx)
 static int
 bpf_program__collect_reloc(struct bpf_program *prog,
 			   size_t nr_maps, GElf_Shdr *shdr,
-			   Elf_Data *data, Elf_Data *symbols)
+			   Elf_Data *data, Elf_Data *symbols,
+			   int maps_shndx)
 {
 	int i, nrels;
 
@@ -724,9 +727,6 @@ bpf_program__collect_reloc(struct bpf_program *prog,
 			return -LIBBPF_ERRNO__FORMAT;
 		}
 
-		insn_idx = rel.r_offset / sizeof(struct bpf_insn);
-		pr_debug("relocation: insn_idx=%u\n", insn_idx);
-
 		if (!gelf_getsym(symbols,
 				 GELF_R_SYM(rel.r_info),
 				 &sym)) {
@@ -735,6 +735,15 @@ bpf_program__collect_reloc(struct bpf_program *prog,
 			return -LIBBPF_ERRNO__FORMAT;
 		}
 
+		if (sym.st_shndx != maps_shndx) {
+			pr_warning("Program '%s' contains non-map related relo data pointing to section %u\n",
+				   prog->section_name, sym.st_shndx);
+			return -LIBBPF_ERRNO__RELOC;
+		}
+
+		insn_idx = rel.r_offset / sizeof(struct bpf_insn);
+		pr_debug("relocation: insn_idx=%u\n", insn_idx);
+
 		if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
 			pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n",
 				   insn_idx, insns[insn_idx].code);
@@ -863,7 +872,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
 
 		err = bpf_program__collect_reloc(prog, nr_maps,
 						 shdr, data,
-						 obj->efile.symbols);
+						 obj->efile.symbols,
+						 obj->efile.maps_shndx);
 		if (err)
 			return err;
 	}
-- 
1.8.3.4

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


#1316435 — [PATCH 21/54] perf core: Add backward attribute to perf event

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 21/54] perf core: Add backward attribute to perf event
Message-ID<qUMpC-2q9-65@gated-at.bofh.it>
In reply to#1316351
In perf_event_attr a new bit 'write_backward' is appended to indicate
this event should write ring buffer from its end to beginning.

In perf_output_begin(), prepare ring buffer according this bit.

This patch introduces small overhead into perf_output_begin():
an extra memory read and a conditional branch. Further patch can remove
this overhead by using custom output handler.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: He Kuang <hekuang@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: Jiri Olsa <jolsa@kernel.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 include/linux/perf_event.h      | 5 +++++
 include/uapi/linux/perf_event.h | 3 ++-
 kernel/events/core.c            | 7 +++++++
 kernel/events/ring_buffer.c     | 2 ++
 4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index f9828a4..54c3fb2 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1032,6 +1032,11 @@ static inline bool has_aux(struct perf_event *event)
 	return event->pmu->setup_aux;
 }
 
+static inline bool is_write_backward(struct perf_event *event)
+{
+	return !!event->attr.write_backward;
+}
+
 extern int perf_output_begin(struct perf_output_handle *handle,
 			     struct perf_event *event, unsigned int size);
 extern void perf_output_end(struct perf_output_handle *handle);
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index a3c1903..43fc8d2 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -340,7 +340,8 @@ struct perf_event_attr {
 				comm_exec      :  1, /* flag comm events that are due to an exec */
 				use_clockid    :  1, /* use @clockid for time fields */
 				context_switch :  1, /* context switch data */
-				__reserved_1   : 37;
+				write_backward :  1, /* Write ring buffer from end to beginning */
+				__reserved_1   : 36;
 
 	union {
 		__u32		wakeup_events;	  /* wakeup every n events */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index f79c4be..8ad22a5 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -8107,6 +8107,13 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
 		goto out;
 
 	/*
+	 * Either writing ring buffer from beginning or from end.
+	 * Mixing is not allowed.
+	 */
+	if (is_write_backward(output_event) != is_write_backward(event))
+		goto out;
+
+	/*
 	 * If both events generate aux data, they must be on the same PMU
 	 */
 	if (has_aux(event) && has_aux(output_event) &&
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 0684e880..28543e1 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -233,6 +233,8 @@ out:
 int perf_output_begin(struct perf_output_handle *handle,
 		      struct perf_event *event, unsigned int size)
 {
+	if (unlikely(is_write_backward(event)))
+		return __perf_output_begin(handle, event, size, true);
 	return __perf_output_begin(handle, event, size, false);
 }
 
-- 
1.8.3.4

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


#1316436 — [PATCH 04/54] perf build: Select all feature checkers for feature-dump

FromWang Nan <wangnan0@huawei.com>
Date2016-01-25 11:20 +0100
Subject[PATCH 04/54] perf build: Select all feature checkers for feature-dump
Message-ID<qUMpC-2q9-67@gated-at.bofh.it>
In reply to#1316351
Set FEATURE_TESTS to 'all' so all possible feature checkers are
executed. Without this setting the output feature dump file miss
some feature, for example, liberity. Select all checker so we won't
get an incomplete feature dump file.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/Makefile.perf | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 97ce869..4d2c0e4 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -165,7 +165,16 @@ ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
 endif
 endif
 
+# Set FEATURE_TESTS to 'all' so all possible feature checkers are
+# executed. Without this setting the output feature dump file miss
+# some feature, for example, liberity. Select all checker so we won't
+# get an incomplete feature dump file.
 ifeq ($(config),1)
+ifdef MAKECMDGOALS
+ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump)
+FEATURE_TESTS := all
+endif
+endif
 include config/Makefile
 endif
 
-- 
1.8.3.4

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


Page 3 of 4 — ← Prev page 1 2 [3] 4  Next page →

Back to top | Article view | linux.kernel


csiph-web