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]
Message-ID: <20180504231102.2850679-2-songliubraving@fb.com>
Date:   Fri, 4 May 2018 16:11:01 -0700
From:   Song Liu <songliubraving@...com>
To:     <linux-kernel@...r.kernel.org>
CC:     Song Liu <songliubraving@...com>, <kernel-team@...com>,
        <tj@...nel.org>, <peterz@...radead.org>, <jolsa@...nel.org>
Subject: [RFC 1/2] perf: add move_dup() for PMU sharing.

To share PMU across different counters, we need a "master event" that
handles interaction with hardware or other software parts. It is
necessary to switch master event to another event. To make this move
compatible with the PMU, it is necessary to move connection or data
from one perf_event to another.

This patch adds a new function to struct pmu, which moves data and/or
data connection from one perf_event to another.
---
 arch/x86/events/core.c          |  8 ++++++++
 include/linux/perf_event.h      |  7 +++++++
 include/linux/trace_events.h    |  3 +++
 kernel/events/core.c            |  3 +++
 kernel/trace/trace_event_perf.c | 11 +++++++++++
 5 files changed, 32 insertions(+)

diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index a6006e7..f850a36 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -2267,6 +2267,13 @@ void perf_check_microcode(void)
 		x86_pmu.check_microcode();
 }
 
+/* RFC NOTE: not fully tested */
+static void x86_pmu_move_dup(struct perf_event *old,
+			     struct perf_event *new)
+{
+	memcpy(&new->hw, &old->hw, sizeof(old->hw));
+}
+
 static struct pmu pmu = {
 	.pmu_enable		= x86_pmu_enable,
 	.pmu_disable		= x86_pmu_disable,
@@ -2280,6 +2287,7 @@ static struct pmu pmu = {
 
 	.add			= x86_pmu_add,
 	.del			= x86_pmu_del,
+	.move_dup		= x86_pmu_move_dup,
 	.start			= x86_pmu_start,
 	.stop			= x86_pmu_stop,
 	.read			= x86_pmu_read,
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index e71e99e..4c84549 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -333,6 +333,13 @@ struct pmu {
 	void (*del)			(struct perf_event *event, int flags);
 
 	/*
+	 * ->move_dup() moves necessary data connection (list, etc.) from
+	 * an old dup master to a new dup master
+	 */
+	void (*move_dup)		(struct perf_event *old,
+					 struct perf_event *new);
+
+	/*
 	 * Starts/Stops a counter present on the PMU.
 	 *
 	 * The PMI handler should stop the counter when perf_event_overflow()
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 2bde3ef..ca48e65 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -557,6 +557,9 @@ extern int  perf_trace_init(struct perf_event *event);
 extern void perf_trace_destroy(struct perf_event *event);
 extern int  perf_trace_add(struct perf_event *event, int flags);
 extern void perf_trace_del(struct perf_event *event, int flags);
+extern void perf_trace_move_dup(struct perf_event *old,
+				struct perf_event *new);
+
 #ifdef CONFIG_KPROBE_EVENTS
 extern int  perf_kprobe_init(struct perf_event *event, bool is_retprobe);
 extern void perf_kprobe_destroy(struct perf_event *event);
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 67612ce..bec1840 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -8349,6 +8349,7 @@ static struct pmu perf_tracepoint = {
 	.event_init	= perf_tp_event_init,
 	.add		= perf_trace_add,
 	.del		= perf_trace_del,
+	.move_dup	= perf_trace_move_dup,
 	.start		= perf_swevent_start,
 	.stop		= perf_swevent_stop,
 	.read		= perf_swevent_read,
@@ -8391,6 +8392,7 @@ static struct pmu perf_kprobe = {
 	.event_init	= perf_kprobe_event_init,
 	.add		= perf_trace_add,
 	.del		= perf_trace_del,
+	.move_dup	= perf_trace_move_dup,
 	.start		= perf_swevent_start,
 	.stop		= perf_swevent_stop,
 	.read		= perf_swevent_read,
@@ -8432,6 +8434,7 @@ static struct pmu perf_uprobe = {
 	.event_init	= perf_uprobe_event_init,
 	.add		= perf_trace_add,
 	.del		= perf_trace_del,
+	.move_dup	= perf_trace_move_dup,
 	.start		= perf_swevent_start,
 	.stop		= perf_swevent_stop,
 	.read		= perf_swevent_read,
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index c79193e..58b0479 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -383,6 +383,17 @@ void perf_trace_del(struct perf_event *p_event, int flags)
 		hlist_del_rcu(&p_event->hlist_entry);
 }
 
+void perf_trace_move_dup(struct perf_event *old,
+			 struct perf_event *new)
+{
+	struct trace_event_call *tp_event = old->tp_event;
+	struct hlist_head __percpu *pcpu_list = tp_event->perf_events;
+	struct hlist_head *list = this_cpu_ptr(pcpu_list);
+
+	hlist_del_rcu(&old->hlist_entry);
+	hlist_add_head_rcu(&new->hlist_entry, list);
+}
+
 void *perf_trace_buf_alloc(int size, struct pt_regs **regs, int *rctxp)
 {
 	char *raw_data;
-- 
2.9.5

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ