perf fixes
Subsystems (3)
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: 18e7a45af91acdde99d3aa1372cc40e1f8142f7b perf/x86: Reject non sampling events with precise_ip
Misc race fixes uncovered by fuzzing efforts, a Sparse fix, two PMU driver fixes, plus miscellanous tooling fixes.
Thanks,
Ingo
------------------>
Arnaldo Carvalho de Melo (4):
samples/bpf sock_example: Avoid getting ethhdr from two includes samples/bpf trace_output_user: Remove duplicate sys/ioctl.h include perf tools: Install tools/lib/traceevent plugins with install-bin perf symbols: Robustify reading of build-id from sysfs
Colin King (1):
perf/x86/intel: Use ULL constant to prevent undefined shift behaviour
Daniel Bristot de Oliveira (1):
tools lib traceevent: Fix prev/next_prio for deadline tasks
David Carrillo-Cisneros (1):
perf/x86: Set pmu->module in Intel PMU modules
Jiri Olsa (5):
tools lib subcmd: Add OPT_STRING_OPTARG_SET option perf record: Make __record_options static
perf record: Fix --switch-output documentation and comment perf/x86/intel: Account interrupts for PEBS errors perf/x86: Reject non sampling events with precise_ip
Masami Hiramatsu (3):
perf probe: Fix to get correct modname from elf header perf probe: Fix --funcs to show correct symbols for offline module perf probe: Fix to probe on gcc generated symbols for offline kernel
Namhyung Kim (1):
perf sched timehist: Show total scheduling time
Peter Zijlstra (2):
perf/core: Fix sys_perf_event_open() vs. hotplug perf/core: Fix concurrent sys_perf_event_open() vs. 'move_group' race
Prarit Bhargava (1):
perf/x86/intel/uncore: Fix hardcoded socket 0 assumption in the Haswell init code
arch/x86/events/core.c | 4 + arch/x86/events/intel/core.c | 2 +- arch/x86/events/intel/cstate.c | 2 + arch/x86/events/intel/ds.c | 6 +- arch/x86/events/intel/rapl.c | 1 + arch/x86/events/intel/uncore.c | 1 + arch/x86/events/intel/uncore_snbep.c | 2 +- include/linux/perf_event.h | 1 + kernel/events/core.c | 175 ++++++++++++++++++++++------- samples/bpf/sock_example.h | 2 +- samples/bpf/trace_output_user.c | 1 - tools/lib/subcmd/parse-options.c | 3 + tools/lib/subcmd/parse-options.h | 5 + tools/lib/traceevent/plugin_sched_switch.c | 4 +- tools/perf/Documentation/perf-record.txt | 4 + tools/perf/Makefile.perf | 4 +- tools/perf/builtin-record.c | 4 +- tools/perf/builtin-sched.c | 17 ++- tools/perf/util/probe-event.c | 105 +++++++++++------ tools/perf/util/symbol-elf.c | 6 + 20 files changed, 257 insertions(+), 92 deletions(-)
arch/x86/events/core.c +4 -0
@@ -505,6 +505,10 @@ int x86_pmu_hw_config(struct perf_event *event)if (event->attr.precise_ip > precise)return -EOPNOTSUPP ; + +/* There's no sense in having PEBS for non sampling events: */ +if (!is_sampling_event (event)) +return -EINVAL ; }/* * check that PEBS LBR correction does not conflict with
arch/x86/events/intel/core.c +1 -1
@@ -3987,7 +3987,7 @@ __init int intel_pmu_init(void) x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC); x86_pmu.num_counters =INTEL_PMC_MAX_GENERIC ; } - x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) -1 ; + x86_pmu.intel_ctrl = (1ULL << x86_pmu.num_counters) -1 ;if (x86_pmu.num_counters_fixed >INTEL_PMC_MAX_FIXED ) { WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
arch/x86/events/intel/cstate.c +2 -0
@@ -434,6 +434,7 @@ static struct pmu cstate_core_pmu = { .stop = cstate_pmu_event_stop, .read = cstate_pmu_event_update, .capabilities = PERF_PMU_CAP_NO_INTERRUPT, + .module = THIS_MODULE, };static struct pmu cstate_pkg_pmu = {
@@ -447,6 +448,7 @@ static struct pmu cstate_pkg_pmu = { .stop = cstate_pmu_event_stop, .read = cstate_pmu_event_update, .capabilities = PERF_PMU_CAP_NO_INTERRUPT, + .module = THIS_MODULE, };static const struct cstate_model nhm_cstates__initconst = {
arch/x86/events/intel/ds.c +5 -1
@@ -1389,9 +1389,13 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)continue ;/* log dropped samples number */ -if (error[bit]) +if (error[bit]) {perf_log_lost_samples (event, error[bit]); +if (perf_event_account_interrupt (event)) +x86_pmu_stop (event,0 ); + } +if (counts[bit]) {__intel_pmu_pebs_event (event, iregs, base, top, bit, counts[bit]);
arch/x86/events/intel/rapl.c +1 -0
@@ -697,6 +697,7 @@ static int __init init_rapl_pmus(void) rapl_pmus->pmu.start = rapl_pmu_event_start; rapl_pmus->pmu.stop = rapl_pmu_event_stop; rapl_pmus->pmu.read = rapl_pmu_event_read; + rapl_pmus->pmu.module =THIS_MODULE ;return 0 ; }
arch/x86/events/intel/uncore.c +1 -0
@@ -733,6 +733,7 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu) .start = uncore_pmu_event_start, .stop = uncore_pmu_event_stop, .read = uncore_pmu_event_read, + .module = THIS_MODULE, }; }else { pmu->pmu = *pmu->type->pmu;
arch/x86/events/intel/uncore_snbep.c +1 -1
@@ -2686,7 +2686,7 @@ static struct intel_uncore_type *hswep_msr_uncores[] = {void hswep_uncore_cpu_init (void ) { -int pkg =topology_phys_to_logical_pkg (0 ); +int pkg = boot_cpu_data.logical_proc_id;if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores) hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
include/linux/perf_event.h +1 -0
@@ -1259,6 +1259,7 @@ extern void perf_event_disable(struct perf_event *event);extern void perf_event_disable_local (struct perf_event *event);extern void perf_event_disable_inatomic (struct perf_event *event);extern void perf_event_task_tick (void ); +extern int perf_event_account_interrupt (struct perf_event *event);#else /* !CONFIG_PERF_EVENTS: */ static inline void * perf_aux_output_begin(struct perf_output_handle *handle,
kernel/events/core.c +133 -42
255 lines not on this page · raw message
samples/bpf/sock_example.h +1 -1
@@ -4,7 +4,7 @@#include <unistd.h> #include <string.h> #include <errno.h> -#include <net/ethernet.h> +#include <linux/if_ether.h> #include <net/if.h> #include <linux/if_packet.h> #include <arpa/inet.h>
samples/bpf/trace_output_user.c +0 -1
@@ -9,7 +9,6 @@#include <string.h> #include <fcntl.h> #include <poll.h> -#include <sys/ioctl.h> #include <linux/perf_event.h> #include <linux/bpf.h> #include <errno.h>
tools/lib/subcmd/parse-options.c +3 -0
@@ -213,6 +213,9 @@ static int get_value(struct parse_opt_ctx_t *p,else err =get_arg (p, opt, flags, (const char **)opt->value); +if (opt->set) + *(bool *)opt->set = true; +/* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */ if (opt->flags &PARSE_OPT_NOEMPTY ) {const char *val = *(const char **)opt->value;
tools/lib/subcmd/parse-options.h +5 -0
@@ -137,6 +137,11 @@ struct option { { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ .value = check_vtype(v, const char **), (a), .help = (h), \ .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) } +#define OPT_STRING_OPTARG_SET (s, l, v, os, a, h, d) \ + { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ + .value = check_vtype(v, const char **), (a), .help = (h), \ + .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \ + .set = check_vtype(os, bool *)}#define OPT_STRING_NOEMPTY (s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}#define OPT_DATE (s, l, v, h) \ { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
tools/lib/traceevent/plugin_sched_switch.c +2 -2
@@ -111,7 +111,7 @@ static int sched_switch_handler(struct trace_seq *s,trace_seq_printf (s,"%lld " , val);if (pevent_get_field_val (s, event,"prev_prio" , record, &val,0 ) ==0 ) -trace_seq_printf (s,"[%lld] " , val); +trace_seq_printf (s,"[%d] " , (int ) val);if (pevent_get_field_val (s, event,"prev_state" , record, &val,0 ) ==0 )write_state (s, val);
@@ -129,7 +129,7 @@ static int sched_switch_handler(struct trace_seq *s,trace_seq_printf (s,"%lld" , val);if (pevent_get_field_val (s, event,"next_prio" , record, &val,0 ) ==0 ) -trace_seq_printf (s," [%lld]" , val); +trace_seq_printf (s," [%d]" , (int ) val);return 0 ; }
tools/perf/Documentation/perf-record.txt +4 -0
@@ -430,6 +430,10 @@ that gets then processed, possibly via a perf script, to decide if that particular perf.data snapshot should be kept or not. Implies --timestamp-filename, --no-buildid and --no-buildid-cache. +The reason for the latter two is to reduce the data file switching +overhead. You can still switch them on with: + + --switch-output --no-no-buildid --no-no-buildid-cache --dry-run:: Parse options then exit. --dry-run can be used to detect errors in cmdline
tools/perf/Makefile.perf +2 -2
@@ -704,9 +704,9 @@ install-tests: all install-gtk $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' -install-bin: install-tools install-tests +install-bin: install-tools install-tests install-traceevent-plugins -install: install-bin try-install-man install-traceevent-plugins +install: install-bin try-install-man install-python_ext: $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
tools/perf/builtin-record.c +2 -2
@@ -1405,7 +1405,7 @@ static bool dry_run;* perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', * using pipes, etc. */ -struct option __record_options[] = { +static struct option __record_options[] = {OPT_CALLBACK ('e' ,"event" , &record.evlist,"event" ,"event selector. use 'perf list' to list available events" , parse_events_option),
@@ -1636,7 +1636,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)* overhead. Still generate buildid if they are required * explicitly using * -* perf record --signal-trigger --no-no-buildid \ +* perf record --switch-output --no-no-buildid \ * --no-no-buildid-cache * * Following code equals to:
tools/perf/builtin-sched.c +14 -3
@@ -209,6 +209,7 @@ struct perf_sched {u64 skipped_samples;const char *time_str;struct perf_time_interval ptime; +struct perf_time_interval hist_time; };/* per thread run time data */
@@ -2460,6 +2461,11 @@ static int timehist_sched_change_event(struct perf_tool *tool,timehist_print_sample (sched, sample, &al, thread, t); out: +if (sched->hist_time.start ==0 && t >= ptime->start) + sched->hist_time.start = t; +if (ptime->end ==0 || t <= ptime->end) + sched->hist_time.end = t; +if (tr) {/* time of this sched_switch event becomes last time task seen */ tr->last_time = sample->time;
@@ -2624,6 +2630,7 @@ static void timehist_print_summary(struct perf_sched *sched,struct thread *t;struct thread_runtime *r;int i; +u64 hist_time = sched->hist_time.end - sched->hist_time.start;memset (&totals,0 ,sizeof (totals));
@@ -2665,7 +2672,7 @@ static void timehist_print_summary(struct perf_sched *sched, totals.sched_count += r->run_stats.n;printf (" CPU %2d idle for " , i);print_sched_time (r->total_run_time,6 ); -printf (" msec\n" ); +printf (" msec (%6.2f%%)\n" ,100.0 * r->total_run_time / hist_time); }else printf (" CPU %2d idle entire time window\n" , i); }
@@ -2701,12 +2708,16 @@ static void timehist_print_summary(struct perf_sched *sched,printf ("\n" " Total number of unique tasks: %" PRIu64"\n" -"Total number of context switches: %" PRIu64"\n" -" Total run time (msec): " , +"Total number of context switches: %" PRIu64"\n" , totals.task_count, totals.sched_count); +printf (" Total run time (msec): " );print_sched_time (totals.total_run_time,2 );printf ("\n" ); + +printf (" Total scheduling time (msec): " ); +print_sched_time (hist_time,2 ); +printf (" (x %d)\n" , sched->max_cpu); } typedef int (*sched_handler)(struct perf_tool *tool,
tools/perf/util/probe-event.c +69 -36
177 lines not on this page · raw message
tools/perf/util/symbol-elf.c +6 -0
@@ -537,6 +537,12 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)break ; }else {int n = namesz + descsz; + +if (n > (int )sizeof (bf)) { + n =sizeof (bf); +pr_debug ("%s: truncating reading of build id in sysfs file %s: n_namesz=%u, n_descsz=%u.\n" , + __func__, filename, nhdr.n_namesz, nhdr.n_descsz); + }if (read (fd, bf, n) != n)break ; }