Skip to contentSkip to conversation

perf events and breakpoints updates

GIT PULL New Frederic Weisbecker 2 participants 9 messages Jun 24, 2010 – Jun 25, 2010

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

Ingo,

Please pull the perf/core branch that can be found at:

git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing.git
perf/core

Thanks,
Frederic
---

Frederic Weisbecker (6):
hw_breakpoints: Fix per task breakpoint tracking
x86: Set resume bit before returning from breakpoint exception
x86: Support for instruction breakpoints
perf: Don't use 4 bytes as a default instruction breakpoint length
perf: Don't print traces when debugging ordering
perf: Report lost events in perf trace debug mode

Nobuhiro Iwamatsu (1):
perf: Fix argument of perf_arch_fetch_caller_regs

 arch/x86/include/asm/hw_breakpoint.h |    2 +-
 arch/x86/kernel/hw_breakpoint.c      |   51 ++++++++++++++++-------
 include/linux/perf_event.h           |    8 ++-
 kernel/hw_breakpoint.c               |   78 ++++++++++++++++++----------------
 tools/perf/builtin-trace.c           |   32 ++++++++++++--
 tools/perf/util/parse-events.c       |   11 ++++-
 6 files changed, 119 insertions(+), 63 deletions(-)
#1 lore raw

PATCH 1/7 hw_breakpoints: Fix per task breakpoint tracking

Freeing a perf event can happen in several ways. A task calls perf_event_exit_task() right before exiting. This helper will detach all the events from the task context and queue their removal through free_event() if they are child tasks. The task also loses its context reference there.

Releasing the breakpoint slot from the constraint table is made from free_event() that calls release_bp_slot(). We count the number of breakpoints this task is running by looking at the task's perf_event_ctxp and iterating through its attached events. But at this time, the reference to this context has been cleaned up already.

So looking at the event->ctx instead of task->perf_event_ctxp to count the remaining breakpoints should solve the problem. At least it would for child breakpoints, but not for parent ones. If the parent exits before the child, it will remove all its events from the context but free_event() will be called later, on fd release time. And checking the number of breakpoints the task has attached to its context at this time is unreliable as all events have been removed from the context.

To solve this, we keep track of the list of per task breakpoints. On top of it, we maintain our array of numbers of breakpoints used by the tasks. We use the context address as a task id.

So, instead of looking at the number of events attached to a context, we walk through our list of per task breakpoints and count the number of breakpoints that use the same ctx than the one to be reserved or released from the constraint table, and update the count on top of this result.

In the meantime it solves a bad refcounting, it also solves a warning, reported by Paul.

Badness at /home/paulus/kernel/perf/kernel/hw_breakpoint.c:114
NIP: c0000000000cb470 LR: c0000000000cb46c CTR: c00000000032d9b8
REGS: c000000118e7b570 TRAP: 0700 Not tainted (2.6.35-rc3-perf-00008-g76b0f13
)
MSR: 9000000000029032 <EE,ME,CE,IR,DR> CR: 44004424 XER: 000fffff TASK = c0000001187dcad0[3143] 'perf' THREAD: c000000118e78000 CPU: 1
GPR00: c0000000000cb46c c000000118e7b7f0 c0000000009866a0 0000000000000020
GPR04: 0000000000000000 000000000000001d 0000000000000000 0000000000000001
GPR08: c0000000009bed68 c00000000086dff8 c000000000a5bf10 0000000000000001
GPR12: 0000000024004422 c00000000ffff200 0000000000000000 0000000000000000
GPR16: 0000000000000000 0000000000000000 0000000000000018 00000000101150f4
GPR20: 0000000010206b40 0000000000000000 0000000000000000 00000000101150f4
GPR24: c0000001199090c0 0000000000000001 0000000000000000 0000000000000001
GPR28: 0000000000000000 0000000000000000 c0000000008ec290 0000000000000000 NIP [c0000000000cb470] .task_bp_pinned+0x5c/0x12c
LR [c0000000000cb46c] .task_bp_pinned+0x58/0x12c

Call Trace:
[c000000118e7b7f0] [c0000000000cb46c] .task_bp_pinned+0x58/0x12c (unreliable)
[c000000118e7b8a0] [c0000000000cb584] .toggle_bp_task_slot+0x44/0xe4
[c000000118e7b940] [c0000000000cb6c8] .toggle_bp_slot+0xa4/0x164
[c000000118e7b9f0] [c0000000000cbafc] .release_bp_slot+0x44/0x6c
[c000000118e7ba80] [c0000000000c4178] .bp_perf_event_destroy+0x10/0x24
[c000000118e7bb00] [c0000000000c4aec] .free_event+0x180/0x1bc
[c000000118e7bbc0] [c0000000000c54c4] .perf_event_release_kernel+0x14c/0x170
Cc Ingo Molnar <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Prasad <[email protected]>
Cc Mahesh Salgaonkar <[email protected]>
Cc Will Deacon <[email protected]>
Cc Jason Wessel <[email protected]>
---
 include/linux/perf_event.h |    6 ++-
 kernel/hw_breakpoint.c     |   78 +++++++++++++++++++++++---------------------
 2 files changed, 45 insertions(+), 39 deletions(-)
include/linux/perf_event.h +4 -2
index 63b5aa5..0dd5f8a 100644
@@ -533,8 +533,10 @@ struct hw_perf_event {
 			struct hrtimer	hrtimer;
 		};
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
-		/* breakpoint */
-		struct arch_hw_breakpoint	info;
+		struct { /* breakpoint */
+			struct arch_hw_breakpoint	info;
+			struct list_head		bp_list;
+		};
 #endif
 	};
 	local64_t			prev_count;
kernel/hw_breakpoint.c +41 -37

146 lines not on this page · raw message

Signature · 1 line
1.6.2.3
#2 lore raw

PATCH 2/7 perf: Fix argument of perf_arch_fetch_caller_regs

In reply to Frederic Weisbecker

From: Nobuhiro Iwamatsu <[email protected]>

"struct regs" was set to argument of perf_arch_fetch_caller_regs off-case. It should be "struct pt_regs".

This fixes various build errors in archs that have CONFIG_PERF_EVENTS=y but no overriden implementation of perf_arch_fetch_caller_regs.

cc1: warnings being treated as errors
In file included from include/linux/ftrace_event.h:8,

                 from include/trace/syscall.h:6,
                 from include/linux/syscalls.h:75,
                 from arch/sh/kernel/sys_sh32.c:9:

include/linux/perf_event.h:937: error: 'struct regs' declared inside parameter list include/linux/perf_event.h:937: error: its scope is only this definition or declaration, which is probably not what you want include/linux/perf_event.h: In function 'perf_fetch_caller_regs':
include/linux/perf_event.h:952: error: passing argument 1 of 'perf_arch_fetch_caller_regs' from incompatible pointer type

Cc Paul Mackerras <[email protected]>
Cc David Miller <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>

LKML-Reference: <[email protected]>

---
 include/linux/perf_event.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/perf_event.h +1 -1
index 0dd5f8a..937495c 100644
@@ -936,7 +936,7 @@ extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64);
 
 #ifndef perf_arch_fetch_caller_regs
 static inline void
-perf_arch_fetch_caller_regs(struct regs *regs, unsigned long ip) { }
+perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip) { }
 #endif
 
 /*
Signature · 1 line
1.6.2.3
#3 lore raw

PATCH 3/7 x86: Set resume bit before returning from breakpoint exception

In reply to Frederic Weisbecker

Instruction breakpoints trigger before the instruction executes, and returning back from the breakpoint handler brings us again to the instruction that breakpointed. This naturally bring to a breakpoint recursion.

To solve this, x86 has the Resume Bit trick. When the cpu flags have the RF flag set, the next instruction won't trigger any instruction breakpoint, and once this instruction is executed, RF is cleared back.

This let's us jump back to the instruction that triggered the breakpoint without recursion.

Use this when an instruction breakpoint triggers.

Cc Will Deacon <[email protected]>
Cc Prasad <[email protected]>
Cc Mahesh Salgaonkar <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Jason Wessel <[email protected]>
---
 arch/x86/kernel/hw_breakpoint.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
arch/x86/kernel/hw_breakpoint.c +7 -0
index a8f1b80..eaa6ae2 100644
@@ -466,6 +466,13 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args)
 
 		perf_bp_event(bp, args->regs);
 
+		/*
+		 * Set up resume flag to avoid breakpoint recursion when
+		 * returning back to origin.
+		 */
+		if (bp->hw.info.type == X86_BREAKPOINT_EXECUTE)
+			args->regs->flags |= X86_EFLAGS_RF;
+
 		rcu_read_unlock();
 	}
 	/*
Signature · 1 line
1.6.2.3
#4 lore raw

PATCH 4/7 x86: Support for instruction breakpoints

In reply to Frederic Weisbecker

Instruction breakpoints need to have a specific length of 0 to be working. Bring this support but also take care the user is not trying to set an unsupported length, like a range breakpoint for example.

Cc Ingo Molnar <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Prasad <[email protected]>
Cc Mahesh Salgaonkar <[email protected]>
Cc Will Deacon <[email protected]>
Cc Jason Wessel <[email protected]>
---
 arch/x86/include/asm/hw_breakpoint.h |    2 +-
 arch/x86/kernel/hw_breakpoint.c      |   44 ++++++++++++++++++++++-----------
 2 files changed, 30 insertions(+), 16 deletions(-)
arch/x86/include/asm/hw_breakpoint.h +1 -1
index 9422553..528a11e 100644
@@ -20,10 +20,10 @@ struct arch_hw_breakpoint {
 #include <linux/list.h>
 
 /* Available HW breakpoint length encodings */
+#define X86_BREAKPOINT_LEN_X		0x00
 #define X86_BREAKPOINT_LEN_1		0x40
 #define X86_BREAKPOINT_LEN_2		0x44
 #define X86_BREAKPOINT_LEN_4		0x4c
-#define X86_BREAKPOINT_LEN_EXECUTE	0x40
 
 #ifdef CONFIG_X86_64
 #define X86_BREAKPOINT_LEN_8		0x48
arch/x86/kernel/hw_breakpoint.c +29 -15

68 lines not on this page · raw message

Signature · 1 line
1.6.2.3
#5 lore raw

PATCH 5/7 perf: Don't use 4 bytes as a default instruction breakpoint length

In reply to Frederic Weisbecker

4 bytes is fine as a default access for data breakpoints. But instruction breakpoints should take the native pointer length, otherwise we get a -EINVAL in x86-64.

Cc Will Deacon <[email protected]>
Cc Prasad <[email protected]>
Cc Mahesh Salgaonkar <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Jason Wessel <[email protected]>
---
 tools/perf/util/parse-events.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)
tools/perf/util/parse-events.c +9 -2
index 9bf0f40..4af5bd5 100644
@@ -602,8 +602,15 @@ parse_breakpoint_event(const char **strp, struct perf_event_attr *attr)
 			return EVT_FAILED;
 	}
 
-	/* We should find a nice way to override the access type */
-	attr->bp_len = HW_BREAKPOINT_LEN_4;
+	/*
+	 * We should find a nice way to override the access length
+	 * Provide some defaults for now
+	 */
+	if (attr->bp_type == HW_BREAKPOINT_X)
+		attr->bp_len = sizeof(long);
+	else
+		attr->bp_len = HW_BREAKPOINT_LEN_4;
+
 	attr->type = PERF_TYPE_BREAKPOINT;
 
 	return EVT_HANDLED;
Signature · 1 line
1.6.2.3
#6 lore raw

PATCH 6/7 perf: Don't print traces when debugging ordering

In reply to Frederic Weisbecker

Errors due to ordering bugs are easily lost in the middle of traces.

When we are in this mode, don't print the traces so that we don't miss the debugging messages.
But display a comforting message if we didn't encounter any ordering problem.

Cc Ingo Molnar <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Paul Mackerras <[email protected]>
---
 tools/perf/builtin-trace.c |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)
tools/perf/builtin-trace.c +11 -1
index dddf3f0..83df8db 100644
@@ -13,6 +13,7 @@ static char const		*script_name;
 static char const		*generate_script_lang;
 static bool			debug_ordering;
 static u64			last_timestamp;
+static u64			nr_unordered;
 
 static int default_start_script(const char *script __unused,
 				int argc __unused,
@@ -96,8 +97,10 @@ static int process_sample_event(event_t *event, struct perf_session *session)
 				pr_err("Samples misordered, previous: %llu "
 					"this: %llu\n", last_timestamp,
 					data.time);
+				nr_unordered++;
 			}
 			last_timestamp = data.time;
+			return 0;
 		}
 		/*
 		 * FIXME: better resolve from pid from the struct trace_entry
@@ -132,9 +135,16 @@ static void sig_handler(int sig __unused)
 
 static int __cmd_trace(struct perf_session *session)
 {
+	int ret;
+
 	signal(SIGINT, sig_handler);
 
-	return perf_session__process_events(session, &event_ops);
+	ret = perf_session__process_events(session, &event_ops);
+
+	if (debug_ordering)
+		pr_err("Misordered timestamps: %llu\n", nr_unordered);
+
+	return ret;
 }
 
 struct script_spec {
Signature · 1 line
1.6.2.3
#7 lore raw

PATCH 7/7 perf: Report lost events in perf trace debug mode

In reply to Frederic Weisbecker

Account and report lost events in perf trace debugging mode, useful to check the reliability of the traces.

Cc Ingo Molnar <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Masami Hiramatsu <[email protected]>
Cc Tom Zanussi <[email protected]>
---
 tools/perf/builtin-trace.c |   22 +++++++++++++++++-----
 1 files changed, 17 insertions(+), 5 deletions(-)
tools/perf/builtin-trace.c +17 -5
index 83df8db..294da72 100644
@@ -11,7 +11,7 @@
 
 static char const		*script_name;
 static char const		*generate_script_lang;
-static bool			debug_ordering;
+static bool			debug_mode;
 static u64			last_timestamp;
 static u64			nr_unordered;
 
@@ -92,7 +92,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
 	}
 
 	if (session->sample_type & PERF_SAMPLE_RAW) {
-		if (debug_ordering) {
+		if (debug_mode) {
 			if (data.time < last_timestamp) {
 				pr_err("Samples misordered, previous: %llu "
 					"this: %llu\n", last_timestamp,
@@ -116,6 +116,15 @@ static int process_sample_event(event_t *event, struct perf_session *session)
 	return 0;
 }
 
+static u64 nr_lost;
+
+static int process_lost_event(event_t *event, struct perf_session *session __used)
+{
+	nr_lost += event->lost.lost;
+
+	return 0;
+}
+
 static struct perf_event_ops event_ops = {
 	.sample	= process_sample_event,
 	.comm	= event__process_comm,
@@ -123,6 +132,7 @@ static struct perf_event_ops event_ops = {
 	.event_type = event__process_event_type,
 	.tracing_data = event__process_tracing_data,
 	.build_id = event__process_build_id,
+	.lost = process_lost_event,
 	.ordered_samples = true,
 };
 
@@ -141,8 +151,10 @@ static int __cmd_trace(struct perf_session *session)
 
 	ret = perf_session__process_events(session, &event_ops);
 
-	if (debug_ordering)
+	if (debug_mode) {
 		pr_err("Misordered timestamps: %llu\n", nr_unordered);
+		pr_err("Lost events: %llu\n", nr_lost);
+	}
 
 	return ret;
 }
@@ -554,8 +566,8 @@ static const struct option options[] = {
 		   "generate perf-trace.xx script in specified language"),
 	OPT_STRING('i', "input", &input_name, "file",
 		    "input file name"),
-	OPT_BOOLEAN('d', "debug-ordering", &debug_ordering,
-		   "check that samples time ordering is monotonic"),
+	OPT_BOOLEAN('d', "debug-mode", &debug_mode,
+		   "do various checks like samples ordering and lost events"),
 
 	OPT_END()
 };
Signature · 1 line
1.6.2.3
#8 lore raw
In reply to Frederic Weisbecker
Quoted 23 lines · Frederic Weisbecker

Ingo,

Please pull the perf/core branch that can be found at:

git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing.git
perf/core

Thanks,
Frederic
---

Frederic Weisbecker (6):
hw_breakpoints: Fix per task breakpoint tracking
x86: Set resume bit before returning from breakpoint exception
x86: Support for instruction breakpoints
perf: Don't use 4 bytes as a default instruction breakpoint length
perf: Don't print traces when debugging ordering
perf: Report lost events in perf trace debug mode

Nobuhiro Iwamatsu (1):
perf: Fix argument of perf_arch_fetch_caller_regs

Quoted 7 lines
 arch/x86/include/asm/hw_breakpoint.h |    2 +-
 arch/x86/kernel/hw_breakpoint.c      |   51 ++++++++++++++++-------
 include/linux/perf_event.h           |    8 ++-
 kernel/hw_breakpoint.c               |   78 ++++++++++++++++++----------------
 tools/perf/builtin-trace.c           |   32 ++++++++++++--
 tools/perf/util/parse-events.c       |   11 ++++-
 6 files changed, 119 insertions(+), 63 deletions(-)

Pulled, thanks a lot Frederic!

Ingo