Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753318AbbGAC61 (ORCPT ); Tue, 30 Jun 2015 22:58:27 -0400 Received: from szxga02-in.huawei.com ([119.145.14.65]:32951 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752625AbbGAC6T (ORCPT ); Tue, 30 Jun 2015 22:58:19 -0400 From: He Kuang To: , , , , , , , CC: , Subject: [RFC PATCH 2/5] perf/trace: Add perf extra percpu trace buffer Date: Wed, 1 Jul 2015 02:57:32 +0000 Message-ID: <1435719455-91155-3-git-send-email-hekuang@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1435719455-91155-1-git-send-email-hekuang@huawei.com> References: <1435719455-91155-1-git-send-email-hekuang@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.197.210] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4310 Lines: 135 Introduce another trace buffer besides perf_trace_buffer, so other utilities like bpf can generate and fill perf event data to it extraly and the data can be collected to the original buffer afterwards. The life cycle of this extra buffer is the same as the original one. Signed-off-by: He Kuang --- include/linux/ftrace_event.h | 5 ++++- kernel/trace/trace_event_perf.c | 46 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index f9ecf63..b6cf5a3 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -411,7 +411,8 @@ struct ftrace_event_file { } \ early_initcall(trace_init_perf_perm_##name); -#define PERF_MAX_TRACE_SIZE 2048 +#define PERF_MAX_TRACE_SIZE 2048 +#define PERF_MAX_EXTRA_TRACE_SIZE 128 #define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */ @@ -614,6 +615,8 @@ extern int ftrace_profile_set_filter(struct perf_event *event, int event_id, extern void ftrace_profile_free_filter(struct perf_event *event); extern void *perf_trace_buf_prepare(int size, unsigned short type, struct pt_regs **regs, int *rctxp); +extern void *perf_extra_trace_buf_prepare(int size, int rctx); +extern void *get_perf_extra_trace_buf(int rctx); static inline void perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr, diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 6fa484d..603b3da 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -10,6 +10,7 @@ #include "trace.h" static char __percpu *perf_trace_buf[PERF_NR_CONTEXTS]; +static char __percpu *perf_extra_trace_buf[PERF_NR_CONTEXTS]; /* * Force it to be aligned to unsigned long to avoid misaligned accesses @@ -18,6 +19,10 @@ static char __percpu *perf_trace_buf[PERF_NR_CONTEXTS]; typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)]) perf_trace_t; +typedef +typeof(unsigned long [PERF_MAX_EXTRA_TRACE_SIZE / sizeof(unsigned long)]) + perf_extra_trace_t; + /* Count the events in use (per event id, not per instance) */ static int total_ref_count; @@ -113,6 +118,13 @@ static int perf_trace_event_reg(struct ftrace_event_call *tp_event, goto fail; perf_trace_buf[i] = buf; + + buf = (char __percpu *) + alloc_percpu(perf_extra_trace_t); + if (!buf) + goto fail; + + perf_extra_trace_buf[i] = buf; } } @@ -130,6 +142,9 @@ fail: for (i = 0; i < PERF_NR_CONTEXTS; i++) { free_percpu(perf_trace_buf[i]); perf_trace_buf[i] = NULL; + + free_percpu(perf_extra_trace_buf[i]); + perf_extra_trace_buf[i] = NULL; } } @@ -164,6 +179,9 @@ static void perf_trace_event_unreg(struct perf_event *p_event) for (i = 0; i < PERF_NR_CONTEXTS; i++) { free_percpu(perf_trace_buf[i]); perf_trace_buf[i] = NULL; + + free_percpu(perf_extra_trace_buf[i]); + perf_extra_trace_buf[i] = NULL; } } out: @@ -260,6 +278,34 @@ void perf_trace_del(struct perf_event *p_event, int flags) tp_event->class->reg(tp_event, TRACE_REG_PERF_DEL, p_event); } +void *perf_extra_trace_buf_prepare(int size, int rctx) +{ + char *raw_data; + + BUILD_BUG_ON(PERF_MAX_EXTRA_TRACE_SIZE % sizeof(unsigned long)); + + if (WARN_ONCE(size > PERF_MAX_EXTRA_TRACE_SIZE, + "perf extra buffer not large enough")) + return NULL; + + raw_data = this_cpu_ptr(perf_extra_trace_buf[rctx]); + + /* The first 4 bytes is raw_data size and it is used as a valid flag */ + *(u32 *)raw_data = size; + raw_data += sizeof(u32); + + return raw_data; +} +EXPORT_SYMBOL_GPL(perf_extra_trace_buf_prepare); +NOKPROBE_SYMBOL(perf_extra_trace_buf_prepare); + +void *get_perf_extra_trace_buf(int rctx) +{ + return this_cpu_ptr(perf_extra_trace_buf[rctx]); +} +EXPORT_SYMBOL_GPL(get_perf_extra_trace_buf); +NOKPROBE_SYMBOL(get_perf_extra_trace_buf); + void *perf_trace_buf_prepare(int size, unsigned short type, struct pt_regs **regs, int *rctxp) { -- 1.8.5.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/