Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c978b946 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'perf-core-for-mingo-5.1-20190225' of...

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 0a157124 de667cce
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -1223,7 +1223,8 @@ static int pt_event_addr_filters_validate(struct list_head *filters)
static void pt_event_addr_filters_sync(struct perf_event *event)
{
	struct perf_addr_filters_head *head = perf_event_addr_filters(event);
	unsigned long msr_a, msr_b, *offs = event->addr_filters_offs;
	unsigned long msr_a, msr_b;
	struct perf_addr_filter_range *fr = event->addr_filter_ranges;
	struct pt_filters *filters = event->hw.addr_filters;
	struct perf_addr_filter *filter;
	int range = 0;
@@ -1232,12 +1233,12 @@ static void pt_event_addr_filters_sync(struct perf_event *event)
		return;

	list_for_each_entry(filter, &head->list, entry) {
		if (filter->path.dentry && !offs[range]) {
		if (filter->path.dentry && !fr[range].start) {
			msr_a = msr_b = 0;
		} else {
			/* apply the offset */
			msr_a = filter->offset + offs[range];
			msr_b = filter->size + msr_a - 1;
			msr_a = fr[range].start;
			msr_b = msr_a + fr[range].size - 1;
		}

		filters->filter[range].msr_a  = msr_a;
+4 −3
Original line number Diff line number Diff line
@@ -433,15 +433,16 @@ static int etm_addr_filters_validate(struct list_head *filters)
static void etm_addr_filters_sync(struct perf_event *event)
{
	struct perf_addr_filters_head *head = perf_event_addr_filters(event);
	unsigned long start, stop, *offs = event->addr_filters_offs;
	unsigned long start, stop;
	struct perf_addr_filter_range *fr = event->addr_filter_ranges;
	struct etm_filters *filters = event->hw.addr_filters;
	struct etm_filter *etm_filter;
	struct perf_addr_filter *filter;
	int i = 0;

	list_for_each_entry(filter, &head->list, entry) {
		start = filter->offset + offs[i];
		stop = start + filter->size;
		start = fr[i].start;
		stop = start + fr[i].size;
		etm_filter = &filters->etm_filter[i];

		switch (filter->action) {
+6 −1
Original line number Diff line number Diff line
@@ -495,6 +495,11 @@ struct perf_addr_filters_head {
	unsigned int		nr_file_filters;
};

struct perf_addr_filter_range {
	unsigned long		start;
	unsigned long		size;
};

/**
 * enum perf_event_state - the states of an event:
 */
@@ -671,7 +676,7 @@ struct perf_event {
	/* address range filters */
	struct perf_addr_filters_head	addr_filters;
	/* vma address array for file-based filders */
	unsigned long			*addr_filters_offs;
	struct perf_addr_filter_range	*addr_filter_ranges;
	unsigned long			addr_filters_gen;

	void (*destroy)(struct perf_event *);
+59 −31
Original line number Diff line number Diff line
@@ -1255,6 +1255,7 @@ static void put_ctx(struct perf_event_context *ctx)
 *	      perf_event_context::lock
 *	    perf_event::mmap_mutex
 *	    mmap_sem
 *	      perf_addr_filters_head::lock
 *
 *    cpu_hotplug_lock
 *      pmus_lock
@@ -2798,7 +2799,7 @@ static int perf_event_stop(struct perf_event *event, int restart)
 *
 * (p1) when userspace mappings change as a result of (1) or (2) or (3) below,
 *      we update the addresses of corresponding vmas in
 *	event::addr_filters_offs array and bump the event::addr_filters_gen;
 *	event::addr_filter_ranges array and bump the event::addr_filters_gen;
 * (p2) when an event is scheduled in (pmu::add), it calls
 *      perf_event_addr_filters_sync() which calls pmu::addr_filters_sync()
 *      if the generation has changed since the previous call.
@@ -4445,7 +4446,7 @@ static void _free_event(struct perf_event *event)

	perf_event_free_bpf_prog(event);
	perf_addr_filters_splice(event, NULL);
	kfree(event->addr_filters_offs);
	kfree(event->addr_filter_ranges);

	if (event->destroy)
		event->destroy(event);
@@ -6694,7 +6695,8 @@ static void perf_event_addr_filters_exec(struct perf_event *event, void *data)
	raw_spin_lock_irqsave(&ifh->lock, flags);
	list_for_each_entry(filter, &ifh->list, entry) {
		if (filter->path.dentry) {
			event->addr_filters_offs[count] = 0;
			event->addr_filter_ranges[count].start = 0;
			event->addr_filter_ranges[count].size = 0;
			restart++;
		}

@@ -7374,28 +7376,47 @@ static bool perf_addr_filter_match(struct perf_addr_filter *filter,
	return true;
}

static bool perf_addr_filter_vma_adjust(struct perf_addr_filter *filter,
					struct vm_area_struct *vma,
					struct perf_addr_filter_range *fr)
{
	unsigned long vma_size = vma->vm_end - vma->vm_start;
	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
	struct file *file = vma->vm_file;

	if (!perf_addr_filter_match(filter, file, off, vma_size))
		return false;

	if (filter->offset < off) {
		fr->start = vma->vm_start;
		fr->size = min(vma_size, filter->size - (off - filter->offset));
	} else {
		fr->start = vma->vm_start + filter->offset - off;
		fr->size = min(vma->vm_end - fr->start, filter->size);
	}

	return true;
}

static void __perf_addr_filters_adjust(struct perf_event *event, void *data)
{
	struct perf_addr_filters_head *ifh = perf_event_addr_filters(event);
	struct vm_area_struct *vma = data;
	unsigned long off = vma->vm_pgoff << PAGE_SHIFT, flags;
	struct file *file = vma->vm_file;
	struct perf_addr_filter *filter;
	unsigned int restart = 0, count = 0;
	unsigned long flags;

	if (!has_addr_filter(event))
		return;

	if (!file)
	if (!vma->vm_file)
		return;

	raw_spin_lock_irqsave(&ifh->lock, flags);
	list_for_each_entry(filter, &ifh->list, entry) {
		if (perf_addr_filter_match(filter, file, off,
					     vma->vm_end - vma->vm_start)) {
			event->addr_filters_offs[count] = vma->vm_start;
		if (perf_addr_filter_vma_adjust(filter, vma,
						&event->addr_filter_ranges[count]))
			restart++;
		}

		count++;
	}
@@ -8985,26 +9006,19 @@ static void perf_addr_filters_splice(struct perf_event *event,
 * @filter; if so, adjust filter's address range.
 * Called with mm::mmap_sem down for reading.
 */
static unsigned long perf_addr_filter_apply(struct perf_addr_filter *filter,
					    struct mm_struct *mm)
static void perf_addr_filter_apply(struct perf_addr_filter *filter,
				   struct mm_struct *mm,
				   struct perf_addr_filter_range *fr)
{
	struct vm_area_struct *vma;

	for (vma = mm->mmap; vma; vma = vma->vm_next) {
		struct file *file = vma->vm_file;
		unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
		unsigned long vma_size = vma->vm_end - vma->vm_start;

		if (!file)
		if (!vma->vm_file)
			continue;

		if (!perf_addr_filter_match(filter, file, off, vma_size))
			continue;

		return vma->vm_start;
		if (perf_addr_filter_vma_adjust(filter, vma, fr))
			return;
	}

	return 0;
}

/*
@@ -9038,15 +9052,15 @@ static void perf_event_addr_filters_apply(struct perf_event *event)

	raw_spin_lock_irqsave(&ifh->lock, flags);
	list_for_each_entry(filter, &ifh->list, entry) {
		event->addr_filters_offs[count] = 0;
		event->addr_filter_ranges[count].start = 0;
		event->addr_filter_ranges[count].size = 0;

		/*
		 * Adjust base offset if the filter is associated to a binary
		 * that needs to be mapped:
		 */
		if (filter->path.dentry)
			event->addr_filters_offs[count] =
				perf_addr_filter_apply(filter, mm);
			perf_addr_filter_apply(filter, mm, &event->addr_filter_ranges[count]);

		count++;
	}
@@ -10320,14 +10334,28 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
		goto err_pmu;

	if (has_addr_filter(event)) {
		event->addr_filters_offs = kcalloc(pmu->nr_addr_filters,
						   sizeof(unsigned long),
		event->addr_filter_ranges = kcalloc(pmu->nr_addr_filters,
						    sizeof(struct perf_addr_filter_range),
						    GFP_KERNEL);
		if (!event->addr_filters_offs) {
		if (!event->addr_filter_ranges) {
			err = -ENOMEM;
			goto err_per_task;
		}

		/*
		 * Clone the parent's vma offsets: they are valid until exec()
		 * even if the mm is not shared with the parent.
		 */
		if (event->parent) {
			struct perf_addr_filters_head *ifh = perf_event_addr_filters(event);

			raw_spin_lock_irq(&ifh->lock);
			memcpy(event->addr_filter_ranges,
			       event->parent->addr_filter_ranges,
			       pmu->nr_addr_filters * sizeof(struct perf_addr_filter_range));
			raw_spin_unlock_irq(&ifh->lock);
		}

		/* force hw sync on the address filters */
		event->addr_filters_gen = 1;
	}
@@ -10346,7 +10374,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
	return event;

err_addr_filters:
	kfree(event->addr_filters_offs);
	kfree(event->addr_filter_ranges);

err_per_task:
	exclusive_event_destroy(event);
+2 −2
Original line number Diff line number Diff line
@@ -441,7 +441,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
	}

	if (total_nr_samples == 0) {
		ui__error("The %s file has no samples!\n", session->data->file.path);
		ui__error("The %s data has no samples!\n", session->data->path);
		goto out;
	}

@@ -578,7 +578,7 @@ int cmd_annotate(int argc, const char **argv)
	if (quiet)
		perf_quiet_option();

	data.file.path = input_name;
	data.path = input_name;

	annotate.session = perf_session__new(&data, false, &annotate.tool);
	if (annotate.session == NULL)
Loading