lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 1 Jul 2015 02:57:32 +0000
From:	He Kuang <hekuang@...wei.com>
To:	<ast@...mgrid.com>, <rostedt@...dmis.org>,
	<masami.hiramatsu.pt@...achi.com>, <mingo@...hat.com>,
	<acme@...hat.com>, <a.p.zijlstra@...llo.nl>, <jolsa@...nel.org>,
	<namhyung@...nel.org>
CC:	<wangnan0@...wei.com>, <linux-kernel@...r.kernel.org>
Subject: [RFC PATCH 2/5] perf/trace: Add perf extra percpu trace buffer

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 <hekuang@...wei.com>
---
 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@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ