Skip to content

Commit

Permalink
Merge tag 'perf-core-for-mingo-5.1-20190225' of git://git.kernel.org/…
Browse files Browse the repository at this point in the history
…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>
  • Loading branch information
Ingo Molnar committed Feb 28, 2019
2 parents 0a15712 + de667cc commit c978b94
Show file tree
Hide file tree
Showing 41 changed files with 1,019 additions and 429 deletions.
9 changes: 5 additions & 4 deletions arch/x86/events/intel/pt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
7 changes: 4 additions & 3 deletions drivers/hwtracing/coresight/coresight-etm-perf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
7 changes: 6 additions & 1 deletion include/linux/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
*/
Expand Down Expand Up @@ -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 *);
Expand Down
90 changes: 59 additions & 31 deletions kernel/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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++;
}

Expand Down Expand Up @@ -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++;
}
Expand Down Expand Up @@ -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;
}

/*
Expand Down Expand Up @@ -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++;
}
Expand Down Expand Up @@ -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),
GFP_KERNEL);
if (!event->addr_filters_offs) {
event->addr_filter_ranges = kcalloc(pmu->nr_addr_filters,
sizeof(struct perf_addr_filter_range),
GFP_KERNEL);
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;
}
Expand All @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/builtin-annotate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/builtin-buildid-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,8 @@ int cmd_buildid_cache(int argc, const char **argv)
nsi = nsinfo__new(ns_id);

if (missing_filename) {
data.file.path = missing_filename;
data.force = force;
data.path = missing_filename;
data.force = force;

session = perf_session__new(&data, false, NULL);
if (session == NULL)
Expand Down
8 changes: 3 additions & 5 deletions tools/perf/builtin-buildid-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
{
struct perf_session *session;
struct perf_data data = {
.file = {
.path = input_name,
},
.mode = PERF_DATA_MODE_READ,
.force = force,
.path = input_name,
.mode = PERF_DATA_MODE_READ,
.force = force,
};

symbol__elf_init();
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/builtin-c2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -2750,8 +2750,8 @@ static int perf_c2c__report(int argc, const char **argv)
if (!input_name || !strlen(input_name))
input_name = "perf.data";

data.file.path = input_name;
data.force = symbol_conf.force;
data.path = input_name;
data.force = symbol_conf.force;

err = setup_display(display);
if (err)
Expand Down
12 changes: 6 additions & 6 deletions tools/perf/builtin-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ static void data__fprintf(void)

data__for_each_file(i, d)
fprintf(stdout, "# [%d] %s %s\n",
d->idx, d->data.file.path,
d->idx, d->data.path,
!d->idx ? "(Baseline)" : "");

fprintf(stdout, "#\n");
Expand Down Expand Up @@ -779,14 +779,14 @@ static int __cmd_diff(void)
data__for_each_file(i, d) {
d->session = perf_session__new(&d->data, false, &tool);
if (!d->session) {
pr_err("Failed to open %s\n", d->data.file.path);
pr_err("Failed to open %s\n", d->data.path);
ret = -1;
goto out_delete;
}

ret = perf_session__process_events(d->session);
if (ret) {
pr_err("Failed to process %s\n", d->data.file.path);
pr_err("Failed to process %s\n", d->data.path);
goto out_delete;
}

Expand Down Expand Up @@ -1289,9 +1289,9 @@ static int data_init(int argc, const char **argv)
data__for_each_file(i, d) {
struct perf_data *data = &d->data;

data->file.path = use_default ? defaults[i] : argv[i];
data->mode = PERF_DATA_MODE_READ,
data->force = force,
data->path = use_default ? defaults[i] : argv[i];
data->mode = PERF_DATA_MODE_READ,
data->force = force,

d->idx = i;
}
Expand Down
4 changes: 1 addition & 3 deletions tools/perf/builtin-evlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
struct perf_session *session;
struct perf_evsel *pos;
struct perf_data data = {
.file = {
.path = file_name,
},
.path = file_name,
.mode = PERF_DATA_MODE_READ,
.force = details->force,
};
Expand Down
10 changes: 4 additions & 6 deletions tools/perf/builtin-inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,10 +770,8 @@ int cmd_inject(int argc, const char **argv)
.input_name = "-",
.samples = LIST_HEAD_INIT(inject.samples),
.output = {
.file = {
.path = "-",
},
.mode = PERF_DATA_MODE_WRITE,
.path = "-",
.mode = PERF_DATA_MODE_WRITE,
},
};
struct perf_data data = {
Expand All @@ -786,7 +784,7 @@ int cmd_inject(int argc, const char **argv)
"Inject build-ids into the output stream"),
OPT_STRING('i', "input", &inject.input_name, "file",
"input file name"),
OPT_STRING('o', "output", &inject.output.file.path, "file",
OPT_STRING('o', "output", &inject.output.path, "file",
"output file name"),
OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
"Merge sched-stat and sched-switch for getting events "
Expand Down Expand Up @@ -834,7 +832,7 @@ int cmd_inject(int argc, const char **argv)

inject.tool.ordered_events = inject.sched_stat;

data.file.path = inject.input_name;
data.path = inject.input_name;
inject.session = perf_session__new(&data, true, &inject.tool);
if (inject.session == NULL)
return -1;
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/builtin-kmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1949,7 +1949,7 @@ int cmd_kmem(int argc, const char **argv)
return __cmd_record(argc, argv);
}

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

kmem_session = session = perf_session__new(&data, false, &perf_kmem);
if (session == NULL)
Expand Down
Loading

0 comments on commit c978b94

Please sign in to comment.