Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
This commit is contained in:
commit
ae18cbfe9f
|
@ -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)
|
||||||
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 {
|
||||||
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 @@ try_again:
|
||||||
!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 @@ try_again:
|
||||||
&& 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 @@ try_again:
|
||||||
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 @@ try_again:
|
||||||
*/
|
*/
|
||||||
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, ...)
|
||||||
}
|
}
|
||||||
#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);
|
||||||
#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 @@ try_again:
|
||||||
* 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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
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)
|
||||||
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 {
|
||||||
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 {
|
||||||
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,
|
||||||
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,
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue