Skip to contentSkip to conversation

perf, bpf: add support for HW_CACHE and RAW events

PATCH In review Alexei Starovoitov 3 participants 10 messages May 22, 2017 – May 23, 2017

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

cover perf, bpf: add support for HW_CACHE and RAW events

Patch 1: add support for HW_CACHE and RAW perf events to bpf:
- similar to PERF_TYPE_RAW and PERF_TYPE_HARDWARE allow PERF_TYPE_HW_CACHE events to be accessed via bpf_perf_event_read()
- similar to PERF_TYPE_HARDWARE and PERF_TYPE_SOFTWARE allow bpf programs to attch to PERF_TYPE_HW_CACHE and PERF_TYPE_RAW events as BPF_PROG_TYPE_PERF_EVENT program type

Patch 2: add tests for HW_CACHE and RAW events

---
Peter,
please review patch 1. It looks trivial and as far as we can see nothing else needed. The existing perf+bpf infra covers it just fine.

Thanks!

Teng Qin (2):
perf, bpf: add support for HW_CACHE and RAW events samples/bpf: add samples for HW_CACHE / RAW events

 kernel/bpf/arraymap.c          |   1 +
 kernel/events/core.c           |   4 +-
 kernel/trace/bpf_trace.c       |   1 +
 samples/bpf/bpf_helpers.h      |   2 +-
 samples/bpf/trace_event_user.c |  46 +++++++++++-
 samples/bpf/tracex6_kern.c     |  28 ++++++--
 samples/bpf/tracex6_user.c     | 155 +++++++++++++++++++++++++++++++----------
 7 files changed, 187 insertions(+), 50 deletions(-)
Signature · 1 line
2.9.3
#1 lore raw

PATCH 1/2 perf, bpf: add support for HW_CACHE and RAW events

From: Teng Qin <[email protected]>

This commit adds support for attach BPF program to RAW and HW_CACHE type events, and support for read HW_CACHE type event counters in BPF program. Existing code logic already supports them, so this commit is just update Enum value checks.

---
 kernel/bpf/arraymap.c    | 1 +
 kernel/events/core.c     | 4 +++-
 kernel/trace/bpf_trace.c | 1 +
 3 files changed, 5 insertions(+), 1 deletion(-)
kernel/bpf/arraymap.c +1 -0
index 5e00b2333c26..f32affe8c335 100644
@@ -473,6 +473,7 @@ static void *perf_event_fd_array_get_ptr(struct bpf_map *map,
 			goto err_out;
 		/* fall-through */
 	case PERF_TYPE_RAW:
+	case PERF_TYPE_HW_CACHE:
 	case PERF_TYPE_HARDWARE:
 		ee = bpf_event_entry_gen(perf_file, map_file);
 		if (ee)
kernel/events/core.c +3 -1
index 6e75a5c9412d..1b68cb751c03 100644
@@ -8038,7 +8038,9 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
 	struct bpf_prog *prog;
 
 	if (event->attr.type == PERF_TYPE_HARDWARE ||
-	    event->attr.type == PERF_TYPE_SOFTWARE)
+	    event->attr.type == PERF_TYPE_SOFTWARE ||
+	    event->attr.type == PERF_TYPE_HW_CACHE ||
+	    event->attr.type == PERF_TYPE_RAW)
 		return perf_event_set_bpf_handler(event, prog_fd);
 
 	if (event->attr.type != PERF_TYPE_TRACEPOINT)
kernel/trace/bpf_trace.c +1 -0
index 460a031c77e5..5cbda7962a32 100644
@@ -249,6 +249,7 @@ BPF_CALL_2(bpf_perf_event_read, struct bpf_map *, map, u64, flags)
 
 	event = ee->event;
 	if (unlikely(event->attr.type != PERF_TYPE_HARDWARE &&
+		     event->attr.type != PERF_TYPE_HW_CACHE &&
 		     event->attr.type != PERF_TYPE_RAW))
 		return -EINVAL;
 
Signature · 1 line
2.9.3
maintainer
#2 lore raw
Quoted 6 lines · Alexei Starovoitov

From: Teng Qin <[email protected]>

This commit adds support for attach BPF program to RAW and HW_CACHE type events, and support for read HW_CACHE type event counters in BPF program. Existing code logic already supports them, so this commit is just update Enum value checks.

So what I'm missing is why they were not supported previously, and what changed to allow it now.

#3 lore raw
Quoted 10 lines · Peter Zijlstra
Quoted 6 lines · Alexei Starovoitov

From: Teng Qin <[email protected]>

This commit adds support for attach BPF program to RAW and HW_CACHE type events, and support for read HW_CACHE type event counters in BPF program. Existing code logic already supports them, so this commit is just update Enum value checks.

So what I'm missing is why they were not supported previously, and what changed to allow it now.

that code path simply wasn't tested previously. Nothing changed on bpf side and on perf side.
Why it wasn't added on day one? There was no demand. Now people use bpf more and more and few folks got confused that these types of perf events were not supported, hence we're adding it.

maintainer
#4 lore raw
Quoted 9 lines · Alexei Starovoitov
Quoted 8 lines · Peter Zijlstra
Quoted 6 lines · Alexei Starovoitov

From: Teng Qin <[email protected]>

This commit adds support for attach BPF program to RAW and HW_CACHE type events, and support for read HW_CACHE type event counters in BPF program. Existing code logic already supports them, so this commit is just update Enum value checks.

Quoted 8 lines
Quoted 2 lines

So what I'm missing is why they were not supported previously, and what changed to allow it now.

that code path simply wasn't tested previously. Nothing changed on bpf side and on perf side.
Why it wasn't added on day one? There was no demand. Now people use bpf more and more and few folks got confused that these types of perf events were not supported, hence we're adding it.

OK. Is there anything stopping people from wanting to use the dynamic types, as found in:

/sys/bus/event_source/devices/*/type

?

In which case, do we want something like this instead?

kernel/events/core.c +1 -5
index 971f7259108f..4aa5f3011cf8 100644
@@ -8063,12 +8063,8 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
 	bool is_kprobe, is_tracepoint;
 	struct bpf_prog *prog;
 
-	if (event->attr.type == PERF_TYPE_HARDWARE ||
-	    event->attr.type == PERF_TYPE_SOFTWARE)
-		return perf_event_set_bpf_handler(event, prog_fd);
-
 	if (event->attr.type != PERF_TYPE_TRACEPOINT)
-		return -EINVAL;
+		return perf_event_set_bpf_handler(event, prog_fd);
 
 	if (event->tp_event->prog)
 		return -EEXIST;
#5 lore raw
Quoted 34 lines · Peter Zijlstra
Quoted 9 lines · Alexei Starovoitov
Quoted 8 lines · Peter Zijlstra
Quoted 6 lines · Alexei Starovoitov

From: Teng Qin <[email protected]>

This commit adds support for attach BPF program to RAW and HW_CACHE type events, and support for read HW_CACHE type event counters in BPF program. Existing code logic already supports them, so this commit is just update Enum value checks.

Quoted 8 lines
Quoted 2 lines

So what I'm missing is why they were not supported previously, and what changed to allow it now.

that code path simply wasn't tested previously. Nothing changed on bpf side and on perf side.
Why it wasn't added on day one? There was no demand. Now people use bpf more and more and few folks got confused that these types of perf events were not supported, hence we're adding it.

OK. Is there anything stopping people from wanting to use the dynamic types, as found in:

/sys/bus/event_source/devices/*/type

?

In which case, do we want something like this instead?

kernel/events/core.c +0 -0
index 971f7259108f..4aa5f3011cf8 100644

kernel/events/core.c static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd) · line 8067

Quoted 10 lines
kernel/events/core.c +1 -5
@@ -8063,12 +8063,8 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
 	bool is_kprobe, is_tracepoint;
 	struct bpf_prog *prog;
 
-	if (event->attr.type == PERF_TYPE_HARDWARE ||
-	    event->attr.type == PERF_TYPE_SOFTWARE)
-		return perf_event_set_bpf_handler(event, prog_fd);
-
 	if (event->attr.type != PERF_TYPE_TRACEPOINT)
-		return -EINVAL;
+		return perf_event_set_bpf_handler(event, prog_fd);

Good point. We were actually looking at how to deal with msr and cstate events. That should indeed address it.
Will respin.
Thanks for the feedback!

#6 lore raw

PATCH 2/2 samples/bpf: add samples for HW_CACHE / RAW events

In reply to Alexei Starovoitov

From: Teng Qin <[email protected]>

This commit adds sample to test attach BPF to HW_CACHE and RAW type events into the trace_event sample. The test outputs a lot of things to screen, therefore make sure it aborts on error so it's easier to see if everything works. Also update clean-up logic to disable the perf event before closing pmu_fd.

This commit also adds sample to test read HW_CACHE and RAW type event counters from BPF program using bpf_perf_event_read. Refactored the existing sample to fork individual task on each CPU, attach kprobe to more controllable function, and more accurately check if each read on every CPU returned with good value.

---
 samples/bpf/bpf_helpers.h      |   2 +-
 samples/bpf/trace_event_user.c |  46 +++++++++++-
 samples/bpf/tracex6_kern.c     |  28 ++++++--
 samples/bpf/tracex6_user.c     | 155 +++++++++++++++++++++++++++++++----------
 4 files changed, 182 insertions(+), 49 deletions(-)
samples/bpf/bpf_helpers.h +1 -1
index 9a9c95f2c9fb..bbe1388ad149 100644
@@ -31,7 +31,7 @@ static unsigned long long (*bpf_get_current_uid_gid)(void) =
 	(void *) BPF_FUNC_get_current_uid_gid;
 static int (*bpf_get_current_comm)(void *buf, int buf_size) =
 	(void *) BPF_FUNC_get_current_comm;
-static int (*bpf_perf_event_read)(void *map, int index) =
+static u64 (*bpf_perf_event_read)(void *map, u64 flags) =
 	(void *) BPF_FUNC_perf_event_read;
 static int (*bpf_clone_redirect)(void *ctx, int ifindex, int flags) =
 	(void *) BPF_FUNC_clone_redirect;
samples/bpf/trace_event_user.c +43 -3

89 lines not on this page · raw message

samples/bpf/tracex6_kern.c +21 -7
index be479c4af9e2..646f86426d09 100644
@@ -3,22 +3,36 @@
 #include <uapi/linux/bpf.h>
 #include "bpf_helpers.h"
 
-struct bpf_map_def SEC("maps") my_map = {
+struct bpf_map_def SEC("maps") counters = {
 	.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
 	.key_size = sizeof(int),
 	.value_size = sizeof(u32),
-	.max_entries = 32,
+	.max_entries = 64,
+};
+struct bpf_map_def SEC("maps") values = {
+	.type = BPF_MAP_TYPE_HASH,
+	.key_size = sizeof(int),
+	.value_size = sizeof(u64),
+	.max_entries = 64,
 };
 
-SEC("kprobe/sys_write")
+SEC("kprobe/htab_map_get_next_key")
 int bpf_prog1(struct pt_regs *ctx)
 {
-	u64 count;
+	u64 count, *val;
+	s64 error;
 	u32 key = bpf_get_smp_processor_id();
-	char fmt[] = "CPU-%d   %llu\n";
 
-	count = bpf_perf_event_read(&my_map, key);
-	bpf_trace_printk(fmt, sizeof(fmt), key, count);
+	count = bpf_perf_event_read(&counters, key);
+	error = (s64)count;
+	if (error < 0 && error > -256)
+		return 0;
+
+	val = bpf_map_lookup_elem(&values, &key);
+	if (val)
+		*val = count;
+	else
+		bpf_map_update_elem(&values, &key, &count, BPF_NOEXIST);
 
 	return 0;
 }
samples/bpf/tracex6_user.c +117 -38

190 lines not on this page · raw message

Signature · 1 line
2.9.3
maintainer
#7 lore raw

Re: [PATCH net-next 2/2] samples/bpf: add samples for HW_CACHE / RAW events

From: Alexei Starovoitov <[email protected]>
Date: Mon, 22 May 2017 15:48:40 -0700

samples/bpf/bpf_helpers.h static unsigned long long (*bpf_get_current_uid_gid)(void) = · line 35

Quoted 7 lines
samples/bpf/bpf_helpers.h +1 -1
@@ -31,7 +31,7 @@ static unsigned long long (*bpf_get_current_uid_gid)(void) =
 	(void *) BPF_FUNC_get_current_uid_gid;
 static int (*bpf_get_current_comm)(void *buf, int buf_size) =
 	(void *) BPF_FUNC_get_current_comm;
-static int (*bpf_perf_event_read)(void *map, int index) =
+static u64 (*bpf_perf_event_read)(void *map, u64 flags) =
 	(void *) BPF_FUNC_perf_event_read;

If the second argument really is "u64 flags", then please update the comments in tools/include/uapi/linux/bpf.h as well.

Thank you.

#8 lore raw

Re: [PATCH net-next 2/2] samples/bpf: add samples for HW_CACHE / RAW events

Quoted 13 lines · David Miller

From: Alexei Starovoitov <[email protected]>
Date: Mon, 22 May 2017 15:48:40 -0700

samples/bpf/bpf_helpers.h static unsigned long long (*bpf_get_current_uid_gid)(void) = · line 35

Quoted 7 lines
samples/bpf/bpf_helpers.h +1 -1
@@ -31,7 +31,7 @@ static unsigned long long (*bpf_get_current_uid_gid)(void) =
 	(void *) BPF_FUNC_get_current_uid_gid;
 static int (*bpf_get_current_comm)(void *buf, int buf_size) =
 	(void *) BPF_FUNC_get_current_comm;
-static int (*bpf_perf_event_read)(void *map, int index) =
+static u64 (*bpf_perf_event_read)(void *map, u64 flags) =
 	(void *) BPF_FUNC_perf_event_read;

If the second argument really is "u64 flags", then please update the comments in tools/include/uapi/linux/bpf.h as well.

of course.
As independent patch, I assume.
For both tools/include/uapi/...bpf.h and include/uapi/...bpf.h

It has some info:
/* BPF_FUNC_perf_event_output and BPF_FUNC_perf_event_read flags. */
#define BPF_F_INDEX_MASK 0xffffffffULL
#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK

yet perf_event_read() is least documented. hmm.
* u64 bpf_perf_event_read(&map, index)
* Return: Number events read or error code

that needs to be fixed.

maintainer
#9 lore raw

Re: [PATCH net-next 2/2] samples/bpf: add samples for HW_CACHE / RAW events

From: Alexei Starovoitov <[email protected]>
Date: Mon, 22 May 2017 16:35:07 -0700

Quoted 5 lines

yet perf_event_read() is least documented. hmm.
* u64 bpf_perf_event_read(&map, index)
* Return: Number events read or error code

that needs to be fixed.

That's exactly what I was talking about :-)