From patchwork Tue Oct 20 07:22:15 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kaixu Xia X-Patchwork-Id: 55275 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lf0-f72.google.com (mail-lf0-f72.google.com [209.85.215.72]) by patches.linaro.org (Postfix) with ESMTPS id 1926622EA2 for ; Tue, 20 Oct 2015 07:27:30 +0000 (UTC) Received: by lffv3 with SMTP id v3sf1048253lff.1 for ; Tue, 20 Oct 2015 00:27:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-type:sender:precedence :list-id:x-original-sender:x-original-authentication-results :mailing-list:list-post:list-help:list-archive:list-unsubscribe; bh=wBRoweVcRbNsfolEWP97lNzTEkpjyyLUEyednDt1Exo=; b=ZkbMglIAFNJyIm/8S8Mlewk6+28Bo/RUiM4Z/6jp9lS9aFZvQTIKBQmUm7BssbhULq yIXP5Tql6BLxaeYm9vsE415xkhM3b9fGbHFb7w/sRbm65t3ALNXKnWigGDksQkYVMzaf gjdWbAEqqWeGXaFTCqXRiG7U9Az8QBpgCa/SmI5mG8iuH981p6WB7w9WxShKRjRtvpGg B8aDh1lpRu+C38S5J+R2pME3pS35IIHLRNSFf9p6vd4S8q0xzSwNWoENWrYhXCqRVncw E/4rtObkSVeFKdQZ5Ph9ZC1JcxSxlNciyu3l32dXWBWorZIdus2DYlNd9B8AuqVFP2/D ffLQ== X-Gm-Message-State: ALoCoQkjNrXPsQE9SMNRLI9dji2kECC3e2pXONH3OppbtrrG0h87E/Go1ttlhoTRlg/0e0WZZ5DI X-Received: by 10.112.209.73 with SMTP id mk9mr303618lbc.14.1445326048709; Tue, 20 Oct 2015 00:27:28 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.168.129 with SMTP id r123ls40137lfe.75.gmail; Tue, 20 Oct 2015 00:27:28 -0700 (PDT) X-Received: by 10.112.13.136 with SMTP id h8mr834330lbc.23.1445326048544; Tue, 20 Oct 2015 00:27:28 -0700 (PDT) Received: from mail-lf0-f50.google.com (mail-lf0-f50.google.com. [209.85.215.50]) by mx.google.com with ESMTPS id r199si1219048lfe.160.2015.10.20.00.27.28 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 20 Oct 2015 00:27:28 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.50 as permitted sender) client-ip=209.85.215.50; Received: by lffy185 with SMTP id y185so1140655lff.2 for ; Tue, 20 Oct 2015 00:27:28 -0700 (PDT) X-Received: by 10.25.145.209 with SMTP id t200mr547511lfd.88.1445326048350; Tue, 20 Oct 2015 00:27:28 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp1906803lbq; Tue, 20 Oct 2015 00:27:27 -0700 (PDT) X-Received: by 10.68.194.133 with SMTP id hw5mr2277958pbc.25.1445326047006; Tue, 20 Oct 2015 00:27:27 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id sg10si3100556pac.170.2015.10.20.00.27.26; Tue, 20 Oct 2015 00:27:26 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752676AbbJTH1Q (ORCPT + 28 others); Tue, 20 Oct 2015 03:27:16 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:55427 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752090AbbJTH1N (ORCPT ); Tue, 20 Oct 2015 03:27:13 -0400 Received: from 172.24.1.48 (EHLO SZXEML424-HUB.china.huawei.com) ([172.24.1.48]) by szxrg03-dlp.huawei.com (MOS 4.4.3-GA FastPath queued) with ESMTP id BPH36915; Tue, 20 Oct 2015 15:22:30 +0800 (CST) Received: from euler.hulk-profiling (10.107.193.250) by SZXEML424-HUB.china.huawei.com (10.82.67.153) with Microsoft SMTP Server id 14.3.235.1; Tue, 20 Oct 2015 15:22:21 +0800 From: Kaixu Xia To: , , , , , , , CC: , , , , , Subject: [PATCH V5 1/1] bpf: control events stored in PERF_EVENT_ARRAY maps trace data output when perf sampling Date: Tue, 20 Oct 2015 07:22:15 +0000 Message-ID: <1445325735-121694-2-git-send-email-xiakaixu@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1445325735-121694-1-git-send-email-xiakaixu@huawei.com> References: <1445325735-121694-1-git-send-email-xiakaixu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.107.193.250] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020206.5625ECC9.000F, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 8150ae44d7949c6e5379a9143781b356 Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: xiakaixu@huawei.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.50 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , This patch adds the flag soft_enable to control the trace data output process when perf sampling. By setting this flag and integrating with ebpf, we can control the data output process and get the samples we are most interested in. The bpf helper bpf_perf_event_control() can control either the perf event on current cpu or all the perf events stored in the maps by checking the third parameter 'flags'. Signed-off-by: Kaixu Xia --- include/linux/perf_event.h | 1 + include/uapi/linux/bpf.h | 11 ++++++++ include/uapi/linux/perf_event.h | 3 +- kernel/bpf/verifier.c | 3 +- kernel/events/core.c | 13 +++++++++ kernel/trace/bpf_trace.c | 62 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 91 insertions(+), 2 deletions(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 092a0e8..bb3bf87 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -472,6 +472,7 @@ struct perf_event { struct irq_work pending; atomic_t event_limit; + atomic_t soft_enable; void (*destroy)(struct perf_event *); struct rcu_head rcu_head; diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 564f1f0..164d2a9 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -287,6 +287,17 @@ enum bpf_func_id { * Return: realm if != 0 */ BPF_FUNC_get_route_realm, + + /** + * u64 bpf_perf_event_control(&map, index, flags) - control perf events in maps + * @map: pointer to PERF_EVENT_ARRAY maps + * @index: the key of perf event + * @flags: bit 0 - if true, dump event data on current cpu + * bit 1 - if true, control all the events in maps + * other bits - reserved + * Return: 0 on success + */ + BPF_FUNC_perf_event_control, __BPF_FUNC_MAX_ID, }; diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 2881145..a791b03 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -331,7 +331,8 @@ struct perf_event_attr { comm_exec : 1, /* flag comm events that are due to an exec */ use_clockid : 1, /* use @clockid for time fields */ context_switch : 1, /* context switch data */ - __reserved_1 : 37; + soft_disable : 1, /* output data on samples by default */ + __reserved_1 : 36; union { __u32 wakeup_events; /* wakeup every n events */ diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 1d6b97b..ffec14b 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -245,6 +245,7 @@ static const struct { } func_limit[] = { {BPF_MAP_TYPE_PROG_ARRAY, BPF_FUNC_tail_call}, {BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_read}, + {BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_control}, }; static void print_verifier_state(struct verifier_env *env) @@ -910,7 +911,7 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id) * don't allow any other map type to be passed into * the special func; */ - if (bool_map != bool_func) + if (bool_func && bool_map != bool_func) return -EINVAL; } diff --git a/kernel/events/core.c b/kernel/events/core.c index b11756f..5219635 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6337,6 +6337,9 @@ static int __perf_event_overflow(struct perf_event *event, irq_work_queue(&event->pending); } + if (unlikely(!atomic_read(&event->soft_enable))) + return 0; + if (event->overflow_handler) event->overflow_handler(event, data, regs); else @@ -7709,6 +7712,14 @@ static void account_event(struct perf_event *event) account_event_cpu(event, event->cpu); } +static void perf_event_check_dump_flag(struct perf_event *event) +{ + if (event->attr.soft_disable == 1) + atomic_set(&event->soft_enable, 0); + else + atomic_set(&event->soft_enable, 1); +} + /* * Allocate and initialize a event structure */ @@ -7840,6 +7851,8 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, } } + perf_event_check_dump_flag(event); + return event; err_per_task: diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 0fe96c7..398ed94 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -215,6 +215,66 @@ const struct bpf_func_proto bpf_perf_event_read_proto = { .arg2_type = ARG_ANYTHING, }; +/* flags for PERF_EVENT_ARRAY maps */ +enum { + BPF_EVENT_CTL_BIT_CUR = 0, + BPF_EVENT_CTL_BIT_ALL = 1, + __NR_BPF_EVENT_CTL_BITS, +}; + +#define BPF_CTL_BIT_FLAG_MASK GENMASK_ULL(63, __NR_BPF_EVENT_CTL_BITS) +#define BPF_CTL_BIT_DUMP_CUR BIT_ULL(BPF_EVENT_CTL_BIT_CUR) +#define BPF_CTL_BIT_DUMP_ALL BIT_ULL(BPF_EVENT_CTL_BIT_ALL) + +static u64 bpf_perf_event_control(u64 r1, u64 index, u64 flags, u64 r4, u64 r5) +{ + struct bpf_map *map = (struct bpf_map *) (unsigned long) r1; + struct bpf_array *array = container_of(map, struct bpf_array, map); + struct perf_event *event; + int i; + + if (unlikely(index >= array->map.max_entries)) + return -E2BIG; + + if (flags & BPF_CTL_BIT_FLAG_MASK) + return -EINVAL; + + if (flags & BPF_CTL_BIT_DUMP_ALL) { + bool dump_control = flags & BPF_CTL_BIT_DUMP_CUR; + + for (i = 0; i < array->map.max_entries; i++) { + event = (struct perf_event *)array->ptrs[i]; + if (!event) + continue; + + if (dump_control) + atomic_inc_unless_negative(&event->soft_enable); + else + atomic_dec_if_positive(&event->soft_enable); + } + return 0; + } + + event = (struct perf_event *)array->ptrs[index]; + if (!event) + return -ENOENT; + + if (flags & BPF_CTL_BIT_DUMP_CUR) + atomic_inc_unless_negative(&event->soft_enable); + else + atomic_dec_if_positive(&event->soft_enable); + return 0; +} + +static const struct bpf_func_proto bpf_perf_event_control_proto = { + .func = bpf_perf_event_control, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_CONST_MAP_PTR, + .arg2_type = ARG_ANYTHING, + .arg3_type = ARG_ANYTHING, +}; + static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func_id) { switch (func_id) { @@ -242,6 +302,8 @@ static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func return &bpf_get_smp_processor_id_proto; case BPF_FUNC_perf_event_read: return &bpf_perf_event_read_proto; + case BPF_FUNC_perf_event_control: + return &bpf_perf_event_control_proto; default: return NULL; }