perf events and breakpoints updates
Subsystems (2)
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(-)
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
--- 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
@@ -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
PATCH 2/7 perf: Fix argument of perf_arch_fetch_caller_regs
In reply to Frederic WeisbeckerFrom: 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
LKML-Reference: <[email protected]>
--- include/linux/perf_event.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/perf_event.h +1 -1
@@ -936,7 +936,7 @@ extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64);#ifndef perf_arch_fetch_caller_regsstatic 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
PATCH 3/7 x86: Set resume bit before returning from breakpoint exception
In reply to Frederic WeisbeckerInstruction 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.
--- arch/x86/kernel/hw_breakpoint.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
arch/x86/kernel/hw_breakpoint.c +7 -0
@@ -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
PATCH 4/7 x86: Support for instruction breakpoints
In reply to Frederic WeisbeckerInstruction 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.
--- 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
@@ -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
PATCH 5/7 perf: Don't use 4 bytes as a default instruction breakpoint length
In reply to Frederic Weisbecker4 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.
--- tools/perf/util/parse-events.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-)
tools/perf/util/parse-events.c +9 -2
@@ -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
PATCH 6/7 perf: Don't print traces when debugging ordering
In reply to Frederic WeisbeckerErrors 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.
--- tools/perf/builtin-trace.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-)
tools/perf/builtin-trace.c +11 -1
@@ -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
PATCH 7/7 perf: Report lost events in perf trace debug mode
In reply to Frederic WeisbeckerAccount and report lost events in perf trace debugging mode, useful to check the reliability of the traces.
--- tools/perf/builtin-trace.c | 22 +++++++++++++++++----- 1 files changed, 17 insertions(+), 5 deletions(-)
tools/perf/builtin-trace.c +17 -5
@@ -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
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/coreThanks,
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 modeNobuhiro Iwamatsu (1):
perf: Fix argument ofperf_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