From patchwork Tue Dec 4 19:53:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1007827 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="Gbxc+l3C"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 438Xcm5Z20z9sBn for ; Wed, 5 Dec 2018 06:54:16 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726337AbeLDTyN (ORCPT ); Tue, 4 Dec 2018 14:54:13 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:39424 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725882AbeLDTyM (ORCPT ); Tue, 4 Dec 2018 14:54:12 -0500 Received: from pps.filterd (m0148460.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id wB4JrsGa009406 for ; Tue, 4 Dec 2018 11:54:10 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=tQKi4Udz0807FiwGgQcPRYS8lVUJNDOBc/CmlTen8yc=; b=Gbxc+l3ChNOSXXGvLtUd4UhktU/0s0R53DDu9wIrI5QlBPlSOfALncGph7MZ5Rouz2pz x6bOxu0aBWq04XiQqnxI6T0dtt92pFrzFMBqGHlpNr/CBfLQBYs4gJu/Ko/8DLDzHvaM JV592S64hV6OtyeyRzg6g8qsRCnBWkEqoMM= Received: from maileast.thefacebook.com ([199.201.65.23]) by mx0a-00082601.pphosted.com with ESMTP id 2p5x89rdg8-11 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 04 Dec 2018 11:54:10 -0800 Received: from mx-out.facebook.com (2620:10d:c0a1:3::13) by mail.thefacebook.com (2620:10d:c021:18::176) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1531.3; Tue, 4 Dec 2018 11:54:08 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 8262462E176A; Tue, 4 Dec 2018 11:54:02 -0800 (PST) Smtp-Origin-Hostprefix: devbig From: Song Liu Smtp-Origin-Hostname: devbig006.ftw2.facebook.com To: , CC: Song Liu , , , , , Smtp-Origin-Cluster: ftw2c04 Subject: [PATCH v2 perf,bpf 1/3] perf, bpf: Introduce PERF_RECORD_BPF_EVENT Date: Tue, 4 Dec 2018 11:53:53 -0800 Message-ID: <20181204195355.4079788-2-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181204195355.4079788-1-songliubraving@fb.com> References: <20181204195355.4079788-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-12-04_08:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org For better performance analysis of BPF programs, this patch introduces PERF_RECORD_BPF_EVENT, a new perf_event_type that exposes BPF program load/unload information to user space. Each BPF program may contain up to BPF_MAX_SUBPROGS (256) sub programs. The following example shows kernel symbols for a BPF program with 7 sub programs: ffffffffa0257cf9 t bpf_prog_b07ccb89267cf242_F ffffffffa02592e1 t bpf_prog_2dcecc18072623fc_F ffffffffa025b0e9 t bpf_prog_bb7a405ebaec5d5c_F ffffffffa025dd2c t bpf_prog_a7540d4a39ec1fc7_F ffffffffa025fcca t bpf_prog_05762d4ade0e3737_F ffffffffa026108f t bpf_prog_db4bd11e35df90d4_F ffffffffa0263f00 t bpf_prog_89d64e4abf0f0126_F ffffffffa0257cf9 t bpf_prog_ae31629322c4b018__dummy_tracepoi Note that these sub programs are not allocated in contiguous memory ranges. Instead, each of them occupies separate page(s). The starting address of these sub programs are randomized within the page(s) for security reasons. The following data structure is used for PERF_RECORD_BPF_EVENT. It is generated for each _sub program_: /* * Record different types of bpf events: * enum perf_bpf_event_type { * PERF_BPF_EVENT_UNKNOWN = 0, * PERF_BPF_EVENT_PROG_LOAD = 1, * PERF_BPF_EVENT_PROG_UNLOAD = 2, * }; * * struct { * struct perf_event_header header; * u32 type; * u32 flags; * u32 id; // prog_id or other id * u32 sub_id; // subprog id * * // for bpf_prog types, bpf prog or subprog * u8 tag[BPF_TAG_SIZE]; * u64 addr; * u64 len; * char name[]; * struct sample_id sample_id; * }; */ This data is designed for different use cases: 1. For simple perf profiling, addr, len, and name[] works similar to PERF_RECORD_MMAP. These raw records are stored in perf.data file. 2. For perf annotation and other cases that needs more details of the BPF program, id and sub_id are used to extract detailed information of the prog through sys_bpf(BPF_OBJ_GET_INFO_BY_FD). User space tools are responsible to save the detailed information properly, as these information will not be available after the bpf program is unloaded. This follows the existing perf model of keeping the ordered records with enough information for profiling while keeping keys for reliably finding extra, more voluminous information for further analysis, like raw jitted binaries augmented with line numbers that can be used for disassembly, annotation, etc Currently, PERF_RECORD_BPF_EVENT only support two events: PERF_BPF_EVENT_PROG_LOAD and PERF_BPF_EVENT_PROG_UNLOAD. But it can be easily extended to support more events. Signed-off-by: Song Liu Reviewed-by: Arnaldo Carvalho de Melo --- include/linux/filter.h | 1 + include/linux/perf_event.h | 10 +++ include/uapi/linux/perf_event.h | 35 ++++++++- kernel/bpf/core.c | 2 +- kernel/bpf/syscall.c | 3 + kernel/events/core.c | 123 +++++++++++++++++++++++++++++++- 6 files changed, 171 insertions(+), 3 deletions(-) diff --git a/include/linux/filter.h b/include/linux/filter.h index 448dcc448f1f..ef2d8ef01329 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -955,6 +955,7 @@ bpf_address_lookup(unsigned long addr, unsigned long *size, void bpf_prog_kallsyms_add(struct bpf_prog *fp); void bpf_prog_kallsyms_del(struct bpf_prog *fp); +void bpf_get_prog_name(const struct bpf_prog *prog, char *sym); #else /* CONFIG_BPF_JIT */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 53c500f0ca79..02217bab64d0 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1113,6 +1113,12 @@ static inline void perf_event_task_sched_out(struct task_struct *prev, } extern void perf_event_mmap(struct vm_area_struct *vma); + +#ifdef CONFIG_BPF_SYSCALL +extern void perf_event_bpf_event_prog(enum perf_bpf_event_type type, + struct bpf_prog *prog); +#endif + extern struct perf_guest_info_callbacks *perf_guest_cbs; extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks); extern int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks); @@ -1333,6 +1339,10 @@ static inline int perf_unregister_guest_info_callbacks (struct perf_guest_info_callbacks *callbacks) { return 0; } static inline void perf_event_mmap(struct vm_area_struct *vma) { } +#ifdef CONFIG_BPF_SYSCALL +static inline void perf_event_bpf_event_prog(enum perf_bpf_event_type type, + struct bpf_prog *prog) { } +#endif static inline void perf_event_exec(void) { } static inline void perf_event_comm(struct task_struct *tsk, bool exec) { } static inline void perf_event_namespaces(struct task_struct *tsk) { } diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 9de8780ac8d9..0ae3dae55fa8 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -372,7 +372,8 @@ struct perf_event_attr { context_switch : 1, /* context switch data */ write_backward : 1, /* Write ring buffer from end to beginning */ namespaces : 1, /* include namespaces data */ - __reserved_1 : 35; + bpf_event : 1, /* include bpf events */ + __reserved_1 : 34; union { __u32 wakeup_events; /* wakeup every n events */ @@ -965,9 +966,41 @@ enum perf_event_type { */ PERF_RECORD_NAMESPACES = 16, + /* + * Record different types of bpf events: + * enum perf_bpf_event_type { + * PERF_BPF_EVENT_UNKNOWN = 0, + * PERF_BPF_EVENT_PROG_LOAD = 1, + * PERF_BPF_EVENT_PROG_UNLOAD = 2, + * }; + * + * struct { + * struct perf_event_header header; + * u32 type; + * u32 flags; + * u32 id; // prog_id or other id + * u32 sub_id; // subprog id + * + * // for bpf_prog types, bpf prog or subprog + * u8 tag[BPF_TAG_SIZE]; + * u64 addr; + * u64 len; + * char name[]; + * struct sample_id sample_id; + * }; + */ + PERF_RECORD_BPF_EVENT = 17, + PERF_RECORD_MAX, /* non-ABI */ }; +enum perf_bpf_event_type { + PERF_BPF_EVENT_UNKNOWN = 0, + PERF_BPF_EVENT_PROG_LOAD = 1, + PERF_BPF_EVENT_PROG_UNLOAD = 2, + PERF_BPF_EVENT_MAX, /* non-ABI */ +}; + #define PERF_MAX_STACK_DEPTH 127 #define PERF_MAX_CONTEXTS_PER_STACK 8 diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index b1a3545d0ec8..bbe8768f7a42 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -387,7 +387,7 @@ bpf_get_prog_addr_region(const struct bpf_prog *prog, *symbol_end = addr + hdr->pages * PAGE_SIZE; } -static void bpf_get_prog_name(const struct bpf_prog *prog, char *sym) +void bpf_get_prog_name(const struct bpf_prog *prog, char *sym) { const char *end = sym + KSYM_NAME_LEN; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index cf5040fd5434..45ef7922cf69 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1210,6 +1210,8 @@ static void __bpf_prog_put_rcu(struct rcu_head *rcu) static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock) { if (atomic_dec_and_test(&prog->aux->refcnt)) { + perf_event_bpf_event_prog(PERF_BPF_EVENT_PROG_UNLOAD, prog); + /* bpf_prog_free_id() must be called first */ bpf_prog_free_id(prog, do_idr_lock); bpf_prog_kallsyms_del_all(prog); @@ -1550,6 +1552,7 @@ static int bpf_prog_load(union bpf_attr *attr) } bpf_prog_kallsyms_add(prog); + perf_event_bpf_event_prog(PERF_BPF_EVENT_PROG_LOAD, prog); return err; free_used_maps: diff --git a/kernel/events/core.c b/kernel/events/core.c index a2a6e0b4a881..983f8d03870d 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -385,6 +385,7 @@ static atomic_t nr_namespaces_events __read_mostly; static atomic_t nr_task_events __read_mostly; static atomic_t nr_freq_events __read_mostly; static atomic_t nr_switch_events __read_mostly; +static atomic_t nr_bpf_events __read_mostly; static LIST_HEAD(pmus); static DEFINE_MUTEX(pmus_lock); @@ -4235,7 +4236,7 @@ static bool is_sb_event(struct perf_event *event) if (attr->mmap || attr->mmap_data || attr->mmap2 || attr->comm || attr->comm_exec || - attr->task || + attr->task || attr->bpf_event || attr->context_switch) return true; return false; @@ -4305,6 +4306,8 @@ static void unaccount_event(struct perf_event *event) dec = true; if (has_branch_stack(event)) dec = true; + if (event->attr.bpf_event) + atomic_dec(&nr_bpf_events); if (dec) { if (!atomic_add_unless(&perf_sched_count, -1, 1)) @@ -7650,6 +7653,122 @@ static void perf_log_throttle(struct perf_event *event, int enable) perf_output_end(&handle); } +/* + * bpf load/unload tracking + */ + +struct perf_bpf_event { + struct bpf_prog *prog; + + struct { + struct perf_event_header header; + u32 type; + u32 flags; + u32 id; + u32 sub_id; + u8 tag[BPF_TAG_SIZE]; + u64 addr; + u64 len; + } event_id; +}; + +static int perf_event_bpf_match(struct perf_event *event) +{ + return event->attr.bpf_event; +} + +static void perf_event_bpf_output(struct perf_event *event, + void *data) +{ + struct perf_bpf_event *bpf_event = data; + struct perf_output_handle handle; + struct perf_sample_data sample; + char name[KSYM_NAME_LEN]; + int name_len; + int ret; + + if (!perf_event_bpf_match(event)) + return; + + /* get prog name and round up to 64 bit aligned */ + bpf_get_prog_name(bpf_event->prog, name); + name_len = strlen(name) + 1; + while (!IS_ALIGNED(name_len, sizeof(u64))) + name[name_len++] = '\0'; + bpf_event->event_id.len += name_len; + + perf_event_header__init_id(&bpf_event->event_id.header, &sample, event); + ret = perf_output_begin(&handle, event, + bpf_event->event_id.header.size); + if (ret) + return; + + perf_output_put(&handle, bpf_event->event_id); + + __output_copy(&handle, name, name_len); + + perf_event__output_id_sample(event, &handle, &sample); + + perf_output_end(&handle); +} + +static void perf_event_bpf(struct perf_bpf_event *bpf_event) +{ + perf_iterate_sb(perf_event_bpf_output, + bpf_event, + NULL); +} + +static void perf_event_bpf_event_subprog( + enum perf_bpf_event_type type, + struct bpf_prog *prog, u32 id, u32 sub_id) +{ + struct perf_bpf_event bpf_event = (struct perf_bpf_event){ + .prog = prog, + .event_id = { + .header = { + .type = PERF_RECORD_BPF_EVENT, + .size = sizeof(bpf_event.event_id), + }, + .type = type, + /* .flags = 0 */ + .id = id, + .sub_id = sub_id, + .addr = (u64)prog->bpf_func, + .len = prog->jited_len, + }, + }; + + memcpy(bpf_event.event_id.tag, prog->tag, BPF_TAG_SIZE); + perf_event_bpf(&bpf_event); +} + +/* + * This is call per bpf_prog. In case of multiple sub programs, + * this function calls perf_event_bpf_event_subprog() multiple times + */ +void perf_event_bpf_event_prog(enum perf_bpf_event_type type, + struct bpf_prog *prog) +{ + if (!atomic_read(&nr_bpf_events)) + return; + + if (type != PERF_BPF_EVENT_PROG_LOAD && + type != PERF_BPF_EVENT_PROG_UNLOAD) + return; + + if (prog->aux->func_cnt == 0) { + perf_event_bpf_event_subprog(type, prog, + prog->aux->id, 0); + } else { + int i; + + for (i = 0; i < prog->aux->func_cnt; i++) + perf_event_bpf_event_subprog(type, prog->aux->func[i], + prog->aux->id, i); + } +} + void perf_event_itrace_started(struct perf_event *event) { event->attach_state |= PERF_ATTACH_ITRACE; @@ -9900,6 +10019,8 @@ static void account_event(struct perf_event *event) inc = true; if (is_cgroup_event(event)) inc = true; + if (event->attr.bpf_event) + atomic_inc(&nr_bpf_events); if (inc) { /* From patchwork Tue Dec 4 19:53:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1007828 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="LOcEA21O"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 438Xcz06q4z9s3Z for ; Wed, 5 Dec 2018 06:54:27 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726400AbeLDTyW (ORCPT ); Tue, 4 Dec 2018 14:54:22 -0500 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:33094 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725882AbeLDTyR (ORCPT ); Tue, 4 Dec 2018 14:54:17 -0500 Received: from pps.filterd (m0109334.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id wB4Jqtfj005137 for ; Tue, 4 Dec 2018 11:54:16 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=QAlyF0rHDzJb/QvzTrRsT8sLE1JOpVlhHYCl4ng3EVU=; b=LOcEA21OME2LZJAbjCJtJXbvRRLxXSTpUPu22QCaPRy09TvckukXyqqdQ++aMS/1IUGn pEmNTwSp4ruPqlXH3cJuGqlLGF39pH2ILtTw/9V9ci+qsMrS9F9hYxTi7Hdm0UqFoDCf mY9pCt3HMYDoqSYucTH+qxfSgUjNh6MRtmM= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2p5wxsrm7h-11 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 04 Dec 2018 11:54:16 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::129) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1531.3; Tue, 4 Dec 2018 11:54:07 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 9209262E18A8; Tue, 4 Dec 2018 11:54:02 -0800 (PST) Smtp-Origin-Hostprefix: devbig From: Song Liu Smtp-Origin-Hostname: devbig006.ftw2.facebook.com To: , CC: Song Liu , , , , , Smtp-Origin-Cluster: ftw2c04 Subject: [PATCH v2 perf, bpf 2/3] perf: sync tools/include/uapi/linux/perf_event.h Date: Tue, 4 Dec 2018 11:53:54 -0800 Message-ID: <20181204195355.4079788-3-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181204195355.4079788-1-songliubraving@fb.com> References: <20181204195355.4079788-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-12-04_08:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Sync changes for PERF_RECORD_BPF_EVENT. Signed-off-by: Song Liu --- tools/include/uapi/linux/perf_event.h | 35 ++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h index 9de8780ac8d9..0ae3dae55fa8 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h @@ -372,7 +372,8 @@ struct perf_event_attr { context_switch : 1, /* context switch data */ write_backward : 1, /* Write ring buffer from end to beginning */ namespaces : 1, /* include namespaces data */ - __reserved_1 : 35; + bpf_event : 1, /* include bpf events */ + __reserved_1 : 34; union { __u32 wakeup_events; /* wakeup every n events */ @@ -965,9 +966,41 @@ enum perf_event_type { */ PERF_RECORD_NAMESPACES = 16, + /* + * Record different types of bpf events: + * enum perf_bpf_event_type { + * PERF_BPF_EVENT_UNKNOWN = 0, + * PERF_BPF_EVENT_PROG_LOAD = 1, + * PERF_BPF_EVENT_PROG_UNLOAD = 2, + * }; + * + * struct { + * struct perf_event_header header; + * u32 type; + * u32 flags; + * u32 id; // prog_id or other id + * u32 sub_id; // subprog id + * + * // for bpf_prog types, bpf prog or subprog + * u8 tag[BPF_TAG_SIZE]; + * u64 addr; + * u64 len; + * char name[]; + * struct sample_id sample_id; + * }; + */ + PERF_RECORD_BPF_EVENT = 17, + PERF_RECORD_MAX, /* non-ABI */ }; +enum perf_bpf_event_type { + PERF_BPF_EVENT_UNKNOWN = 0, + PERF_BPF_EVENT_PROG_LOAD = 1, + PERF_BPF_EVENT_PROG_UNLOAD = 2, + PERF_BPF_EVENT_MAX, /* non-ABI */ +}; + #define PERF_MAX_STACK_DEPTH 127 #define PERF_MAX_CONTEXTS_PER_STACK 8 From patchwork Tue Dec 4 19:53:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 1007830 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="R53k8nBQ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 438XdB5w5Qz9s3Z for ; Wed, 5 Dec 2018 06:54:38 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726230AbeLDTyh (ORCPT ); Tue, 4 Dec 2018 14:54:37 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:54130 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726375AbeLDTyV (ORCPT ); Tue, 4 Dec 2018 14:54:21 -0500 Received: from pps.filterd (m0001303.ppops.net [127.0.0.1]) by m0001303.ppops.net (8.16.0.27/8.16.0.27) with SMTP id wB4Jk80N032470 for ; Tue, 4 Dec 2018 11:54:20 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=9VodBoRK8qP/GUwWKVvU2YiUFbCHu4E9Td2/AwSxeZc=; b=R53k8nBQ676YG4lsoKrTmkkXgFpf3LgDSy1q0AGadBbhkn6FTVO1VUKGM1J7myu02TAU y/yJh8RoxB7SjRW+Br1l7wbI8P538zWiVDxkHrelozUZCZeLCrCL33mLCMbJQyWm0ze1 1cNhFnsXMyFDcjLcAadthHZx+SLArSvKavM= Received: from mail.thefacebook.com ([199.201.64.23]) by m0001303.ppops.net with ESMTP id 2p5xqu89s8-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 04 Dec 2018 11:54:20 -0800 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::129) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1531.3; Tue, 4 Dec 2018 11:54:08 -0800 Received: by devbig006.ftw2.facebook.com (Postfix, from userid 4523) id 9FA1762E19D2; Tue, 4 Dec 2018 11:54:02 -0800 (PST) Smtp-Origin-Hostprefix: devbig From: Song Liu Smtp-Origin-Hostname: devbig006.ftw2.facebook.com To: , CC: Song Liu , , , , , Smtp-Origin-Cluster: ftw2c04 Subject: [PATCH v2 perf, bpf 3/3] perf util: basic handling of PERF_RECORD_BPF_EVENT Date: Tue, 4 Dec 2018 11:53:55 -0800 Message-ID: <20181204195355.4079788-4-songliubraving@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181204195355.4079788-1-songliubraving@fb.com> References: <20181204195355.4079788-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-12-04_08:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds basic handling of PERF_RECORD_BPF_EVENT in perf util. Future patches add more logic that leverages these events. Signed-off-by: Song Liu --- tools/perf/util/event.c | 22 ++++++++++++++++++++++ tools/perf/util/event.h | 26 ++++++++++++++++++++++++++ tools/perf/util/evsel.c | 1 + tools/perf/util/machine.c | 10 ++++++++++ tools/perf/util/machine.h | 2 ++ tools/perf/util/session.c | 4 ++++ tools/perf/util/tool.h | 4 +++- 7 files changed, 68 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index e9c108a6b1c3..ada7797006f9 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -24,6 +24,7 @@ #include "symbol/kallsyms.h" #include "asm/bug.h" #include "stat.h" +#include "session.h" static const char *perf_event__names[] = { [0] = "TOTAL", @@ -43,6 +44,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_SWITCH] = "SWITCH", [PERF_RECORD_SWITCH_CPU_WIDE] = "SWITCH_CPU_WIDE", [PERF_RECORD_NAMESPACES] = "NAMESPACES", + [PERF_RECORD_BPF_EVENT] = "BPF_EVENT", [PERF_RECORD_HEADER_ATTR] = "ATTR", [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", @@ -1335,6 +1337,14 @@ int perf_event__process_switch(struct perf_tool *tool __maybe_unused, return machine__process_switch_event(machine, event); } +int perf_event__process_bpf_event(struct perf_tool *tool __maybe_unused, + union perf_event *event, + struct perf_sample *sample __maybe_unused, + struct machine *machine) +{ + return machine__process_bpf_event(machine, event); +} + size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) { return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n", @@ -1467,6 +1477,15 @@ static size_t perf_event__fprintf_lost(union perf_event *event, FILE *fp) return fprintf(fp, " lost %" PRIu64 "\n", event->lost.lost); } +size_t perf_event__fprintf_bpf_event(union perf_event *event, FILE *fp) +{ + return fprintf(fp, " bpf event with type %u, flags %u, id %u sub_id %u addr %lx len %lu name %s\n", + event->bpf_event.type, event->bpf_event.flags, + event->bpf_event.id, event->bpf_event.sub_id, + event->bpf_event.addr, event->bpf_event.len, + event->bpf_event.name); +} + size_t perf_event__fprintf(union perf_event *event, FILE *fp) { size_t ret = fprintf(fp, "PERF_RECORD_%s", @@ -1502,6 +1521,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp) case PERF_RECORD_LOST: ret += perf_event__fprintf_lost(event, fp); break; + case PERF_RECORD_BPF_EVENT: + ret += perf_event__fprintf_bpf_event(event, fp); + break; default: ret += fprintf(fp, "\n"); } diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index bfa60bcafbde..cea19b1b128a 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "../perf.h" #include "build-id.h" @@ -84,6 +85,25 @@ struct throttle_event { u64 stream_id; }; +#ifndef KSYM_NAME_LEN +#define KSYM_NAME_LEN 256 +#endif + +/* Record different types of bpf events, see enum perf_bpf_event_type */ +struct bpf_event { + struct perf_event_header header; + u32 type; + u32 flags; + u32 id; + u32 sub_id; + + /* for bpf_prog types */ + u8 tag[BPF_TAG_SIZE]; // prog tag + u64 addr; + u64 len; + char name[KSYM_NAME_LEN]; +}; + #define PERF_SAMPLE_MASK \ (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \ @@ -651,6 +671,7 @@ union perf_event { struct stat_round_event stat_round; struct time_conv_event time_conv; struct feature_event feat; + struct bpf_event bpf_event; }; void perf_event__print_totals(void); @@ -750,6 +771,10 @@ int perf_event__process_exit(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine); +int perf_event__process_bpf_event(struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine); int perf_tool__process_synth_event(struct perf_tool *tool, union perf_event *event, struct machine *machine, @@ -814,6 +839,7 @@ size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp); size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp); size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp); size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp); +size_t perf_event__fprintf_bpf_event(union perf_event *event, FILE *fp); size_t perf_event__fprintf(union perf_event *event, FILE *fp); int kallsyms__get_function_start(const char *kallsyms_filename, diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index dbc0466db368..484ea0b19414 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1652,6 +1652,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, PRINT_ATTRf(context_switch, p_unsigned); PRINT_ATTRf(write_backward, p_unsigned); PRINT_ATTRf(namespaces, p_unsigned); + PRINT_ATTRf(bpf_event, p_unsigned); PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned); PRINT_ATTRf(bp_type, p_unsigned); diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 8f36ce813bc5..eee444fbaa7a 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -681,6 +681,14 @@ int machine__process_switch_event(struct machine *machine __maybe_unused, return 0; } +int machine__process_bpf_event(struct machine *machine __maybe_unused, + union perf_event *event) +{ + if (dump_trace) + perf_event__fprintf_bpf_event(event, stdout); + return 0; +} + static void dso__adjust_kmod_long_name(struct dso *dso, const char *filename) { const char *dup_filename; @@ -1812,6 +1820,8 @@ int machine__process_event(struct machine *machine, union perf_event *event, case PERF_RECORD_SWITCH: case PERF_RECORD_SWITCH_CPU_WIDE: ret = machine__process_switch_event(machine, event); break; + case PERF_RECORD_BPF_EVENT: + ret = machine__process_bpf_event(machine, event); break; default: ret = -1; break; diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index d856b85862e2..0ed237d6fd0a 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -127,6 +127,8 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event struct perf_sample *sample); int machine__process_mmap2_event(struct machine *machine, union perf_event *event, struct perf_sample *sample); +int machine__process_bpf_event(struct machine *machine, + union perf_event *event); int machine__process_event(struct machine *machine, union perf_event *event, struct perf_sample *sample); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 7d2c8ce6cfad..dffe5120d2d3 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -371,6 +371,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->itrace_start = perf_event__process_itrace_start; if (tool->context_switch == NULL) tool->context_switch = perf_event__process_switch; + if (tool->bpf_event == NULL) + tool->bpf_event = perf_event__process_bpf_event; if (tool->read == NULL) tool->read = process_event_sample_stub; if (tool->throttle == NULL) @@ -1300,6 +1302,8 @@ static int machines__deliver_event(struct machines *machines, case PERF_RECORD_SWITCH: case PERF_RECORD_SWITCH_CPU_WIDE: return tool->context_switch(tool, event, sample, machine); + case PERF_RECORD_BPF_EVENT: + return tool->bpf_event(tool, event, sample, machine); default: ++evlist->stats.nr_unknown_events; return -1; diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 56e4ca54020a..69ae898ca024 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -53,7 +53,9 @@ struct perf_tool { itrace_start, context_switch, throttle, - unthrottle; + unthrottle, + bpf_event; + event_attr_op attr; event_attr_op event_update; event_op2 tracing_data;