mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 13:51:44 +00:00
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->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;
|
||||
@ -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;
|
||||
|
@ -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[];
|
||||
|
@ -275,11 +275,10 @@ try_again:
|
||||
!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) {
|
||||
@ -302,11 +301,19 @@ try_again:
|
||||
&& 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));
|
||||
|
@ -850,10 +850,10 @@ try_again:
|
||||
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
|
||||
@ -861,25 +861,41 @@ try_again:
|
||||
*/
|
||||
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)
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -710,7 +710,7 @@ try_again:
|
||||
* 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;
|
||||
|
@ -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)
|
||||
{
|
||||
@ -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 */
|
||||
@ -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);
|
||||
@ -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)
|
||||
@ -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);
|
||||
|
@ -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 */
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user