bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH bpf-next 0/5] Add PERF_FORMAT_LOST read_format
@ 2019-09-17 13:30 Daniel Xu
  2019-09-17 13:30 ` [PATCH bpf-next 1/5] perf/core: " Daniel Xu
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Daniel Xu @ 2019-09-17 13:30 UTC (permalink / raw)
  To: bpf, songliubraving, yhs, andriin, peterz, mingo, acme
  Cc: Daniel Xu, ast, alexander.shishkin, jolsa, namhyung,
	linux-kernel, netdev, kernel-team

It's useful to know kprobe's nmissed count. For example with tracing
tools, it's important to know when events may have been lost.  debugfs
currently exposes a control file to get this information, but it is not
compatible with probes registered with the perf API.

While bpf programs may be able to manually count nhit, there is no way
to gather nmissed. In other words, it is currently not possible to this
retrieve information about FD-based probes.

This patch adds a new field to perf's read_format that lets users query
misses. Misses include both misses from the underlying kprobe
infrastructure and misses from ringbuffer infrastructure.

I studied the code various code paths for perf software events and perf
tracepoints and it does not look like anything can "miss" in the same
way kprobes can. They can all, however, suffer from ringbuffer misses.
It's possible I missed something while reading the code so please let
me know if I am mistaken.

Daniel Xu (5):
  perf/core: Add PERF_FORMAT_LOST read_format
  perf/core: Sync perf_event.h to tools
  libbpf: Add helpers to extract perf fd from bpf_link
  libbpf: Set read_format PERF_FORMAT_LOST on kprobe perf fds
  libbpf: Add selftest for PERF_FORMAT_LOST perf read_format

 include/linux/trace_events.h                  |  1 +
 include/uapi/linux/perf_event.h               |  5 ++-
 kernel/events/core.c                          | 39 +++++++++++++++++--
 kernel/trace/trace_kprobe.c                   |  8 ++++
 tools/include/uapi/linux/perf_event.h         |  5 ++-
 tools/lib/bpf/libbpf.c                        | 30 ++++++++++++--
 tools/lib/bpf/libbpf.h                        | 13 +++++++
 tools/lib/bpf/libbpf.map                      |  3 ++
 .../selftests/bpf/prog_tests/attach_probe.c   | 32 ++++++++++++++-
 9 files changed, 127 insertions(+), 9 deletions(-)

-- 
2.21.0


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

* [PATCH bpf-next 1/5] perf/core: Add PERF_FORMAT_LOST read_format
  2019-09-17 13:30 [PATCH bpf-next 0/5] Add PERF_FORMAT_LOST read_format Daniel Xu
@ 2019-09-17 13:30 ` Daniel Xu
  2019-09-17 14:32   ` kbuild test robot
                     ` (2 more replies)
  2019-09-17 13:30 ` [PATCH bpf-next 2/5] perf/core: Sync perf_event.h to tools Daniel Xu
                   ` (3 subsequent siblings)
  4 siblings, 3 replies; 14+ messages in thread
From: Daniel Xu @ 2019-09-17 13:30 UTC (permalink / raw)
  To: bpf, songliubraving, yhs, andriin, peterz, mingo, acme
  Cc: Daniel Xu, ast, alexander.shishkin, jolsa, namhyung,
	linux-kernel, netdev, kernel-team

It's useful to know kprobe's nmissed count. For example with tracing
tools, it's important to know when events may have been lost.  debugfs
currently exposes a control file to get this information, but it is not
compatible with probes registered with the perf API.

While bpf programs may be able to manually count nhit, there is no way
to gather nmissed. In other words, it is currently not possible to this
retrieve information about FD-based probes.

This patch adds a new field to perf's read_format that lets users query
misses. Misses include both misses from the underlying kprobe
infrastructure and misses from ringbuffer infrastructure.

Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
---
 include/linux/trace_events.h    |  1 +
 include/uapi/linux/perf_event.h |  5 ++++-
 kernel/events/core.c            | 39 ++++++++++++++++++++++++++++++---
 kernel/trace/trace_kprobe.c     |  8 +++++++
 4 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 30a8cdcfd4a4..952520c1240a 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -587,6 +587,7 @@ extern int bpf_get_kprobe_info(const struct perf_event *event,
 			       u32 *fd_type, const char **symbol,
 			       u64 *probe_offset, u64 *probe_addr,
 			       bool perf_type_tracepoint);
+extern u64 perf_kprobe_missed(const struct perf_event *event);
 #endif
 #ifdef CONFIG_UPROBE_EVENTS
 extern int  perf_uprobe_init(struct perf_event *event,
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 7198ddd0c6b1..bd874c7257f0 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -273,6 +273,7 @@ enum {
  *	  { u64		time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
  *	  { u64		time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
  *	  { u64		id;           } && PERF_FORMAT_ID
+ *	  { u64		missed;       } && PERF_FORMAT_LOST
  *	} && !PERF_FORMAT_GROUP
  *
  *	{ u64		nr;
@@ -280,6 +281,7 @@ enum {
  *	  { u64		time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
  *	  { u64		value;
  *	    { u64	id;           } && PERF_FORMAT_ID
+ *	    { u64	missed;       } && PERF_FORMAT_LOST
  *	  }		cntr[nr];
  *	} && PERF_FORMAT_GROUP
  * };
@@ -289,8 +291,9 @@ enum perf_event_read_format {
 	PERF_FORMAT_TOTAL_TIME_RUNNING		= 1U << 1,
 	PERF_FORMAT_ID				= 1U << 2,
 	PERF_FORMAT_GROUP			= 1U << 3,
+	PERF_FORMAT_LOST			= 1U << 4,
 
-	PERF_FORMAT_MAX = 1U << 4,		/* non-ABI */
+	PERF_FORMAT_MAX = 1U << 5,		/* non-ABI */
 };
 
 #define PERF_ATTR_SIZE_VER0	64	/* sizeof first published struct */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 0463c1151bae..ee08d3ed6299 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1715,6 +1715,9 @@ static void __perf_event_read_size(struct perf_event *event, int nr_siblings)
 	if (event->attr.read_format & PERF_FORMAT_ID)
 		entry += sizeof(u64);
 
+	if (event->attr.read_format & PERF_FORMAT_LOST)
+		entry += sizeof(u64);
+
 	if (event->attr.read_format & PERF_FORMAT_GROUP) {
 		nr += nr_siblings;
 		size += sizeof(u64);
@@ -4734,6 +4737,24 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
 }
 EXPORT_SYMBOL_GPL(perf_event_read_value);
 
+static struct pmu perf_kprobe;
+static u64 perf_event_lost(struct perf_event *event)
+{
+	struct ring_buffer *rb;
+	u64 lost = 0;
+
+	rcu_read_lock();
+	rb = rcu_dereference(event->rb);
+	if (likely(!!rb))
+		lost += local_read(&rb->lost);
+	rcu_read_unlock();
+
+	if (event->attr.type == perf_kprobe.type)
+		lost += perf_kprobe_missed(event);
+
+	return lost;
+}
+
 static int __perf_read_group_add(struct perf_event *leader,
 					u64 read_format, u64 *values)
 {
@@ -4770,11 +4791,15 @@ static int __perf_read_group_add(struct perf_event *leader,
 	values[n++] += perf_event_count(leader);
 	if (read_format & PERF_FORMAT_ID)
 		values[n++] = primary_event_id(leader);
+	if (read_format & PERF_FORMAT_LOST)
+		values[n++] = perf_event_lost(leader);
 
 	for_each_sibling_event(sub, leader) {
 		values[n++] += perf_event_count(sub);
 		if (read_format & PERF_FORMAT_ID)
 			values[n++] = primary_event_id(sub);
+		if (read_format & PERF_FORMAT_LOST)
+			values[n++] = perf_event_lost(sub);
 	}
 
 	raw_spin_unlock_irqrestore(&ctx->lock, flags);
@@ -4831,7 +4856,7 @@ static int perf_read_one(struct perf_event *event,
 				 u64 read_format, char __user *buf)
 {
 	u64 enabled, running;
-	u64 values[4];
+	u64 values[5];
 	int n = 0;
 
 	values[n++] = __perf_event_read_value(event, &enabled, &running);
@@ -4841,6 +4866,8 @@ static int perf_read_one(struct perf_event *event,
 		values[n++] = running;
 	if (read_format & PERF_FORMAT_ID)
 		values[n++] = primary_event_id(event);
+	if (read_format & PERF_FORMAT_LOST)
+		values[n++] = perf_event_lost(event);
 
 	if (copy_to_user(buf, values, n * sizeof(u64)))
 		return -EFAULT;
@@ -6141,7 +6168,7 @@ static void perf_output_read_one(struct perf_output_handle *handle,
 				 u64 enabled, u64 running)
 {
 	u64 read_format = event->attr.read_format;
-	u64 values[4];
+	u64 values[5];
 	int n = 0;
 
 	values[n++] = perf_event_count(event);
@@ -6155,6 +6182,8 @@ static void perf_output_read_one(struct perf_output_handle *handle,
 	}
 	if (read_format & PERF_FORMAT_ID)
 		values[n++] = primary_event_id(event);
+	if (read_format & PERF_FORMAT_LOST)
+		values[n++] = perf_event_lost(event);
 
 	__output_copy(handle, values, n * sizeof(u64));
 }
@@ -6165,7 +6194,7 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 {
 	struct perf_event *leader = event->group_leader, *sub;
 	u64 read_format = event->attr.read_format;
-	u64 values[5];
+	u64 values[6];
 	int n = 0;
 
 	values[n++] = 1 + leader->nr_siblings;
@@ -6183,6 +6212,8 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 	values[n++] = perf_event_count(leader);
 	if (read_format & PERF_FORMAT_ID)
 		values[n++] = primary_event_id(leader);
+	if (read_format & PERF_FORMAT_LOST)
+		values[n++] = perf_event_lost(leader);
 
 	__output_copy(handle, values, n * sizeof(u64));
 
@@ -6196,6 +6227,8 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 		values[n++] = perf_event_count(sub);
 		if (read_format & PERF_FORMAT_ID)
 			values[n++] = primary_event_id(sub);
+		if (read_format & PERF_FORMAT_LOST)
+			values[n++] = perf_event_lost(sub);
 
 		__output_copy(handle, values, n * sizeof(u64));
 	}
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 9d483ad9bb6c..cff471c8750b 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -196,6 +196,14 @@ bool trace_kprobe_error_injectable(struct trace_event_call *call)
 	return within_error_injection_list(trace_kprobe_address(tk));
 }
 
+u64 perf_kprobe_missed(const struct perf_event *event)
+{
+	struct trace_event_call *call = event->tp_event;
+	struct trace_kprobe *tk = (struct trace_kprobe *)call->data;
+
+	return tk->rp.kp.nmissed;
+}
+
 static int register_kprobe_event(struct trace_kprobe *tk);
 static int unregister_kprobe_event(struct trace_kprobe *tk);
 
-- 
2.21.0


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

* [PATCH bpf-next 2/5] perf/core: Sync perf_event.h to tools
  2019-09-17 13:30 [PATCH bpf-next 0/5] Add PERF_FORMAT_LOST read_format Daniel Xu
  2019-09-17 13:30 ` [PATCH bpf-next 1/5] perf/core: " Daniel Xu
@ 2019-09-17 13:30 ` Daniel Xu
  2019-09-17 13:30 ` [PATCH bpf-next 3/5] libbpf: Add helpers to extract perf fd from bpf_link Daniel Xu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 14+ messages in thread
From: Daniel Xu @ 2019-09-17 13:30 UTC (permalink / raw)
  To: bpf, songliubraving, yhs, andriin, peterz, mingo, acme
  Cc: Daniel Xu, ast, alexander.shishkin, jolsa, namhyung,
	linux-kernel, netdev, kernel-team

Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
---
 tools/include/uapi/linux/perf_event.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 7198ddd0c6b1..bd874c7257f0 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -273,6 +273,7 @@ enum {
  *	  { u64		time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
  *	  { u64		time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
  *	  { u64		id;           } && PERF_FORMAT_ID
+ *	  { u64		missed;       } && PERF_FORMAT_LOST
  *	} && !PERF_FORMAT_GROUP
  *
  *	{ u64		nr;
@@ -280,6 +281,7 @@ enum {
  *	  { u64		time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
  *	  { u64		value;
  *	    { u64	id;           } && PERF_FORMAT_ID
+ *	    { u64	missed;       } && PERF_FORMAT_LOST
  *	  }		cntr[nr];
  *	} && PERF_FORMAT_GROUP
  * };
@@ -289,8 +291,9 @@ enum perf_event_read_format {
 	PERF_FORMAT_TOTAL_TIME_RUNNING		= 1U << 1,
 	PERF_FORMAT_ID				= 1U << 2,
 	PERF_FORMAT_GROUP			= 1U << 3,
+	PERF_FORMAT_LOST			= 1U << 4,
 
-	PERF_FORMAT_MAX = 1U << 4,		/* non-ABI */
+	PERF_FORMAT_MAX = 1U << 5,		/* non-ABI */
 };
 
 #define PERF_ATTR_SIZE_VER0	64	/* sizeof first published struct */
-- 
2.21.0


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

* [PATCH bpf-next 3/5] libbpf: Add helpers to extract perf fd from bpf_link
  2019-09-17 13:30 [PATCH bpf-next 0/5] Add PERF_FORMAT_LOST read_format Daniel Xu
  2019-09-17 13:30 ` [PATCH bpf-next 1/5] perf/core: " Daniel Xu
  2019-09-17 13:30 ` [PATCH bpf-next 2/5] perf/core: Sync perf_event.h to tools Daniel Xu
@ 2019-09-17 13:30 ` Daniel Xu
  2019-09-17 13:30 ` [PATCH bpf-next 4/5] libbpf: Set read_format PERF_FORMAT_LOST on kprobe perf fds Daniel Xu
  2019-09-17 13:30 ` [PATCH bpf-next 5/5] libbpf: Add selftest for PERF_FORMAT_LOST perf read_format Daniel Xu
  4 siblings, 0 replies; 14+ messages in thread
From: Daniel Xu @ 2019-09-17 13:30 UTC (permalink / raw)
  To: bpf, songliubraving, yhs, andriin, peterz, mingo, acme
  Cc: Daniel Xu, ast, alexander.shishkin, jolsa, namhyung,
	linux-kernel, netdev, kernel-team

It is sometimes necessary to perform operations on the underlying perf fd.
There is not currently a way to extract the fd given a bpf_link, so add a
a pair of casting and getting helpers.

The casting and getting helpers are nice because they let us define
broad categories of links that makes it clear to users what they can
expect to extract from what type of link.

Acked-by: Song Liu <songliubraving@fb.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
---
 tools/lib/bpf/libbpf.c   | 21 +++++++++++++++++++++
 tools/lib/bpf/libbpf.h   | 13 +++++++++++++
 tools/lib/bpf/libbpf.map |  3 +++
 3 files changed, 37 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e0276520171b..1ca0acd1d823 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -4875,6 +4875,7 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
 
 struct bpf_link {
 	int (*destroy)(struct bpf_link *link);
+	enum bpf_link_type type;
 };
 
 int bpf_link__destroy(struct bpf_link *link)
@@ -4908,6 +4909,24 @@ static int bpf_link__destroy_perf_event(struct bpf_link *link)
 	return err;
 }
 
+const struct bpf_link_fd *bpf_link__as_fd(const struct bpf_link *link)
+{
+	if (link->type != LIBBPF_LINK_FD)
+		return NULL;
+
+	return (struct bpf_link_fd *)link;
+}
+
+enum bpf_link_type bpf_link__type(const struct bpf_link *link)
+{
+	return link->type;
+}
+
+int bpf_link_fd__fd(const struct bpf_link_fd *link)
+{
+	return link->fd;
+}
+
 struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog,
 						int pfd)
 {
@@ -4931,6 +4950,7 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog,
 	if (!link)
 		return ERR_PTR(-ENOMEM);
 	link->link.destroy = &bpf_link__destroy_perf_event;
+	link->link.type = LIBBPF_LINK_FD;
 	link->fd = pfd;
 
 	if (ioctl(pfd, PERF_EVENT_IOC_SET_BPF, prog_fd) < 0) {
@@ -5224,6 +5244,7 @@ struct bpf_link *bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
 	link = malloc(sizeof(*link));
 	if (!link)
 		return ERR_PTR(-ENOMEM);
+	link->link.type = LIBBPF_LINK_FD;
 	link->link.destroy = &bpf_link__destroy_fd;
 
 	pfd = bpf_raw_tracepoint_open(tp_name, prog_fd);
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index e8f70977d137..2ddef5315ff9 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -166,7 +166,20 @@ LIBBPF_API int bpf_program__pin(struct bpf_program *prog, const char *path);
 LIBBPF_API int bpf_program__unpin(struct bpf_program *prog, const char *path);
 LIBBPF_API void bpf_program__unload(struct bpf_program *prog);
 
+enum bpf_link_type {
+	LIBBPF_LINK_FD,
+};
+
 struct bpf_link;
+struct bpf_link_fd;
+
+/* casting APIs */
+LIBBPF_API const struct bpf_link_fd *
+bpf_link__as_fd(const struct bpf_link *link);
+
+/* getters APIs */
+LIBBPF_API enum bpf_link_type bpf_link__type(const struct bpf_link *link);
+LIBBPF_API int bpf_link_fd__fd(const struct bpf_link_fd *link);
 
 LIBBPF_API int bpf_link__destroy(struct bpf_link *link);
 
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index d04c7cb623ed..216713b9eef6 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -189,4 +189,7 @@ LIBBPF_0.0.4 {
 LIBBPF_0.0.5 {
 	global:
 		bpf_btf_get_next_id;
+		bpf_link__type;
+		bpf_link__as_fd;
+		bpf_link_fd__fd;
 } LIBBPF_0.0.4;
-- 
2.21.0


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

* [PATCH bpf-next 4/5] libbpf: Set read_format PERF_FORMAT_LOST on kprobe perf fds
  2019-09-17 13:30 [PATCH bpf-next 0/5] Add PERF_FORMAT_LOST read_format Daniel Xu
                   ` (2 preceding siblings ...)
  2019-09-17 13:30 ` [PATCH bpf-next 3/5] libbpf: Add helpers to extract perf fd from bpf_link Daniel Xu
@ 2019-09-17 13:30 ` Daniel Xu
  2019-09-17 13:30 ` [PATCH bpf-next 5/5] libbpf: Add selftest for PERF_FORMAT_LOST perf read_format Daniel Xu
  4 siblings, 0 replies; 14+ messages in thread
From: Daniel Xu @ 2019-09-17 13:30 UTC (permalink / raw)
  To: bpf, songliubraving, yhs, andriin, peterz, mingo, acme
  Cc: Daniel Xu, ast, alexander.shishkin, jolsa, namhyung,
	linux-kernel, netdev, kernel-team

There is no way to get the nmissed count from kprobes that are created
using the perf API. The previous commits added read_format support for
this count. Enable it in this commit.

Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
---
 tools/lib/bpf/libbpf.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 1ca0acd1d823..43f45f6d914d 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -5031,7 +5031,7 @@ static int determine_uprobe_retprobe_bit(void)
 }
 
 static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name,
-				 uint64_t offset, int pid)
+				 uint64_t offset, int pid, uint64_t read_format)
 {
 	struct perf_event_attr attr = {};
 	char errmsg[STRERR_BUFSIZE];
@@ -5060,6 +5060,7 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name,
 	}
 	attr.size = sizeof(attr);
 	attr.type = type;
+	attr.read_format = read_format;
 	attr.config1 = ptr_to_u64(name); /* kprobe_func or uprobe_path */
 	attr.config2 = offset;		 /* kprobe_addr or probe_offset */
 
@@ -5087,7 +5088,8 @@ struct bpf_link *bpf_program__attach_kprobe(struct bpf_program *prog,
 	int pfd, err;
 
 	pfd = perf_event_open_probe(false /* uprobe */, retprobe, func_name,
-				    0 /* offset */, -1 /* pid */);
+				    0 /* offset */, -1 /* pid */,
+				    PERF_FORMAT_LOST /* read_format */);
 	if (pfd < 0) {
 		pr_warning("program '%s': failed to create %s '%s' perf event: %s\n",
 			   bpf_program__title(prog, false),
@@ -5118,7 +5120,8 @@ struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog,
 	int pfd, err;
 
 	pfd = perf_event_open_probe(true /* uprobe */, retprobe,
-				    binary_path, func_offset, pid);
+				    binary_path, func_offset, pid,
+				    0 /* read_format */);
 	if (pfd < 0) {
 		pr_warning("program '%s': failed to create %s '%s:0x%zx' perf event: %s\n",
 			   bpf_program__title(prog, false),
-- 
2.21.0


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

* [PATCH bpf-next 5/5] libbpf: Add selftest for PERF_FORMAT_LOST perf read_format
  2019-09-17 13:30 [PATCH bpf-next 0/5] Add PERF_FORMAT_LOST read_format Daniel Xu
                   ` (3 preceding siblings ...)
  2019-09-17 13:30 ` [PATCH bpf-next 4/5] libbpf: Set read_format PERF_FORMAT_LOST on kprobe perf fds Daniel Xu
@ 2019-09-17 13:30 ` Daniel Xu
  4 siblings, 0 replies; 14+ messages in thread
From: Daniel Xu @ 2019-09-17 13:30 UTC (permalink / raw)
  To: bpf, songliubraving, yhs, andriin, peterz, mingo, acme
  Cc: Daniel Xu, ast, alexander.shishkin, jolsa, namhyung,
	linux-kernel, netdev, kernel-team

Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
---
 .../selftests/bpf/prog_tests/attach_probe.c   | 32 ++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/attach_probe.c b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
index 5ecc267d98b0..3d636cccb6dc 100644
--- a/tools/testing/selftests/bpf/prog_tests/attach_probe.c
+++ b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
@@ -1,6 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <test_progs.h>
 
+struct perf_read_output {
+	u64 count;
+	u64 lost;
+};
+
 ssize_t get_base_addr() {
 	size_t start;
 	char buf[256];
@@ -32,6 +37,8 @@ void test_attach_probe(void)
 	const char *file = "./test_attach_probe.o";
 	struct bpf_program *kprobe_prog, *kretprobe_prog;
 	struct bpf_program *uprobe_prog, *uretprobe_prog;
+	struct perf_read_output kprobe_read_output;
+	const struct bpf_link_fd *kprobe_fd_link;
 	struct bpf_object *obj;
 	int err, prog_fd, duration = 0, res;
 	struct bpf_link *kprobe_link = NULL;
@@ -40,7 +47,8 @@ void test_attach_probe(void)
 	struct bpf_link *uretprobe_link = NULL;
 	int results_map_fd;
 	size_t uprobe_offset;
-	ssize_t base_addr;
+	ssize_t base_addr, nread;
+	int kprobe_fd;
 
 	base_addr = get_base_addr();
 	if (CHECK(base_addr < 0, "get_base_addr",
@@ -116,6 +124,28 @@ void test_attach_probe(void)
 	/* trigger & validate kprobe && kretprobe */
 	usleep(1);
 
+	kprobe_fd_link = bpf_link__as_fd(kprobe_link);
+	if (CHECK(!kprobe_fd_link, "kprobe_link_as_fd",
+		  "failed to cast link to fd link\n"))
+		goto cleanup;
+
+	kprobe_fd = bpf_link_fd__fd(kprobe_fd_link);
+	if (CHECK(kprobe_fd < 0, "kprobe_get_perf_fd",
+	    "failed to get perf fd from kprobe link\n"))
+		goto cleanup;
+
+	/* Set to unexpected value so we can check the read(2) did stuff */
+	kprobe_read_output.lost = 1;
+	nread = read(kprobe_fd, &kprobe_read_output,
+		     sizeof(kprobe_read_output));
+	if (CHECK(nread != sizeof(kprobe_read_output), "kprobe_perf_read",
+		  "failed to read from perf fd\n"))
+		goto cleanup;
+	if (CHECK(kprobe_read_output.lost != 0, "kprobe_lost",
+		  "read wrong value from perf fd: %lu\n",
+		  kprobe_read_output.lost))
+		goto cleanup;
+
 	err = bpf_map_lookup_elem(results_map_fd, &kprobe_idx, &res);
 	if (CHECK(err, "get_kprobe_res",
 		  "failed to get kprobe res: %d\n", err))
-- 
2.21.0


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

* Re: [PATCH bpf-next 1/5] perf/core: Add PERF_FORMAT_LOST read_format
  2019-09-17 13:30 ` [PATCH bpf-next 1/5] perf/core: " Daniel Xu
@ 2019-09-17 14:32   ` kbuild test robot
  2019-09-17 15:22   ` kbuild test robot
  2019-09-24  8:33   ` Jiri Olsa
  2 siblings, 0 replies; 14+ messages in thread
From: kbuild test robot @ 2019-09-17 14:32 UTC (permalink / raw)
  To: Daniel Xu
  Cc: kbuild-all, bpf, songliubraving, yhs, andriin, peterz, mingo,
	acme, Daniel Xu, ast, alexander.shishkin, jolsa, namhyung,
	linux-kernel, netdev, kernel-team

[-- Attachment #1: Type: text/plain, Size: 1672 bytes --]

Hi Daniel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on bpf-next/master]

url:    https://github.com/0day-ci/linux/commits/Daniel-Xu/perf-core-Add-PERF_FORMAT_LOST-read_format/20190917-213515
base:   https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: i386-tinyconfig (attached as .config)
compiler: gcc-7 (Debian 7.4.0-11) 7.4.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   kernel/events/core.c: In function 'perf_event_lost':
>> kernel/events/core.c:4753:11: error: implicit declaration of function 'perf_kprobe_missed'; did you mean 'perf_release'? [-Werror=implicit-function-declaration]
      lost += perf_kprobe_missed(event);
              ^~~~~~~~~~~~~~~~~~
              perf_release
   cc1: some warnings being treated as errors

vim +4753 kernel/events/core.c

  4739	
  4740	static struct pmu perf_kprobe;
  4741	static u64 perf_event_lost(struct perf_event *event)
  4742	{
  4743		struct ring_buffer *rb;
  4744		u64 lost = 0;
  4745	
  4746		rcu_read_lock();
  4747		rb = rcu_dereference(event->rb);
  4748		if (likely(!!rb))
  4749			lost += local_read(&rb->lost);
  4750		rcu_read_unlock();
  4751	
  4752		if (event->attr.type == perf_kprobe.type)
> 4753			lost += perf_kprobe_missed(event);
  4754	
  4755		return lost;
  4756	}
  4757	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 7185 bytes --]

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

* Re: [PATCH bpf-next 1/5] perf/core: Add PERF_FORMAT_LOST read_format
  2019-09-17 13:30 ` [PATCH bpf-next 1/5] perf/core: " Daniel Xu
  2019-09-17 14:32   ` kbuild test robot
@ 2019-09-17 15:22   ` kbuild test robot
  2019-09-24  8:33   ` Jiri Olsa
  2 siblings, 0 replies; 14+ messages in thread
From: kbuild test robot @ 2019-09-17 15:22 UTC (permalink / raw)
  To: Daniel Xu
  Cc: kbuild-all, bpf, songliubraving, yhs, andriin, peterz, mingo,
	acme, Daniel Xu, ast, alexander.shishkin, jolsa, namhyung,
	linux-kernel, netdev, kernel-team

[-- Attachment #1: Type: text/plain, Size: 1692 bytes --]

Hi Daniel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on bpf-next/master]

url:    https://github.com/0day-ci/linux/commits/Daniel-Xu/perf-core-Add-PERF_FORMAT_LOST-read_format/20190917-213515
base:   https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: i386-randconfig-e003-201937 (attached as .config)
compiler: gcc-7 (Debian 7.4.0-11) 7.4.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   kernel/events/core.c: In function 'perf_event_lost':
>> kernel/events/core.c:4753:11: error: implicit declaration of function 'perf_kprobe_missed'; did you mean 'perf_uprobe_init'? [-Werror=implicit-function-declaration]
      lost += perf_kprobe_missed(event);
              ^~~~~~~~~~~~~~~~~~
              perf_uprobe_init
   cc1: some warnings being treated as errors

vim +4753 kernel/events/core.c

  4739	
  4740	static struct pmu perf_kprobe;
  4741	static u64 perf_event_lost(struct perf_event *event)
  4742	{
  4743		struct ring_buffer *rb;
  4744		u64 lost = 0;
  4745	
  4746		rcu_read_lock();
  4747		rb = rcu_dereference(event->rb);
  4748		if (likely(!!rb))
  4749			lost += local_read(&rb->lost);
  4750		rcu_read_unlock();
  4751	
  4752		if (event->attr.type == perf_kprobe.type)
> 4753			lost += perf_kprobe_missed(event);
  4754	
  4755		return lost;
  4756	}
  4757	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36877 bytes --]

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

* Re: [PATCH bpf-next 1/5] perf/core: Add PERF_FORMAT_LOST read_format
  2019-09-17 13:30 ` [PATCH bpf-next 1/5] perf/core: " Daniel Xu
  2019-09-17 14:32   ` kbuild test robot
  2019-09-17 15:22   ` kbuild test robot
@ 2019-09-24  8:33   ` Jiri Olsa
  2019-09-27 21:28     ` Daniel Xu
  2019-10-28  9:12     ` Peter Zijlstra
  2 siblings, 2 replies; 14+ messages in thread
From: Jiri Olsa @ 2019-09-24  8:33 UTC (permalink / raw)
  To: Daniel Xu
  Cc: bpf, songliubraving, yhs, andriin, peterz, mingo, acme, ast,
	alexander.shishkin, namhyung, linux-kernel, netdev, kernel-team

On Tue, Sep 17, 2019 at 06:30:52AM -0700, Daniel Xu wrote:

SNIP

> +	PERF_FORMAT_MAX = 1U << 5,		/* non-ABI */
>  };
>  
>  #define PERF_ATTR_SIZE_VER0	64	/* sizeof first published struct */
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 0463c1151bae..ee08d3ed6299 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -1715,6 +1715,9 @@ static void __perf_event_read_size(struct perf_event *event, int nr_siblings)
>  	if (event->attr.read_format & PERF_FORMAT_ID)
>  		entry += sizeof(u64);
>  
> +	if (event->attr.read_format & PERF_FORMAT_LOST)
> +		entry += sizeof(u64);
> +
>  	if (event->attr.read_format & PERF_FORMAT_GROUP) {
>  		nr += nr_siblings;
>  		size += sizeof(u64);
> @@ -4734,6 +4737,24 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
>  }
>  EXPORT_SYMBOL_GPL(perf_event_read_value);
>  
> +static struct pmu perf_kprobe;
> +static u64 perf_event_lost(struct perf_event *event)
> +{
> +	struct ring_buffer *rb;
> +	u64 lost = 0;
> +
> +	rcu_read_lock();
> +	rb = rcu_dereference(event->rb);
> +	if (likely(!!rb))
> +		lost += local_read(&rb->lost);
> +	rcu_read_unlock();
> +
> +	if (event->attr.type == perf_kprobe.type)
> +		lost += perf_kprobe_missed(event);

not sure what was the peterz's suggestion, but here you are mixing
ring buffer's lost count with kprobes missed count, seems wrong

maybe we could add PERF_FORMAT_KPROBE_MISSED

jirka

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

* Re: [PATCH bpf-next 1/5] perf/core: Add PERF_FORMAT_LOST read_format
  2019-09-24  8:33   ` Jiri Olsa
@ 2019-09-27 21:28     ` Daniel Xu
  2019-10-25 18:19       ` Daniel Xu
  2019-10-28  9:12     ` Peter Zijlstra
  1 sibling, 1 reply; 14+ messages in thread
From: Daniel Xu @ 2019-09-27 21:28 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: bpf, songliubraving, yhs, andriin, peterz, mingo, acme, ast,
	alexander.shishkin, namhyung, linux-kernel, netdev, kernel-team

Hi Jiri,

On Tue Sep 24, 2019 at 10:33 AM Jiri Olsa wrote:
> On Tue, Sep 17, 2019 at 06:30:52AM -0700, Daniel Xu wrote:
> 
> SNIP
> 
> > +	PERF_FORMAT_MAX = 1U << 5,		/* non-ABI */
> >  };
> >  
> >  #define PERF_ATTR_SIZE_VER0	64	/* sizeof first published struct */
> > diff --git a/kernel/events/core.c b/kernel/events/core.c
> > index 0463c1151bae..ee08d3ed6299 100644
> > --- a/kernel/events/core.c
> > +++ b/kernel/events/core.c
> > @@ -1715,6 +1715,9 @@ static void __perf_event_read_size(struct perf_event *event, int nr_siblings)
> >  	if (event->attr.read_format & PERF_FORMAT_ID)
> >  		entry += sizeof(u64);
> >  
> > +	if (event->attr.read_format & PERF_FORMAT_LOST)
> > +		entry += sizeof(u64);
> > +
> >  	if (event->attr.read_format & PERF_FORMAT_GROUP) {
> >  		nr += nr_siblings;
> >  		size += sizeof(u64);
> > @@ -4734,6 +4737,24 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
> >  }
> >  EXPORT_SYMBOL_GPL(perf_event_read_value);
> >  
> > +static struct pmu perf_kprobe;
> > +static u64 perf_event_lost(struct perf_event *event)
> > +{
> > +	struct ring_buffer *rb;
> > +	u64 lost = 0;
> > +
> > +	rcu_read_lock();
> > +	rb = rcu_dereference(event->rb);
> > +	if (likely(!!rb))
> > +		lost += local_read(&rb->lost);
> > +	rcu_read_unlock();
> > +
> > +	if (event->attr.type == perf_kprobe.type)
> > +		lost += perf_kprobe_missed(event);
> 
> not sure what was the peterz's suggestion, but here you are mixing
> ring buffer's lost count with kprobes missed count, seems wrong

To be honest, I'm not 100% sure what the correct semantics here should
be. I thought it might be less misleading if we included ring buffer
related misses as well.

Regardless, I am ok with either.

> maybe we could add PERF_FORMAT_KPROBE_MISSED

I think the feedback from the last patchset was that we want to keep
the misses unified.

Peter, do you have any thoughts?

Thanks,
Daniel

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

* Re: [PATCH bpf-next 1/5] perf/core: Add PERF_FORMAT_LOST read_format
  2019-09-27 21:28     ` Daniel Xu
@ 2019-10-25 18:19       ` Daniel Xu
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Xu @ 2019-10-25 18:19 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: bpf, Song Liu, Yonghong Song, Andrii Nakryiko, mingo, acme,
	Alexei Starovoitov, alexander.shishkin, namhyung, linux-kernel,
	netdev, Kernel Team, Jiri Olsa

Ping :)

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

* Re: [PATCH bpf-next 1/5] perf/core: Add PERF_FORMAT_LOST read_format
  2019-09-24  8:33   ` Jiri Olsa
  2019-09-27 21:28     ` Daniel Xu
@ 2019-10-28  9:12     ` Peter Zijlstra
  2023-03-08 12:20       ` Lorenz Bauer
  1 sibling, 1 reply; 14+ messages in thread
From: Peter Zijlstra @ 2019-10-28  9:12 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Daniel Xu, bpf, songliubraving, yhs, andriin, mingo, acme, ast,
	alexander.shishkin, namhyung, linux-kernel, netdev, kernel-team

On Tue, Sep 24, 2019 at 10:33:42AM +0200, Jiri Olsa wrote:
> On Tue, Sep 17, 2019 at 06:30:52AM -0700, Daniel Xu wrote:
> 
> SNIP
> 
> > +	PERF_FORMAT_MAX = 1U << 5,		/* non-ABI */
> >  };
> >  
> >  #define PERF_ATTR_SIZE_VER0	64	/* sizeof first published struct */
> > diff --git a/kernel/events/core.c b/kernel/events/core.c
> > index 0463c1151bae..ee08d3ed6299 100644
> > --- a/kernel/events/core.c
> > +++ b/kernel/events/core.c
> > @@ -1715,6 +1715,9 @@ static void __perf_event_read_size(struct perf_event *event, int nr_siblings)
> >  	if (event->attr.read_format & PERF_FORMAT_ID)
> >  		entry += sizeof(u64);
> >  
> > +	if (event->attr.read_format & PERF_FORMAT_LOST)
> > +		entry += sizeof(u64);
> > +
> >  	if (event->attr.read_format & PERF_FORMAT_GROUP) {
> >  		nr += nr_siblings;
> >  		size += sizeof(u64);
> > @@ -4734,6 +4737,24 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
> >  }
> >  EXPORT_SYMBOL_GPL(perf_event_read_value);
> >  
> > +static struct pmu perf_kprobe;
> > +static u64 perf_event_lost(struct perf_event *event)
> > +{
> > +	struct ring_buffer *rb;
> > +	u64 lost = 0;
> > +
> > +	rcu_read_lock();
> > +	rb = rcu_dereference(event->rb);
> > +	if (likely(!!rb))
> > +		lost += local_read(&rb->lost);
> > +	rcu_read_unlock();
> > +
> > +	if (event->attr.type == perf_kprobe.type)
> > +		lost += perf_kprobe_missed(event);
> 
> not sure what was the peterz's suggestion, but here you are mixing
> ring buffer's lost count with kprobes missed count, seems wrong

Jiri is right, this isn't quite what I meant.

The below is what I was thinking of (I also renamed everything to
missing, to avoid confusion).

But now that I wrote it, I'm a little scared of what I had to do for
__perf_sw_event(). Let me ponder that a little bit more.

---
 include/linux/perf_event.h      |  1 +
 include/linux/trace_events.h    |  1 +
 include/uapi/linux/perf_event.h |  5 ++++-
 kernel/events/core.c            | 42 +++++++++++++++++++++++++++++++++--------
 kernel/trace/trace_event_perf.c |  4 +++-
 kernel/trace/trace_kprobe.c     |  8 ++++++++
 6 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index a9ef8be8c83a..ec6c867203c3 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -625,6 +625,7 @@ struct perf_event {
 	unsigned int			attach_state;
 	local64_t			count;
 	atomic64_t			child_count;
+	local64_t			missed;
 
 	/*
 	 * These are the total time in nanoseconds that the event
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index a379255c14a9..18d315a0f0f9 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -603,6 +603,7 @@ extern int bpf_get_kprobe_info(const struct perf_event *event,
 			       u32 *fd_type, const char **symbol,
 			       u64 *probe_offset, u64 *probe_addr,
 			       bool perf_type_tracepoint);
+extern u64 perf_kprobe_missed(const struct perf_event *event);
 #endif
 #ifdef CONFIG_UPROBE_EVENTS
 extern int  perf_uprobe_init(struct perf_event *event,
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index bb7b271397a6..2dd3c3f21087 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -273,6 +273,7 @@ enum {
  *	  { u64		time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
  *	  { u64		time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
  *	  { u64		id;           } && PERF_FORMAT_ID
+ *	  { u64		missed;       } && PERF_FORMAT_MISSED
  *	} && !PERF_FORMAT_GROUP
  *
  *	{ u64		nr;
@@ -280,6 +281,7 @@ enum {
  *	  { u64		time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
  *	  { u64		value;
  *	    { u64	id;           } && PERF_FORMAT_ID
+ *	    { u64	missed;       } && PERF_FORMAT_MISSED
  *	  }		cntr[nr];
  *	} && PERF_FORMAT_GROUP
  * };
@@ -289,8 +291,9 @@ enum perf_event_read_format {
 	PERF_FORMAT_TOTAL_TIME_RUNNING		= 1U << 1,
 	PERF_FORMAT_ID				= 1U << 2,
 	PERF_FORMAT_GROUP			= 1U << 3,
+	PERF_FORMAT_MISSED			= 1U << 4,
 
-	PERF_FORMAT_MAX = 1U << 4,		/* non-ABI */
+	PERF_FORMAT_MAX = 1U << 5,		/* non-ABI */
 };
 
 #define PERF_ATTR_SIZE_VER0	64	/* sizeof first published struct */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index d8b9034857d7..7e72f919d2e7 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1817,6 +1817,9 @@ static void __perf_event_read_size(struct perf_event *event, int nr_siblings)
 	if (event->attr.read_format & PERF_FORMAT_ID)
 		entry += sizeof(u64);
 
+	if (event->attr.read_format & PERF_FORMAT_MISSED)
+		entry += sizeof(u64);
+
 	if (event->attr.read_format & PERF_FORMAT_GROUP) {
 		nr += nr_siblings;
 		size += sizeof(u64);
@@ -4994,6 +4997,15 @@ u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
 }
 EXPORT_SYMBOL_GPL(perf_event_read_value);
 
+static struct pmu perf_kprobe;
+static u64 perf_event_missed(struct perf_event *event)
+{
+	if (event->attr.type == perf_kprobe.type)
+		return perf_kprobe_missed(event);
+
+	return local64_read(&event->missed);
+}
+
 static int __perf_read_group_add(struct perf_event *leader,
 					u64 read_format, u64 *values)
 {
@@ -5030,11 +5042,15 @@ static int __perf_read_group_add(struct perf_event *leader,
 	values[n++] += perf_event_count(leader);
 	if (read_format & PERF_FORMAT_ID)
 		values[n++] = primary_event_id(leader);
+	if (read_format & PERF_FORMAT_MISSED)
+		values[n++] = perf_event_missed(leader);
 
 	for_each_sibling_event(sub, leader) {
 		values[n++] += perf_event_count(sub);
 		if (read_format & PERF_FORMAT_ID)
 			values[n++] = primary_event_id(sub);
+		if (read_format & PERF_FORMAT_MISSED)
+			values[n++] = perf_event_missed(sub);
 	}
 
 	raw_spin_unlock_irqrestore(&ctx->lock, flags);
@@ -5091,7 +5107,7 @@ static int perf_read_one(struct perf_event *event,
 				 u64 read_format, char __user *buf)
 {
 	u64 enabled, running;
-	u64 values[4];
+	u64 values[5];
 	int n = 0;
 
 	values[n++] = __perf_event_read_value(event, &enabled, &running);
@@ -5101,6 +5117,8 @@ static int perf_read_one(struct perf_event *event,
 		values[n++] = running;
 	if (read_format & PERF_FORMAT_ID)
 		values[n++] = primary_event_id(event);
+	if (read_format & PERF_FORMAT_MISSED)
+		values[n++] = perf_event_lost(event);
 
 	if (copy_to_user(buf, values, n * sizeof(u64)))
 		return -EFAULT;
@@ -6427,7 +6445,7 @@ static void perf_output_read_one(struct perf_output_handle *handle,
 				 u64 enabled, u64 running)
 {
 	u64 read_format = event->attr.read_format;
-	u64 values[4];
+	u64 values[5];
 	int n = 0;
 
 	values[n++] = perf_event_count(event);
@@ -6441,6 +6459,8 @@ static void perf_output_read_one(struct perf_output_handle *handle,
 	}
 	if (read_format & PERF_FORMAT_ID)
 		values[n++] = primary_event_id(event);
+	if (read_format & PERF_FORMAT_MISSED)
+		values[n++] = perf_event_lost(event);
 
 	__output_copy(handle, values, n * sizeof(u64));
 }
@@ -6451,7 +6471,7 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 {
 	struct perf_event *leader = event->group_leader, *sub;
 	u64 read_format = event->attr.read_format;
-	u64 values[5];
+	u64 values[6];
 	int n = 0;
 
 	values[n++] = 1 + leader->nr_siblings;
@@ -6469,6 +6489,8 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 	values[n++] = perf_event_count(leader);
 	if (read_format & PERF_FORMAT_ID)
 		values[n++] = primary_event_id(leader);
+	if (read_format & PERF_FORMAT_MISSED)
+		values[n++] = perf_event_lost(leader);
 
 	__output_copy(handle, values, n * sizeof(u64));
 
@@ -6482,6 +6504,8 @@ static void perf_output_read_group(struct perf_output_handle *handle,
 		values[n++] = perf_event_count(sub);
 		if (read_format & PERF_FORMAT_ID)
 			values[n++] = primary_event_id(sub);
+		if (read_format & PERF_FORMAT_MISSED)
+			values[n++] = perf_event_lost(sub);
 
 		__output_copy(handle, values, n * sizeof(u64));
 	}
@@ -8500,7 +8524,6 @@ static int perf_exclude_event(struct perf_event *event,
 static int perf_swevent_match(struct perf_event *event,
 				enum perf_type_id type,
 				u32 event_id,
-				struct perf_sample_data *data,
 				struct pt_regs *regs)
 {
 	if (event->attr.type != type)
@@ -8579,8 +8602,12 @@ static void do_perf_sw_event(enum perf_type_id type, u32 event_id,
 		goto end;
 
 	hlist_for_each_entry_rcu(event, head, hlist_entry) {
-		if (perf_swevent_match(event, type, event_id, data, regs))
-			perf_swevent_event(event, nr, data, regs);
+		if (perf_swevent_match(event, type, event_id, regs)) {
+			if (nr == ~0ULL)
+				local64_inc(&event->missed);
+			else
+				perf_swevent_event(event, nr, data, regs);
+		}
 	}
 end:
 	rcu_read_unlock();
@@ -8621,12 +8648,11 @@ void __perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr)
 	preempt_disable_notrace();
 	rctx = perf_swevent_get_recursion_context();
 	if (unlikely(rctx < 0))
-		goto fail;
+		nr = ~0ULL;
 
 	___perf_sw_event(event_id, nr, regs, addr);
 
 	perf_swevent_put_recursion_context(rctx);
-fail:
 	preempt_enable_notrace();
 }
 
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 0917fee6ee7c..73a0de204d7a 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -458,8 +458,10 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip,
 	perf_fetch_caller_regs(&regs);
 
 	entry = perf_trace_buf_alloc(ENTRY_SIZE, NULL, &rctx);
-	if (!entry)
+	if (!entry) {
+		local64_inc(&event->missed);
 		return;
+	}
 
 	entry->ip = ip;
 	entry->parent_ip = parent_ip;
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 66e0a8ff1c01..5e1889c161e3 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -233,6 +233,14 @@ bool trace_kprobe_error_injectable(struct trace_event_call *call)
 	       false;
 }
 
+u64 perf_kprobe_missed(const struct perf_event *event)
+{
+	struct trace_event_call *call = event->tp_event;
+	struct trace_kprobe *tk = (struct trace_kprobe *)call->data;
+
+	return tk->rp.kp.nmissed;
+}
+
 static int register_kprobe_event(struct trace_kprobe *tk);
 static int unregister_kprobe_event(struct trace_kprobe *tk);
 

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

* Re: [PATCH bpf-next 1/5] perf/core: Add PERF_FORMAT_LOST read_format
  2019-10-28  9:12     ` Peter Zijlstra
@ 2023-03-08 12:20       ` Lorenz Bauer
  0 siblings, 0 replies; 14+ messages in thread
From: Lorenz Bauer @ 2023-03-08 12:20 UTC (permalink / raw)
  To: peterz; +Cc: Lorenz Bauer, Daniel Xu, bpf

Hi Peter,

On Mon, 28 Oct 2019 10:12:29 +0100 you wrote:

> But now that I wrote it, I'm a little scared of what I had to do for
> __perf_sw_event(). Let me ponder that a little bit more.

Do you have an idea how to resolve this?

For context, I maintain a Go library that interacts with perf_events
for the purpose of attaching eBPF kprobes. Users keep asking for an
explicit tracefs fallback since the miss counter is so valuable to
them. It'd be great to find a solution!

Best
Lorenz

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

* Re: [PATCH bpf-next 1/5] perf/core: Add PERF_FORMAT_LOST read_format
@ 2019-09-17 15:14 Daniel Xu
  0 siblings, 0 replies; 14+ messages in thread
From: Daniel Xu @ 2019-09-17 15:14 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, bpf, songliubraving, yhs, andriin, peterz, mingo,
	acme, Daniel Xu, ast, alexander.shishkin, jolsa, namhyung,
	linux-kernel, netdev, kernel-team

On Tue Sep 17, 2019 at 10:32 PM kbuild test robot wrote:
> All errors (new ones prefixed by >>):
> 
>    kernel/events/core.c: In function 'perf_event_lost':
> >> kernel/events/core.c:4753:11: error: implicit declaration of function 'perf_kprobe_missed'; did you mean 'perf_release'? [-Werror=implicit-function-declaration]
>       lost += perf_kprobe_missed(event);
>               ^~~~~~~~~~~~~~~~~~
>               perf_release
>    cc1: some warnings being treated as errors
> 

Ah forgot the #ifdef for CONFIG_KPROBE_EVENTS. I've applied the fix and
will send it in the next version.

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

end of thread, other threads:[~2023-03-08 12:22 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-17 13:30 [PATCH bpf-next 0/5] Add PERF_FORMAT_LOST read_format Daniel Xu
2019-09-17 13:30 ` [PATCH bpf-next 1/5] perf/core: " Daniel Xu
2019-09-17 14:32   ` kbuild test robot
2019-09-17 15:22   ` kbuild test robot
2019-09-24  8:33   ` Jiri Olsa
2019-09-27 21:28     ` Daniel Xu
2019-10-25 18:19       ` Daniel Xu
2019-10-28  9:12     ` Peter Zijlstra
2023-03-08 12:20       ` Lorenz Bauer
2019-09-17 13:30 ` [PATCH bpf-next 2/5] perf/core: Sync perf_event.h to tools Daniel Xu
2019-09-17 13:30 ` [PATCH bpf-next 3/5] libbpf: Add helpers to extract perf fd from bpf_link Daniel Xu
2019-09-17 13:30 ` [PATCH bpf-next 4/5] libbpf: Set read_format PERF_FORMAT_LOST on kprobe perf fds Daniel Xu
2019-09-17 13:30 ` [PATCH bpf-next 5/5] libbpf: Add selftest for PERF_FORMAT_LOST perf read_format Daniel Xu
2019-09-17 15:14 [PATCH bpf-next 1/5] perf/core: Add PERF_FORMAT_LOST read_format Daniel Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).