perf fixes
Subsystems (2)
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: 636fa4a7b0d2987b7395cd2e259962cdca16e887 Merge tag 'perf-urgent-for-mingo-20160512' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
An uncharacteristically large number of bugs popped up in the last week:
- various tooling fixes, two crashes and build problems
- two Intel PT fixes
- an KNL uncore driver fix
- an Intel PMU driver fix
Thanks,
Ingo
------------------>
Alexander Shishkin (2):
perf/x86/intel/pt: Generate PMI in the STOP region as well perf/core: Disable the event on a truncated AUX record
Andrey Ryabinin (1):
perf/x86: Fix undefined shift on 32-bit kernels
Arnaldo Carvalho de Melo (9):
perf tools: Use readdir() instead of deprecated readdir_r() perf script: Use readdir() instead of deprecated readdir_r() perf thread_map: Use readdir() instead of deprecated readdir_r() perf tools: Use readdir() instead of deprecated readdir_r() perf dwarf: Guard !x86_64 definitions under #ifdef else clause perf probe: Check if dwarf_getlocations() is available perf evsel: Improve EPERM error handling in open_strerror() perf evsel: Handle EACCESS + perf_event_paranoid=2 in fallback() perf stat: Fallback to user only counters when perf_event_paranoid > 1
Namhyung Kim (1):
perf diff: Fix duplicated output column
Peter Zijlstra (1):
perf/x86/msr: Fix SMI overflow
Steven Rostedt (1):
tools lib traceevent: Do not reassign parg after collapse_tree()
hchrzani (1):
perf/x86/intel/uncore: Fix CHA registers configuration procedure for Knights Landing platform
arch/x86/events/intel/core.c | 2 +- arch/x86/events/intel/pt.c | 2 + arch/x86/events/intel/uncore_snbep.c | 7 +++ arch/x86/events/msr.c | 2 +- kernel/events/ring_buffer.c | 10 +++- tools/build/Makefile.feature | 2 + tools/build/feature/Makefile | 4 ++ tools/build/feature/test-all.c | 5 ++ tools/build/feature/test-dwarf_getlocations.c | 12 +++++ tools/lib/traceevent/parse-filter.c | 4 +- tools/perf/arch/x86/util/dwarf-regs.c | 8 +-- tools/perf/builtin-script.c | 70 +++++++++++++-------------- tools/perf/builtin-stat.c | 7 ++- tools/perf/config/Makefile | 6 +++ tools/perf/util/dwarf-aux.c | 9 ++++ tools/perf/util/event.c | 12 ++--- tools/perf/util/evsel.c | 23 ++++++++- tools/perf/util/parse-events.c | 60 +++++++++++------------ tools/perf/util/sort.c | 3 ++ tools/perf/util/thread_map.c | 8 +-- 20 files changed, 168 insertions(+), 88 deletions(-) create mode 100644 tools/build/feature/test-dwarf_getlocations.c
arch/x86/events/intel/core.c +1 -1
@@ -3708,7 +3708,7 @@ __init int intel_pmu_init(void) c->idxmsk64 |= (1ULL << x86_pmu.num_counters) -1 ; } c->idxmsk64 &= - ~(~0UL << (INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed)); + ~(~0ULL << (INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed)); c->weight =hweight64 (c->idxmsk64); } }
arch/x86/events/intel/pt.c +2 -0
@@ -709,6 +709,7 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,/* clear STOP and INT from current entry */ buf->topa_index[buf->stop_pos]->stop =0 ; + buf->topa_index[buf->stop_pos]->intr =0 ; buf->topa_index[buf->intr_pos]->intr =0 ;/* how many pages till the STOP marker */
@@ -733,6 +734,7 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf, buf->intr_pos = idx; buf->topa_index[buf->stop_pos]->stop =1 ; + buf->topa_index[buf->stop_pos]->intr =1 ; buf->topa_index[buf->intr_pos]->intr =1 ;return 0 ;
arch/x86/events/intel/uncore_snbep.c +7 -0
@@ -219,6 +219,9 @@#define KNL_CHA_MSR_PMON_BOX_FILTER_TID 0x1ff#define KNL_CHA_MSR_PMON_BOX_FILTER_STATE (7 << 18)#define KNL_CHA_MSR_PMON_BOX_FILTER_OP (0xfffffe2aULL << 32) +#define KNL_CHA_MSR_PMON_BOX_FILTER_REMOTE_NODE (0x1ULL << 32) +#define KNL_CHA_MSR_PMON_BOX_FILTER_LOCAL_NODE (0x1ULL << 33) +#define KNL_CHA_MSR_PMON_BOX_FILTER_NNC (0x1ULL << 37)/* KNL EDC/MC UCLK */ #define KNL_UCLK_MSR_PMON_CTR0_LOW 0x400
@@ -1902,6 +1905,10 @@ static int knl_cha_hw_config(struct intel_uncore_box *box, reg1->reg =HSWEP_C0_MSR_PMON_BOX_FILTER0 +KNL_CHA_MSR_OFFSET * box->pmu->pmu_idx; reg1->config = event->attr.config1 &knl_cha_filter_mask (idx); + + reg1->config |=KNL_CHA_MSR_PMON_BOX_FILTER_REMOTE_NODE ; + reg1->config |=KNL_CHA_MSR_PMON_BOX_FILTER_LOCAL_NODE ; + reg1->config |=KNL_CHA_MSR_PMON_BOX_FILTER_NNC ; reg1->idx = idx; }return 0 ;
arch/x86/events/msr.c +1 -1
@@ -166,7 +166,7 @@ static void msr_event_update(struct perf_event *event)if (unlikely (event->hw.event_base ==MSR_SMI_COUNT )) delta =sign_extend64 (delta,31 ); -local64_add (now - prev, &event->count); +local64_add (delta, &event->count); }static void msr_event_start (struct perf_event *event,int flags)
kernel/events/ring_buffer.c +9 -1
@@ -347,6 +347,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, bool truncated) {struct ring_buffer *rb = handle->rb; +bool wakeup = truncated;unsigned long aux_head;u64 flags =0 ;
@@ -375,9 +376,16 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, aux_head = rb->user_page->aux_head =local_read (&rb->aux_head);if (aux_head -local_read (&rb->aux_wakeup) >= rb->aux_watermark) { -perf_output_wakeup (handle); + wakeup = true;local_add (rb->aux_watermark, &rb->aux_wakeup); } + +if (wakeup) { +if (truncated) + handle->event->pending_disable =1 ; +perf_output_wakeup (handle); + } + handle->event =NULL ;local_set (&rb->aux_nest,0 );
tools/build/Makefile.feature +2 -0
@@ -30,6 +30,7 @@ endef FEATURE_TESTS_BASIC := \ backtrace \ dwarf \ + dwarf_getlocations \ fortify-source \ sync-compare-and-swap \ glibc \
@@ -78,6 +79,7 @@ endif FEATURE_DISPLAY ?= \ dwarf \ + dwarf_getlocations \ glibc \ gtk2 \ libaudit \
tools/build/feature/Makefile +4 -0
@@ -3,6 +3,7 @@ FILES= \ test-backtrace.bin \ test-bionic.bin \ test-dwarf.bin \ + test-dwarf_getlocations.bin \ test-fortify-source.bin \ test-sync-compare-and-swap.bin \ test-glibc.bin \
@@ -82,6 +83,9 @@ endif $(OUTPUT)test-dwarf.bin: $(BUILD) $(DWARFLIBS) +$(OUTPUT)test-dwarf_getlocations.bin: + $(BUILD) $(DWARFLIBS) + $(OUTPUT)test-libelf-mmap.bin: $(BUILD) -lelf
tools/build/feature/test-all.c +5 -0
@@ -41,6 +41,10 @@# include "test-dwarf.c" #undef main +#define main main_test_dwarf_getlocations +# include "test-dwarf_getlocations.c" +#undef main +#define main main_test_libelf_getphdrnum# include "test-libelf-getphdrnum.c" #undef main
@@ -143,6 +147,7 @@ int main(int argc, char *argv[])main_test_libelf_mmap ();main_test_glibc ();main_test_dwarf (); +main_test_dwarf_getlocations ();main_test_libelf_getphdrnum ();main_test_libunwind ();main_test_libaudit ();
tools/build/feature/test-dwarf_getlocations.c new file +12 -0
@@ -0,0 +1,12 @@ +#include <stdlib.h> +#include <elfutils/libdw.h> + +int main (void ) +{ +Dwarf_Addr base, start, end; +Dwarf_Attribute attr; +Dwarf_Op *op; +size_t nops; +ptrdiff_t offset =0 ; +return (int )dwarf_getlocations (&attr, offset, &base, &start, &end, &op, &nops); +}
tools/lib/traceevent/parse-filter.c +2 -2
@@ -1164,11 +1164,11 @@ process_filter(struct event_format *event, struct filter_arg **parg, current_op = current_exp; ret =collapse_tree (current_op, parg, error_str); +/* collapse_tree() may free current_op, and updates parg accordingly */ + current_op =NULL ;if (ret <0 ) goto fail; - *parg = current_op; -free (token);return 0 ;
tools/perf/arch/x86/util/dwarf-regs.c +4 -4
@@ -63,6 +63,8 @@ struct pt_regs_offset {# define REG_OFFSET_NAME_32 (n, r) {.name = n, .offset = offsetof(struct pt_regs, r)}#endif +/* TODO: switching by dwarf address size */ +#ifndef __x86_64__static const struct pt_regs_offset x86_32_regoffset_table[] = {REG_OFFSET_NAME_32 ("%ax" , eax), REG_OFFSET_NAME_32("%cx", ecx),
@@ -75,6 +77,8 @@ static const struct pt_regs_offset x86_32_regoffset_table[] = { REG_OFFSET_END, }; +#define regoffset_table x86_32_regoffset_table +#else static const struct pt_regs_offset x86_64_regoffset_table[] = {REG_OFFSET_NAME_64 ("%ax" , rax), REG_OFFSET_NAME_64("%dx", rdx),
@@ -95,11 +99,7 @@ static const struct pt_regs_offset x86_64_regoffset_table[] = { REG_OFFSET_END, }; -/* TODO: switching by dwarf address size */ -#ifdef __x86_64__#define regoffset_table x86_64_regoffset_table -#else -#define regoffset_table x86_32_regoffset_table#endif /* Minus 1 for the ending REG_OFFSET_END */
tools/perf/builtin-script.c +34 -36
141 lines not on this page · raw message
tools/perf/builtin-stat.c +6 -1
@@ -528,6 +528,7 @@ static int __run_perf_stat(int argc, const char **argv)perf_evlist__set_leader (evsel_list);evlist__for_each (evsel_list, counter) { +try_again:if (create_perf_stat_counter (counter) <0 ) {/* * PPC returns ENXIO for HW counters until 2.6.37
@@ -544,7 +545,11 @@ static int __run_perf_stat(int argc, const char **argv)if ((counter->leader != counter) || !(counter->leader->nr_members >1 ))continue ; - } + }else if (perf_evsel__fallback (counter, errno, msg,sizeof (msg))) { +if (verbose) +ui__warning ("%s\n" , msg); + goto try_again; + }perf_evsel__open_strerror (counter, &target, errno, msg,sizeof (msg));
tools/perf/config/Makefile +6 -0
@@ -268,6 +268,12 @@ else ifneq ($(feature-dwarf), 1) msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); NO_DWARF := 1 + else + ifneq ($(feature-dwarf_getlocations), 1) + msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157); + else + CFLAGS += -DHAVE_DWARF_GETLOCATIONS + endif # dwarf_getlocations endif # Dwarf support endif # libelf support endif # NO_LIBELF
tools/perf/util/dwarf-aux.c +9 -0
@@ -959,6 +959,7 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)return 0 ; } +#ifdef HAVE_DWARF_GETLOCATIONS /** * die_get_var_innermost_scope - Get innermost scope range of given variable DIE * @sp_die: a subprogram DIE
@@ -1080,3 +1081,11 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) return ret; } +#else +int die_get_var_range (Dwarf_Die *sp_die__maybe_unused , +Dwarf_Die *vr_die__maybe_unused , +struct strbuf *buf__maybe_unused ) +{ +return -ENOTSUP ; +} +#endif
tools/perf/util/event.c +6 -6
@@ -433,7 +433,7 @@ static int __event__synthesize_thread(union perf_event *comm_event, {char filename[PATH_MAX ];DIR *tasks; -struct dirent dirent, *next; +struct dirent *dirent;pid_t tgid, ppid;int rc =0 ;
@@ -462,11 +462,11 @@ static int __event__synthesize_thread(union perf_event *comm_event,return 0 ; } -while (!readdir_r (tasks, &dirent, &next) && next) { +while ((dirent =readdir (tasks)) !=NULL ) {char *end;pid_t _pid; - _pid =strtol (dirent.d_name, &end,10 ); + _pid =strtol (dirent->d_name, &end,10 );if (*end)continue ;
@@ -575,7 +575,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool, {DIR *proc;char proc_path[PATH_MAX ]; -struct dirent dirent, *next; +struct dirent *dirent;union perf_event *comm_event, *mmap_event, *fork_event;int err =-1 ;
@@ -600,9 +600,9 @@ int perf_event__synthesize_threads(struct perf_tool *tool,if (proc ==NULL ) goto out_free_fork; -while (!readdir_r (proc, &dirent, &next) && next) { +while ((dirent =readdir (proc)) !=NULL ) {char *end; -pid_t pid =strtol (dirent.d_name, &end,10 ); +pid_t pid =strtol (dirent->d_name, &end,10 );if (*end)/* only interested in proper numerical dirents */ continue ;
tools/perf/util/evsel.c +21 -2
@@ -2345,6 +2345,8 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,bool perf_evsel__fallback (struct perf_evsel *evsel,int err,char *msg,size_t msgsize) { +int paranoid; +if ((err ==ENOENT || err ==ENXIO || err ==ENODEV ) && evsel->attr.type ==PERF_TYPE_HARDWARE && evsel->attr.config ==PERF_COUNT_HW_CPU_CYCLES ) {
@@ -2364,6 +2366,22 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,zfree (&evsel->name);return true; + }else if (err ==EACCES && !evsel->attr.exclude_kernel && + (paranoid =perf_event_paranoid ()) >1 ) { +const char *name =perf_evsel__name (evsel); +char *new_name; + +if (asprintf (&new_name,"%s%su" , name,strchr (name,':' ) ?"" :":" ) <0 ) +return false; + +if (evsel->name) +free (evsel->name); + evsel->name = new_name; +scnprintf (msg, msgsize, +"kernel.perf_event_paranoid=%d, trying to fall back to excluding kernel samples" , paranoid); + evsel->attr.exclude_kernel =1 ; + +return true; }return false;
@@ -2382,12 +2400,13 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,"Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n" "which controls use of the performance events system by\n" "unprivileged users (without CAP_SYS_ADMIN).\n\n" -"The default value is 1:\n\n" +"The current value is %d:\n\n" " -1: Allow use of (almost) all events by all users\n" ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n" ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n" ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN" , - target->system_wide ? "system-wide " : ""); + target->system_wide ?"system-wide " :"" , + perf_event_paranoid());case ENOENT :return scnprintf (msg, size,"The %s event is not supported." ,perf_evsel__name (evsel));
tools/perf/util/parse-events.c +30 -30
145 lines not on this page · raw message
tools/perf/util/sort.c +3 -0
@@ -2445,6 +2445,9 @@ static char *prefix_if_not_in(const char *pre, char *str)static char *setup_overhead (char *keys) { +if (sort__mode ==SORT_MODE__DIFF ) +return keys; + keys =prefix_if_not_in ("overhead" , keys);if (symbol_conf.cumulate_callchain)
tools/perf/util/thread_map.c +4 -4
@@ -94,7 +94,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)DIR *proc;int max_threads =32 , items, i;char path[256 ]; -struct dirent dirent, *next, **namelist =NULL ; +struct dirent *dirent, **namelist =NULL ;struct thread_map *threads =thread_map__alloc (max_threads);if (threads ==NULL )
@@ -107,16 +107,16 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) threads->nr =0 ;atomic_set (&threads->refcnt,1 ); -while (!readdir_r (proc, &dirent, &next) && next) { +while ((dirent =readdir (proc)) !=NULL ) {char *end;bool grow = false;struct stat st; -pid_t pid =strtol (dirent.d_name, &end,10 ); +pid_t pid =strtol (dirent->d_name, &end,10 );if (*end)/* only interested in proper numerical dirents */ continue ; -snprintf (path,sizeof (path),"/proc/%s" , dirent.d_name); +snprintf (path,sizeof (path),"/proc/%s" , dirent->d_name);if (stat (path, &st) !=0 )continue ;