diff options
| author | Ingo Molnar <mingo@kernel.org> | 2019-02-28 02:29:50 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2019-02-28 02:29:50 -0500 |
| commit | c978b9460fe1d4a1e1effa0abd6bd69b18a098a8 (patch) | |
| tree | eecc4c6179dea191c55ac8ef50467573b29a0b06 /kernel | |
| parent | 0a1571243d3f150fa99c6f41f1b8e17a307a2b8b (diff) | |
| parent | de667cce7f4f96b6e22da8fd9c065b961f355080 (diff) | |
Merge tag 'perf-core-for-mingo-5.1-20190225' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
perf annotate:
Wei Li:
- Fix getting source line failure
perf script:
Andi Kleen:
- Handle missing fields with -F +...
perf data:
Jiri Olsa:
- Prep work to support per-cpu files in a directory.
Intel PT:
Adrian Hunter:
- Improve thread_stack__no_call_return()
- Hide x86 retpolines in thread stacks.
- exported SQL viewer refactorings, new 'top calls' report..
Alexander Shishkin:
- Copy parent's address filter offsets on clone
- Fix address filters for vmas with non-zero offset. Applies to
ARM's CoreSight as well.
python scripts:
Tony Jones:
- Python3 support for several 'perf script' python scripts.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/events/core.c | 90 |
1 files changed, 59 insertions, 31 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index 932babd9e86c..5f59d848171e 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -1255,6 +1255,7 @@ static void put_ctx(struct perf_event_context *ctx) | |||
| 1255 | * perf_event_context::lock | 1255 | * perf_event_context::lock |
| 1256 | * perf_event::mmap_mutex | 1256 | * perf_event::mmap_mutex |
| 1257 | * mmap_sem | 1257 | * mmap_sem |
| 1258 | * perf_addr_filters_head::lock | ||
| 1258 | * | 1259 | * |
| 1259 | * cpu_hotplug_lock | 1260 | * cpu_hotplug_lock |
| 1260 | * pmus_lock | 1261 | * pmus_lock |
| @@ -2798,7 +2799,7 @@ static int perf_event_stop(struct perf_event *event, int restart) | |||
| 2798 | * | 2799 | * |
| 2799 | * (p1) when userspace mappings change as a result of (1) or (2) or (3) below, | 2800 | * (p1) when userspace mappings change as a result of (1) or (2) or (3) below, |
| 2800 | * we update the addresses of corresponding vmas in | 2801 | * we update the addresses of corresponding vmas in |
| 2801 | * event::addr_filters_offs array and bump the event::addr_filters_gen; | 2802 | * event::addr_filter_ranges array and bump the event::addr_filters_gen; |
| 2802 | * (p2) when an event is scheduled in (pmu::add), it calls | 2803 | * (p2) when an event is scheduled in (pmu::add), it calls |
| 2803 | * perf_event_addr_filters_sync() which calls pmu::addr_filters_sync() | 2804 | * perf_event_addr_filters_sync() which calls pmu::addr_filters_sync() |
| 2804 | * if the generation has changed since the previous call. | 2805 | * if the generation has changed since the previous call. |
| @@ -4445,7 +4446,7 @@ static void _free_event(struct perf_event *event) | |||
| 4445 | 4446 | ||
| 4446 | perf_event_free_bpf_prog(event); | 4447 | perf_event_free_bpf_prog(event); |
| 4447 | perf_addr_filters_splice(event, NULL); | 4448 | perf_addr_filters_splice(event, NULL); |
| 4448 | kfree(event->addr_filters_offs); | 4449 | kfree(event->addr_filter_ranges); |
| 4449 | 4450 | ||
| 4450 | if (event->destroy) | 4451 | if (event->destroy) |
| 4451 | event->destroy(event); | 4452 | event->destroy(event); |
| @@ -6694,7 +6695,8 @@ static void perf_event_addr_filters_exec(struct perf_event *event, void *data) | |||
| 6694 | raw_spin_lock_irqsave(&ifh->lock, flags); | 6695 | raw_spin_lock_irqsave(&ifh->lock, flags); |
| 6695 | list_for_each_entry(filter, &ifh->list, entry) { | 6696 | list_for_each_entry(filter, &ifh->list, entry) { |
| 6696 | if (filter->path.dentry) { | 6697 | if (filter->path.dentry) { |
| 6697 | event->addr_filters_offs[count] = 0; | 6698 | event->addr_filter_ranges[count].start = 0; |
| 6699 | event->addr_filter_ranges[count].size = 0; | ||
| 6698 | restart++; | 6700 | restart++; |
| 6699 | } | 6701 | } |
| 6700 | 6702 | ||
| @@ -7374,28 +7376,47 @@ static bool perf_addr_filter_match(struct perf_addr_filter *filter, | |||
| 7374 | return true; | 7376 | return true; |
| 7375 | } | 7377 | } |
| 7376 | 7378 | ||
| 7379 | static bool perf_addr_filter_vma_adjust(struct perf_addr_filter *filter, | ||
| 7380 | struct vm_area_struct *vma, | ||
| 7381 | struct perf_addr_filter_range *fr) | ||
| 7382 | { | ||
| 7383 | unsigned long vma_size = vma->vm_end - vma->vm_start; | ||
| 7384 | unsigned long off = vma->vm_pgoff << PAGE_SHIFT; | ||
| 7385 | struct file *file = vma->vm_file; | ||
| 7386 | |||
| 7387 | if (!perf_addr_filter_match(filter, file, off, vma_size)) | ||
| 7388 | return false; | ||
| 7389 | |||
| 7390 | if (filter->offset < off) { | ||
| 7391 | fr->start = vma->vm_start; | ||
| 7392 | fr->size = min(vma_size, filter->size - (off - filter->offset)); | ||
| 7393 | } else { | ||
| 7394 | fr->start = vma->vm_start + filter->offset - off; | ||
| 7395 | fr->size = min(vma->vm_end - fr->start, filter->size); | ||
| 7396 | } | ||
| 7397 | |||
| 7398 | return true; | ||
| 7399 | } | ||
| 7400 | |||
| 7377 | static void __perf_addr_filters_adjust(struct perf_event *event, void *data) | 7401 | static void __perf_addr_filters_adjust(struct perf_event *event, void *data) |
| 7378 | { | 7402 | { |
| 7379 | struct perf_addr_filters_head *ifh = perf_event_addr_filters(event); | 7403 | struct perf_addr_filters_head *ifh = perf_event_addr_filters(event); |
| 7380 | struct vm_area_struct *vma = data; | 7404 | struct vm_area_struct *vma = data; |
| 7381 | unsigned long off = vma->vm_pgoff << PAGE_SHIFT, flags; | ||
| 7382 | struct file *file = vma->vm_file; | ||
| 7383 | struct perf_addr_filter *filter; | 7405 | struct perf_addr_filter *filter; |
| 7384 | unsigned int restart = 0, count = 0; | 7406 | unsigned int restart = 0, count = 0; |
| 7407 | unsigned long flags; | ||
| 7385 | 7408 | ||
| 7386 | if (!has_addr_filter(event)) | 7409 | if (!has_addr_filter(event)) |
| 7387 | return; | 7410 | return; |
| 7388 | 7411 | ||
| 7389 | if (!file) | 7412 | if (!vma->vm_file) |
| 7390 | return; | 7413 | return; |
| 7391 | 7414 | ||
| 7392 | raw_spin_lock_irqsave(&ifh->lock, flags); | 7415 | raw_spin_lock_irqsave(&ifh->lock, flags); |
| 7393 | list_for_each_entry(filter, &ifh->list, entry) { | 7416 | list_for_each_entry(filter, &ifh->list, entry) { |
| 7394 | if (perf_addr_filter_match(filter, file, off, | 7417 | if (perf_addr_filter_vma_adjust(filter, vma, |
| 7395 | vma->vm_end - vma->vm_start)) { | 7418 | &event->addr_filter_ranges[count])) |
| 7396 | event->addr_filters_offs[count] = vma->vm_start; | ||
| 7397 | restart++; | 7419 | restart++; |
| 7398 | } | ||
| 7399 | 7420 | ||
| 7400 | count++; | 7421 | count++; |
| 7401 | } | 7422 | } |
| @@ -8985,26 +9006,19 @@ static void perf_addr_filters_splice(struct perf_event *event, | |||
| 8985 | * @filter; if so, adjust filter's address range. | 9006 | * @filter; if so, adjust filter's address range. |
| 8986 | * Called with mm::mmap_sem down for reading. | 9007 | * Called with mm::mmap_sem down for reading. |
| 8987 | */ | 9008 | */ |
| 8988 | static unsigned long perf_addr_filter_apply(struct perf_addr_filter *filter, | 9009 | static void perf_addr_filter_apply(struct perf_addr_filter *filter, |
| 8989 | struct mm_struct *mm) | 9010 | struct mm_struct *mm, |
| 9011 | struct perf_addr_filter_range *fr) | ||
| 8990 | { | 9012 | { |
| 8991 | struct vm_area_struct *vma; | 9013 | struct vm_area_struct *vma; |
| 8992 | 9014 | ||
| 8993 | for (vma = mm->mmap; vma; vma = vma->vm_next) { | 9015 | for (vma = mm->mmap; vma; vma = vma->vm_next) { |
| 8994 | struct file *file = vma->vm_file; | 9016 | if (!vma->vm_file) |
| 8995 | unsigned long off = vma->vm_pgoff << PAGE_SHIFT; | ||
| 8996 | unsigned long vma_size = vma->vm_end - vma->vm_start; | ||
| 8997 | |||
| 8998 | if (!file) | ||
| 8999 | continue; | 9017 | continue; |
| 9000 | 9018 | ||
| 9001 | if (!perf_addr_filter_match(filter, file, off, vma_size)) | 9019 | if (perf_addr_filter_vma_adjust(filter, vma, fr)) |
| 9002 | continue; | 9020 | return; |
| 9003 | |||
| 9004 | return vma->vm_start; | ||
| 9005 | } | 9021 | } |
| 9006 | |||
| 9007 | return 0; | ||
| 9008 | } | 9022 | } |
| 9009 | 9023 | ||
| 9010 | /* | 9024 | /* |
| @@ -9038,15 +9052,15 @@ static void perf_event_addr_filters_apply(struct perf_event *event) | |||
| 9038 | 9052 | ||
| 9039 | raw_spin_lock_irqsave(&ifh->lock, flags); | 9053 | raw_spin_lock_irqsave(&ifh->lock, flags); |
| 9040 | list_for_each_entry(filter, &ifh->list, entry) { | 9054 | list_for_each_entry(filter, &ifh->list, entry) { |
| 9041 | event->addr_filters_offs[count] = 0; | 9055 | event->addr_filter_ranges[count].start = 0; |
| 9056 | event->addr_filter_ranges[count].size = 0; | ||
| 9042 | 9057 | ||
| 9043 | /* | 9058 | /* |
| 9044 | * Adjust base offset if the filter is associated to a binary | 9059 | * Adjust base offset if the filter is associated to a binary |
| 9045 | * that needs to be mapped: | 9060 | * that needs to be mapped: |
| 9046 | */ | 9061 | */ |
| 9047 | if (filter->path.dentry) | 9062 | if (filter->path.dentry) |
| 9048 | event->addr_filters_offs[count] = | 9063 | perf_addr_filter_apply(filter, mm, &event->addr_filter_ranges[count]); |
| 9049 | perf_addr_filter_apply(filter, mm); | ||
| 9050 | 9064 | ||
| 9051 | count++; | 9065 | count++; |
| 9052 | } | 9066 | } |
| @@ -10320,14 +10334,28 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, | |||
| 10320 | goto err_pmu; | 10334 | goto err_pmu; |
| 10321 | 10335 | ||
| 10322 | if (has_addr_filter(event)) { | 10336 | if (has_addr_filter(event)) { |
| 10323 | event->addr_filters_offs = kcalloc(pmu->nr_addr_filters, | 10337 | event->addr_filter_ranges = kcalloc(pmu->nr_addr_filters, |
| 10324 | sizeof(unsigned long), | 10338 | sizeof(struct perf_addr_filter_range), |
| 10325 | GFP_KERNEL); | 10339 | GFP_KERNEL); |
| 10326 | if (!event->addr_filters_offs) { | 10340 | if (!event->addr_filter_ranges) { |
| 10327 | err = -ENOMEM; | 10341 | err = -ENOMEM; |
| 10328 | goto err_per_task; | 10342 | goto err_per_task; |
| 10329 | } | 10343 | } |
| 10330 | 10344 | ||
| 10345 | /* | ||
| 10346 | * Clone the parent's vma offsets: they are valid until exec() | ||
| 10347 | * even if the mm is not shared with the parent. | ||
| 10348 | */ | ||
| 10349 | if (event->parent) { | ||
| 10350 | struct perf_addr_filters_head *ifh = perf_event_addr_filters(event); | ||
| 10351 | |||
| 10352 | raw_spin_lock_irq(&ifh->lock); | ||
| 10353 | memcpy(event->addr_filter_ranges, | ||
| 10354 | event->parent->addr_filter_ranges, | ||
| 10355 | pmu->nr_addr_filters * sizeof(struct perf_addr_filter_range)); | ||
| 10356 | raw_spin_unlock_irq(&ifh->lock); | ||
| 10357 | } | ||
| 10358 | |||
| 10331 | /* force hw sync on the address filters */ | 10359 | /* force hw sync on the address filters */ |
| 10332 | event->addr_filters_gen = 1; | 10360 | event->addr_filters_gen = 1; |
| 10333 | } | 10361 | } |
| @@ -10346,7 +10374,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, | |||
| 10346 | return event; | 10374 | return event; |
| 10347 | 10375 | ||
| 10348 | err_addr_filters: | 10376 | err_addr_filters: |
| 10349 | kfree(event->addr_filters_offs); | 10377 | kfree(event->addr_filter_ranges); |
| 10350 | 10378 | ||
| 10351 | err_per_task: | 10379 | err_per_task: |
| 10352 | exclusive_event_destroy(event); | 10380 | exclusive_event_destroy(event); |
