From patchwork Tue Dec 5 01:27:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 844534 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@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; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="jXUHAdfN"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yrPLM6Gw8z9sBZ for ; Tue, 5 Dec 2017 12:29:47 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752524AbdLEB2M (ORCPT ); Mon, 4 Dec 2017 20:28:12 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:42094 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752325AbdLEB1o (ORCPT ); Mon, 4 Dec 2017 20:27:44 -0500 Received: from pps.filterd (m0001303.ppops.net [127.0.0.1]) by m0001303.ppops.net (8.16.0.21/8.16.0.21) with SMTP id vB51RaO0003682 for ; Mon, 4 Dec 2017 17:27:43 -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=xoGsAbdEfxEDMnCfnja+VUcldQt0WBfhaA8lCDz6vfM=; b=jXUHAdfNcpE7l/faJkY34vkmyz3HgQMgh4AyKf/rYNFaQ47QrkqM0kEngoaKu4X6QI/U 0lqNl3SUIJ/wdCDVpRJAE/vjpicmxXt6Ni7Z5YDjSRkKyrCY5ZxjtaCWM+CxD5MkwlkU pmy6ZXKbTG7di27yT0roO3TPLHaWIVT2MI4= Received: from mail.thefacebook.com ([199.201.64.23]) by m0001303.ppops.net with ESMTP id 2engk186ud-5 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Mon, 04 Dec 2017 17:27:43 -0800 Received: from mx-out.facebook.com (192.168.52.123) by PRN-CHUB12.TheFacebook.com (192.168.16.22) with Microsoft SMTP Server id 14.3.319.2; Mon, 4 Dec 2017 17:27:41 -0800 Received: by devbig102.frc2.facebook.com (Postfix, from userid 4523) id 2C0F642827D0; Mon, 4 Dec 2017 17:27:41 -0800 (PST) Smtp-Origin-Hostprefix: devbig From: Song Liu Smtp-Origin-Hostname: devbig102.frc2.facebook.com To: , , , , , , CC: , Song Liu Smtp-Origin-Cluster: frc2c02 Subject: [PATCH v4 5/6] bpf: add option for bpf_load.c to use perf_kprobe Date: Mon, 4 Dec 2017 17:27:28 -0800 Message-ID: <20171205012729.358860-8-songliubraving@fb.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20171205012729.358860-1-songliubraving@fb.com> References: <20171205012729.358860-1-songliubraving@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-12-04_07:, , 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 Function load_and_attach() is updated to be able to create kprobes with either old text based API, or the new perf_event_open API. A global flag use_perf_kprobe is added to select between the two APIs. Signed-off-by: Song Liu Reviewed-by: Josef Bacik --- samples/bpf/bpf_load.c | 59 +++++++++++++++++++++++++++++++++++++++++++------- samples/bpf/bpf_load.h | 10 +++++++++ 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c index 2325d7a..b11c1c1 100644 --- a/samples/bpf/bpf_load.c +++ b/samples/bpf/bpf_load.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -29,6 +28,7 @@ #include "perf-sys.h" #define DEBUGFS "/sys/kernel/debug/tracing/" +#define KPROBE_TYPE_FILE "/sys/bus/event_source/devices/kprobe/type" static char license[128]; static int kern_version; @@ -42,6 +42,8 @@ int prog_array_fd = -1; struct bpf_map_data map_data[MAX_MAPS]; int map_data_count = 0; +bool use_perf_kprobe = true; +int perf_kprobe_type = -1; static int populate_prog_array(const char *event, int prog_fd) { @@ -55,6 +57,26 @@ static int populate_prog_array(const char *event, int prog_fd) return 0; } +int get_perf_kprobe_type_id(void) +{ + int tfd; + int err; + char buf[16]; + + tfd = open(KPROBE_TYPE_FILE, O_RDONLY); + if (tfd < 0) + return -1; + + err = read(tfd, buf, sizeof(buf)); + close(tfd); + + if (err < 0 || err >= sizeof(buf)) + return -1; + buf[err] = 0; + perf_kprobe_type = atoi(buf); + return perf_kprobe_type; +} + static int load_and_attach(const char *event, struct bpf_insn *prog, int size) { bool is_socket = strncmp(event, "socket", 6) == 0; @@ -70,7 +92,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) size_t insns_cnt = size / sizeof(struct bpf_insn); enum bpf_prog_type prog_type; char buf[256]; - int fd, efd, err, id; + int fd, efd, err, id = -1; struct perf_event_attr attr = {}; attr.type = PERF_TYPE_TRACEPOINT; @@ -128,7 +150,13 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) return populate_prog_array(event, fd); } - if (is_kprobe || is_kretprobe) { + if (use_perf_kprobe && perf_kprobe_type == -1) { + get_perf_kprobe_type_id(); + if (perf_kprobe_type == -1) + use_perf_kprobe = false; + } + + if (!use_perf_kprobe && (is_kprobe || is_kretprobe)) { if (is_kprobe) event += 7; else @@ -169,27 +197,42 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) strcat(buf, "/id"); } + if (use_perf_kprobe && (is_kprobe || is_kretprobe)) { + attr.type = perf_kprobe_type; + attr.kprobe_func = ptr_to_u64( + event + strlen(is_kprobe ? "kprobe/" : "kretprobe/")); + attr.probe_offset = 0; + if (is_kretprobe) + attr.config |= PERF_PROBE_CONFIG_IS_RETPROBE; + } else { efd = open(buf, O_RDONLY, 0); if (efd < 0) { printf("failed to open event %s\n", event); return -1; } - err = read(efd, buf, sizeof(buf)); if (err < 0 || err >= sizeof(buf)) { - printf("read from '%s' failed '%s'\n", event, strerror(errno)); + printf("read from '%s' failed '%s'\n", event, + strerror(errno)); return -1; } - close(efd); - buf[err] = 0; id = atoi(buf); attr.config = id; + } efd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0); if (efd < 0) { - printf("event %d fd %d err %s\n", id, efd, strerror(errno)); + if (use_perf_kprobe && (is_kprobe || is_kretprobe)) + printf("k%sprobe %s fd %d err %s\n", + is_kprobe ? "" : "ret", + event + strlen(is_kprobe ? "kprobe/" + : "kretprobe/"), + efd, strerror(errno)); + else + printf("event %d fd %d err %s\n", id, efd, + strerror(errno)); return -1; } event_fd[prog_cnt - 1] = efd; diff --git a/samples/bpf/bpf_load.h b/samples/bpf/bpf_load.h index 7d57a42..95d6be5 100644 --- a/samples/bpf/bpf_load.h +++ b/samples/bpf/bpf_load.h @@ -2,6 +2,7 @@ #ifndef __BPF_LOAD_H #define __BPF_LOAD_H +#include #include "libbpf.h" #define MAX_MAPS 32 @@ -38,6 +39,10 @@ extern int map_fd[MAX_MAPS]; extern struct bpf_map_data map_data[MAX_MAPS]; extern int map_data_count; +extern bool use_perf_kprobe; +extern int perf_kprobe_type; +extern int get_perf_kprobe_type_id(void); + /* parses elf file compiled by llvm .c->.o * . parses 'maps' section and creates maps via BPF syscall * . parses 'license' section and passes it to syscall @@ -59,6 +64,11 @@ struct ksym { char *name; }; +static inline __u64 ptr_to_u64(const void *ptr) +{ + return (__u64) (unsigned long) ptr; +} + int load_kallsyms(void); struct ksym *ksym_search(long key); int set_link_xdp_fd(int ifindex, int fd, __u32 flags);