perf updates
Subsystems (16)
Linus,
Please pull the latest perf-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf-urgent-for-linus
# HEAD: 0c9f790fcbdaf8cfb6dd7fb4e88fadf55082e37e Merge tag 'perf-core-for-mingo-20160523' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Mostly tooling and PMU driver fixes, but also a number of late updates such as the reworking of the call-chain size limiting logic to make call-graph recording more robust, plus tooling side changes for the new 'backwards ring-buffer' extension to the perf ring-buffer.
Thanks,
Ingo
------------------>
Andi Kleen (2):
perf stat: Avoid fractional digits for integer scales perf report: Add srcline_from/to branch sort keys
Arnaldo Carvalho de Melo (15):
perf core: Generalize max_stack sysctl handler
perf core: Pass max stack as a perf_callchain_entry context
perf core: Add a 'nr' field to perf_event_callchain_context
perf core: Add perf_callchain_store_context() helper
perf core: Separate accounting of contexts and real addresses in a stack trace perf tools: Separate accounting of contexts and real addresses in a stack trace perf machine: Do not bail out if not managing to read ref reloc symbol perf trace: Warn when trying to resolve kernel addresses with kptr_restrict=1 perf top: Use machine->kptr_restrict_warned
perf trace: Fix exit_group() formatting
perf callchain: Stop validating callchains by the max_stack sysctl perf tools: Fix usage of max_stack sysctl
perf trace: Only auto set call-graph to "dwarf" when syscalls are being traced perf trace: Use the fd->name beautifier as default for "fd" args perf trace: Use the ptr->name beautifier as default for "filename" args
Chris Ryder (2):
perf annotate: Fix identification of ARM blt and bls instructions perf annotate: Sort list of recognised instructions
Colin Ian King (1):
perf/x86/intel/p4: Trival indentation fix, remove space
He Kuang (2):
perf symbols: Store vdso buildid unconditionally
perf tools: Set buildid dir under symfs when --symfs is provided
Jiri Olsa (1):
perf/x86/intel/uncore: Remove WARN_ON_ONCE in uncore_pci_probe
Masami Hiramatsu (1):
perf symbols: Introduce DSO__NAME_KALLSYMS and DSO__NAME_KCORE
Namhyung Kim (3):
perf stat: Fix indentation of stalled backend cycle perf stat: Update runtime using cpu-clock event perf stat: Use cpu-clock event for cpu targets
Peter Zijlstra (1):
perf: Update MAINTAINERS for x86 move
Wang Nan (6):
perf evsel: Add overwrite attribute and check write_backward perf evsel: Record fd into perf_mmap
perf evlist: Add API to pause/resume
perf record: Prevent reading invalid data in record__mmap_read perf record: Rename variable to make code clear perf record: Read from backward ring buffer
Documentation/sysctl/kernel.txt | 14 ++ MAINTAINERS | 1 + arch/arc/kernel/perf_event.c | 6 +- arch/arm/kernel/perf_callchain.c | 10 +- arch/arm64/kernel/perf_callchain.c | 14 +- arch/metag/kernel/perf_callchain.c | 10 +- arch/mips/kernel/perf_event.c | 12 +- arch/powerpc/perf/callchain.c | 20 +- arch/s390/kernel/perf_event.c | 4 +- arch/sh/kernel/perf_callchain.c | 4 +- arch/sparc/kernel/perf_event.c | 14 +- arch/tile/kernel/perf_event.c | 6 +- arch/x86/events/core.c | 14 +- arch/x86/events/intel/p4.c | 2 +- arch/x86/events/intel/uncore.c | 2 +- arch/xtensa/kernel/perf_event.c | 10 +- include/linux/perf_event.h | 34 ++- include/uapi/linux/perf_event.h | 1 + kernel/bpf/stackmap.c | 3 +- kernel/events/callchain.c | 36 ++- kernel/sysctl.c | 11 +- tools/perf/Documentation/perf-report.txt | 5 +- tools/perf/Documentation/perf-script.txt | 2 +- tools/perf/Documentation/perf-trace.txt | 3 +- tools/perf/builtin-annotate.c | 5 +- tools/perf/builtin-buildid-cache.c | 8 +- tools/perf/builtin-diff.c | 5 +- tools/perf/builtin-record.c | 81 +++++- tools/perf/builtin-report.c | 7 +- tools/perf/builtin-script.c | 7 +- tools/perf/builtin-stat.c | 22 +- tools/perf/builtin-timechart.c | 5 +- tools/perf/builtin-top.c | 6 +- tools/perf/builtin-trace.c | 274 +++++++++------------ tools/perf/perf.c | 3 + tools/perf/util/annotate.c | 32 ++- tools/perf/util/build-id.c | 2 +- tools/perf/util/db-export.c | 3 +- tools/perf/util/dso.c | 7 +- tools/perf/util/evlist.c | 34 +++ tools/perf/util/evlist.h | 4 + tools/perf/util/evsel.c | 13 + tools/perf/util/evsel.h | 1 + tools/perf/util/hist.c | 9 + tools/perf/util/hist.h | 2 + tools/perf/util/machine.c | 35 ++- tools/perf/util/machine.h | 1 + .../perf/util/scripting-engines/trace-event-perl.c | 3 +- tools/perf/util/sort.c | 84 +++++++ tools/perf/util/sort.h | 2 + tools/perf/util/stat-shadow.c | 8 +- tools/perf/util/symbol.c | 33 ++- tools/perf/util/symbol.h | 7 + tools/perf/util/top.h | 1 - tools/perf/util/util.c | 3 +- tools/perf/util/util.h | 3 +- 56 files changed, 618 insertions(+), 330 deletions(-)
Documentation/sysctl/kernel.txt +14 -0
@@ -61,6 +61,7 @@ Currently, these files might (depending on your configuration) - perf_cpu_time_max_percent - perf_event_paranoid - perf_event_max_stack +- perf_event_max_contexts_per_stack - pid_max - powersave-nap [ PPC only ] - printk
@@ -668,6 +669,19 @@ The default value is 127. ============================================================== +perf_event_max_contexts_per_stack: + +Controls maximum number of stack frame context entries for +(attr.sample_type & PERF_SAMPLE_CALLCHAIN) configured events, for +instance, when using 'perf record -g' or 'perf trace --call-graph fp'. + +This can only be done when no events are in use that have callchains +enabled, otherwise writing to this file will return -EBUSY. + +The default value is 8. + +============================================================== + pid_max: PID allocation wrap value. When the kernel's next PID value
MAINTAINERS +1 -0
@@ -8637,6 +8637,7 @@ F: arch/*/kernel/*/perf_event*.c F: arch/*/kernel/*/*/perf_event*.c F: arch/*/include/asm/perf_event.h F: arch/*/kernel/perf_callchain.c +F: arch/*/events/* F: tools/perf/ PERSONALITY HANDLING
arch/arc/kernel/perf_event.c +3 -3
@@ -48,7 +48,7 @@ struct arc_callchain_trace {static int callchain_trace (unsigned int addr,void *data) {struct arc_callchain_trace *ctrl = data; -struct perf_callchain_entry *entry = ctrl->perf_stuff; +struct perf_callchain_entry_ctx *entry = ctrl->perf_stuff;perf_callchain_store (entry, addr);if (ctrl->depth++ <3 )
@@ -58,7 +58,7 @@ static int callchain_trace(unsigned int addr, void *data) }void -perf_callchain_kernel (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {struct arc_callchain_trace ctrl = { .depth =0 ,
@@ -69,7 +69,7 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) }void -perf_callchain_user (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {/* * User stack can't be unwound trivially with kernel dwarf unwinder
arch/arm/kernel/perf_callchain.c +5 -5
@@ -31,7 +31,7 @@ struct frame_tail {*/ static struct frame_tail __user *user_backtrace (struct frame_tail __user *tail, -struct perf_callchain_entry *entry) +struct perf_callchain_entry_ctx *entry) {struct frame_tail buftail;unsigned long err;
@@ -59,7 +59,7 @@ user_backtrace(struct frame_tail __user *tail, }void -perf_callchain_user (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {struct frame_tail __user *tail;
@@ -75,7 +75,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) tail = (struct frame_tail __user *)regs->ARM_fp -1 ; -while ((entry->nr < sysctl_perf_event_max_stack) && +while ((entry->nr < entry->max_stack) && tail && !((unsigned long )tail &0x3 )) tail =user_backtrace (tail, entry); }
@@ -89,13 +89,13 @@ static int callchain_trace(struct stackframe *fr, void *data) { - struct perf_callchain_entry *entry = data; + struct perf_callchain_entry_ctx *entry = data;perf_callchain_store (entry, fr->pc);return 0 ; }void -perf_callchain_kernel (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {struct stackframe fr;
arch/arm64/kernel/perf_callchain.c +7 -7
@@ -31,7 +31,7 @@ struct frame_tail {*/ static struct frame_tail __user *user_backtrace (struct frame_tail __user *tail, -struct perf_callchain_entry *entry) +struct perf_callchain_entry_ctx *entry) {struct frame_tail buftail;unsigned long err;
@@ -76,7 +76,7 @@ struct compat_frame_tail {static struct compat_frame_tail __user *compat_user_backtrace (struct compat_frame_tail __user *tail, -struct perf_callchain_entry *entry) +struct perf_callchain_entry_ctx *entry) {struct compat_frame_tail buftail;unsigned long err;
@@ -106,7 +106,7 @@ compat_user_backtrace(struct compat_frame_tail __user *tail, }#endif /* CONFIG_COMPAT */ -void perf_callchain_user (struct perf_callchain_entry *entry, +void perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {if (perf_guest_cbs && perf_guest_cbs->is_in_guest ()) {
@@ -122,7 +122,7 @@ void perf_callchain_user(struct perf_callchain_entry *entry, tail = (struct frame_tail __user *)regs->regs[29 ]; -while (entry->nr < sysctl_perf_event_max_stack && +while (entry->nr < entry->max_stack && tail && !((unsigned long )tail &0xf )) tail =user_backtrace (tail, entry); }else {
@@ -132,7 +132,7 @@ void perf_callchain_user(struct perf_callchain_entry *entry, tail = (struct compat_frame_tail __user *)regs->compat_fp -1 ; -while ((entry->nr < sysctl_perf_event_max_stack) && +while ((entry->nr < entry->max_stack) && tail && !((unsigned long )tail &0x3 )) tail =compat_user_backtrace (tail, entry);#endif
@@ -146,12 +146,12 @@ void perf_callchain_user(struct perf_callchain_entry *entry,*/ static int callchain_trace (struct stackframe *frame,void *data) { -struct perf_callchain_entry *entry = data; +struct perf_callchain_entry_ctx *entry = data;perf_callchain_store (entry, frame->pc);return 0 ; } -void perf_callchain_kernel (struct perf_callchain_entry *entry, +void perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {struct stackframe frame;
arch/metag/kernel/perf_callchain.c +5 -5
@@ -29,7 +29,7 @@ static bool is_valid_call(unsigned long calladdr)static struct metag_frame __user *user_backtrace (struct metag_frame __user *user_frame, -struct perf_callchain_entry *entry) +struct perf_callchain_entry_ctx *entry) {struct metag_frame frame;unsigned long calladdr;
@@ -56,7 +56,7 @@ user_backtrace(struct metag_frame __user *user_frame, }void -perf_callchain_user (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {unsigned long sp = regs->ctx.AX[0 ].U0;struct metag_frame __user *frame;
@@ -65,7 +65,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) --frame; -while ((entry->nr < sysctl_perf_event_max_stack) && frame) +while ((entry->nr < entry->max_stack) && frame) frame =user_backtrace (frame, entry); }
@@ -78,13 +78,13 @@ static int callchain_trace(struct stackframe *fr, void *data) { - struct perf_callchain_entry *entry = data; + struct perf_callchain_entry_ctx *entry = data;perf_callchain_store (entry, fr->pc);return 0 ; }void -perf_callchain_kernel (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {struct stackframe fr;
arch/mips/kernel/perf_event.c +6 -6
@@ -25,8 +25,8 @@* the user stack callchains, we will add it here. */ -static void save_raw_perf_callchain (struct perf_callchain_entry *entry, -unsigned long reg29) +static void save_raw_perf_callchain (struct perf_callchain_entry_ctx *entry, +unsigned long reg29) {unsigned long *sp = (unsigned long *)reg29;unsigned long addr;
@@ -35,14 +35,14 @@ static void save_raw_perf_callchain(struct perf_callchain_entry *entry, addr = *sp++;if (__kernel_text_address (addr)) {perf_callchain_store (entry, addr); -if (entry->nr >= sysctl_perf_event_max_stack) +if (entry->nr >= entry->max_stack)break ; } } } -void perf_callchain_kernel (struct perf_callchain_entry *entry, -struct pt_regs *regs) +void perf_callchain_kernel (struct perf_callchain_entry_ctx *entry, +struct pt_regs *regs) {unsigned long sp = regs->regs[29 ];#ifdef CONFIG_KALLSYMS
@@ -59,7 +59,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, }do {perf_callchain_store (entry, pc); -if (entry->nr >= sysctl_perf_event_max_stack) +if (entry->nr >= entry->max_stack)break ; pc =unwind_stack (current, &sp, pc, &ra); }while (pc);
arch/powerpc/perf/callchain.c +10 -10
@@ -47,7 +47,7 @@ static int valid_next_sp(unsigned long sp, unsigned long prev_sp) }void -perf_callchain_kernel (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {unsigned long sp, next_sp;unsigned long next_ip;
@@ -76,7 +76,7 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) next_ip = regs->nip; lr = regs->link; level =0 ; -perf_callchain_store (entry,PERF_CONTEXT_KERNEL ); +perf_callchain_store_context (entry,PERF_CONTEXT_KERNEL ); }else {if (level ==0 )
@@ -232,7 +232,7 @@ static int sane_signal_64_frame(unsigned long sp) puc == (unsigned long ) &sf->uc; } -static void perf_callchain_user_64 (struct perf_callchain_entry *entry, +static void perf_callchain_user_64 (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {unsigned long sp, next_sp;
@@ -247,7 +247,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, sp = regs->gpr[1 ];perf_callchain_store (entry, next_ip); -while (entry->nr < sysctl_perf_event_max_stack) { +while (entry->nr < entry->max_stack) { fp = (unsigned long __user *) sp;if (!valid_user_sp (sp,1 ) ||read_user_stack_64 (fp, &next_sp))return ;
@@ -274,7 +274,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, read_user_stack_64(&uregs[PT_R1], &sp))return ; level =0 ; -perf_callchain_store (entry,PERF_CONTEXT_USER ); +perf_callchain_store_context (entry,PERF_CONTEXT_USER );perf_callchain_store (entry, next_ip);continue ; }
@@ -319,7 +319,7 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)return rc; } -static inline void perf_callchain_user_64 (struct perf_callchain_entry *entry, +static inline void perf_callchain_user_64 (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) { }
@@ -439,7 +439,7 @@ static unsigned int __user *signal_frame_32_regs(unsigned int sp,return mctx->mc_gregs; } -static void perf_callchain_user_32 (struct perf_callchain_entry *entry, +static void perf_callchain_user_32 (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {unsigned int sp, next_sp;
@@ -453,7 +453,7 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, sp = regs->gpr[1 ];perf_callchain_store (entry, next_ip); -while (entry->nr < sysctl_perf_event_max_stack) { +while (entry->nr < entry->max_stack) { fp = (unsigned int __user *) (unsigned long ) sp;if (!valid_user_sp (sp,0 ) ||read_user_stack_32 (fp, &next_sp))return ;
@@ -473,7 +473,7 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, read_user_stack_32(&uregs[PT_R1], &sp))return ; level =0 ; -perf_callchain_store (entry,PERF_CONTEXT_USER ); +perf_callchain_store_context (entry,PERF_CONTEXT_USER );perf_callchain_store (entry, next_ip);continue ; }
@@ -487,7 +487,7 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, }void -perf_callchain_user (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {if (current_is_64bit ())perf_callchain_user_64 (entry, regs);
arch/s390/kernel/perf_event.c +2 -2
@@ -224,13 +224,13 @@ arch_initcall(service_level_perf_register);static int __perf_callchain_kernel (void *data,unsigned long address) { -struct perf_callchain_entry *entry = data; +struct perf_callchain_entry_ctx *entry = data;perf_callchain_store (entry, address);return 0 ; } -void perf_callchain_kernel (struct perf_callchain_entry *entry, +void perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {if (user_mode (regs))
arch/sh/kernel/perf_callchain.c +2 -2
@@ -21,7 +21,7 @@ static int callchain_stack(void *data, char *name)static void callchain_address (void *data,unsigned long addr,int reliable) { -struct perf_callchain_entry *entry = data; +struct perf_callchain_entry_ctx *entry = data;if (reliable)perf_callchain_store (entry, addr);
@@ -33,7 +33,7 @@ static const struct stacktrace_ops callchain_ops = { };void -perf_callchain_kernel (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {perf_callchain_store (entry, regs->pc);
arch/sparc/kernel/perf_event.c +7 -7
@@ -1711,7 +1711,7 @@ static int __init init_hw_perf_events(void) }pure_initcall (init_hw_perf_events); -void perf_callchain_kernel (struct perf_callchain_entry *entry, +void perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {unsigned long ksp, fp;
@@ -1756,7 +1756,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, } }#endif - }while (entry->nr < sysctl_perf_event_max_stack); + }while (entry->nr < entry->max_stack); } static inline int
@@ -1769,7 +1769,7 @@ valid_user_frame(const void __user *fp, unsigned long size)return (__range_not_ok (fp, size,TASK_SIZE ) ==0 ); } -static void perf_callchain_user_64 (struct perf_callchain_entry *entry, +static void perf_callchain_user_64 (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {unsigned long ufp;
@@ -1790,10 +1790,10 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, pc = sf.callers_pc; ufp = (unsigned long )sf.fp +STACK_BIAS ;perf_callchain_store (entry, pc); - }while (entry->nr < sysctl_perf_event_max_stack); + }while (entry->nr < entry->max_stack); } -static void perf_callchain_user_32 (struct perf_callchain_entry *entry, +static void perf_callchain_user_32 (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {unsigned long ufp;
@@ -1822,11 +1822,11 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, ufp = (unsigned long )sf.fp; }perf_callchain_store (entry, pc); - }while (entry->nr < sysctl_perf_event_max_stack); + }while (entry->nr < entry->max_stack); }void -perf_callchain_user (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {u64 saved_fault_address =current_thread_info ()->fault_address;u8 saved_fault_code =get_thread_fault_code ();
arch/tile/kernel/perf_event.c +3 -3
@@ -941,7 +941,7 @@ arch_initcall(init_hw_perf_events);/* * Tile specific backtracing code for perf_events. */ -static inline void perf_callchain (struct perf_callchain_entry *entry, +static inline void perf_callchain (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {struct KBacktraceIterator kbt;
@@ -992,13 +992,13 @@ static inline void perf_callchain(struct perf_callchain_entry *entry, } } -void perf_callchain_user (struct perf_callchain_entry *entry, +void perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {perf_callchain (entry, regs); } -void perf_callchain_kernel (struct perf_callchain_entry *entry, +void perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {perf_callchain (entry, regs);
arch/x86/events/core.c +7 -7
@@ -2202,7 +2202,7 @@ static int backtrace_stack(void *data, char *name)static int backtrace_address (void *data,unsigned long addr,int reliable) { -struct perf_callchain_entry *entry = data; +struct perf_callchain_entry_ctx *entry = data;return perf_callchain_store (entry, addr); }
@@ -2214,7 +2214,7 @@ static const struct stacktrace_ops backtrace_ops = { };void -perf_callchain_kernel (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {if (perf_guest_cbs && perf_guest_cbs->is_in_guest ()) {/* TODO: We don't support guest os callchain now */
@@ -2268,7 +2268,7 @@ static unsigned long get_segment_base(unsigned int segment)#include <asm/compat.h> static inline int -perf_callchain_user32 (struct pt_regs *regs,struct perf_callchain_entry *entry) +perf_callchain_user32 (struct pt_regs *regs,struct perf_callchain_entry_ctx *entry) {/* 32-bit process in 64-bit kernel. */ unsigned long ss_base, cs_base;
@@ -2283,7 +2283,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) fp =compat_ptr (ss_base + regs->bp);pagefault_disable (); -while (entry->nr < sysctl_perf_event_max_stack) { +while (entry->nr < entry->max_stack) {unsigned long bytes; frame.next_frame =0 ; frame.return_address =0 ;
@@ -2309,14 +2309,14 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) }#else static inline int -perf_callchain_user32 (struct pt_regs *regs,struct perf_callchain_entry *entry) +perf_callchain_user32 (struct pt_regs *regs,struct perf_callchain_entry_ctx *entry) {return 0 ; }#endif void -perf_callchain_user (struct perf_callchain_entry *entry,struct pt_regs *regs) +perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) {struct stack_frame frame;const void __user *fp;
@@ -2343,7 +2343,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)return ;pagefault_disable (); -while (entry->nr < sysctl_perf_event_max_stack) { +while (entry->nr < entry->max_stack) {unsigned long bytes; frame.next_frame =NULL ; frame.return_address =0 ;
arch/x86/events/intel/p4.c +1 -1
@@ -826,7 +826,7 @@ static int p4_hw_config(struct perf_event *event)* Clear bits we reserve to be managed by kernel itself * and never allowed from a user space */ - event->attr.config &=P4_CONFIG_MASK ; + event->attr.config &=P4_CONFIG_MASK ; rc =p4_validate_raw_event (event);if (rc)
arch/x86/events/intel/uncore.c +1 -1
@@ -891,7 +891,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *idreturn -ENODEV ; pkg =topology_phys_to_logical_pkg (phys_id); -if (WARN_ON_ONCE (pkg <0 )) +if (pkg <0 )return -EINVAL ;if (UNCORE_PCI_DEV_TYPE (id->driver_data) ==UNCORE_EXTRA_PCI_DEV ) {
arch/xtensa/kernel/perf_event.c +5 -5
@@ -323,23 +323,23 @@ static void xtensa_pmu_read(struct perf_event *event)static int callchain_trace (struct stackframe *frame,void *data) { -struct perf_callchain_entry *entry = data; +struct perf_callchain_entry_ctx *entry = data;perf_callchain_store (entry, frame->pc);return 0 ; } -void perf_callchain_kernel (struct perf_callchain_entry *entry, +void perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) { -xtensa_backtrace_kernel (regs, sysctl_perf_event_max_stack, +xtensa_backtrace_kernel (regs, entry->max_stack, callchain_trace,NULL , entry); } -void perf_callchain_user (struct perf_callchain_entry *entry, +void perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) { -xtensa_backtrace_user (regs, sysctl_perf_event_max_stack, +xtensa_backtrace_user (regs, entry->max_stack, callchain_trace, entry); }
include/linux/perf_event.h +29 -5
@@ -61,6 +61,14 @@ struct perf_callchain_entry {__u64 ip[0 ];/* /proc/sys/kernel/perf_event_max_stack */ }; +struct perf_callchain_entry_ctx { +struct perf_callchain_entry *entry; +u32 max_stack; +u32 nr; +short contexts; +bool contexts_maxed; +}; +struct perf_raw_record {u32 size;void *data;
@@ -1063,20 +1071,36 @@ extern void perf_event_fork(struct task_struct *tsk);/* Callchains */ DECLARE_PER_CPU(struct perf_callchain_entry, perf_callchain_entry); -extern void perf_callchain_user (struct perf_callchain_entry *entry,struct pt_regs *regs); -extern void perf_callchain_kernel (struct perf_callchain_entry *entry,struct pt_regs *regs); +extern void perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs); +extern void perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs);extern struct perf_callchain_entry *get_perf_callchain (struct pt_regs *regs,u32 init_nr,bool kernel,bool user, -bool crosstask,bool add_mark); +u32 max_stack,bool crosstask,bool add_mark);extern int get_callchain_buffers (void );extern void put_callchain_buffers (void );extern int sysctl_perf_event_max_stack; +extern int sysctl_perf_event_max_contexts_per_stack; + +static inline int perf_callchain_store_context (struct perf_callchain_entry_ctx *ctx,u64 ip) +{ +if (ctx->contexts < sysctl_perf_event_max_contexts_per_stack) { +struct perf_callchain_entry *entry = ctx->entry; + entry->ip[entry->nr++] = ip; + ++ctx->contexts; +return 0 ; + }else { + ctx->contexts_maxed = true; +return -1 ;/* no more room, stop walking the stack */ + } +} -static inline int perf_callchain_store (struct perf_callchain_entry *entry,u64 ip) +static inline int perf_callchain_store (struct perf_callchain_entry_ctx *ctx,u64 ip) { -if (entry->nr < sysctl_perf_event_max_stack) { +if (ctx->nr < ctx->max_stack && !ctx->contexts_maxed) { +struct perf_callchain_entry *entry = ctx->entry; entry->ip[entry->nr++] = ip; + ++ctx->nr;return 0 ; }else {return -1 ;/* no more room, stop walking the stack */
include/uapi/linux/perf_event.h +1 -0
@@ -862,6 +862,7 @@ enum perf_event_type { };#define PERF_MAX_STACK_DEPTH 127 +#define PERF_MAX_CONTEXTS_PER_STACK 8enum perf_callchain_context {PERF_CONTEXT_HV = (__u64)-32 ,
kernel/bpf/stackmap.c +2 -1
@@ -136,7 +136,8 @@ static u64 bpf_get_stackid(u64 r1, u64 r2, u64 flags, u64 r4, u64 r5) BPF_F_FAST_STACK_CMP | BPF_F_REUSE_STACKID)))return -EINVAL ; - trace =get_perf_callchain (regs, init_nr, kernel, user, false, false); + trace =get_perf_callchain (regs, init_nr, kernel, user, + sysctl_perf_event_max_stack, false, false);if (unlikely (!trace))/* couldn't fetch the stack trace */
kernel/events/callchain.c +24 -12
@@ -19,11 +19,13 @@ struct callchain_cpus_entries { };int sysctl_perf_event_max_stack__read_mostly =PERF_MAX_STACK_DEPTH ; +int sysctl_perf_event_max_contexts_per_stack__read_mostly =PERF_MAX_CONTEXTS_PER_STACK ;static inline size_t perf_callchain_entry__sizeof (void ) {return (sizeof (struct perf_callchain_entry ) + -sizeof (__u64) * sysctl_perf_event_max_stack); +sizeof (__u64) * (sysctl_perf_event_max_stack + + sysctl_perf_event_max_contexts_per_stack)); } static DEFINE_PER_CPU(int, callchain_recursion[PERF_NR_CONTEXTS]);
@@ -32,12 +34,12 @@ static DEFINE_MUTEX(callchain_mutex);static struct callchain_cpus_entries *callchain_cpus_entries; -__weak void perf_callchain_kernel (struct perf_callchain_entry *entry, +__weak void perf_callchain_kernel (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) { } -__weak void perf_callchain_user (struct perf_callchain_entry *entry, +__weak void perf_callchain_user (struct perf_callchain_entry_ctx *entry,struct pt_regs *regs) { }
@@ -176,14 +178,15 @@ perf_callchain(struct perf_event *event, struct pt_regs *regs)if (!kernel && !user)return NULL ; -return get_perf_callchain (regs,0 , kernel, user, crosstask, true); +return get_perf_callchain (regs,0 , kernel, user, sysctl_perf_event_max_stack, crosstask, true); }struct perf_callchain_entry *get_perf_callchain (struct pt_regs *regs,u32 init_nr,bool kernel,bool user, -bool crosstask,bool add_mark) +u32 max_stack,bool crosstask,bool add_mark) {struct perf_callchain_entry *entry; +struct perf_callchain_entry_ctx ctx;int rctx; entry =get_callchain_entry (&rctx);
@@ -193,12 +196,16 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,if (!entry) goto exit_put; - entry->nr = init_nr; + ctx.entry = entry; + ctx.max_stack = max_stack; + ctx.nr = entry->nr = init_nr; + ctx.contexts =0 ; + ctx.contexts_maxed = false;if (kernel && !user_mode (regs)) {if (add_mark) -perf_callchain_store (entry,PERF_CONTEXT_KERNEL ); -perf_callchain_kernel (entry, regs); +perf_callchain_store_context (&ctx,PERF_CONTEXT_KERNEL ); +perf_callchain_kernel (&ctx, regs); }if (user) {
@@ -214,8 +221,8 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, goto exit_put;if (add_mark) -perf_callchain_store (entry,PERF_CONTEXT_USER ); -perf_callchain_user (entry, regs); +perf_callchain_store_context (&ctx,PERF_CONTEXT_USER ); +perf_callchain_user (&ctx, regs); } }
@@ -225,10 +232,15 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,return entry; } +/* +* Used for sysctl_perf_event_max_stack and +* sysctl_perf_event_max_contexts_per_stack. +*/ int perf_event_max_stack_handler (struct ctl_table *table,int write,void __user *buffer,size_t *lenp,loff_t *ppos) { -int new_value = sysctl_perf_event_max_stack, ret; +int *value = table->data; +int new_value = *value, ret;struct ctl_table new_table = *table; new_table.data = &new_value;
@@ -240,7 +252,7 @@ int perf_event_max_stack_handler(struct ctl_table *table, int write,if (atomic_read (&nr_callchain_events)) ret = -EBUSY ;else - sysctl_perf_event_max_stack = new_value; + *value = new_value;mutex_unlock (&callchain_mutex);
kernel/sysctl.c +10 -1
@@ -1149,13 +1149,22 @@ static struct ctl_table kern_table[] = { }, { .procname = "perf_event_max_stack", - .data = NULL, /* filled in by handler */ + .data = &sysctl_perf_event_max_stack, .maxlen = sizeof(sysctl_perf_event_max_stack), .mode = 0644, .proc_handler = perf_event_max_stack_handler, .extra1 = &zero, .extra2 = &six_hundred_forty_kb, }, + { + .procname = "perf_event_max_contexts_per_stack", + .data = &sysctl_perf_event_max_contexts_per_stack, + .maxlen = sizeof(sysctl_perf_event_max_contexts_per_stack), + .mode = 0644, + .proc_handler = perf_event_max_stack_handler, + .extra1 = &zero, + .extra2 = &one_thousand, + }, #endif #ifdef CONFIG_KMEMCHECK {
tools/perf/Documentation/perf-report.txt +3 -2
@@ -103,12 +103,13 @@ OPTIONS If --branch-stack option is used, following sort keys are also available: - dso_from, dso_to, symbol_from, symbol_to, mispredict. - dso_from: name of library or module branched from - dso_to: name of library or module branched to - symbol_from: name of function branched from - symbol_to: name of function branched to + - srcline_from: source file and line branched from + - srcline_to: source file and line branched to - mispredict: "N" for predicted branch, "Y" for mispredicted branch - in_tx: branch in TSX transaction - abort: TSX transaction abort.
@@ -248,7 +249,7 @@ OPTIONS Note that when using the --itrace option the synthesized callchain size will override this value if the synthesized callchain size is bigger. - Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. + Default: 127 -G:: --inverted::
tools/perf/Documentation/perf-script.txt +1 -1
@@ -267,7 +267,7 @@ include::itrace.txt[] Note that when using the --itrace option the synthesized callchain size will override this value if the synthesized callchain size is bigger. - Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. + Default: 127 --ns:: Use 9 decimal places when displaying time (i.e. show the nanoseconds)
tools/perf/Documentation/perf-trace.txt +2 -1
@@ -143,7 +143,8 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. Implies '--call-graph dwarf' when --call-graph not present on the command line, on systems where DWARF unwinding was built in. - Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise. + Default: /proc/sys/kernel/perf_event_max_stack when present for + live sessions (without --input/-i), 127 otherwise. --min-stack:: Set the stack depth limit when parsing the callchain, anything
tools/perf/builtin-annotate.c +3 -2
@@ -324,8 +324,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)OPT_BOOLEAN (0 ,"skip-missing" , &annotate.skip_missing,"Skip symbols that cannot be annotated" ),OPT_STRING ('C' ,"cpu" , &annotate.cpu_list,"cpu" ,"list of cpus to profile" ), -OPT_STRING (0 ,"symfs" , &symbol_conf.symfs,"directory" , -"Look for files with symbols relative to this directory" ), +OPT_CALLBACK (0 ,"symfs" ,NULL ,"directory" , +"Look for files with symbols relative to this directory" , + symbol__config_symfs),OPT_BOOLEAN (0 ,"source" , &symbol_conf.annotate_src,"Interleave source code with assembly code (default)" ), OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
tools/perf/builtin-buildid-cache.c +4 -4
@@ -119,8 +119,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force)if (build_id_cache__kcore_buildid (from_dir, sbuildid) <0 )return -1 ; -scnprintf (to_dir,sizeof (to_dir),"%s/[kernel.kcore]/%s" , - buildid_dir, sbuildid); +scnprintf (to_dir,sizeof (to_dir),"%s/%s/%s" , + buildid_dir,DSO__NAME_KCORE , sbuildid);if (!force && !build_id_cache__kcore_existing (from_dir, to_dir,sizeof (to_dir))) {
@@ -131,8 +131,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force)if (build_id_cache__kcore_dir (dir,sizeof (dir)))return -1 ; -scnprintf (to_dir,sizeof (to_dir),"%s/[kernel.kcore]/%s/%s" , - buildid_dir, sbuildid, dir); +scnprintf (to_dir,sizeof (to_dir),"%s/%s/%s/%s" , + buildid_dir,DSO__NAME_KCORE , sbuildid, dir);if (mkdir_p (to_dir,0755 ))return -1 ;
tools/perf/builtin-diff.c +3 -2
@@ -812,8 +812,9 @@ static const struct option options[] = {OPT_STRING_NOEMPTY ('t' ,"field-separator" , &symbol_conf.field_sep,"separator" ,"separator for columns, no spaces will be added between " "columns '.' is reserved." ), -OPT_STRING (0 ,"symfs" , &symbol_conf.symfs,"directory" , -"Look for files with symbols relative to this directory" ), +OPT_CALLBACK (0 ,"symfs" ,NULL ,"directory" , +"Look for files with symbols relative to this directory" , + symbol__config_symfs),OPT_UINTEGER ('o' ,"order" , &sort_compute,"Specify compute sorting." ),OPT_CALLBACK (0 ,"percentage" ,NULL ,"relative|absolute" , "How to display percentage of filtered entries", parse_filter_percentage),
tools/perf/builtin-record.c +71 -10
120 lines not on this page · raw message
tools/perf/builtin-report.c +4 -3
@@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) .ordered_events = true, .ordering_requires_timestamps = true, }, - .max_stack = sysctl_perf_event_max_stack, + .max_stack = PERF_MAX_STACK_DEPTH, .pretty_printing_style = "normal", .socket_filter = -1, };
@@ -770,8 +770,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "columns '.' is reserved."),OPT_BOOLEAN ('U' ,"hide-unresolved" , &symbol_conf.hide_unresolved,"Only display entries resolved to a symbol" ), -OPT_STRING (0 ,"symfs" , &symbol_conf.symfs,"directory" , -"Look for files with symbols relative to this directory" ), +OPT_CALLBACK (0 ,"symfs" ,NULL ,"directory" , +"Look for files with symbols relative to this directory" , + symbol__config_symfs),OPT_STRING ('C' ,"cpu" , &report.cpu_list,"cpu" ,"list of cpus to profile" ), OPT_BOOLEAN('I', "show-info", &report.show_full_info,
tools/perf/builtin-script.c +3 -4
@@ -2010,8 +2010,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) "file", "kallsyms pathname"),OPT_BOOLEAN ('G' ,"hide-call-graph" , &no_callchain,"When printing symbols do not display call chain" ), -OPT_STRING (0 ,"symfs" , &symbol_conf.symfs,"directory" , -"Look for files with symbols relative to this directory" ), +OPT_CALLBACK (0 ,"symfs" ,NULL ,"directory" , +"Look for files with symbols relative to this directory" , + symbol__config_symfs),OPT_CALLBACK ('F' ,"fields" ,NULL ,"str" ,"comma separated output fields prepend with 'type:'. " "Valid types: hw,sw,trace,raw. "
@@ -2067,8 +2068,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)NULL }; - scripting_max_stack = sysctl_perf_event_max_stack; -setup_scripting (); argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
tools/perf/builtin-stat.c +13 -9
@@ -66,6 +66,7 @@#include <stdlib.h> #include <sys/prctl.h> #include <locale.h> +#include <math.h> #define DEFAULT_SEPARATOR " "#define CNTR_NOT_SUPPORTED "<not supported>"
@@ -991,12 +992,12 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)const char *fmt;if (csv_output) { - fmt = sc !=1.0 ?"%.2f%s" :"%.0f%s" ; + fmt =floor (sc) != sc ?"%.2f%s" :"%.0f%s" ; }else {if (big_num) - fmt = sc !=1.0 ?"%'18.2f%s" :"%'18.0f%s" ; + fmt =floor (sc) != sc ?"%'18.2f%s" :"%'18.0f%s" ;else - fmt = sc !=1.0 ?"%18.2f%s" :"%18.0f%s" ; + fmt =floor (sc) != sc ?"%18.2f%s" :"%18.0f%s" ; }aggr_printout (evsel, id, nr);
@@ -1909,6 +1910,9 @@ static int add_default_attributes(void) }if (!evsel_list->nr_entries) { +if (target__has_cpu (&target)) + default_attrs0[0 ].config =PERF_COUNT_SW_CPU_CLOCK ; +if (perf_evlist__add_default_attrs (evsel_list, default_attrs0) <0 )return -1 ;if (pmu_have_event ("cpu" ,"stalled-cycles-frontend" )) {
@@ -2000,7 +2004,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,union perf_event *event, struct perf_session *session) { - struct stat_round_event *round = &event->stat_round; + struct stat_round_event *stat_round = &event->stat_round;struct perf_evsel *counter;struct timespec tsh, *ts =NULL ;const char **argv = session->header.env.cmdline_argv;
@@ -2009,12 +2013,12 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,evlist__for_each (evsel_list, counter)perf_stat_process_counter (&stat_config, counter); -if (round->type ==PERF_STAT_ROUND_TYPE__FINAL ) -update_stats (&walltime_nsecs_stats, round->time); +if (stat_round->type ==PERF_STAT_ROUND_TYPE__FINAL ) +update_stats (&walltime_nsecs_stats, stat_round->time); -if (stat_config.interval && round->time) { - tsh.tv_sec = round->time /NSECS_PER_SEC ; - tsh.tv_nsec = round->time %NSECS_PER_SEC ; +if (stat_config.interval && stat_round->time) { + tsh.tv_sec = stat_round->time /NSECS_PER_SEC ; + tsh.tv_nsec = stat_round->time %NSECS_PER_SEC ; ts = &tsh; }
tools/perf/builtin-timechart.c +3 -2
@@ -1945,8 +1945,9 @@ int cmd_timechart(int argc, const char **argv,OPT_CALLBACK ('p' ,"process" ,NULL ,"process" ,"process selector. Pass a pid or process name." , parse_process), -OPT_STRING (0 ,"symfs" , &symbol_conf.symfs,"directory" , -"Look for files with symbols relative to this directory" ), +OPT_CALLBACK (0 ,"symfs" ,NULL ,"directory" , +"Look for files with symbols relative to this directory" , + symbol__config_symfs),OPT_INTEGER ('n' ,"proc-num" , &tchart.proc_num,"min. number of tasks to print" ), OPT_BOOLEAN('t', "topology", &tchart.topology,
tools/perf/builtin-top.c +3 -3
@@ -732,7 +732,7 @@ static void perf_event__process_sample(struct perf_tool *tool,if (machine__resolve (machine, &al, sample) <0 )return ; -if (!top->kptr_restrict_warned && +if (!machine->kptr_restrict_warned && symbol_conf.kptr_restrict && al.cpumode ==PERF_RECORD_MISC_KERNEL ) { ui__warning(
@@ -743,7 +743,7 @@ static void perf_event__process_sample(struct perf_tool *tool, " modules" : "");if (use_browser <=0 )sleep (5 ); - top->kptr_restrict_warned = true; + machine->kptr_restrict_warned = true; }if (al.sym ==NULL ) {
@@ -759,7 +759,7 @@ static void perf_event__process_sample(struct perf_tool *tool,* --hide-kernel-symbols, even if the user specifies an * invalid --vmlinux ;-) */ -if (!top->kptr_restrict_warned && !top->vmlinux_warned && +if (!machine->kptr_restrict_warned && !top->vmlinux_warned && al.map == machine->vmlinux_maps[MAP__FUNCTION ] &&RB_EMPTY_ROOT (&al.map->dso->symbols[MAP__FUNCTION ])) {if (symbol_conf.vmlinux_name) {
tools/perf/builtin-trace.c +117 -157
430 lines not on this page · raw message
tools/perf/perf.c +3 -0
@@ -549,6 +549,9 @@ int main(int argc, const char **argv)if (sysctl__read_int ("kernel/perf_event_max_stack" , &value) ==0 ) sysctl_perf_event_max_stack = value; +if (sysctl__read_int ("kernel/perf_event_max_contexts_per_stack" , &value) ==0 ) + sysctl_perf_event_max_contexts_per_stack = value; + cmd =extract_argv0_path (argv[0 ]);if (!cmd) cmd ="perf-help" ;
tools/perf/util/annotate.c +25 -7
@@ -354,9 +354,6 @@ static struct ins_ops nop_ops = { .scnprintf = nop__scnprintf, }; -/* -* Must be sorted by name! -*/ static struct ins instructions[] = { { .name ="add" , .ops = &mov_ops, }, { .name ="addl" , .ops = &mov_ops, },
@@ -372,8 +369,8 @@ static struct ins instructions[] = { { .name = "bgt", .ops = &jump_ops, }, { .name = "bhi", .ops = &jump_ops, }, { .name = "bl", .ops = &call_ops, }, - { .name = "blt", .ops = &jump_ops, }, { .name = "bls", .ops = &jump_ops, }, + { .name = "blt", .ops = &jump_ops, }, { .name = "blx", .ops = &call_ops, }, { .name = "bne", .ops = &jump_ops, }, #endif
@@ -449,18 +446,39 @@ static struct ins instructions[] = { { .name = "xbeginq", .ops = &jump_ops, }, }; -static int ins__cmp (const void *name,const void *insp) +static int ins__key_cmp (const void *name,const void *insp) {const struct ins *ins = insp;return strcmp (name, ins->name); } +static int ins__cmp (const void *a,const void *b) +{ +const struct ins *ia = a; +const struct ins *ib = b; + +return strcmp (ia->name, ib->name); +} + +static void ins__sort (void ) +{ +const int nmemb =ARRAY_SIZE (instructions); + +qsort (instructions, nmemb,sizeof (struct ins ), ins__cmp); +} +static struct ins *ins__find (const char *name) {const int nmemb =ARRAY_SIZE (instructions); +static bool sorted; + +if (!sorted) { +ins__sort (); + sorted = true; + } -return bsearch (name, instructions, nmemb,sizeof (struct ins ), ins__cmp); +return bsearch (name, instructions, nmemb,sizeof (struct ins ), ins__key_cmp); }int symbol__annotate_init (struct map *map__maybe_unused ,struct symbol *sym)
@@ -1122,7 +1140,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) }else if (dso__is_kcore (dso)) { goto fallback; }else if (readlink (symfs_filename, command,sizeof (command)) <0 || -strstr (command,"[kernel.kallsyms]" ) || +strstr (command,DSO__NAME_KALLSYMS ) ||access (symfs_filename,R_OK )) {free (filename); fallback:
tools/perf/util/build-id.c +1 -1
@@ -256,7 +256,7 @@ static int machine__write_buildid_table(struct machine *machine, int fd)size_t name_len;bool in_kernel = false; -if (!pos->hit) +if (!pos->hit && !dso__is_vdso (pos))continue ;if (dso__is_vdso (pos)) {
tools/perf/util/db-export.c +1 -2
@@ -298,8 +298,7 @@ static struct call_path *call_path_from_sample(struct db_export *dbe,*/ callchain_param.order =ORDER_CALLER ; err =thread__resolve_callchain (thread, &callchain_cursor, evsel, - sample,NULL ,NULL , - sysctl_perf_event_max_stack); + sample,NULL ,NULL ,PERF_MAX_STACK_DEPTH );if (err) { callchain_param.order = saved_order;return NULL ;
tools/perf/util/dso.c +3 -4
@@ -7,6 +7,7 @@#include "auxtrace.h" #include "util.h" #include "debug.h" +#include "vdso.h" char dso__symtab_origin (const struct dso *dso) {
@@ -62,9 +63,7 @@ int dso__read_binary_type_filename(const struct dso *dso, }break ;case DSO_BINARY_TYPE__BUILD_ID_CACHE : -/* skip the locally configured cache if a symfs is given */ -if (symbol_conf.symfs[0 ] || - (dso__build_id_filename (dso, filename, size) ==NULL )) +if (dso__build_id_filename (dso, filename, size) ==NULL ) ret =-1 ;break ;
@@ -1169,7 +1168,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)struct dso *pos;list_for_each_entry (pos, head, node) { -if (with_hits && !pos->hit) +if (with_hits && !pos->hit && !dso__is_vdso (pos))continue ;if (pos->has_build_id) { have_build_id = true;
tools/perf/util/evlist.c +34 -0
@@ -44,6 +44,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,perf_evlist__set_maps (evlist, cpus, threads);fdarray__init (&evlist->pollfd,64 ); evlist->workload.pid =-1 ; + evlist->backward = false; }struct perf_evlist *perf_evlist__new (void )
@@ -679,6 +680,33 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,return NULL ; } +static int perf_evlist__set_paused (struct perf_evlist *evlist,bool value) +{ +int i; + +for (i =0 ; i < evlist->nr_mmaps; i++) { +int fd = evlist->mmap[i].fd; +int err; + +if (fd <0 ) +continue ; + err =ioctl (fd,PERF_EVENT_IOC_PAUSE_OUTPUT , value ?1 :0 ); +if (err) +return err; + } +return 0 ; +} + +int perf_evlist__pause (struct perf_evlist *evlist) +{ +return perf_evlist__set_paused (evlist, true); +} + +int perf_evlist__resume (struct perf_evlist *evlist) +{ +return perf_evlist__set_paused (evlist, false); +} +/* When check_messup is true, 'end' must points to a good entry */ static union perf_event * perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start,
@@ -881,6 +909,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)if (evlist->mmap[idx].base !=NULL ) {munmap (evlist->mmap[idx].base, evlist->mmap_len); evlist->mmap[idx].base =NULL ; + evlist->mmap[idx].fd =-1 ;atomic_set (&evlist->mmap[idx].refcnt,0 ); }auxtrace_mmap__munmap (&evlist->mmap[idx].auxtrace_mmap);
@@ -901,10 +930,14 @@ void perf_evlist__munmap(struct perf_evlist *evlist)static int perf_evlist__alloc_mmap (struct perf_evlist *evlist) { +int i; + evlist->nr_mmaps =cpu_map__nr (evlist->cpus);if (cpu_map__empty (evlist->cpus)) evlist->nr_mmaps =thread_map__nr (evlist->threads); evlist->mmap =zalloc (evlist->nr_mmaps *sizeof (struct perf_mmap )); +for (i =0 ; i < evlist->nr_mmaps; i++) + evlist->mmap[i].fd =-1 ;return evlist->mmap !=NULL ?0 : -ENOMEM ; }
@@ -941,6 +974,7 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, evlist->mmap[idx].base =NULL ;return -1 ; } + evlist->mmap[idx].fd = fd;if (auxtrace_mmap__mmap (&evlist->mmap[idx].auxtrace_mmap, &mp->auxtrace_mp, evlist->mmap[idx].base, fd))
tools/perf/util/evlist.h +4 -0
@@ -28,6 +28,7 @@ struct record_opts;struct perf_mmap {void *base;int mask; +int fd;atomic_t refcnt;u64 prev;struct auxtrace_mmap auxtrace_mmap;
@@ -43,6 +44,7 @@ struct perf_evlist {bool overwrite;bool enabled;bool has_user_cpus; +bool backward;size_t mmap_len;int id_pos;int is_pos;
@@ -135,6 +137,8 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);void perf_evlist__mmap_consume (struct perf_evlist *evlist,int idx); +int perf_evlist__pause (struct perf_evlist *evlist); +int perf_evlist__resume (struct perf_evlist *evlist);int perf_evlist__open (struct perf_evlist *evlist);void perf_evlist__close (struct perf_evlist *evlist);
tools/perf/util/evsel.c +13 -0
@@ -37,6 +37,7 @@ static struct {bool clockid;bool clockid_wrong;bool lbr_flags; +bool write_backward; } perf_missing_features;static clockid_t clockid;
@@ -1376,6 +1377,8 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,if (perf_missing_features.lbr_flags) evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |PERF_SAMPLE_BRANCH_NO_CYCLES ); +if (perf_missing_features.write_backward) + evsel->attr.write_backward = false; retry_sample_id:if (perf_missing_features.sample_id_all) evsel->attr.sample_id_all =0 ;
@@ -1438,6 +1441,12 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, err = -EINVAL ; goto out_close; } + +if (evsel->overwrite && + perf_missing_features.write_backward) { + err = -EINVAL ; + goto out_close; + } } }
@@ -1500,6 +1509,10 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, PERF_SAMPLE_BRANCH_NO_FLAGS))) { perf_missing_features.lbr_flags = true; goto fallback_missing_features; + } else if (!perf_missing_features.write_backward && + evsel->attr.write_backward) { + perf_missing_features.write_backward = true; + goto fallback_missing_features; } out_close:
tools/perf/util/evsel.h +1 -0
@@ -112,6 +112,7 @@ struct perf_evsel {bool tracking;bool per_pkg;bool precise_max; +bool overwrite;/* parse modifier helper */ int exclude_GH;int nr_members;
tools/perf/util/hist.c +9 -0
@@ -117,6 +117,13 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)hists__new_col_len (hists,HISTC_SYMBOL_TO , symlen);hists__set_unres_dso_col_len (hists,HISTC_DSO_TO ); } + +if (h->branch_info->srcline_from) +hists__new_col_len (hists,HISTC_SRCLINE_FROM , +strlen (h->branch_info->srcline_from)); +if (h->branch_info->srcline_to) +hists__new_col_len (hists,HISTC_SRCLINE_TO , +strlen (h->branch_info->srcline_to)); }if (h->mem_info) {
@@ -1042,6 +1049,8 @@ void hist_entry__delete(struct hist_entry *he)if (he->branch_info) {map__zput (he->branch_info->from.map);map__zput (he->branch_info->to.map); +free_srcline (he->branch_info->srcline_from); +free_srcline (he->branch_info->srcline_to);zfree (&he->branch_info); }
tools/perf/util/hist.h +2 -0
@@ -52,6 +52,8 @@ enum hist_column {HISTC_MEM_IADDR_SYMBOL ,HISTC_TRANSACTION ,HISTC_CYCLES , +HISTC_SRCLINE_FROM , +HISTC_SRCLINE_TO ,HISTC_TRACE , HISTC_NR_COLS, /* Last entry */ };
tools/perf/util/machine.c +15 -20
@@ -43,6 +43,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) machine->symbol_filter =NULL ; machine->id_hdr_size =0 ; + machine->kptr_restrict_warned = false; machine->comm_exec = false; machine->kernel_start =0 ;
@@ -709,7 +710,7 @@ static struct dso *machine__get_kernel(struct machine *machine)if (machine__is_host (machine)) { vmlinux_name = symbol_conf.vmlinux_name;if (!vmlinux_name) - vmlinux_name ="[kernel.kallsyms]" ; + vmlinux_name =DSO__NAME_KALLSYMS ; kernel =machine__findnew_kernel (machine, vmlinux_name,"[kernel]" ,DSO_TYPE_KERNEL );
@@ -1135,10 +1136,10 @@ int machine__create_kernel_maps(struct machine *machine) {struct dso *kernel =machine__get_kernel (machine);const char *name; -u64 addr =machine__get_running_kernel_start (machine, &name); +u64 addr;int ret; -if (!addr || kernel ==NULL ) +if (kernel ==NULL )return -1 ; ret =__machine__create_kernel_maps (machine, kernel);
@@ -1160,8 +1161,9 @@ int machine__create_kernel_maps(struct machine *machine)*/ map_groups__fixup_end (&machine->kmaps); -if (maps__set_kallsyms_ref_reloc_sym (machine->vmlinux_maps, name, - addr)) { + addr =machine__get_running_kernel_start (machine, &name); +if (!addr) { + }else if (maps__set_kallsyms_ref_reloc_sym (machine->vmlinux_maps, name, addr)) {machine__destroy_kernel_maps (machine);return -1 ; }
@@ -1769,11 +1771,6 @@ static int resolve_lbr_callchain_sample(struct thread *thread,*/ int mix_chain_nr = i +1 + lbr_nr +1 ; -if (mix_chain_nr > (int )sysctl_perf_event_max_stack +PERF_MAX_BRANCH_DEPTH ) { -pr_warning ("corrupted callchain. skipping...\n" ); -return 0 ; - } -for (j =0 ; j < mix_chain_nr; j++) {if (callchain_param.order ==ORDER_CALLEE ) {if (j < i +1 )
@@ -1811,9 +1808,9 @@ static int thread__resolve_callchain_sample(struct thread *thread, {struct branch_stack *branch = sample->branch_stack;struct ip_callchain *chain = sample->callchain; -int chain_nr =min (max_stack, (int )chain->nr); +int chain_nr = chain->nr;u8 cpumode =PERF_RECORD_MISC_USER ; -int i, j, err; +int i, j, err, nr_entries;int skip_idx =-1 ;int first_call =0 ;
@@ -1828,8 +1825,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,* Based on DWARF debug information, some architectures skip * a callchain entry saved by the kernel. */ -if (chain->nr < sysctl_perf_event_max_stack) - skip_idx =arch_skip_callchain_idx (thread, chain); + skip_idx =arch_skip_callchain_idx (thread, chain);/* * Add branches to call stack for easier browsing. This gives
@@ -1889,12 +1885,8 @@ static int thread__resolve_callchain_sample(struct thread *thread, } check_calls: -if (chain->nr > sysctl_perf_event_max_stack && (int )chain->nr > max_stack) { -pr_warning ("corrupted callchain. skipping...\n" ); -return 0 ; - } - -for (i = first_call; i < chain_nr; i++) { +for (i = first_call, nr_entries =0 ; + i < chain_nr && nr_entries < max_stack; i++) {u64 ip;if (callchain_param.order ==ORDER_CALLEE )
@@ -1908,6 +1900,9 @@ static int thread__resolve_callchain_sample(struct thread *thread,#endif ip = chain->ips[j]; +if (ip <PERF_CONTEXT_MAX ) + ++nr_entries; + err =add_callchain_ip (thread, cursor, parent, root_al, &cpumode, ip);if (err)
tools/perf/util/machine.h +1 -0
@@ -28,6 +28,7 @@ struct machine {pid_t pid;u16 id_hdr_size;bool comm_exec; +bool kptr_restrict_warned;char *root_dir;struct rb_root threads;pthread_rwlock_t threads_lock;
tools/perf/util/scripting-engines/trace-event-perl.c +1 -2
@@ -264,8 +264,7 @@ static SV *perl_process_callchain(struct perf_sample *sample, goto exit;if (thread__resolve_callchain (al->thread, &callchain_cursor, evsel, - sample,NULL ,NULL , - sysctl_perf_event_max_stack) !=0 ) { + sample,NULL ,NULL , scripting_max_stack) !=0 ) {pr_err ("Failed to resolve callchain. Skipping\n" ); goto exit; }
tools/perf/util/sort.c +84 -0
96 lines not on this page · raw message
tools/perf/util/sort.h +2 -0
@@ -215,6 +215,8 @@ enum sort_type {SORT_ABORT ,SORT_IN_TX ,SORT_CYCLES , +SORT_SRCLINE_FROM , +SORT_SRCLINE_TO ,/* memory mode specific sort keys */ __SORT_MEMORY_MODE,
tools/perf/util/stat-shadow.c +5 -3
@@ -94,7 +94,8 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, {int ctx =evsel_context (counter); -if (perf_evsel__match (counter,SOFTWARE ,SW_TASK_CLOCK )) +if (perf_evsel__match (counter,SOFTWARE ,SW_TASK_CLOCK ) || +perf_evsel__match (counter,SOFTWARE ,SW_CPU_CLOCK ))update_stats (&runtime_nsecs_stats[cpu], count[0 ]);else if (perf_evsel__match (counter,HARDWARE ,HW_CPU_CYCLES ))update_stats (&runtime_cycles_stats[ctx][cpu], count[0 ]);
@@ -188,7 +189,7 @@ static void print_stalled_cycles_backend(int cpu, color =get_ratio_color (GRC_STALLED_CYCLES_BE , ratio); - out->print_metric (out->ctx, color,"%6.2f%%" ,"backend cycles idle" , ratio); + out->print_metric (out->ctx, color,"%7.2f%%" ,"backend cycles idle" , ratio); } static void print_branch_misses(int cpu,
@@ -444,7 +445,8 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, ratio = total / avg;print_metric (ctxp,NULL ,"%8.0f" ,"cycles / elision" , ratio); - }else if (perf_evsel__match (evsel,SOFTWARE ,SW_TASK_CLOCK )) { + }else if (perf_evsel__match (evsel,SOFTWARE ,SW_TASK_CLOCK ) || +perf_evsel__match (evsel,SOFTWARE ,SW_CPU_CLOCK )) {if ((ratio =avg_stats (&walltime_nsecs_stats)) !=0 )print_metric (ctxp,NULL ,"%8.3f" ,"CPUs utilized" , avg / ratio);
tools/perf/util/symbol.c +28 -5
@@ -1662,8 +1662,8 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)build_id__sprintf (dso->build_id,sizeof (dso->build_id), sbuild_id); -scnprintf (path,sizeof (path),"%s/[kernel.kcore]/%s" , buildid_dir, - sbuild_id); +scnprintf (path,sizeof (path),"%s/%s/%s" , buildid_dir, +DSO__NAME_KCORE , sbuild_id);/* Use /proc/kallsyms if possible */ if (is_host) {
@@ -1699,8 +1699,8 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)if (!find_matching_kcore (map, path,sizeof (path)))return strdup (path); -scnprintf (path,sizeof (path),"%s/[kernel.kallsyms]/%s" , - buildid_dir, sbuild_id); +scnprintf (path,sizeof (path),"%s/%s/%s" , + buildid_dir,DSO__NAME_KALLSYMS , sbuild_id);if (access (path,F_OK )) { pr_err("No kallsyms or vmlinux with build-id %s was found\n",
@@ -1769,7 +1769,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,if (err >0 && !dso__is_kcore (dso)) { dso->binary_type =DSO_BINARY_TYPE__KALLSYMS ; -dso__set_long_name (dso,"[kernel.kallsyms]" , false); +dso__set_long_name (dso,DSO__NAME_KALLSYMS , false);map__fixup_start (map);map__fixup_end (map); }
@@ -2033,3 +2033,26 @@ void symbol__exit(void) symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list =NULL ; symbol_conf.initialized = false; } + +int symbol__config_symfs (const struct option *opt__maybe_unused , +const char *dir,int unset__maybe_unused ) +{ +char *bf =NULL ; +int ret; + + symbol_conf.symfs =strdup (dir); +if (symbol_conf.symfs ==NULL ) +return -ENOMEM ; + +/* skip the locally configured cache if a symfs is given, and +* config buildid dir to symfs/.debug +*/ + ret =asprintf (&bf,"%s/%s" , dir,".debug" ); +if (ret <0 ) +return -ENOMEM ; + +set_buildid_dir (bf); + +free (bf); +return 0 ; +}
tools/perf/util/symbol.h +7 -0
@@ -44,6 +44,9 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,#define DMGL_ANSI (1 << 1)/* Include const, volatile, etc */ #endif +#define DSO__NAME_KALLSYMS "[kernel.kallsyms]" +#define DSO__NAME_KCORE "[kernel.kcore]" +/** struct symbol - symtab entry * * @ignore - resolvable but tools ignore it (e.g. idle routines)
@@ -183,6 +186,8 @@ struct branch_info {struct addr_map_symbol from;struct addr_map_symbol to;struct branch_flags flags; +char *srcline_from; +char *srcline_to; };struct mem_info {
@@ -287,6 +292,8 @@ bool symbol_type__is_a(char symbol_type, enum map_type map_type);bool symbol__restricted_filename (const char *filename,const char *restricted_filename);bool symbol__is_idle (struct symbol *sym); +int symbol__config_symfs (const struct option *opt__maybe_unused , +const char *dir,int unset__maybe_unused ); int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, struct symsrc *runtime_ss, symbol_filter_t filter,
tools/perf/util/top.h +0 -1
@@ -27,7 +27,6 @@ struct perf_top {int max_stack;bool hide_kernel_symbols, hide_user_symbols, zero;bool use_tui, use_stdio; -bool kptr_restrict_warned;bool vmlinux_warned;bool dump_symtab;struct hist_entry *sym_filter_entry;
tools/perf/util/util.c +2 -1
@@ -33,7 +33,8 @@ struct callchain_param callchain_param = {unsigned int page_size;int cacheline_size; -unsigned int sysctl_perf_event_max_stack =PERF_MAX_STACK_DEPTH ; +int sysctl_perf_event_max_stack =PERF_MAX_STACK_DEPTH ; +int sysctl_perf_event_max_contexts_per_stack =PERF_MAX_CONTEXTS_PER_STACK ;bool test_attr__enabled;
tools/perf/util/util.h +2 -1
@@ -261,7 +261,8 @@ void sighandler_dump_stack(int sig);extern unsigned int page_size;extern int cacheline_size; -extern unsigned int sysctl_perf_event_max_stack; +extern int sysctl_perf_event_max_stack; +extern int sysctl_perf_event_max_contexts_per_stack;struct parse_tag {char tag;