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:	Fri, 21 May 2010 16:05:13 +0200
From:	Frederic Weisbecker <fweisbec@...il.com>
To:	Ingo Molnar <mingo@...e.hu>
Cc:	LKML <linux-kernel@...r.kernel.org>,
	Frederic Weisbecker <fweisbec@...il.com>,
	Ingo Molnar <mingo@...e.hu>,
	Peter Zijlstra <a.p.zijlstra@...llo.nl>,
	Arnaldo Carvalho de Melo <acme@...hat.com>,
	Paul Mackerras <paulus@...ba.org>
Subject: [PATCH 2/4] perf: Add exclude_task perf event attribute

Excluding is useful when you want to trace only hard and softirqs.

For this we use a new generic perf_exclude_event() (the previous
one beeing turned into perf_exclude_swevent) to which you can pass
the preemption offset to which your events trigger.

Computing preempt_count() - offset gives us the preempt_count() of
the context that the event has interrupted, on top of which we
can filter the non-irq contexts.

Signed-off-by: Frederic Weisbecker <fweisbec@...il.com>
Cc: Ingo Molnar <mingo@...e.hu>
Cc: Peter Zijlstra <a.p.zijlstra@...llo.nl>
Cc: Arnaldo Carvalho de Melo <acme@...hat.com>
Cc: Paul Mackerras <paulus@...ba.org>
---
 include/linux/perf_event.h |    3 ++-
 kernel/perf_event.c        |   41 ++++++++++++++++++++++++++++++++++-------
 2 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index fe50347..d939fc7 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -214,8 +214,9 @@ struct perf_event_attr {
 				 *  See also PERF_RECORD_MISC_EXACT_IP
 				 */
 				precise_ip     :  2, /* skid constraint       */
+				exclude_task   :  1, /* don't count task context */
 
-				__reserved_1   : 47;
+				__reserved_1   : 46;
 
 	union {
 		__u32		wakeup_events;	  /* wakeup every n events */
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 45b7aec..ab96411 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -3907,10 +3907,33 @@ static int __perf_event_overflow(struct perf_event *event, int nmi,
 	return ret;
 }
 
+static bool
+perf_exclude_event(struct perf_event *event, int offset)
+{
+	if (!in_interrupt_offset(preempt_count() - offset)) {
+		if (event->attr.exclude_task)
+			return true;
+	}
+
+	return false;
+}
+
 int perf_event_overflow(struct perf_event *event, int nmi,
 			  struct perf_sample_data *data,
 			  struct pt_regs *regs)
 {
+	int offset = HARDIRQ_OFFSET;
+
+	if (nmi)
+		offset += NMI_OFFSET;
+	/*
+	 * Hardware events trigger on NMI or simple hardirq, which offset we
+	 * need to substract to get the preempt_count() of the interrupted
+	 * context.
+	 */
+	if (perf_exclude_event(event, offset))
+		return 0;
+
 	return __perf_event_overflow(event, nmi, 1, data, regs);
 }
 
@@ -4008,8 +4031,8 @@ static void perf_swevent_add(struct perf_event *event, u64 nr,
 static int perf_tp_event_match(struct perf_event *event,
 				struct perf_sample_data *data);
 
-static int perf_exclude_event(struct perf_event *event,
-			      struct pt_regs *regs)
+static int perf_exclude_swevent(struct perf_event *event,
+			      struct pt_regs *regs, int offset)
 {
 	if (regs) {
 		if (event->attr.exclude_user && user_mode(regs))
@@ -4019,7 +4042,7 @@ static int perf_exclude_event(struct perf_event *event,
 			return 1;
 	}
 
-	return 0;
+	return perf_exclude_event(event, offset);
 }
 
 static int perf_swevent_match(struct perf_event *event,
@@ -4034,7 +4057,7 @@ static int perf_swevent_match(struct perf_event *event,
 	if (event->attr.config != event_id)
 		return 0;
 
-	if (perf_exclude_event(event, regs))
+	if (perf_exclude_swevent(event, regs, 0))
 		return 0;
 
 	if (event->attr.type == PERF_TYPE_TRACEPOINT &&
@@ -4230,9 +4253,13 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
 	data.period = event->hw.last_period;
 	regs = get_irq_regs();
 
-	if (regs && !perf_exclude_event(event, regs)) {
+	/*
+	 * we are in hardirq, so we need to substract our preempt offset
+	 * to retrieve the interrupted one
+	 */
+	if (regs && !perf_exclude_swevent(event, regs, HARDIRQ_OFFSET)) {
 		if (!(event->attr.exclude_idle && current->pid == 0))
-			if (perf_event_overflow(event, 0, &data, regs))
+			if (__perf_event_overflow(event, 0, 1, &data, regs))
 				ret = HRTIMER_NORESTART;
 	}
 
@@ -4624,7 +4651,7 @@ void perf_bp_event(struct perf_event *bp, void *data)
 
 	perf_sample_data_init(&sample, bp->attr.bp_addr);
 
-	if (!perf_exclude_event(bp, regs))
+	if (!perf_exclude_swevent(bp, regs, 0))
 		perf_swevent_add(bp, 1, 1, &sample, regs);
 }
 #else
-- 
1.6.2.3

--
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