Commit 96ad9999 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'perf-fixes-for-linus' of...

Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  perf, x86: Fix AMD family 15h FPU event constraints
  perf, x86: Fix pre-defined cache-misses event for AMD family 15h cpus
  perf evsel: Fix use of inherit
  perf hists browser: Fix seg fault when annotate null symbol
parents 71460af5 855357a2
...@@ -8,7 +8,7 @@ static __initconst const u64 amd_hw_cache_event_ids ...@@ -8,7 +8,7 @@ static __initconst const u64 amd_hw_cache_event_ids
[ C(L1D) ] = { [ C(L1D) ] = {
[ C(OP_READ) ] = { [ C(OP_READ) ] = {
[ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */
[ C(RESULT_MISS) ] = 0x0041, /* Data Cache Misses */ [ C(RESULT_MISS) ] = 0x0141, /* Data Cache Misses */
}, },
[ C(OP_WRITE) ] = { [ C(OP_WRITE) ] = {
[ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */ [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */
...@@ -427,7 +427,9 @@ static __initconst const struct x86_pmu amd_pmu = { ...@@ -427,7 +427,9 @@ static __initconst const struct x86_pmu amd_pmu = {
* *
* Exceptions: * Exceptions:
* *
* 0x000 FP PERF_CTL[3], PERF_CTL[5:3] (*)
* 0x003 FP PERF_CTL[3] * 0x003 FP PERF_CTL[3]
* 0x004 FP PERF_CTL[3], PERF_CTL[5:3] (*)
* 0x00B FP PERF_CTL[3] * 0x00B FP PERF_CTL[3]
* 0x00D FP PERF_CTL[3] * 0x00D FP PERF_CTL[3]
* 0x023 DE PERF_CTL[2:0] * 0x023 DE PERF_CTL[2:0]
...@@ -448,6 +450,8 @@ static __initconst const struct x86_pmu amd_pmu = { ...@@ -448,6 +450,8 @@ static __initconst const struct x86_pmu amd_pmu = {
* 0x0DF LS PERF_CTL[5:0] * 0x0DF LS PERF_CTL[5:0]
* 0x1D6 EX PERF_CTL[5:0] * 0x1D6 EX PERF_CTL[5:0]
* 0x1D8 EX PERF_CTL[5:0] * 0x1D8 EX PERF_CTL[5:0]
*
* (*) depending on the umask all FPU counters may be used
*/ */
static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0); static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0);
...@@ -460,18 +464,28 @@ static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0); ...@@ -460,18 +464,28 @@ static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
static struct event_constraint * static struct event_constraint *
amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event) amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event)
{ {
unsigned int event_code = amd_get_event_code(&event->hw); struct hw_perf_event *hwc = &event->hw;
unsigned int event_code = amd_get_event_code(hwc);
switch (event_code & AMD_EVENT_TYPE_MASK) { switch (event_code & AMD_EVENT_TYPE_MASK) {
case AMD_EVENT_FP: case AMD_EVENT_FP:
switch (event_code) { switch (event_code) {
case 0x000:
if (!(hwc->config & 0x0000F000ULL))
break;
if (!(hwc->config & 0x00000F00ULL))
break;
return &amd_f15_PMC3;
case 0x004:
if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
break;
return &amd_f15_PMC3;
case 0x003: case 0x003:
case 0x00B: case 0x00B:
case 0x00D: case 0x00D:
return &amd_f15_PMC3; return &amd_f15_PMC3;
default:
return &amd_f15_PMC53;
} }
return &amd_f15_PMC53;
case AMD_EVENT_LS: case AMD_EVENT_LS:
case AMD_EVENT_DC: case AMD_EVENT_DC:
case AMD_EVENT_EX_LS: case AMD_EVENT_EX_LS:
......
...@@ -163,6 +163,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist) ...@@ -163,6 +163,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
struct perf_event_attr *attr = &evsel->attr; struct perf_event_attr *attr = &evsel->attr;
int track = !evsel->idx; /* only the first counter needs these */ int track = !evsel->idx; /* only the first counter needs these */
attr->inherit = !no_inherit;
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_TOTAL_TIME_RUNNING |
PERF_FORMAT_ID; PERF_FORMAT_ID;
...@@ -251,6 +252,9 @@ static void open_counters(struct perf_evlist *evlist) ...@@ -251,6 +252,9 @@ static void open_counters(struct perf_evlist *evlist)
{ {
struct perf_evsel *pos; struct perf_evsel *pos;
if (evlist->cpus->map[0] < 0)
no_inherit = true;
list_for_each_entry(pos, &evlist->entries, node) { list_for_each_entry(pos, &evlist->entries, node) {
struct perf_event_attr *attr = &pos->attr; struct perf_event_attr *attr = &pos->attr;
/* /*
...@@ -271,8 +275,7 @@ static void open_counters(struct perf_evlist *evlist) ...@@ -271,8 +275,7 @@ static void open_counters(struct perf_evlist *evlist)
retry_sample_id: retry_sample_id:
attr->sample_id_all = sample_id_all_avail ? 1 : 0; attr->sample_id_all = sample_id_all_avail ? 1 : 0;
try_again: try_again:
if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group, if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
!no_inherit) < 0) {
int err = errno; int err = errno;
if (err == EPERM || err == EACCES) { if (err == EPERM || err == EACCES) {
......
...@@ -167,16 +167,17 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) ...@@ -167,16 +167,17 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING; PERF_FORMAT_TOTAL_TIME_RUNNING;
attr->inherit = !no_inherit;
if (system_wide) if (system_wide)
return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false); return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false);
attr->inherit = !no_inherit;
if (target_pid == -1 && target_tid == -1) { if (target_pid == -1 && target_tid == -1) {
attr->disabled = 1; attr->disabled = 1;
attr->enable_on_exec = 1; attr->enable_on_exec = 1;
} }
return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false); return perf_evsel__open_per_thread(evsel, evsel_list->threads, false);
} }
/* /*
......
...@@ -290,7 +290,7 @@ static int test__open_syscall_event(void) ...@@ -290,7 +290,7 @@ static int test__open_syscall_event(void)
goto out_thread_map_delete; goto out_thread_map_delete;
} }
if (perf_evsel__open_per_thread(evsel, threads, false, false) < 0) { if (perf_evsel__open_per_thread(evsel, threads, false) < 0) {
pr_debug("failed to open counter: %s, " pr_debug("failed to open counter: %s, "
"tweak /proc/sys/kernel/perf_event_paranoid?\n", "tweak /proc/sys/kernel/perf_event_paranoid?\n",
strerror(errno)); strerror(errno));
...@@ -303,7 +303,7 @@ static int test__open_syscall_event(void) ...@@ -303,7 +303,7 @@ static int test__open_syscall_event(void)
} }
if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) { if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
pr_debug("perf_evsel__open_read_on_cpu\n"); pr_debug("perf_evsel__read_on_cpu\n");
goto out_close_fd; goto out_close_fd;
} }
...@@ -365,7 +365,7 @@ static int test__open_syscall_event_on_all_cpus(void) ...@@ -365,7 +365,7 @@ static int test__open_syscall_event_on_all_cpus(void)
goto out_thread_map_delete; goto out_thread_map_delete;
} }
if (perf_evsel__open(evsel, cpus, threads, false, false) < 0) { if (perf_evsel__open(evsel, cpus, threads, false) < 0) {
pr_debug("failed to open counter: %s, " pr_debug("failed to open counter: %s, "
"tweak /proc/sys/kernel/perf_event_paranoid?\n", "tweak /proc/sys/kernel/perf_event_paranoid?\n",
strerror(errno)); strerror(errno));
...@@ -418,7 +418,7 @@ static int test__open_syscall_event_on_all_cpus(void) ...@@ -418,7 +418,7 @@ static int test__open_syscall_event_on_all_cpus(void)
continue; continue;
if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) { if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
pr_debug("perf_evsel__open_read_on_cpu\n"); pr_debug("perf_evsel__read_on_cpu\n");
err = -1; err = -1;
break; break;
} }
...@@ -529,7 +529,7 @@ static int test__basic_mmap(void) ...@@ -529,7 +529,7 @@ static int test__basic_mmap(void)
perf_evlist__add(evlist, evsels[i]); perf_evlist__add(evlist, evsels[i]);
if (perf_evsel__open(evsels[i], cpus, threads, false, false) < 0) { if (perf_evsel__open(evsels[i], cpus, threads, false) < 0) {
pr_debug("failed to open counter: %s, " pr_debug("failed to open counter: %s, "
"tweak /proc/sys/kernel/perf_event_paranoid?\n", "tweak /proc/sys/kernel/perf_event_paranoid?\n",
strerror(errno)); strerror(errno));
......
...@@ -845,9 +845,10 @@ static void start_counters(struct perf_evlist *evlist) ...@@ -845,9 +845,10 @@ static void start_counters(struct perf_evlist *evlist)
} }
attr->mmap = 1; attr->mmap = 1;
attr->inherit = inherit;
try_again: try_again:
if (perf_evsel__open(counter, top.evlist->cpus, if (perf_evsel__open(counter, top.evlist->cpus,
top.evlist->threads, group, inherit) < 0) { top.evlist->threads, group) < 0) {
int err = errno; int err = errno;
if (err == EPERM || err == EACCES) { if (err == EPERM || err == EACCES) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
#include "util.h" #include "util.h"
#include "debug.h"
#include <sys/mman.h> #include <sys/mman.h>
...@@ -250,15 +251,19 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist) ...@@ -250,15 +251,19 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
return evlist->mmap != NULL ? 0 : -ENOMEM; return evlist->mmap != NULL ? 0 : -ENOMEM;
} }
static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot, static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel,
int mask, int fd) int cpu, int prot, int mask, int fd)
{ {
evlist->mmap[cpu].prev = 0; evlist->mmap[cpu].prev = 0;
evlist->mmap[cpu].mask = mask; evlist->mmap[cpu].mask = mask;
evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot, evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot,
MAP_SHARED, fd, 0); MAP_SHARED, fd, 0);
if (evlist->mmap[cpu].base == MAP_FAILED) if (evlist->mmap[cpu].base == MAP_FAILED) {
if (evlist->cpus->map[cpu] == -1 && evsel->attr.inherit)
ui__warning("Inherit is not allowed on per-task "
"events using mmap.\n");
return -1; return -1;
}
perf_evlist__add_pollfd(evlist, fd); perf_evlist__add_pollfd(evlist, fd);
return 0; return 0;
...@@ -312,7 +317,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) ...@@ -312,7 +317,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT,
FD(first_evsel, cpu, 0)) != 0) FD(first_evsel, cpu, 0)) != 0)
goto out_unmap; goto out_unmap;
} else if (__perf_evlist__mmap(evlist, cpu, prot, mask, fd) < 0) } else if (__perf_evlist__mmap(evlist, evsel, cpu,
prot, mask, fd) < 0)
goto out_unmap; goto out_unmap;
if ((evsel->attr.read_format & PERF_FORMAT_ID) && if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
......
...@@ -175,7 +175,7 @@ int __perf_evsel__read(struct perf_evsel *evsel, ...@@ -175,7 +175,7 @@ int __perf_evsel__read(struct perf_evsel *evsel,
} }
static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
struct thread_map *threads, bool group, bool inherit) struct thread_map *threads, bool group)
{ {
int cpu, thread; int cpu, thread;
unsigned long flags = 0; unsigned long flags = 0;
...@@ -192,19 +192,6 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, ...@@ -192,19 +192,6 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
for (cpu = 0; cpu < cpus->nr; cpu++) { for (cpu = 0; cpu < cpus->nr; cpu++) {
int group_fd = -1; int group_fd = -1;
/*
* Don't allow mmap() of inherited per-task counters. This
* would create a performance issue due to all children writing
* to the same buffer.
*
* FIXME:
* Proper fix is not to pass 'inherit' to perf_evsel__open*,
* but a 'flags' parameter, with 'group' folded there as well,
* then introduce a PERF_O_{MMAP,GROUP,INHERIT} enum, and if
* O_MMAP is set, emit a warning if cpu < 0 and O_INHERIT is
* set. Lets go for the minimal fix first tho.
*/
evsel->attr.inherit = (cpus->map[cpu] >= 0) && inherit;
for (thread = 0; thread < threads->nr; thread++) { for (thread = 0; thread < threads->nr; thread++) {
...@@ -253,7 +240,7 @@ static struct { ...@@ -253,7 +240,7 @@ static struct {
}; };
int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
struct thread_map *threads, bool group, bool inherit) struct thread_map *threads, bool group)
{ {
if (cpus == NULL) { if (cpus == NULL) {
/* Work around old compiler warnings about strict aliasing */ /* Work around old compiler warnings about strict aliasing */
...@@ -263,19 +250,19 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, ...@@ -263,19 +250,19 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
if (threads == NULL) if (threads == NULL)
threads = &empty_thread_map.map; threads = &empty_thread_map.map;
return __perf_evsel__open(evsel, cpus, threads, group, inherit); return __perf_evsel__open(evsel, cpus, threads, group);
} }
int perf_evsel__open_per_cpu(struct perf_evsel *evsel, int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
struct cpu_map *cpus, bool group, bool inherit) struct cpu_map *cpus, bool group)
{ {
return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, inherit); return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group);
} }
int perf_evsel__open_per_thread(struct perf_evsel *evsel, int perf_evsel__open_per_thread(struct perf_evsel *evsel,
struct thread_map *threads, bool group, bool inherit) struct thread_map *threads, bool group)
{ {
return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit); return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group);
} }
static int perf_event__parse_id_sample(const union perf_event *event, u64 type, static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
......
...@@ -81,11 +81,11 @@ void perf_evsel__free_id(struct perf_evsel *evsel); ...@@ -81,11 +81,11 @@ void perf_evsel__free_id(struct perf_evsel *evsel);
void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
int perf_evsel__open_per_cpu(struct perf_evsel *evsel, int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
struct cpu_map *cpus, bool group, bool inherit); struct cpu_map *cpus, bool group);
int perf_evsel__open_per_thread(struct perf_evsel *evsel, int perf_evsel__open_per_thread(struct perf_evsel *evsel,
struct thread_map *threads, bool group, bool inherit); struct thread_map *threads, bool group);
int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
struct thread_map *threads, bool group, bool inherit); struct thread_map *threads, bool group);
#define perf_evsel__match(evsel, t, c) \ #define perf_evsel__match(evsel, t, c) \
(evsel->attr.type == PERF_TYPE_##t && \ (evsel->attr.type == PERF_TYPE_##t && \
......
...@@ -498,11 +498,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, ...@@ -498,11 +498,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
struct cpu_map *cpus = NULL; struct cpu_map *cpus = NULL;
struct thread_map *threads = NULL; struct thread_map *threads = NULL;
PyObject *pcpus = NULL, *pthreads = NULL; PyObject *pcpus = NULL, *pthreads = NULL;
int group = 0, overwrite = 0; int group = 0, inherit = 0;
static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL}; static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
&pcpus, &pthreads, &group, &overwrite)) &pcpus, &pthreads, &group, &inherit))
return NULL; return NULL;
if (pthreads != NULL) if (pthreads != NULL)
...@@ -511,7 +511,8 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, ...@@ -511,7 +511,8 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
if (pcpus != NULL) if (pcpus != NULL)
cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) { evsel->attr.inherit = inherit;
if (perf_evsel__open(evsel, cpus, threads, group) < 0) {
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
return NULL; return NULL;
} }
......
...@@ -256,10 +256,9 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, ...@@ -256,10 +256,9 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
int refresh) int refresh)
{ {
struct objdump_line *pos, *n; struct objdump_line *pos, *n;
struct annotation *notes = symbol__annotation(sym); struct annotation *notes;
struct annotate_browser browser = { struct annotate_browser browser = {
.b = { .b = {
.entries = &notes->src->source,
.refresh = ui_browser__list_head_refresh, .refresh = ui_browser__list_head_refresh,
.seek = ui_browser__list_head_seek, .seek = ui_browser__list_head_seek,
.write = annotate_browser__write, .write = annotate_browser__write,
...@@ -281,6 +280,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, ...@@ -281,6 +280,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
ui_helpline__push("Press <- or ESC to exit"); ui_helpline__push("Press <- or ESC to exit");
notes = symbol__annotation(sym);
list_for_each_entry(pos, &notes->src->source, node) { list_for_each_entry(pos, &notes->src->source, node) {
struct objdump_line_rb_node *rbpos; struct objdump_line_rb_node *rbpos;
size_t line_len = strlen(pos->line); size_t line_len = strlen(pos->line);
...@@ -291,6 +292,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, ...@@ -291,6 +292,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
rbpos->idx = browser.b.nr_entries++; rbpos->idx = browser.b.nr_entries++;
} }
browser.b.entries = &notes->src->source,
browser.b.width += 18; /* Percentage */ browser.b.width += 18; /* Percentage */
ret = annotate_browser__run(&browser, evidx, refresh); ret = annotate_browser__run(&browser, evidx, refresh);
list_for_each_entry_safe(pos, n, &notes->src->source, node) { list_for_each_entry_safe(pos, n, &notes->src->source, node) {
......
...@@ -851,7 +851,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, ...@@ -851,7 +851,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
goto out_free_stack; goto out_free_stack;
case 'a': case 'a':
if (browser->selection == NULL || if (browser->selection == NULL ||
browser->selection->map == NULL || browser->selection->sym == NULL ||
browser->selection->map->dso->annotate_warned) browser->selection->map->dso->annotate_warned)
continue; continue;
goto do_annotate; goto do_annotate;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment