Skip to content

Commit

Permalink
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/acme/linux-2.6 into perf/core
  • Loading branch information
Ingo Molnar committed Mar 30, 2011
2 parents 1d32188 + cd25f8b commit ae18cbf
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 21 deletions.
5 changes: 5 additions & 0 deletions arch/x86/oprofile/nmi_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -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->kernel ? ARCH_PERFMON_EVENTSEL_OS : 0;
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;
val |= event & 0xFF;
val |= (event & 0x0F00) << 24;
Expand Down Expand Up @@ -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, "kernel", &counter_config[i].kernel);
oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
oprofilefs_create_ulong(sb, dir, "extra", &counter_config[i].extra);
}

return 0;
Expand Down
1 change: 1 addition & 0 deletions arch/x86/oprofile/op_counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct op_counter_config {
unsigned long kernel;
unsigned long user;
unsigned long unit_mask;
unsigned long extra;
};

extern struct op_counter_config counter_config[];
Expand Down
19 changes: 13 additions & 6 deletions tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,10 @@ static void open_counters(struct perf_evlist *evlist)
!no_inherit) < 0) {
int err = errno;

if (err == EPERM || err == EACCES)
die("Permission error - are you root?\n"
"\t Consider tweaking"
" /proc/sys/kernel/perf_event_paranoid.\n");
else if (err == ENODEV && cpu_list) {
if (err == EPERM || err == EACCES) {
ui__warning_paranoid();
exit(EXIT_FAILURE);
} else if (err == ENODEV && cpu_list) {
die("No such device - did you specify"
" an out-of-range profile CPU?\n");
} else if (err == EINVAL && sample_id_all_avail) {
Expand All @@ -302,11 +301,19 @@ static void open_counters(struct perf_evlist *evlist)
&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {

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->config = PERF_COUNT_SW_CPU_CLOCK;
goto try_again;
}

if (err == ENOENT) {
ui__warning("The %s event is not supported.\n",
event_name(pos));
exit(EXIT_FAILURE);
}

printf("\n");
error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
err, strerror(err));
Expand Down
44 changes: 30 additions & 14 deletions tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -850,36 +850,52 @@ static void start_counters(struct perf_evlist *evlist)
top.evlist->threads, group, inherit) < 0) {
int err = errno;

if (err == EPERM || err == EACCES)
die("Permission error - are you root?\n"
"\t Consider tweaking"
" /proc/sys/kernel/perf_event_paranoid.\n");
if (err == EPERM || err == EACCES) {
ui__warning_paranoid();
goto out_err;
}
/*
* If it's cycles then fall back to hrtimer
* based cpu-clock-tick sw counter, which
* is always available even if no PMU support:
*/
if (attr->type == PERF_TYPE_HARDWARE &&
attr->config == PERF_COUNT_HW_CPU_CYCLES) {

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->config = PERF_COUNT_SW_CPU_CLOCK;
goto try_again;
}
printf("\n");
error("sys_perf_event_open() syscall returned with %d "
"(%s). /bin/dmesg may provide additional information.\n",
err, strerror(err));
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
exit(-1);

if (err == ENOENT) {
ui__warning("The %s event is not supported.\n",
event_name(counter));
goto out_err;
}

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)
die("failed to mmap with %d (%s)\n", errno, strerror(errno));
if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) {
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)
Expand Down
10 changes: 10 additions & 0 deletions tools/perf/util/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ void ui__warning(const char *format, ...)
}
#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)
{
unsigned char *raw_event = (void *)event;
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ int ui_helpline__show_help(const char *format, va_list ap);
#endif

void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
void ui__warning_paranoid(void);

#endif /* __PERF_DEBUG_H */
2 changes: 1 addition & 1 deletion tools/perf/util/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ void thread__find_addr_map(struct thread *self,
* in the whole kernel symbol list.
*/
if ((long long)al->addr < 0 &&
cpumode == PERF_RECORD_MISC_KERNEL &&
cpumode == PERF_RECORD_MISC_USER &&
machine && mg != &machine->kmaps) {
mg = &machine->kmaps;
goto try_again;
Expand Down
72 changes: 72 additions & 0 deletions tools/perf/util/probe-finder.c
Original file line number Diff line number Diff line change
Expand Up @@ -1435,6 +1435,38 @@ static int find_probe_point_by_func(struct probe_finder *pf)
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 */
static int find_probes(int fd, struct probe_finder *pf)
{
Expand All @@ -1461,6 +1493,27 @@ static int find_probes(int fd, struct probe_finder *pf)

off = 0;
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) */
while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
/* Get the DIE(Debugging Information Entry) of this CU */
Expand Down Expand Up @@ -1488,6 +1541,8 @@ static int find_probes(int fd, struct probe_finder *pf)
}
off = noff;
}

found:
line_list__free(&pf->lcache);
if (dwfl)
dwfl_end(dwfl);
Expand Down Expand Up @@ -1895,6 +1950,22 @@ int find_line_range(int fd, struct line_range *lr)
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) */
while (!lf.found && ret >= 0) {
if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
Expand Down Expand Up @@ -1923,6 +1994,7 @@ int find_line_range(int fd, struct line_range *lr)
off = noff;
}

found:
/* Store comp_dir */
if (lf.found) {
comp_dir = cu_get_comp_dir(&lf.cu_die);
Expand Down
2 changes: 2 additions & 0 deletions tools/perf/util/probe-finder.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ struct probe_finder {
Dwarf_Addr addr; /* Address */
const char *fname; /* Real file name */
Dwarf_Die cu_die; /* Current CU */
Dwarf_Die sp_die;
struct list_head lcache; /* Line cache for lazy match */

/* For variable searching */
Expand Down Expand Up @@ -83,6 +84,7 @@ struct line_finder {
int lno_s; /* Start line number */
int lno_e; /* End line number */
Dwarf_Die cu_die; /* Current CU */
Dwarf_Die sp_die;
int found;
};

Expand Down
3 changes: 3 additions & 0 deletions tools/perf/util/symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
if (curr_dso == NULL)
goto out_elf_end;
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,
map->type);
if (curr_map == NULL) {
Expand Down Expand Up @@ -1842,6 +1844,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map,
if (fd < 0)
return -1;

dso__set_long_name(self, (char *)vmlinux);
dso__set_loaded(self, map->type);
err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
close(fd);
Expand Down

0 comments on commit ae18cbf

Please sign in to comment.