All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/5] perf util: bpf perf improvements
@ 2021-04-25 21:43 Song Liu
  2021-04-25 21:43 ` [PATCH v5 1/5] perf util: move bpf_perf definitions to a libperf header Song Liu
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: Song Liu @ 2021-04-25 21:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: kernel-team, acme, acme, namhyung, jolsa, songliubraving, Song Liu

This patches set improves bpf_perf (perf-stat --bpf-counter) by
 1) exposing key definitions to a libperf header;
 2) adding compatibility check for perf_attr_map;
 3) introducing config stat.bpf-counter-events.
 4) introducing 'b' modify to event parser.
 5) add bpf_counter_ops->disable()

Changes v4 => v5:
1. Add bpf_counter_ops->disable(). (Namhyung, Jiri)

Changes v3 => v4:
1. Improve the logic that decides when to skip read_affinity_counters().
   (Jiri)
2. Clean up a condition in bpf_counters.c:read_counters(). (Jiri)

Changes v2 => v3:
1. Add 'b' modifier. (Jiri)
2. Allow configuring stat.bpf-counter-events with any event name (instead
  of limiting to hardware events). (Jiri)

Changes v1 => v2:
1. Separte 2/3 from 1/3. (Jiri)
2. Rename bperf.h to bpf_perf.h. (Jiri)
3. Other small fixes/optimizations. (Jiri)

Song Liu (5):
  perf util: move bpf_perf definitions to a libperf header
  perf bpf: check perf_attr_map is compatible with the perf binary
  perf-stat: introduce config stat.bpf-counter-events
  perf-stat: introduce ':b' modifier
  perf-stat: introduce bpf_counter_ops->disable()

 tools/lib/perf/include/perf/bpf_perf.h | 31 +++++++++++
 tools/perf/Documentation/perf-stat.txt |  2 +
 tools/perf/builtin-stat.c              | 42 +++++++++------
 tools/perf/util/bpf_counter.c          | 75 +++++++++++++++++---------
 tools/perf/util/bpf_counter.h          |  7 +++
 tools/perf/util/config.c               |  4 ++
 tools/perf/util/evlist.c               |  4 ++
 tools/perf/util/evsel.c                | 22 ++++++++
 tools/perf/util/evsel.h                |  9 ++++
 tools/perf/util/parse-events.c         |  8 ++-
 tools/perf/util/parse-events.l         |  2 +-
 tools/perf/util/target.h               |  5 --
 12 files changed, 162 insertions(+), 49 deletions(-)
 create mode 100644 tools/lib/perf/include/perf/bpf_perf.h

--
2.30.2

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v5 1/5] perf util: move bpf_perf definitions to a libperf header
  2021-04-25 21:43 [PATCH v5 0/5] perf util: bpf perf improvements Song Liu
@ 2021-04-25 21:43 ` Song Liu
  2021-04-25 21:43 ` [PATCH v5 2/5] perf bpf: check perf_attr_map is compatible with the perf binary Song Liu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 15+ messages in thread
From: Song Liu @ 2021-04-25 21:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: kernel-team, acme, acme, namhyung, jolsa, songliubraving, Song Liu

By following the same protocol, other tools can share hardware PMCs with
perf. Move perf_event_attr_map_entry and BPF_PERF_DEFAULT_ATTR_MAP_PATH to
bpf_perf.h for other tools to use.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/lib/perf/include/perf/bpf_perf.h | 31 ++++++++++++++++++++++++++
 tools/perf/util/bpf_counter.c          | 27 +++-------------------
 2 files changed, 34 insertions(+), 24 deletions(-)
 create mode 100644 tools/lib/perf/include/perf/bpf_perf.h

diff --git a/tools/lib/perf/include/perf/bpf_perf.h b/tools/lib/perf/include/perf/bpf_perf.h
new file mode 100644
index 0000000000000..e7cf6ba7b674b
--- /dev/null
+++ b/tools/lib/perf/include/perf/bpf_perf.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
+#ifndef __LIBPERF_BPF_PERF_H
+#define __LIBPERF_BPF_PERF_H
+
+#include <linux/types.h>  /* for __u32 */
+
+/*
+ * bpf_perf uses a hashmap, the attr_map, to track all the leader programs.
+ * The hashmap is pinned in bpffs. flock() on this file is used to ensure
+ * no concurrent access to the attr_map.  The key of attr_map is struct
+ * perf_event_attr, and the value is struct perf_event_attr_map_entry.
+ *
+ * struct perf_event_attr_map_entry contains two __u32 IDs, bpf_link of the
+ * leader prog, and the diff_map. Each perf-stat session holds a reference
+ * to the bpf_link to make sure the leader prog is attached to sched_switch
+ * tracepoint.
+ *
+ * Since the hashmap only contains IDs of the bpf_link and diff_map, it
+ * does not hold any references to the leader program. Once all perf-stat
+ * sessions of these events exit, the leader prog, its maps, and the
+ * perf_events will be freed.
+ */
+struct perf_event_attr_map_entry {
+	__u32 link_id;
+	__u32 diff_map_id;
+};
+
+/* default attr_map name */
+#define BPF_PERF_DEFAULT_ATTR_MAP_PATH "perf_attr_map"
+
+#endif /* __LIBPERF_BPF_PERF_H */
diff --git a/tools/perf/util/bpf_counter.c b/tools/perf/util/bpf_counter.c
index 81d1df3c4ec0e..be484ddbbd5be 100644
--- a/tools/perf/util/bpf_counter.c
+++ b/tools/perf/util/bpf_counter.c
@@ -14,6 +14,7 @@
 #include <bpf/btf.h>
 #include <bpf/libbpf.h>
 #include <api/fs/fs.h>
+#include <perf/bpf_perf.h>
 
 #include "bpf_counter.h"
 #include "counts.h"
@@ -29,28 +30,6 @@
 #include "bpf_skel/bperf_leader.skel.h"
 #include "bpf_skel/bperf_follower.skel.h"
 
-/*
- * bperf uses a hashmap, the attr_map, to track all the leader programs.
- * The hashmap is pinned in bpffs. flock() on this file is used to ensure
- * no concurrent access to the attr_map.  The key of attr_map is struct
- * perf_event_attr, and the value is struct perf_event_attr_map_entry.
- *
- * struct perf_event_attr_map_entry contains two __u32 IDs, bpf_link of the
- * leader prog, and the diff_map. Each perf-stat session holds a reference
- * to the bpf_link to make sure the leader prog is attached to sched_switch
- * tracepoint.
- *
- * Since the hashmap only contains IDs of the bpf_link and diff_map, it
- * does not hold any references to the leader program. Once all perf-stat
- * sessions of these events exit, the leader prog, its maps, and the
- * perf_events will be freed.
- */
-struct perf_event_attr_map_entry {
-	__u32 link_id;
-	__u32 diff_map_id;
-};
-
-#define DEFAULT_ATTR_MAP_PATH "fs/bpf/perf_attr_map"
 #define ATTR_MAP_SIZE 16
 
 static inline void *u64_to_ptr(__u64 ptr)
@@ -341,8 +320,8 @@ static int bperf_lock_attr_map(struct target *target)
 	if (target->attr_map) {
 		scnprintf(path, PATH_MAX, "%s", target->attr_map);
 	} else {
-		scnprintf(path, PATH_MAX, "%s/%s", sysfs__mountpoint(),
-			  DEFAULT_ATTR_MAP_PATH);
+		scnprintf(path, PATH_MAX, "%s/fs/bpf/%s", sysfs__mountpoint(),
+			  BPF_PERF_DEFAULT_ATTR_MAP_PATH);
 	}
 
 	if (access(path, F_OK)) {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v5 2/5] perf bpf: check perf_attr_map is compatible with the perf binary
  2021-04-25 21:43 [PATCH v5 0/5] perf util: bpf perf improvements Song Liu
  2021-04-25 21:43 ` [PATCH v5 1/5] perf util: move bpf_perf definitions to a libperf header Song Liu
@ 2021-04-25 21:43 ` Song Liu
  2021-04-25 21:43 ` [PATCH v5 3/5] perf-stat: introduce config stat.bpf-counter-events Song Liu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 15+ messages in thread
From: Song Liu @ 2021-04-25 21:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: kernel-team, acme, acme, namhyung, jolsa, songliubraving, Song Liu

perf_attr_map could be shared among different version of perf binary. Add
bperf_attr_map_compatible() to check whether the existing attr_map is
compatible with current perf binary.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/perf/util/bpf_counter.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/tools/perf/util/bpf_counter.c b/tools/perf/util/bpf_counter.c
index be484ddbbd5be..5de991ab46af9 100644
--- a/tools/perf/util/bpf_counter.c
+++ b/tools/perf/util/bpf_counter.c
@@ -312,6 +312,20 @@ static __u32 bpf_map_get_id(int fd)
 	return map_info.id;
 }
 
+static bool bperf_attr_map_compatible(int attr_map_fd)
+{
+	struct bpf_map_info map_info = {0};
+	__u32 map_info_len = sizeof(map_info);
+	int err;
+
+	err = bpf_obj_get_info_by_fd(attr_map_fd, &map_info, &map_info_len);
+
+	if (err)
+		return false;
+	return (map_info.key_size == sizeof(struct perf_event_attr)) &&
+		(map_info.value_size == sizeof(struct perf_event_attr_map_entry));
+}
+
 static int bperf_lock_attr_map(struct target *target)
 {
 	char path[PATH_MAX];
@@ -346,6 +360,11 @@ static int bperf_lock_attr_map(struct target *target)
 			return -1;
 	}
 
+	if (!bperf_attr_map_compatible(map_fd)) {
+		close(map_fd);
+		return -1;
+
+	}
 	err = flock(map_fd, LOCK_EX);
 	if (err) {
 		close(map_fd);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v5 3/5] perf-stat: introduce config stat.bpf-counter-events
  2021-04-25 21:43 [PATCH v5 0/5] perf util: bpf perf improvements Song Liu
  2021-04-25 21:43 ` [PATCH v5 1/5] perf util: move bpf_perf definitions to a libperf header Song Liu
  2021-04-25 21:43 ` [PATCH v5 2/5] perf bpf: check perf_attr_map is compatible with the perf binary Song Liu
@ 2021-04-25 21:43 ` Song Liu
  2021-04-25 21:43 ` [PATCH v5 4/5] perf-stat: introduce ':b' modifier Song Liu
  2021-04-25 21:43 ` [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable() Song Liu
  4 siblings, 0 replies; 15+ messages in thread
From: Song Liu @ 2021-04-25 21:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: kernel-team, acme, acme, namhyung, jolsa, songliubraving, Song Liu

Currently, to use BPF to aggregate perf event counters, the user uses
--bpf-counters option. Enable "use bpf by default" events with a config
option, stat.bpf-counter-events. Events with name in the option will use
BPF.

This also enables mixed BPF event and regular event in the same sesssion.
For example:

   perf config stat.bpf-counter-events=instructions
   perf stat -e instructions,cs

The second command will use BPF for "instructions" but not "cs".

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/perf/Documentation/perf-stat.txt |  2 ++
 tools/perf/builtin-stat.c              | 42 +++++++++++++++-----------
 tools/perf/util/bpf_counter.c          |  3 +-
 tools/perf/util/config.c               |  4 +++
 tools/perf/util/evsel.c                | 22 ++++++++++++++
 tools/perf/util/evsel.h                |  8 +++++
 tools/perf/util/target.h               |  5 ---
 7 files changed, 63 insertions(+), 23 deletions(-)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 6ec5960b08c3d..f10e24da23e90 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -97,6 +97,8 @@ report::
 	Use BPF programs to aggregate readings from perf_events.  This
 	allows multiple perf-stat sessions that are counting the same metric (cycles,
 	instructions, etc.) to share hardware counters.
+	To use BPF programs on common events by default, use
+	"perf config stat.bpf-counter-events=<list_of_events>".
 
 --bpf-attr-map::
 	With option "--bpf-counters", different perf-stat sessions share
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 2a2c15cac80a3..8729eed30b668 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -160,6 +160,7 @@ static const char *smi_cost_attrs = {
 };
 
 static struct evlist	*evsel_list;
+static bool all_counters_use_bpf = true;
 
 static struct target target = {
 	.uid	= UINT_MAX,
@@ -399,6 +400,9 @@ static int read_affinity_counters(struct timespec *rs)
 	struct affinity affinity;
 	int i, ncpus, cpu;
 
+	if (all_counters_use_bpf)
+		return 0;
+
 	if (affinity__setup(&affinity) < 0)
 		return -1;
 
@@ -413,6 +417,8 @@ static int read_affinity_counters(struct timespec *rs)
 		evlist__for_each_entry(evsel_list, counter) {
 			if (evsel__cpu_iter_skip(counter, cpu))
 				continue;
+			if (evsel__is_bpf(counter))
+				continue;
 			if (!counter->err) {
 				counter->err = read_counter_cpu(counter, rs,
 								counter->cpu_iter - 1);
@@ -429,6 +435,9 @@ static int read_bpf_map_counters(void)
 	int err;
 
 	evlist__for_each_entry(evsel_list, counter) {
+		if (!evsel__is_bpf(counter))
+			continue;
+
 		err = bpf_counter__read(counter);
 		if (err)
 			return err;
@@ -439,14 +448,10 @@ static int read_bpf_map_counters(void)
 static void read_counters(struct timespec *rs)
 {
 	struct evsel *counter;
-	int err;
 
 	if (!stat_config.stop_read_counter) {
-		if (target__has_bpf(&target))
-			err = read_bpf_map_counters();
-		else
-			err = read_affinity_counters(rs);
-		if (err < 0)
+		if (read_bpf_map_counters() ||
+		    read_affinity_counters(rs))
 			return;
 	}
 
@@ -535,12 +540,13 @@ static int enable_counters(void)
 	struct evsel *evsel;
 	int err;
 
-	if (target__has_bpf(&target)) {
-		evlist__for_each_entry(evsel_list, evsel) {
-			err = bpf_counter__enable(evsel);
-			if (err)
-				return err;
-		}
+	evlist__for_each_entry(evsel_list, evsel) {
+		if (!evsel__is_bpf(evsel))
+			continue;
+
+		err = bpf_counter__enable(evsel);
+		if (err)
+			return err;
 	}
 
 	if (stat_config.initial_delay < 0) {
@@ -784,11 +790,11 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 	if (affinity__setup(&affinity) < 0)
 		return -1;
 
-	if (target__has_bpf(&target)) {
-		evlist__for_each_entry(evsel_list, counter) {
-			if (bpf_counter__load(counter, &target))
-				return -1;
-		}
+	evlist__for_each_entry(evsel_list, counter) {
+		if (bpf_counter__load(counter, &target))
+			return -1;
+		if (!evsel__is_bpf(counter))
+			all_counters_use_bpf = false;
 	}
 
 	evlist__for_each_cpu (evsel_list, i, cpu) {
@@ -805,6 +811,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
 				continue;
 			if (counter->reset_group || counter->errored)
 				continue;
+			if (evsel__is_bpf(counter))
+				continue;
 try_again:
 			if (create_perf_stat_counter(counter, &stat_config, &target,
 						     counter->cpu_iter - 1) < 0) {
diff --git a/tools/perf/util/bpf_counter.c b/tools/perf/util/bpf_counter.c
index 5de991ab46af9..33b1888103dfa 100644
--- a/tools/perf/util/bpf_counter.c
+++ b/tools/perf/util/bpf_counter.c
@@ -790,7 +790,8 @@ int bpf_counter__load(struct evsel *evsel, struct target *target)
 {
 	if (target->bpf_str)
 		evsel->bpf_counter_ops = &bpf_program_profiler_ops;
-	else if (target->use_bpf)
+	else if (target->use_bpf ||
+		 evsel__match_bpf_counter_events(evsel->name))
 		evsel->bpf_counter_ops = &bperf_ops;
 
 	if (evsel->bpf_counter_ops)
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 6bcb5ef221f8c..63d472b336de2 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -18,6 +18,7 @@
 #include "util/hist.h"  /* perf_hist_config */
 #include "util/llvm-utils.h"   /* perf_llvm_config */
 #include "util/stat.h"  /* perf_stat__set_big_num */
+#include "util/evsel.h"  /* evsel__hw_names, evsel__use_bpf_counters */
 #include "build-id.h"
 #include "debug.h"
 #include "config.h"
@@ -460,6 +461,9 @@ static int perf_stat_config(const char *var, const char *value)
 	if (!strcmp(var, "stat.no-csv-summary"))
 		perf_stat__set_no_csv_summary(perf_config_bool(var, value));
 
+	if (!strcmp(var, "stat.bpf-counter-events"))
+		evsel__bpf_counter_events = strdup(value);
+
 	/* Add other config variables here. */
 	return 0;
 }
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 2d2614eeaa20e..080ddcfefbcd2 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -492,6 +492,28 @@ const char *evsel__hw_names[PERF_COUNT_HW_MAX] = {
 	"ref-cycles",
 };
 
+char *evsel__bpf_counter_events;
+
+bool evsel__match_bpf_counter_events(const char *name)
+{
+	int name_len;
+	bool match;
+	char *ptr;
+
+	if (!evsel__bpf_counter_events)
+		return false;
+
+	ptr = strstr(evsel__bpf_counter_events, name);
+	name_len = strlen(name);
+
+	/* check name matches a full token in evsel__bpf_counter_events */
+	match = (ptr != NULL) &&
+		((ptr == evsel__bpf_counter_events) || (*(ptr - 1) == ',')) &&
+		((*(ptr + name_len) == ',') || (*(ptr + name_len) == '\0'));
+
+	return match;
+}
+
 static const char *__evsel__hw_name(u64 config)
 {
 	if (config < PERF_COUNT_HW_MAX && evsel__hw_names[config])
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index eccc4fd5b3eb4..ce4b629d659c2 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -239,6 +239,11 @@ void evsel__calc_id_pos(struct evsel *evsel);
 
 bool evsel__is_cache_op_valid(u8 type, u8 op);
 
+static inline bool evsel__is_bpf(struct evsel *evsel)
+{
+	return evsel->bpf_counter_ops != NULL;
+}
+
 #define EVSEL__MAX_ALIASES 8
 
 extern const char *evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX][EVSEL__MAX_ALIASES];
@@ -246,6 +251,9 @@ extern const char *evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][EVSEL__MAX_ALI
 extern const char *evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX][EVSEL__MAX_ALIASES];
 extern const char *evsel__hw_names[PERF_COUNT_HW_MAX];
 extern const char *evsel__sw_names[PERF_COUNT_SW_MAX];
+extern char *evsel__bpf_counter_events;
+bool evsel__match_bpf_counter_events(const char *name);
+
 int __evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, char *bf, size_t size);
 const char *evsel__name(struct evsel *evsel);
 
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
index 1bce3eb28ef25..4ff56217f2a65 100644
--- a/tools/perf/util/target.h
+++ b/tools/perf/util/target.h
@@ -66,11 +66,6 @@ static inline bool target__has_cpu(struct target *target)
 	return target->system_wide || target->cpu_list;
 }
 
-static inline bool target__has_bpf(struct target *target)
-{
-	return target->bpf_str || target->use_bpf;
-}
-
 static inline bool target__none(struct target *target)
 {
 	return !target__has_task(target) && !target__has_cpu(target);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v5 4/5] perf-stat: introduce ':b' modifier
  2021-04-25 21:43 [PATCH v5 0/5] perf util: bpf perf improvements Song Liu
                   ` (2 preceding siblings ...)
  2021-04-25 21:43 ` [PATCH v5 3/5] perf-stat: introduce config stat.bpf-counter-events Song Liu
@ 2021-04-25 21:43 ` Song Liu
  2021-04-25 21:43 ` [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable() Song Liu
  4 siblings, 0 replies; 15+ messages in thread
From: Song Liu @ 2021-04-25 21:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: kernel-team, acme, acme, namhyung, jolsa, songliubraving, Song Liu

Introduce 'b' modifier to event parser, which means use BPF program to
manage this event. This is the same as --bpf-counters option, but only
applies to this event. For example,

  perf stat -e cycles:b,cs               # use bpf for cycles, but not cs
  perf stat -e cycles,cs --bpf-counters  # use bpf for both cycles and cs

Suggested-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Song Liu <song@kernel.org>
---
 tools/perf/util/bpf_counter.c  | 2 +-
 tools/perf/util/evsel.h        | 1 +
 tools/perf/util/parse-events.c | 8 +++++++-
 tools/perf/util/parse-events.l | 2 +-
 4 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/bpf_counter.c b/tools/perf/util/bpf_counter.c
index 33b1888103dfa..f179f57430253 100644
--- a/tools/perf/util/bpf_counter.c
+++ b/tools/perf/util/bpf_counter.c
@@ -790,7 +790,7 @@ int bpf_counter__load(struct evsel *evsel, struct target *target)
 {
 	if (target->bpf_str)
 		evsel->bpf_counter_ops = &bpf_program_profiler_ops;
-	else if (target->use_bpf ||
+	else if (target->use_bpf || evsel->bpf_counter ||
 		 evsel__match_bpf_counter_events(evsel->name))
 		evsel->bpf_counter_ops = &bperf_ops;
 
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index ce4b629d659c2..8f66cdcb338d0 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -82,6 +82,7 @@ struct evsel {
 		bool			auto_merge_stats;
 		bool			collect_stat;
 		bool			weak_group;
+		bool			bpf_counter;
 		int			bpf_fd;
 		struct bpf_object	*bpf_obj;
 	};
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 8123d218ad17c..46ebd269a98d1 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1804,6 +1804,7 @@ struct event_modifier {
 	int pinned;
 	int weak;
 	int exclusive;
+	int bpf_counter;
 };
 
 static int get_event_modifier(struct event_modifier *mod, char *str,
@@ -1824,6 +1825,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
 	int exclude = eu | ek | eh;
 	int exclude_GH = evsel ? evsel->exclude_GH : 0;
 	int weak = 0;
+	int bpf_counter = 0;
 
 	memset(mod, 0, sizeof(*mod));
 
@@ -1867,6 +1869,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
 			exclusive = 1;
 		} else if (*str == 'W') {
 			weak = 1;
+		} else if (*str == 'b') {
+			bpf_counter = 1;
 		} else
 			break;
 
@@ -1898,6 +1902,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
 	mod->sample_read = sample_read;
 	mod->pinned = pinned;
 	mod->weak = weak;
+	mod->bpf_counter = bpf_counter;
 	mod->exclusive = exclusive;
 
 	return 0;
@@ -1912,7 +1917,7 @@ static int check_modifier(char *str)
 	char *p = str;
 
 	/* The sizeof includes 0 byte as well. */
-	if (strlen(str) > (sizeof("ukhGHpppPSDIWe") - 1))
+	if (strlen(str) > (sizeof("ukhGHpppPSDIWeb") - 1))
 		return -1;
 
 	while (*p) {
@@ -1953,6 +1958,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
 		evsel->sample_read         = mod.sample_read;
 		evsel->precise_max         = mod.precise_max;
 		evsel->weak_group	   = mod.weak;
+		evsel->bpf_counter	   = mod.bpf_counter;
 
 		if (evsel__is_group_leader(evsel)) {
 			evsel->core.attr.pinned = mod.pinned;
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 0b36285a9435d..fb8646cc3e834 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -210,7 +210,7 @@ name_tag	[\'][a-zA-Z_*?\[\]][a-zA-Z0-9_*?\-,\.\[\]:=]*[\']
 name_minus	[a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
 drv_cfg_term	[a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
 /* If you add a modifier you need to update check_modifier() */
-modifier_event	[ukhpPGHSDIWe]+
+modifier_event	[ukhpPGHSDIWeb]+
 modifier_bp	[rwx]{1,3}
 
 %%
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable()
  2021-04-25 21:43 [PATCH v5 0/5] perf util: bpf perf improvements Song Liu
                   ` (3 preceding siblings ...)
  2021-04-25 21:43 ` [PATCH v5 4/5] perf-stat: introduce ':b' modifier Song Liu
@ 2021-04-25 21:43 ` Song Liu
  2021-04-26 21:27   ` Jiri Olsa
  2021-04-27 19:27   ` Arnaldo Carvalho de Melo
  4 siblings, 2 replies; 15+ messages in thread
From: Song Liu @ 2021-04-25 21:43 UTC (permalink / raw)
  To: linux-kernel
  Cc: kernel-team, acme, acme, namhyung, jolsa, songliubraving, Song Liu

Introduce bpf_counter_ops->disable(), which is used stop counting the
event.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/perf/util/bpf_counter.c | 26 ++++++++++++++++++++++++++
 tools/perf/util/bpf_counter.h |  7 +++++++
 tools/perf/util/evlist.c      |  4 ++++
 3 files changed, 37 insertions(+)

diff --git a/tools/perf/util/bpf_counter.c b/tools/perf/util/bpf_counter.c
index f179f57430253..ddb52f748c8e8 100644
--- a/tools/perf/util/bpf_counter.c
+++ b/tools/perf/util/bpf_counter.c
@@ -215,6 +215,17 @@ static int bpf_program_profiler__enable(struct evsel *evsel)
 	return 0;
 }
 
+static int bpf_program_profiler__disable(struct evsel *evsel)
+{
+	struct bpf_counter *counter;
+
+	list_for_each_entry(counter, &evsel->bpf_counter_list, list) {
+		assert(counter->skel != NULL);
+		bpf_prog_profiler_bpf__detach(counter->skel);
+	}
+	return 0;
+}
+
 static int bpf_program_profiler__read(struct evsel *evsel)
 {
 	// perf_cpu_map uses /sys/devices/system/cpu/online
@@ -280,6 +291,7 @@ static int bpf_program_profiler__install_pe(struct evsel *evsel, int cpu,
 struct bpf_counter_ops bpf_program_profiler_ops = {
 	.load       = bpf_program_profiler__load,
 	.enable	    = bpf_program_profiler__enable,
+	.disable    = bpf_program_profiler__disable,
 	.read       = bpf_program_profiler__read,
 	.destroy    = bpf_program_profiler__destroy,
 	.install_pe = bpf_program_profiler__install_pe,
@@ -627,6 +639,12 @@ static int bperf__enable(struct evsel *evsel)
 	return 0;
 }
 
+static int bperf__disable(struct evsel *evsel)
+{
+	evsel->follower_skel->bss->enabled = 0;
+	return 0;
+}
+
 static int bperf__read(struct evsel *evsel)
 {
 	struct bperf_follower_bpf *skel = evsel->follower_skel;
@@ -768,6 +786,7 @@ static int bperf__destroy(struct evsel *evsel)
 struct bpf_counter_ops bperf_ops = {
 	.load       = bperf__load,
 	.enable     = bperf__enable,
+	.disable    = bperf__disable,
 	.read       = bperf__read,
 	.install_pe = bperf__install_pe,
 	.destroy    = bperf__destroy,
@@ -806,6 +825,13 @@ int bpf_counter__enable(struct evsel *evsel)
 	return evsel->bpf_counter_ops->enable(evsel);
 }
 
+int bpf_counter__disable(struct evsel *evsel)
+{
+	if (bpf_counter_skip(evsel))
+		return 0;
+	return evsel->bpf_counter_ops->disable(evsel);
+}
+
 int bpf_counter__read(struct evsel *evsel)
 {
 	if (bpf_counter_skip(evsel))
diff --git a/tools/perf/util/bpf_counter.h b/tools/perf/util/bpf_counter.h
index cb9c532e0a079..d6d907c3dcf92 100644
--- a/tools/perf/util/bpf_counter.h
+++ b/tools/perf/util/bpf_counter.h
@@ -18,6 +18,7 @@ typedef int (*bpf_counter_evsel_install_pe_op)(struct evsel *evsel,
 struct bpf_counter_ops {
 	bpf_counter_evsel_target_op load;
 	bpf_counter_evsel_op enable;
+	bpf_counter_evsel_op disable;
 	bpf_counter_evsel_op read;
 	bpf_counter_evsel_op destroy;
 	bpf_counter_evsel_install_pe_op install_pe;
@@ -32,6 +33,7 @@ struct bpf_counter {
 
 int bpf_counter__load(struct evsel *evsel, struct target *target);
 int bpf_counter__enable(struct evsel *evsel);
+int bpf_counter__disable(struct evsel *evsel);
 int bpf_counter__read(struct evsel *evsel);
 void bpf_counter__destroy(struct evsel *evsel);
 int bpf_counter__install_pe(struct evsel *evsel, int cpu, int fd);
@@ -51,6 +53,11 @@ static inline int bpf_counter__enable(struct evsel *evsel __maybe_unused)
 	return 0;
 }
 
+static inline int bpf_counter__disable(struct evsel *evsel __maybe_unused)
+{
+	return 0;
+}
+
 static inline int bpf_counter__read(struct evsel *evsel __maybe_unused)
 {
 	return -EAGAIN;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d29a8a118973c..e71041c890102 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -17,6 +17,7 @@
 #include "evsel.h"
 #include "debug.h"
 #include "units.h"
+#include "bpf_counter.h"
 #include <internal/lib.h> // page_size
 #include "affinity.h"
 #include "../perf.h"
@@ -421,6 +422,9 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
 	if (affinity__setup(&affinity) < 0)
 		return;
 
+	evlist__for_each_entry(evlist, pos)
+		bpf_counter__disable(pos);
+
 	/* Disable 'immediate' events last */
 	for (imm = 0; imm <= 1; imm++) {
 		evlist__for_each_cpu(evlist, i, cpu) {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable()
  2021-04-25 21:43 ` [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable() Song Liu
@ 2021-04-26 21:27   ` Jiri Olsa
  2021-04-26 22:18     ` Song Liu
  2021-04-27 19:27   ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 15+ messages in thread
From: Jiri Olsa @ 2021-04-26 21:27 UTC (permalink / raw)
  To: Song Liu
  Cc: linux-kernel, kernel-team, acme, acme, namhyung, jolsa, songliubraving

On Sun, Apr 25, 2021 at 02:43:33PM -0700, Song Liu wrote:

SNIP

> +static inline int bpf_counter__disable(struct evsel *evsel __maybe_unused)
> +{
> +	return 0;
> +}
> +
>  static inline int bpf_counter__read(struct evsel *evsel __maybe_unused)
>  {
>  	return -EAGAIN;
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index d29a8a118973c..e71041c890102 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -17,6 +17,7 @@
>  #include "evsel.h"
>  #include "debug.h"
>  #include "units.h"
> +#include "bpf_counter.h"
>  #include <internal/lib.h> // page_size
>  #include "affinity.h"
>  #include "../perf.h"
> @@ -421,6 +422,9 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
>  	if (affinity__setup(&affinity) < 0)
>  		return;
>  
> +	evlist__for_each_entry(evlist, pos)
> +		bpf_counter__disable(pos);

I was wondering why you don't check evsel__is_bpf like
for the enable case.. and realized that we don't skip
bpf evsels in __evlist__enable and __evlist__disable
like we do in read_affinity_counters

so I guess there's extra affinity setup and bunch of
wrong ioctls being called?

jirka


> +
>  	/* Disable 'immediate' events last */
>  	for (imm = 0; imm <= 1; imm++) {
>  		evlist__for_each_cpu(evlist, i, cpu) {
> -- 
> 2.30.2
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable()
  2021-04-26 21:27   ` Jiri Olsa
@ 2021-04-26 22:18     ` Song Liu
  2021-04-27 12:33       ` Jiri Olsa
  0 siblings, 1 reply; 15+ messages in thread
From: Song Liu @ 2021-04-26 22:18 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Song Liu, linux-kernel, Kernel Team, acme, acme, namhyung, jolsa



> On Apr 26, 2021, at 2:27 PM, Jiri Olsa <jolsa@redhat.com> wrote:
> 
> On Sun, Apr 25, 2021 at 02:43:33PM -0700, Song Liu wrote:
> 
> SNIP
> 
>> +static inline int bpf_counter__disable(struct evsel *evsel __maybe_unused)
>> +{
>> +	return 0;
>> +}
>> +
>> static inline int bpf_counter__read(struct evsel *evsel __maybe_unused)
>> {
>> 	return -EAGAIN;
>> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
>> index d29a8a118973c..e71041c890102 100644
>> --- a/tools/perf/util/evlist.c
>> +++ b/tools/perf/util/evlist.c
>> @@ -17,6 +17,7 @@
>> #include "evsel.h"
>> #include "debug.h"
>> #include "units.h"
>> +#include "bpf_counter.h"
>> #include <internal/lib.h> // page_size
>> #include "affinity.h"
>> #include "../perf.h"
>> @@ -421,6 +422,9 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
>> 	if (affinity__setup(&affinity) < 0)
>> 		return;
>> 
>> +	evlist__for_each_entry(evlist, pos)
>> +		bpf_counter__disable(pos);
> 
> I was wondering why you don't check evsel__is_bpf like
> for the enable case.. and realized that we don't skip
> bpf evsels in __evlist__enable and __evlist__disable
> like we do in read_affinity_counters
> 
> so I guess there's extra affinity setup and bunch of
> wrong ioctls being called?

We actually didn't do wrong ioctls because the following check:

       if (... || !pos->core.fd)
                continue;

in __evlist__enable and __evlist__disable. That we don't allocate 
core.fd for is_bpf events. 

It is probably good to be more safe with an extra check of 
evsel__is_bpf(). But it is not required with current code. 

Thanks,
Song

[...]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable()
  2021-04-26 22:18     ` Song Liu
@ 2021-04-27 12:33       ` Jiri Olsa
  2021-04-27 19:30         ` Song Liu
  0 siblings, 1 reply; 15+ messages in thread
From: Jiri Olsa @ 2021-04-27 12:33 UTC (permalink / raw)
  To: Song Liu; +Cc: Song Liu, linux-kernel, Kernel Team, acme, acme, namhyung, jolsa

On Mon, Apr 26, 2021 at 10:18:57PM +0000, Song Liu wrote:
> 
> 
> > On Apr 26, 2021, at 2:27 PM, Jiri Olsa <jolsa@redhat.com> wrote:
> > 
> > On Sun, Apr 25, 2021 at 02:43:33PM -0700, Song Liu wrote:
> > 
> > SNIP
> > 
> >> +static inline int bpf_counter__disable(struct evsel *evsel __maybe_unused)
> >> +{
> >> +	return 0;
> >> +}
> >> +
> >> static inline int bpf_counter__read(struct evsel *evsel __maybe_unused)
> >> {
> >> 	return -EAGAIN;
> >> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> >> index d29a8a118973c..e71041c890102 100644
> >> --- a/tools/perf/util/evlist.c
> >> +++ b/tools/perf/util/evlist.c
> >> @@ -17,6 +17,7 @@
> >> #include "evsel.h"
> >> #include "debug.h"
> >> #include "units.h"
> >> +#include "bpf_counter.h"
> >> #include <internal/lib.h> // page_size
> >> #include "affinity.h"
> >> #include "../perf.h"
> >> @@ -421,6 +422,9 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
> >> 	if (affinity__setup(&affinity) < 0)
> >> 		return;
> >> 
> >> +	evlist__for_each_entry(evlist, pos)
> >> +		bpf_counter__disable(pos);
> > 
> > I was wondering why you don't check evsel__is_bpf like
> > for the enable case.. and realized that we don't skip
> > bpf evsels in __evlist__enable and __evlist__disable
> > like we do in read_affinity_counters
> > 
> > so I guess there's extra affinity setup and bunch of
> > wrong ioctls being called?
> 
> We actually didn't do wrong ioctls because the following check:
> 
>        if (... || !pos->core.fd)
>                 continue;
> 
> in __evlist__enable and __evlist__disable. That we don't allocate 
> core.fd for is_bpf events. 
> 
> It is probably good to be more safe with an extra check of 
> evsel__is_bpf(). But it is not required with current code. 

hum, but it will do all the affinity setup no? for no reason,
if there's no non-bpb event

jirka

> 
> Thanks,
> Song
> 
> [...]
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable()
  2021-04-25 21:43 ` [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable() Song Liu
  2021-04-26 21:27   ` Jiri Olsa
@ 2021-04-27 19:27   ` Arnaldo Carvalho de Melo
  2021-04-27 19:42     ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 15+ messages in thread
From: Arnaldo Carvalho de Melo @ 2021-04-27 19:27 UTC (permalink / raw)
  To: Song Liu; +Cc: linux-kernel, kernel-team, acme, namhyung, jolsa, songliubraving

Em Sun, Apr 25, 2021 at 02:43:33PM -0700, Song Liu escreveu:
> Introduce bpf_counter_ops->disable(), which is used stop counting the
> event.

[acme@five perf]$ perf test -v python
Couldn't bump rlimit(MEMLOCK), failures may take place when creating BPF maps, etc
19: 'import perf' in python                                         :
--- start ---
test child forked, pid 1497924
python usage test: "echo "import sys ; sys.path.append('/tmp/build/perf/python'); import perf" | '/usr/bin/python3' "
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /tmp/build/perf/python/perf.cpython-39-x86_64-linux-gnu.so: undefined symbol: bpf_counter__disable
test child finished with -1
---- end ----
'import perf' in python: FAILED!
[acme@five perf]$

I'll fix this up in my local tree, if you need to respin, please pick
patches from tmp.perf/core, will refresh it later today.

- Arnaldo
 
> Signed-off-by: Song Liu <song@kernel.org>
> ---
>  tools/perf/util/bpf_counter.c | 26 ++++++++++++++++++++++++++
>  tools/perf/util/bpf_counter.h |  7 +++++++
>  tools/perf/util/evlist.c      |  4 ++++
>  3 files changed, 37 insertions(+)
> 
> diff --git a/tools/perf/util/bpf_counter.c b/tools/perf/util/bpf_counter.c
> index f179f57430253..ddb52f748c8e8 100644
> --- a/tools/perf/util/bpf_counter.c
> +++ b/tools/perf/util/bpf_counter.c
> @@ -215,6 +215,17 @@ static int bpf_program_profiler__enable(struct evsel *evsel)
>  	return 0;
>  }
>  
> +static int bpf_program_profiler__disable(struct evsel *evsel)
> +{
> +	struct bpf_counter *counter;
> +
> +	list_for_each_entry(counter, &evsel->bpf_counter_list, list) {
> +		assert(counter->skel != NULL);
> +		bpf_prog_profiler_bpf__detach(counter->skel);
> +	}
> +	return 0;
> +}
> +
>  static int bpf_program_profiler__read(struct evsel *evsel)
>  {
>  	// perf_cpu_map uses /sys/devices/system/cpu/online
> @@ -280,6 +291,7 @@ static int bpf_program_profiler__install_pe(struct evsel *evsel, int cpu,
>  struct bpf_counter_ops bpf_program_profiler_ops = {
>  	.load       = bpf_program_profiler__load,
>  	.enable	    = bpf_program_profiler__enable,
> +	.disable    = bpf_program_profiler__disable,
>  	.read       = bpf_program_profiler__read,
>  	.destroy    = bpf_program_profiler__destroy,
>  	.install_pe = bpf_program_profiler__install_pe,
> @@ -627,6 +639,12 @@ static int bperf__enable(struct evsel *evsel)
>  	return 0;
>  }
>  
> +static int bperf__disable(struct evsel *evsel)
> +{
> +	evsel->follower_skel->bss->enabled = 0;
> +	return 0;
> +}
> +
>  static int bperf__read(struct evsel *evsel)
>  {
>  	struct bperf_follower_bpf *skel = evsel->follower_skel;
> @@ -768,6 +786,7 @@ static int bperf__destroy(struct evsel *evsel)
>  struct bpf_counter_ops bperf_ops = {
>  	.load       = bperf__load,
>  	.enable     = bperf__enable,
> +	.disable    = bperf__disable,
>  	.read       = bperf__read,
>  	.install_pe = bperf__install_pe,
>  	.destroy    = bperf__destroy,
> @@ -806,6 +825,13 @@ int bpf_counter__enable(struct evsel *evsel)
>  	return evsel->bpf_counter_ops->enable(evsel);
>  }
>  
> +int bpf_counter__disable(struct evsel *evsel)
> +{
> +	if (bpf_counter_skip(evsel))
> +		return 0;
> +	return evsel->bpf_counter_ops->disable(evsel);
> +}
> +
>  int bpf_counter__read(struct evsel *evsel)
>  {
>  	if (bpf_counter_skip(evsel))
> diff --git a/tools/perf/util/bpf_counter.h b/tools/perf/util/bpf_counter.h
> index cb9c532e0a079..d6d907c3dcf92 100644
> --- a/tools/perf/util/bpf_counter.h
> +++ b/tools/perf/util/bpf_counter.h
> @@ -18,6 +18,7 @@ typedef int (*bpf_counter_evsel_install_pe_op)(struct evsel *evsel,
>  struct bpf_counter_ops {
>  	bpf_counter_evsel_target_op load;
>  	bpf_counter_evsel_op enable;
> +	bpf_counter_evsel_op disable;
>  	bpf_counter_evsel_op read;
>  	bpf_counter_evsel_op destroy;
>  	bpf_counter_evsel_install_pe_op install_pe;
> @@ -32,6 +33,7 @@ struct bpf_counter {
>  
>  int bpf_counter__load(struct evsel *evsel, struct target *target);
>  int bpf_counter__enable(struct evsel *evsel);
> +int bpf_counter__disable(struct evsel *evsel);
>  int bpf_counter__read(struct evsel *evsel);
>  void bpf_counter__destroy(struct evsel *evsel);
>  int bpf_counter__install_pe(struct evsel *evsel, int cpu, int fd);
> @@ -51,6 +53,11 @@ static inline int bpf_counter__enable(struct evsel *evsel __maybe_unused)
>  	return 0;
>  }
>  
> +static inline int bpf_counter__disable(struct evsel *evsel __maybe_unused)
> +{
> +	return 0;
> +}
> +
>  static inline int bpf_counter__read(struct evsel *evsel __maybe_unused)
>  {
>  	return -EAGAIN;
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index d29a8a118973c..e71041c890102 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -17,6 +17,7 @@
>  #include "evsel.h"
>  #include "debug.h"
>  #include "units.h"
> +#include "bpf_counter.h"
>  #include <internal/lib.h> // page_size
>  #include "affinity.h"
>  #include "../perf.h"
> @@ -421,6 +422,9 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
>  	if (affinity__setup(&affinity) < 0)
>  		return;
>  
> +	evlist__for_each_entry(evlist, pos)
> +		bpf_counter__disable(pos);
> +
>  	/* Disable 'immediate' events last */
>  	for (imm = 0; imm <= 1; imm++) {
>  		evlist__for_each_cpu(evlist, i, cpu) {
> -- 
> 2.30.2
> 

-- 

- Arnaldo

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable()
  2021-04-27 12:33       ` Jiri Olsa
@ 2021-04-27 19:30         ` Song Liu
  2021-04-29 22:40           ` Song Liu
  0 siblings, 1 reply; 15+ messages in thread
From: Song Liu @ 2021-04-27 19:30 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Song Liu, linux-kernel, Kernel Team, acme, acme, namhyung, jolsa



> On Apr 27, 2021, at 5:33 AM, Jiri Olsa <jolsa@redhat.com> wrote:
> 
> On Mon, Apr 26, 2021 at 10:18:57PM +0000, Song Liu wrote:
>> 
>> 
>>> On Apr 26, 2021, at 2:27 PM, Jiri Olsa <jolsa@redhat.com> wrote:
>>> 
>>> On Sun, Apr 25, 2021 at 02:43:33PM -0700, Song Liu wrote:
>>> 
>>> SNIP
>>> 
>>>> +static inline int bpf_counter__disable(struct evsel *evsel __maybe_unused)
>>>> +{
>>>> +	return 0;
>>>> +}
>>>> +
>>>> static inline int bpf_counter__read(struct evsel *evsel __maybe_unused)
>>>> {
>>>> 	return -EAGAIN;
>>>> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
>>>> index d29a8a118973c..e71041c890102 100644
>>>> --- a/tools/perf/util/evlist.c
>>>> +++ b/tools/perf/util/evlist.c
>>>> @@ -17,6 +17,7 @@
>>>> #include "evsel.h"
>>>> #include "debug.h"
>>>> #include "units.h"
>>>> +#include "bpf_counter.h"
>>>> #include <internal/lib.h> // page_size
>>>> #include "affinity.h"
>>>> #include "../perf.h"
>>>> @@ -421,6 +422,9 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
>>>> 	if (affinity__setup(&affinity) < 0)
>>>> 		return;
>>>> 
>>>> +	evlist__for_each_entry(evlist, pos)
>>>> +		bpf_counter__disable(pos);
>>> 
>>> I was wondering why you don't check evsel__is_bpf like
>>> for the enable case.. and realized that we don't skip
>>> bpf evsels in __evlist__enable and __evlist__disable
>>> like we do in read_affinity_counters
>>> 
>>> so I guess there's extra affinity setup and bunch of
>>> wrong ioctls being called?
>> 
>> We actually didn't do wrong ioctls because the following check:
>> 
>>       if (... || !pos->core.fd)
>>                continue;
>> 
>> in __evlist__enable and __evlist__disable. That we don't allocate 
>> core.fd for is_bpf events. 
>> 
>> It is probably good to be more safe with an extra check of 
>> evsel__is_bpf(). But it is not required with current code. 
> 
> hum, but it will do all the affinity setup no? for no reason,
> if there's no non-bpb event

Yes, it will do the affinity setup. Let me see how to get something
like all_counters_use_bpf here (or within builtin-stat.c).

Thanks,
Song


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable()
  2021-04-27 19:27   ` Arnaldo Carvalho de Melo
@ 2021-04-27 19:42     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 15+ messages in thread
From: Arnaldo Carvalho de Melo @ 2021-04-27 19:42 UTC (permalink / raw)
  To: Song Liu; +Cc: linux-kernel, kernel-team, acme, namhyung, jolsa, songliubraving

Em Tue, Apr 27, 2021 at 04:27:22PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Sun, Apr 25, 2021 at 02:43:33PM -0700, Song Liu escreveu:
> > Introduce bpf_counter_ops->disable(), which is used stop counting the
> > event.
> 
> [acme@five perf]$ perf test -v python
> Couldn't bump rlimit(MEMLOCK), failures may take place when creating BPF maps, etc
> 19: 'import perf' in python                                         :
> --- start ---
> test child forked, pid 1497924
> python usage test: "echo "import sys ; sys.path.append('/tmp/build/perf/python'); import perf" | '/usr/bin/python3' "
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> ImportError: /tmp/build/perf/python/perf.cpython-39-x86_64-linux-gnu.so: undefined symbol: bpf_counter__disable
> test child finished with -1
> ---- end ----
> 'import perf' in python: FAILED!
> [acme@five perf]$
> 
> I'll fix this up in my local tree, if you need to respin, please pick
> patches from tmp.perf/core, will refresh it later today.

Added this:


diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 278abecb5bdfc0d2..27940edb161c2d8c 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -100,6 +100,11 @@ int bpf_counter__install_pe(struct evsel *evsel __maybe_unused, int cpu __maybe_
 	return 0;
 }
 
+int bpf_counter__disable(struct evsel *evsel __maybe_unused)
+{
+	return 0;
+}
+
 /*
  * Support debug printing even though util/debug.c is not linked.  That means
  * implementing 'verbose' and 'eprintf'.



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable()
  2021-04-27 19:30         ` Song Liu
@ 2021-04-29 22:40           ` Song Liu
  2021-05-03 14:09             ` Jiri Olsa
  0 siblings, 1 reply; 15+ messages in thread
From: Song Liu @ 2021-04-29 22:40 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Song Liu, linux-kernel, Kernel Team, acme, acme, namhyung, jolsa



> On Apr 27, 2021, at 12:30 PM, Song Liu <songliubraving@fb.com> wrote:
> 
> 
> 
>> On Apr 27, 2021, at 5:33 AM, Jiri Olsa <jolsa@redhat.com> wrote:
>> 
>> On Mon, Apr 26, 2021 at 10:18:57PM +0000, Song Liu wrote:
>>> 
>>> 
>>>> On Apr 26, 2021, at 2:27 PM, Jiri Olsa <jolsa@redhat.com> wrote:
>>>> 
>>>> On Sun, Apr 25, 2021 at 02:43:33PM -0700, Song Liu wrote:
>>>> 
>>>> SNIP
>>>> 
>>>>> +static inline int bpf_counter__disable(struct evsel *evsel __maybe_unused)
>>>>> +{
>>>>> +	return 0;
>>>>> +}
>>>>> +
>>>>> static inline int bpf_counter__read(struct evsel *evsel __maybe_unused)
>>>>> {
>>>>> 	return -EAGAIN;
>>>>> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
>>>>> index d29a8a118973c..e71041c890102 100644
>>>>> --- a/tools/perf/util/evlist.c
>>>>> +++ b/tools/perf/util/evlist.c
>>>>> @@ -17,6 +17,7 @@
>>>>> #include "evsel.h"
>>>>> #include "debug.h"
>>>>> #include "units.h"
>>>>> +#include "bpf_counter.h"
>>>>> #include <internal/lib.h> // page_size
>>>>> #include "affinity.h"
>>>>> #include "../perf.h"
>>>>> @@ -421,6 +422,9 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
>>>>> 	if (affinity__setup(&affinity) < 0)
>>>>> 		return;
>>>>> 
>>>>> +	evlist__for_each_entry(evlist, pos)
>>>>> +		bpf_counter__disable(pos);
>>>> 
>>>> I was wondering why you don't check evsel__is_bpf like
>>>> for the enable case.. and realized that we don't skip
>>>> bpf evsels in __evlist__enable and __evlist__disable
>>>> like we do in read_affinity_counters
>>>> 
>>>> so I guess there's extra affinity setup and bunch of
>>>> wrong ioctls being called?
>>> 
>>> We actually didn't do wrong ioctls because the following check:
>>> 
>>>      if (... || !pos->core.fd)
>>>               continue;
>>> 
>>> in __evlist__enable and __evlist__disable. That we don't allocate 
>>> core.fd for is_bpf events. 
>>> 
>>> It is probably good to be more safe with an extra check of 
>>> evsel__is_bpf(). But it is not required with current code. 
>> 
>> hum, but it will do all the affinity setup no? for no reason,
>> if there's no non-bpb event
> 
> Yes, it will do the affinity setup. Let me see how to get something
> like all_counters_use_bpf here (or within builtin-stat.c).
> 

Would something like the following work? It is not clean (skipping some 
useful logic in __evlist__[enable|disable]). But it seems to work in the
tests.

Thanks,
Song



From ecb75a1fa747ca5521bcda972840df1e97c09b11 Mon Sep 17 00:00:00 2001
From: Song Liu <song@kernel.org>
Date: Wed, 28 Apr 2021 17:41:28 -0700
Subject: [PATCH] perf-stat: skip evlist__[enable|disable] when all events uses
 BPF

When all events of a perf-stat session use BPF, it is not necessary to
call evlist__enable() and evlist__disable(). Skip them when
all_counters_use_bpf is true.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/perf/builtin-stat.c | 12 +++++++++---
 tools/perf/util/evlist.c  |  3 ---
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 5a830ae09418e..44459e0352fda 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -572,7 +572,8 @@ static int enable_counters(void)
         * - we have initial delay configured
         */
        if (!target__none(&target) || stat_config.initial_delay) {
-               evlist__enable(evsel_list);
+               if (!all_counters_use_bpf)
+                       evlist__enable(evsel_list);
                if (stat_config.initial_delay > 0)
                        pr_info(EVLIST_ENABLED_MSG);
        }
@@ -581,13 +582,18 @@ static int enable_counters(void)

 static void disable_counters(void)
 {
+       struct evsel *counter;
        /*
         * If we don't have tracee (attaching to task or cpu), counters may
         * still be running. To get accurate group ratios, we must stop groups
         * from counting before reading their constituent counters.
         */
-       if (!target__none(&target))
-               evlist__disable(evsel_list);
+       if (!target__none(&target)) {
+               evlist__for_each_entry(evsel_list, counter)
+                       bpf_counter__disable(counter);
+               if (!all_counters_use_bpf)
+                       evlist__disable(evsel_list);
+       }
 }

 static volatile int workload_exec_errno;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 6e5c41528c7d0..6ea3e677dc1e7 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -425,9 +425,6 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
        if (affinity__setup(&affinity) < 0)
                return;

-       evlist__for_each_entry(evlist, pos)
-               bpf_counter__disable(pos);
-
        /* Disable 'immediate' events last */
        for (imm = 0; imm <= 1; imm++) {
                evlist__for_each_cpu(evlist, i, cpu) {
--
2.30.2

 


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable()
  2021-04-29 22:40           ` Song Liu
@ 2021-05-03 14:09             ` Jiri Olsa
  2021-05-03 15:25               ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 15+ messages in thread
From: Jiri Olsa @ 2021-05-03 14:09 UTC (permalink / raw)
  To: Song Liu; +Cc: Song Liu, linux-kernel, Kernel Team, acme, acme, namhyung, jolsa

On Thu, Apr 29, 2021 at 10:40:01PM +0000, Song Liu wrote:

SNIP

> >>>>> #include "../perf.h"
> >>>>> @@ -421,6 +422,9 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
> >>>>> 	if (affinity__setup(&affinity) < 0)
> >>>>> 		return;
> >>>>> 
> >>>>> +	evlist__for_each_entry(evlist, pos)
> >>>>> +		bpf_counter__disable(pos);
> >>>> 
> >>>> I was wondering why you don't check evsel__is_bpf like
> >>>> for the enable case.. and realized that we don't skip
> >>>> bpf evsels in __evlist__enable and __evlist__disable
> >>>> like we do in read_affinity_counters
> >>>> 
> >>>> so I guess there's extra affinity setup and bunch of
> >>>> wrong ioctls being called?
> >>> 
> >>> We actually didn't do wrong ioctls because the following check:
> >>> 
> >>>      if (... || !pos->core.fd)
> >>>               continue;
> >>> 
> >>> in __evlist__enable and __evlist__disable. That we don't allocate 
> >>> core.fd for is_bpf events. 
> >>> 
> >>> It is probably good to be more safe with an extra check of 
> >>> evsel__is_bpf(). But it is not required with current code. 
> >> 
> >> hum, but it will do all the affinity setup no? for no reason,
> >> if there's no non-bpb event
> > 
> > Yes, it will do the affinity setup. Let me see how to get something
> > like all_counters_use_bpf here (or within builtin-stat.c).
> > 
> 
> Would something like the following work? It is not clean (skipping some 
> useful logic in __evlist__[enable|disable]). But it seems to work in the
> tests.

sorry for late reply, but I can't no longer apply this:

	patching file tools/perf/builtin-stat.c
	Hunk #1 FAILED at 572.
	Hunk #2 FAILED at 581.
	2 out of 2 hunks FAILED -- saving rejects to file tools/perf/builtin-stat.c.rej
	patching file tools/perf/util/evlist.c
	Hunk #1 FAILED at 425.
	1 out of 1 hunk FAILED -- saving rejects to file tools/perf/util/evlist.c.rej

ah, I see the patchset got already merged.. not sure why I'm doing review then ;-)

thanks,
jirka


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable()
  2021-05-03 14:09             ` Jiri Olsa
@ 2021-05-03 15:25               ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 15+ messages in thread
From: Arnaldo Carvalho de Melo @ 2021-05-03 15:25 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Song Liu, Song Liu, linux-kernel, Kernel Team, acme, namhyung, jolsa

Em Mon, May 03, 2021 at 04:09:45PM +0200, Jiri Olsa escreveu:
> On Thu, Apr 29, 2021 at 10:40:01PM +0000, Song Liu wrote:
> 
> SNIP
> 
> > >>>>> #include "../perf.h"
> > >>>>> @@ -421,6 +422,9 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
> > >>>>> 	if (affinity__setup(&affinity) < 0)
> > >>>>> 		return;

> > >>>>> +	evlist__for_each_entry(evlist, pos)
> > >>>>> +		bpf_counter__disable(pos);

> > >>>> I was wondering why you don't check evsel__is_bpf like
> > >>>> for the enable case.. and realized that we don't skip
> > >>>> bpf evsels in __evlist__enable and __evlist__disable
> > >>>> like we do in read_affinity_counters

> > >>>> so I guess there's extra affinity setup and bunch of
> > >>>> wrong ioctls being called?

> > >>> We actually didn't do wrong ioctls because the following check:

> > >>>      if (... || !pos->core.fd)
> > >>>               continue;

> > >>> in __evlist__enable and __evlist__disable. That we don't allocate 
> > >>> core.fd for is_bpf events. 

> > >>> It is probably good to be more safe with an extra check of 
> > >>> evsel__is_bpf(). But it is not required with current code. 

> > >> hum, but it will do all the affinity setup no? for no reason,
> > >> if there's no non-bpb event

> > > Yes, it will do the affinity setup. Let me see how to get something
> > > like all_counters_use_bpf here (or within builtin-stat.c).

> > Would something like the following work? It is not clean (skipping some 
> > useful logic in __evlist__[enable|disable]). But it seems to work in the
> > tests.

> sorry for late reply, but I can't no longer apply this:
 
> 	patching file tools/perf/builtin-stat.c
> 	Hunk #1 FAILED at 572.
> 	Hunk #2 FAILED at 581.
> 	2 out of 2 hunks FAILED -- saving rejects to file tools/perf/builtin-stat.c.rej
> 	patching file tools/perf/util/evlist.c
> 	Hunk #1 FAILED at 425.
> 	1 out of 1 hunk FAILED -- saving rejects to file tools/perf/util/evlist.c.rej
 
> ah, I see the patchset got already merged.. not sure why I'm doing review then ;-)

Hey, sometimes this can happen, sorry. Song, please submit on top of
what is upstream.

- Arnaldo

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2021-05-03 15:25 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-25 21:43 [PATCH v5 0/5] perf util: bpf perf improvements Song Liu
2021-04-25 21:43 ` [PATCH v5 1/5] perf util: move bpf_perf definitions to a libperf header Song Liu
2021-04-25 21:43 ` [PATCH v5 2/5] perf bpf: check perf_attr_map is compatible with the perf binary Song Liu
2021-04-25 21:43 ` [PATCH v5 3/5] perf-stat: introduce config stat.bpf-counter-events Song Liu
2021-04-25 21:43 ` [PATCH v5 4/5] perf-stat: introduce ':b' modifier Song Liu
2021-04-25 21:43 ` [PATCH v5 5/5] perf-stat: introduce bpf_counter_ops->disable() Song Liu
2021-04-26 21:27   ` Jiri Olsa
2021-04-26 22:18     ` Song Liu
2021-04-27 12:33       ` Jiri Olsa
2021-04-27 19:30         ` Song Liu
2021-04-29 22:40           ` Song Liu
2021-05-03 14:09             ` Jiri Olsa
2021-05-03 15:25               ` Arnaldo Carvalho de Melo
2021-04-27 19:27   ` Arnaldo Carvalho de Melo
2021-04-27 19:42     ` Arnaldo Carvalho de Melo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.