diff options
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 23 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_cqm.c | 8 | ||||
| -rw-r--r-- | kernel/events/core.c | 91 | ||||
| -rw-r--r-- | kernel/events/ring_buffer.c | 10 | ||||
| -rw-r--r-- | tools/perf/config/Makefile | 2 | ||||
| -rw-r--r-- | tools/perf/util/stat-shadow.c | 8 |
6 files changed, 96 insertions, 46 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index b9826a981fb2..6326ae24e4d5 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
| @@ -2534,7 +2534,7 @@ static int intel_pmu_cpu_prepare(int cpu) | |||
| 2534 | if (x86_pmu.extra_regs || x86_pmu.lbr_sel_map) { | 2534 | if (x86_pmu.extra_regs || x86_pmu.lbr_sel_map) { |
| 2535 | cpuc->shared_regs = allocate_shared_regs(cpu); | 2535 | cpuc->shared_regs = allocate_shared_regs(cpu); |
| 2536 | if (!cpuc->shared_regs) | 2536 | if (!cpuc->shared_regs) |
| 2537 | return NOTIFY_BAD; | 2537 | goto err; |
| 2538 | } | 2538 | } |
| 2539 | 2539 | ||
| 2540 | if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) { | 2540 | if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) { |
| @@ -2542,18 +2542,27 @@ static int intel_pmu_cpu_prepare(int cpu) | |||
| 2542 | 2542 | ||
| 2543 | cpuc->constraint_list = kzalloc(sz, GFP_KERNEL); | 2543 | cpuc->constraint_list = kzalloc(sz, GFP_KERNEL); |
| 2544 | if (!cpuc->constraint_list) | 2544 | if (!cpuc->constraint_list) |
| 2545 | return NOTIFY_BAD; | 2545 | goto err_shared_regs; |
| 2546 | 2546 | ||
| 2547 | cpuc->excl_cntrs = allocate_excl_cntrs(cpu); | 2547 | cpuc->excl_cntrs = allocate_excl_cntrs(cpu); |
| 2548 | if (!cpuc->excl_cntrs) { | 2548 | if (!cpuc->excl_cntrs) |
| 2549 | kfree(cpuc->constraint_list); | 2549 | goto err_constraint_list; |
| 2550 | kfree(cpuc->shared_regs); | 2550 | |
| 2551 | return NOTIFY_BAD; | ||
| 2552 | } | ||
| 2553 | cpuc->excl_thread_id = 0; | 2551 | cpuc->excl_thread_id = 0; |
| 2554 | } | 2552 | } |
| 2555 | 2553 | ||
| 2556 | return NOTIFY_OK; | 2554 | return NOTIFY_OK; |
| 2555 | |||
| 2556 | err_constraint_list: | ||
| 2557 | kfree(cpuc->constraint_list); | ||
| 2558 | cpuc->constraint_list = NULL; | ||
| 2559 | |||
| 2560 | err_shared_regs: | ||
| 2561 | kfree(cpuc->shared_regs); | ||
| 2562 | cpuc->shared_regs = NULL; | ||
| 2563 | |||
| 2564 | err: | ||
| 2565 | return NOTIFY_BAD; | ||
| 2557 | } | 2566 | } |
| 2558 | 2567 | ||
| 2559 | static void intel_pmu_cpu_starting(int cpu) | 2568 | static void intel_pmu_cpu_starting(int cpu) |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_cqm.c b/arch/x86/kernel/cpu/perf_event_intel_cqm.c index 63eb68b73589..377e8f8ed391 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_cqm.c +++ b/arch/x86/kernel/cpu/perf_event_intel_cqm.c | |||
| @@ -1255,7 +1255,7 @@ static inline void cqm_pick_event_reader(int cpu) | |||
| 1255 | cpumask_set_cpu(cpu, &cqm_cpumask); | 1255 | cpumask_set_cpu(cpu, &cqm_cpumask); |
| 1256 | } | 1256 | } |
| 1257 | 1257 | ||
| 1258 | static void intel_cqm_cpu_prepare(unsigned int cpu) | 1258 | static void intel_cqm_cpu_starting(unsigned int cpu) |
| 1259 | { | 1259 | { |
| 1260 | struct intel_pqr_state *state = &per_cpu(pqr_state, cpu); | 1260 | struct intel_pqr_state *state = &per_cpu(pqr_state, cpu); |
| 1261 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 1261 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
| @@ -1296,13 +1296,11 @@ static int intel_cqm_cpu_notifier(struct notifier_block *nb, | |||
| 1296 | unsigned int cpu = (unsigned long)hcpu; | 1296 | unsigned int cpu = (unsigned long)hcpu; |
| 1297 | 1297 | ||
| 1298 | switch (action & ~CPU_TASKS_FROZEN) { | 1298 | switch (action & ~CPU_TASKS_FROZEN) { |
| 1299 | case CPU_UP_PREPARE: | ||
| 1300 | intel_cqm_cpu_prepare(cpu); | ||
| 1301 | break; | ||
| 1302 | case CPU_DOWN_PREPARE: | 1299 | case CPU_DOWN_PREPARE: |
| 1303 | intel_cqm_cpu_exit(cpu); | 1300 | intel_cqm_cpu_exit(cpu); |
| 1304 | break; | 1301 | break; |
| 1305 | case CPU_STARTING: | 1302 | case CPU_STARTING: |
| 1303 | intel_cqm_cpu_starting(cpu); | ||
| 1306 | cqm_pick_event_reader(cpu); | 1304 | cqm_pick_event_reader(cpu); |
| 1307 | break; | 1305 | break; |
| 1308 | } | 1306 | } |
| @@ -1373,7 +1371,7 @@ static int __init intel_cqm_init(void) | |||
| 1373 | goto out; | 1371 | goto out; |
| 1374 | 1372 | ||
| 1375 | for_each_online_cpu(i) { | 1373 | for_each_online_cpu(i) { |
| 1376 | intel_cqm_cpu_prepare(i); | 1374 | intel_cqm_cpu_starting(i); |
| 1377 | cqm_pick_event_reader(i); | 1375 | cqm_pick_event_reader(i); |
| 1378 | } | 1376 | } |
| 1379 | 1377 | ||
diff --git a/kernel/events/core.c b/kernel/events/core.c index d3dae3419b99..e6feb5114134 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -1868,8 +1868,6 @@ event_sched_in(struct perf_event *event, | |||
| 1868 | 1868 | ||
| 1869 | perf_pmu_disable(event->pmu); | 1869 | perf_pmu_disable(event->pmu); |
| 1870 | 1870 | ||
| 1871 | event->tstamp_running += tstamp - event->tstamp_stopped; | ||
| 1872 | |||
| 1873 | perf_set_shadow_time(event, ctx, tstamp); | 1871 | perf_set_shadow_time(event, ctx, tstamp); |
| 1874 | 1872 | ||
| 1875 | perf_log_itrace_start(event); | 1873 | perf_log_itrace_start(event); |
| @@ -1881,6 +1879,8 @@ event_sched_in(struct perf_event *event, | |||
| 1881 | goto out; | 1879 | goto out; |
| 1882 | } | 1880 | } |
| 1883 | 1881 | ||
| 1882 | event->tstamp_running += tstamp - event->tstamp_stopped; | ||
| 1883 | |||
| 1884 | if (!is_software_event(event)) | 1884 | if (!is_software_event(event)) |
| 1885 | cpuctx->active_oncpu++; | 1885 | cpuctx->active_oncpu++; |
| 1886 | if (!ctx->nr_active++) | 1886 | if (!ctx->nr_active++) |
| @@ -3958,28 +3958,21 @@ static void perf_event_for_each(struct perf_event *event, | |||
| 3958 | perf_event_for_each_child(sibling, func); | 3958 | perf_event_for_each_child(sibling, func); |
| 3959 | } | 3959 | } |
| 3960 | 3960 | ||
| 3961 | static int perf_event_period(struct perf_event *event, u64 __user *arg) | 3961 | struct period_event { |
| 3962 | { | 3962 | struct perf_event *event; |
| 3963 | struct perf_event_context *ctx = event->ctx; | ||
| 3964 | int ret = 0, active; | ||
| 3965 | u64 value; | 3963 | u64 value; |
| 3964 | }; | ||
| 3966 | 3965 | ||
| 3967 | if (!is_sampling_event(event)) | 3966 | static int __perf_event_period(void *info) |
| 3968 | return -EINVAL; | 3967 | { |
| 3969 | 3968 | struct period_event *pe = info; | |
| 3970 | if (copy_from_user(&value, arg, sizeof(value))) | 3969 | struct perf_event *event = pe->event; |
| 3971 | return -EFAULT; | 3970 | struct perf_event_context *ctx = event->ctx; |
| 3972 | 3971 | u64 value = pe->value; | |
| 3973 | if (!value) | 3972 | bool active; |
| 3974 | return -EINVAL; | ||
| 3975 | 3973 | ||
| 3976 | raw_spin_lock_irq(&ctx->lock); | 3974 | raw_spin_lock(&ctx->lock); |
| 3977 | if (event->attr.freq) { | 3975 | if (event->attr.freq) { |
| 3978 | if (value > sysctl_perf_event_sample_rate) { | ||
| 3979 | ret = -EINVAL; | ||
| 3980 | goto unlock; | ||
| 3981 | } | ||
| 3982 | |||
| 3983 | event->attr.sample_freq = value; | 3976 | event->attr.sample_freq = value; |
| 3984 | } else { | 3977 | } else { |
| 3985 | event->attr.sample_period = value; | 3978 | event->attr.sample_period = value; |
| @@ -3998,11 +3991,53 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg) | |||
| 3998 | event->pmu->start(event, PERF_EF_RELOAD); | 3991 | event->pmu->start(event, PERF_EF_RELOAD); |
| 3999 | perf_pmu_enable(ctx->pmu); | 3992 | perf_pmu_enable(ctx->pmu); |
| 4000 | } | 3993 | } |
| 3994 | raw_spin_unlock(&ctx->lock); | ||
| 4001 | 3995 | ||
| 4002 | unlock: | 3996 | return 0; |
| 3997 | } | ||
| 3998 | |||
| 3999 | static int perf_event_period(struct perf_event *event, u64 __user *arg) | ||
| 4000 | { | ||
| 4001 | struct period_event pe = { .event = event, }; | ||
| 4002 | struct perf_event_context *ctx = event->ctx; | ||
| 4003 | struct task_struct *task; | ||
| 4004 | u64 value; | ||
| 4005 | |||
| 4006 | if (!is_sampling_event(event)) | ||
| 4007 | return -EINVAL; | ||
| 4008 | |||
| 4009 | if (copy_from_user(&value, arg, sizeof(value))) | ||
| 4010 | return -EFAULT; | ||
| 4011 | |||
| 4012 | if (!value) | ||
| 4013 | return -EINVAL; | ||
| 4014 | |||
| 4015 | if (event->attr.freq && value > sysctl_perf_event_sample_rate) | ||
| 4016 | return -EINVAL; | ||
| 4017 | |||
| 4018 | task = ctx->task; | ||
| 4019 | pe.value = value; | ||
| 4020 | |||
| 4021 | if (!task) { | ||
| 4022 | cpu_function_call(event->cpu, __perf_event_period, &pe); | ||
| 4023 | return 0; | ||
| 4024 | } | ||
| 4025 | |||
| 4026 | retry: | ||
| 4027 | if (!task_function_call(task, __perf_event_period, &pe)) | ||
| 4028 | return 0; | ||
| 4029 | |||
| 4030 | raw_spin_lock_irq(&ctx->lock); | ||
| 4031 | if (ctx->is_active) { | ||
| 4032 | raw_spin_unlock_irq(&ctx->lock); | ||
| 4033 | task = ctx->task; | ||
| 4034 | goto retry; | ||
| 4035 | } | ||
| 4036 | |||
| 4037 | __perf_event_period(&pe); | ||
| 4003 | raw_spin_unlock_irq(&ctx->lock); | 4038 | raw_spin_unlock_irq(&ctx->lock); |
| 4004 | 4039 | ||
| 4005 | return ret; | 4040 | return 0; |
| 4006 | } | 4041 | } |
| 4007 | 4042 | ||
| 4008 | static const struct file_operations perf_fops; | 4043 | static const struct file_operations perf_fops; |
| @@ -4740,12 +4775,20 @@ static const struct file_operations perf_fops = { | |||
| 4740 | * to user-space before waking everybody up. | 4775 | * to user-space before waking everybody up. |
| 4741 | */ | 4776 | */ |
| 4742 | 4777 | ||
| 4778 | static inline struct fasync_struct **perf_event_fasync(struct perf_event *event) | ||
| 4779 | { | ||
| 4780 | /* only the parent has fasync state */ | ||
| 4781 | if (event->parent) | ||
| 4782 | event = event->parent; | ||
| 4783 | return &event->fasync; | ||
| 4784 | } | ||
| 4785 | |||
| 4743 | void perf_event_wakeup(struct perf_event *event) | 4786 | void perf_event_wakeup(struct perf_event *event) |
| 4744 | { | 4787 | { |
| 4745 | ring_buffer_wakeup(event); | 4788 | ring_buffer_wakeup(event); |
| 4746 | 4789 | ||
| 4747 | if (event->pending_kill) { | 4790 | if (event->pending_kill) { |
| 4748 | kill_fasync(&event->fasync, SIGIO, event->pending_kill); | 4791 | kill_fasync(perf_event_fasync(event), SIGIO, event->pending_kill); |
| 4749 | event->pending_kill = 0; | 4792 | event->pending_kill = 0; |
| 4750 | } | 4793 | } |
| 4751 | } | 4794 | } |
| @@ -6124,7 +6167,7 @@ static int __perf_event_overflow(struct perf_event *event, | |||
| 6124 | else | 6167 | else |
| 6125 | perf_event_output(event, data, regs); | 6168 | perf_event_output(event, data, regs); |
| 6126 | 6169 | ||
| 6127 | if (event->fasync && event->pending_kill) { | 6170 | if (*perf_event_fasync(event) && event->pending_kill) { |
| 6128 | event->pending_wakeup = 1; | 6171 | event->pending_wakeup = 1; |
| 6129 | irq_work_queue(&event->pending); | 6172 | irq_work_queue(&event->pending); |
| 6130 | } | 6173 | } |
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index b2be01b1aa9d..c8aa3f75bc4d 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c | |||
| @@ -559,11 +559,13 @@ static void __rb_free_aux(struct ring_buffer *rb) | |||
| 559 | rb->aux_priv = NULL; | 559 | rb->aux_priv = NULL; |
| 560 | } | 560 | } |
| 561 | 561 | ||
| 562 | for (pg = 0; pg < rb->aux_nr_pages; pg++) | 562 | if (rb->aux_nr_pages) { |
| 563 | rb_free_aux_page(rb, pg); | 563 | for (pg = 0; pg < rb->aux_nr_pages; pg++) |
| 564 | rb_free_aux_page(rb, pg); | ||
| 564 | 565 | ||
| 565 | kfree(rb->aux_pages); | 566 | kfree(rb->aux_pages); |
| 566 | rb->aux_nr_pages = 0; | 567 | rb->aux_nr_pages = 0; |
| 568 | } | ||
| 567 | } | 569 | } |
| 568 | 570 | ||
| 569 | void rb_free_aux(struct ring_buffer *rb) | 571 | void rb_free_aux(struct ring_buffer *rb) |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 094ddaee104c..d31fac19c30b 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
| @@ -638,7 +638,7 @@ ifndef DESTDIR | |||
| 638 | prefix ?= $(HOME) | 638 | prefix ?= $(HOME) |
| 639 | endif | 639 | endif |
| 640 | bindir_relative = bin | 640 | bindir_relative = bin |
| 641 | bindir = $(prefix)/$(bindir_relative) | 641 | bindir = $(abspath $(prefix)/$(bindir_relative)) |
| 642 | mandir = share/man | 642 | mandir = share/man |
| 643 | infodir = share/info | 643 | infodir = share/info |
| 644 | perfexecdir = libexec/perf-core | 644 | perfexecdir = libexec/perf-core |
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 53e8bb7bc852..2a5d8d7698ae 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c | |||
| @@ -85,7 +85,7 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, | |||
| 85 | else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) | 85 | else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) |
| 86 | update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); | 86 | update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); |
| 87 | else if (perf_stat_evsel__is(counter, CYCLES_IN_TX)) | 87 | else if (perf_stat_evsel__is(counter, CYCLES_IN_TX)) |
| 88 | update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); | 88 | update_stats(&runtime_cycles_in_tx_stats[ctx][cpu], count[0]); |
| 89 | else if (perf_stat_evsel__is(counter, TRANSACTION_START)) | 89 | else if (perf_stat_evsel__is(counter, TRANSACTION_START)) |
| 90 | update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); | 90 | update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); |
| 91 | else if (perf_stat_evsel__is(counter, ELISION_START)) | 91 | else if (perf_stat_evsel__is(counter, ELISION_START)) |
| @@ -398,20 +398,18 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel, | |||
| 398 | " # %5.2f%% aborted cycles ", | 398 | " # %5.2f%% aborted cycles ", |
| 399 | 100.0 * ((total2-avg) / total)); | 399 | 100.0 * ((total2-avg) / total)); |
| 400 | } else if (perf_stat_evsel__is(evsel, TRANSACTION_START) && | 400 | } else if (perf_stat_evsel__is(evsel, TRANSACTION_START) && |
| 401 | avg > 0 && | ||
| 402 | runtime_cycles_in_tx_stats[ctx][cpu].n != 0) { | 401 | runtime_cycles_in_tx_stats[ctx][cpu].n != 0) { |
| 403 | total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]); | 402 | total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]); |
| 404 | 403 | ||
| 405 | if (total) | 404 | if (avg) |
| 406 | ratio = total / avg; | 405 | ratio = total / avg; |
| 407 | 406 | ||
| 408 | fprintf(out, " # %8.0f cycles / transaction ", ratio); | 407 | fprintf(out, " # %8.0f cycles / transaction ", ratio); |
| 409 | } else if (perf_stat_evsel__is(evsel, ELISION_START) && | 408 | } else if (perf_stat_evsel__is(evsel, ELISION_START) && |
| 410 | avg > 0 && | ||
| 411 | runtime_cycles_in_tx_stats[ctx][cpu].n != 0) { | 409 | runtime_cycles_in_tx_stats[ctx][cpu].n != 0) { |
| 412 | total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]); | 410 | total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]); |
| 413 | 411 | ||
| 414 | if (total) | 412 | if (avg) |
| 415 | ratio = total / avg; | 413 | ratio = total / avg; |
| 416 | 414 | ||
| 417 | fprintf(out, " # %8.0f cycles / elision ", ratio); | 415 | fprintf(out, " # %8.0f cycles / elision ", ratio); |
