From: Teng Qin <qint...@fb.com> Allow BPF program to attach to all perf_event types supported by the current bpf and perf code logic, including HW_CACHE, RAW, and dynamic pmu events.
Also add support for reading these event counters using bpf_perf_event_read() helper. Signed-off-by: Teng Qin <qint...@fb.com> Signed-off-by: Alexei Starovoitov <a...@kernel.org> --- kernel/bpf/arraymap.c | 26 +++++++++++--------------- kernel/events/core.c | 6 +----- kernel/trace/bpf_trace.c | 4 ++-- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 5e00b2333c26..55ffa9949128 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -462,26 +462,22 @@ static void *perf_event_fd_array_get_ptr(struct bpf_map *map, event = perf_file->private_data; ee = ERR_PTR(-EINVAL); + /* Per-task events are not supported */ + if (event->attach_state & PERF_ATTACH_TASK) + goto err_out; attr = perf_event_attrs(event); if (IS_ERR(attr) || attr->inherit) goto err_out; + /* TRACEPOINT and BREAKPOINT not supported in perf_event_read_local */ + if (attr->type == PERF_TYPE_TRACEPOINT || + attr->type == PERF_TYPE_BREAKPOINT) + goto err_out; - switch (attr->type) { - case PERF_TYPE_SOFTWARE: - if (attr->config != PERF_COUNT_SW_BPF_OUTPUT) - goto err_out; - /* fall-through */ - case PERF_TYPE_RAW: - case PERF_TYPE_HARDWARE: - ee = bpf_event_entry_gen(perf_file, map_file); - if (ee) - return ee; - ee = ERR_PTR(-ENOMEM); - /* fall-through */ - default: - break; - } + ee = bpf_event_entry_gen(perf_file, map_file); + if (ee) + return ee; + ee = ERR_PTR(-ENOMEM); err_out: fput(perf_file); diff --git a/kernel/events/core.c b/kernel/events/core.c index 6e75a5c9412d..52f667046599 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -8037,12 +8037,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; diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 460a031c77e5..8425bf193f39 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -248,8 +248,8 @@ BPF_CALL_2(bpf_perf_event_read, struct bpf_map *, map, u64, flags) return -ENOENT; event = ee->event; - if (unlikely(event->attr.type != PERF_TYPE_HARDWARE && - event->attr.type != PERF_TYPE_RAW)) + if (unlikely(event->attr.type == PERF_TYPE_SOFTWARE && + event->attr.config == PERF_COUNT_SW_BPF_OUTPUT)) return -EINVAL; /* make sure event is local and doesn't have pmu::count */ -- 2.9.3