Commit ae18cbfe authored by Ingo Molnar's avatar Ingo Molnar

Merge branch 'perf/core' of...

Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
parents 1d321881 cd25f8bc
...@@ -49,6 +49,10 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model, ...@@ -49,6 +49,10 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model,
val |= counter_config->user ? ARCH_PERFMON_EVENTSEL_USR : 0; val |= counter_config->user ? ARCH_PERFMON_EVENTSEL_USR : 0;
val |= counter_config->kernel ? ARCH_PERFMON_EVENTSEL_OS : 0; val |= counter_config->kernel ? ARCH_PERFMON_EVENTSEL_OS : 0;
val |= (counter_config->unit_mask & 0xFF) << 8; val |= (counter_config->unit_mask & 0xFF) << 8;
counter_config->extra &= (ARCH_PERFMON_EVENTSEL_INV |
ARCH_PERFMON_EVENTSEL_EDGE |
ARCH_PERFMON_EVENTSEL_CMASK);
val |= counter_config->extra;
event &= model->event_mask ? model->event_mask : 0xFF; event &= model->event_mask ? model->event_mask : 0xFF;
val |= event & 0xFF; val |= event & 0xFF;
val |= (event & 0x0F00) << 24; val |= (event & 0x0F00) << 24;
...@@ -440,6 +444,7 @@ static int nmi_create_files(struct super_block *sb, struct dentry *root) ...@@ -440,6 +444,7 @@ static int nmi_create_files(struct super_block *sb, struct dentry *root)
oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask); oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel); oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user); oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
oprofilefs_create_ulong(sb, dir, "extra", &counter_config[i].extra);
} }
return 0; return 0;
......
...@@ -22,6 +22,7 @@ struct op_counter_config { ...@@ -22,6 +22,7 @@ struct op_counter_config {
unsigned long kernel; unsigned long kernel;
unsigned long user; unsigned long user;
unsigned long unit_mask; unsigned long unit_mask;
unsigned long extra;
}; };
extern struct op_counter_config counter_config[]; extern struct op_counter_config counter_config[];
......
...@@ -275,11 +275,10 @@ static void open_counters(struct perf_evlist *evlist) ...@@ -275,11 +275,10 @@ static void open_counters(struct perf_evlist *evlist)
!no_inherit) < 0) { !no_inherit) < 0) {
int err = errno; int err = errno;
if (err == EPERM || err == EACCES) if (err == EPERM || err == EACCES) {
die("Permission error - are you root?\n" ui__warning_paranoid();
"\t Consider tweaking" exit(EXIT_FAILURE);
" /proc/sys/kernel/perf_event_paranoid.\n"); } else if (err == ENODEV && cpu_list) {
else if (err == ENODEV && cpu_list) {
die("No such device - did you specify" die("No such device - did you specify"
" an out-of-range profile CPU?\n"); " an out-of-range profile CPU?\n");
} else if (err == EINVAL && sample_id_all_avail) { } else if (err == EINVAL && sample_id_all_avail) {
...@@ -302,11 +301,19 @@ static void open_counters(struct perf_evlist *evlist) ...@@ -302,11 +301,19 @@ static void open_counters(struct perf_evlist *evlist)
&& attr->config == PERF_COUNT_HW_CPU_CYCLES) { && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
if (verbose) if (verbose)
warning(" ... trying to fall back to cpu-clock-ticks\n"); ui__warning("The cycles event is not supported, "
"trying to fall back to cpu-clock-ticks\n");
attr->type = PERF_TYPE_SOFTWARE; attr->type = PERF_TYPE_SOFTWARE;
attr->config = PERF_COUNT_SW_CPU_CLOCK; attr->config = PERF_COUNT_SW_CPU_CLOCK;
goto try_again; goto try_again;
} }
if (err == ENOENT) {
ui__warning("The %s event is not supported.\n",
event_name(pos));
exit(EXIT_FAILURE);
}
printf("\n"); printf("\n");
error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
err, strerror(err)); err, strerror(err));
......
...@@ -850,10 +850,10 @@ static void start_counters(struct perf_evlist *evlist) ...@@ -850,10 +850,10 @@ static void start_counters(struct perf_evlist *evlist)
top.evlist->threads, group, inherit) < 0) { top.evlist->threads, group, inherit) < 0) {
int err = errno; int err = errno;
if (err == EPERM || err == EACCES) if (err == EPERM || err == EACCES) {
die("Permission error - are you root?\n" ui__warning_paranoid();
"\t Consider tweaking" goto out_err;
" /proc/sys/kernel/perf_event_paranoid.\n"); }
/* /*
* If it's cycles then fall back to hrtimer * If it's cycles then fall back to hrtimer
* based cpu-clock-tick sw counter, which * based cpu-clock-tick sw counter, which
...@@ -861,25 +861,41 @@ static void start_counters(struct perf_evlist *evlist) ...@@ -861,25 +861,41 @@ static void start_counters(struct perf_evlist *evlist)
*/ */
if (attr->type == PERF_TYPE_HARDWARE && if (attr->type == PERF_TYPE_HARDWARE &&
attr->config == PERF_COUNT_HW_CPU_CYCLES) { attr->config == PERF_COUNT_HW_CPU_CYCLES) {
if (verbose) if (verbose)
warning(" ... trying to fall back to cpu-clock-ticks\n"); ui__warning("Cycles event not supported,\n"
"trying to fall back to cpu-clock-ticks\n");
attr->type = PERF_TYPE_SOFTWARE; attr->type = PERF_TYPE_SOFTWARE;
attr->config = PERF_COUNT_SW_CPU_CLOCK; attr->config = PERF_COUNT_SW_CPU_CLOCK;
goto try_again; goto try_again;
} }
printf("\n");
error("sys_perf_event_open() syscall returned with %d " if (err == ENOENT) {
"(%s). /bin/dmesg may provide additional information.\n", ui__warning("The %s event is not supported.\n",
err, strerror(err)); event_name(counter));
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); goto out_err;
exit(-1); }
ui__warning("The sys_perf_event_open() syscall "
"returned with %d (%s). /bin/dmesg "
"may provide additional information.\n"
"No CONFIG_PERF_EVENTS=y kernel support "
"configured?\n", err, strerror(err));
goto out_err;
} }
} }
if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) {
die("failed to mmap with %d (%s)\n", errno, strerror(errno)); ui__warning("Failed to mmap with %d (%s)\n",
errno, strerror(errno));
goto out_err;
}
return;
out_err:
exit_browser(0);
exit(0);
} }
static int __cmd_top(void) static int __cmd_top(void)
......
...@@ -57,6 +57,16 @@ void ui__warning(const char *format, ...) ...@@ -57,6 +57,16 @@ void ui__warning(const char *format, ...)
} }
#endif #endif
void ui__warning_paranoid(void)
{
ui__warning("Permission error - are you root?\n"
"Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
" -1 - Not paranoid at all\n"
" 0 - Disallow raw tracepoint access for unpriv\n"
" 1 - Disallow cpu events for unpriv\n"
" 2 - Disallow kernel profiling for unpriv\n");
}
void trace_event(union perf_event *event) void trace_event(union perf_event *event)
{ {
unsigned char *raw_event = (void *)event; unsigned char *raw_event = (void *)event;
......
...@@ -36,5 +36,6 @@ int ui_helpline__show_help(const char *format, va_list ap); ...@@ -36,5 +36,6 @@ int ui_helpline__show_help(const char *format, va_list ap);
#endif #endif
void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
void ui__warning_paranoid(void);
#endif /* __PERF_DEBUG_H */ #endif /* __PERF_DEBUG_H */
...@@ -710,7 +710,7 @@ void thread__find_addr_map(struct thread *self, ...@@ -710,7 +710,7 @@ void thread__find_addr_map(struct thread *self,
* in the whole kernel symbol list. * in the whole kernel symbol list.
*/ */
if ((long long)al->addr < 0 && if ((long long)al->addr < 0 &&
cpumode == PERF_RECORD_MISC_KERNEL && cpumode == PERF_RECORD_MISC_USER &&
machine && mg != &machine->kmaps) { machine && mg != &machine->kmaps) {
mg = &machine->kmaps; mg = &machine->kmaps;
goto try_again; goto try_again;
......
...@@ -1435,6 +1435,38 @@ static int find_probe_point_by_func(struct probe_finder *pf) ...@@ -1435,6 +1435,38 @@ static int find_probe_point_by_func(struct probe_finder *pf)
return _param.retval; return _param.retval;
} }
struct pubname_callback_param {
char *function;
char *file;
Dwarf_Die *cu_die;
Dwarf_Die *sp_die;
int found;
};
static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
{
struct pubname_callback_param *param = data;
if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) {
if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
return DWARF_CB_OK;
if (die_compare_name(param->sp_die, param->function)) {
if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
return DWARF_CB_OK;
if (param->file &&
strtailcmp(param->file, dwarf_decl_file(param->sp_die)))
return DWARF_CB_OK;
param->found = 1;
return DWARF_CB_ABORT;
}
}
return DWARF_CB_OK;
}
/* Find probe points from debuginfo */ /* Find probe points from debuginfo */
static int find_probes(int fd, struct probe_finder *pf) static int find_probes(int fd, struct probe_finder *pf)
{ {
...@@ -1461,6 +1493,27 @@ static int find_probes(int fd, struct probe_finder *pf) ...@@ -1461,6 +1493,27 @@ static int find_probes(int fd, struct probe_finder *pf)
off = 0; off = 0;
line_list__init(&pf->lcache); line_list__init(&pf->lcache);
/* Fastpath: lookup by function name from .debug_pubnames section */
if (pp->function) {
struct pubname_callback_param pubname_param = {
.function = pp->function,
.file = pp->file,
.cu_die = &pf->cu_die,
.sp_die = &pf->sp_die,
};
struct dwarf_callback_param probe_param = {
.data = pf,
};
dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0);
if (pubname_param.found) {
ret = probe_point_search_cb(&pf->sp_die, &probe_param);
if (ret)
goto found;
}
}
/* Loop on CUs (Compilation Unit) */ /* Loop on CUs (Compilation Unit) */
while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
/* Get the DIE(Debugging Information Entry) of this CU */ /* Get the DIE(Debugging Information Entry) of this CU */
...@@ -1488,6 +1541,8 @@ static int find_probes(int fd, struct probe_finder *pf) ...@@ -1488,6 +1541,8 @@ static int find_probes(int fd, struct probe_finder *pf)
} }
off = noff; off = noff;
} }
found:
line_list__free(&pf->lcache); line_list__free(&pf->lcache);
if (dwfl) if (dwfl)
dwfl_end(dwfl); dwfl_end(dwfl);
...@@ -1895,6 +1950,22 @@ int find_line_range(int fd, struct line_range *lr) ...@@ -1895,6 +1950,22 @@ int find_line_range(int fd, struct line_range *lr)
return -EBADF; return -EBADF;
} }
/* Fastpath: lookup by function name from .debug_pubnames section */
if (lr->function) {
struct pubname_callback_param pubname_param = {
.function = lr->function, .file = lr->file,
.cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0};
struct dwarf_callback_param line_range_param = {
.data = (void *)&lf, .retval = 0};
dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0);
if (pubname_param.found) {
line_range_search_cb(&lf.sp_die, &line_range_param);
if (lf.found)
goto found;
}
}
/* Loop on CUs (Compilation Unit) */ /* Loop on CUs (Compilation Unit) */
while (!lf.found && ret >= 0) { while (!lf.found && ret >= 0) {
if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
...@@ -1923,6 +1994,7 @@ int find_line_range(int fd, struct line_range *lr) ...@@ -1923,6 +1994,7 @@ int find_line_range(int fd, struct line_range *lr)
off = noff; off = noff;
} }
found:
/* Store comp_dir */ /* Store comp_dir */
if (lf.found) { if (lf.found) {
comp_dir = cu_get_comp_dir(&lf.cu_die); comp_dir = cu_get_comp_dir(&lf.cu_die);
......
...@@ -49,6 +49,7 @@ struct probe_finder { ...@@ -49,6 +49,7 @@ struct probe_finder {
Dwarf_Addr addr; /* Address */ Dwarf_Addr addr; /* Address */
const char *fname; /* Real file name */ const char *fname; /* Real file name */
Dwarf_Die cu_die; /* Current CU */ Dwarf_Die cu_die; /* Current CU */
Dwarf_Die sp_die;
struct list_head lcache; /* Line cache for lazy match */ struct list_head lcache; /* Line cache for lazy match */
/* For variable searching */ /* For variable searching */
...@@ -83,6 +84,7 @@ struct line_finder { ...@@ -83,6 +84,7 @@ struct line_finder {
int lno_s; /* Start line number */ int lno_s; /* Start line number */
int lno_e; /* End line number */ int lno_e; /* End line number */
Dwarf_Die cu_die; /* Current CU */ Dwarf_Die cu_die; /* Current CU */
Dwarf_Die sp_die;
int found; int found;
}; };
......
...@@ -1196,6 +1196,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, ...@@ -1196,6 +1196,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
if (curr_dso == NULL) if (curr_dso == NULL)
goto out_elf_end; goto out_elf_end;
curr_dso->kernel = self->kernel; curr_dso->kernel = self->kernel;
curr_dso->long_name = self->long_name;
curr_dso->long_name_len = self->long_name_len;
curr_map = map__new2(start, curr_dso, curr_map = map__new2(start, curr_dso,
map->type); map->type);
if (curr_map == NULL) { if (curr_map == NULL) {
...@@ -1842,6 +1844,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map, ...@@ -1842,6 +1844,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map,
if (fd < 0) if (fd < 0)
return -1; return -1;
dso__set_long_name(self, (char *)vmlinux);
dso__set_loaded(self, map->type); dso__set_loaded(self, map->type);
err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0); err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
close(fd); close(fd);
......
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