Commit d14aef38 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull perf fixes from Ingo Molnar:
 "Tooling fixes and an Intel PMU driver fixlet"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf: Do not allow optimized switch for non-cloned events
  perf/x86/intel: ignore CondChgd bit to avoid false NMI handling
  perf symbols: Get kernel start address by symbol name
  perf tools: Fix segfault in cumulative.callchain report
parents 2da29447 1f9a7268
...@@ -1381,6 +1381,15 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) ...@@ -1381,6 +1381,15 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
intel_pmu_lbr_read(); intel_pmu_lbr_read();
/*
* CondChgd bit 63 doesn't mean any overflow status. Ignore
* and clear the bit.
*/
if (__test_and_clear_bit(63, (unsigned long *)&status)) {
if (!status)
goto done;
}
/* /*
* PEBS overflow sets bit 62 in the global status register * PEBS overflow sets bit 62 in the global status register
*/ */
......
...@@ -2320,7 +2320,7 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn, ...@@ -2320,7 +2320,7 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
next_parent = rcu_dereference(next_ctx->parent_ctx); next_parent = rcu_dereference(next_ctx->parent_ctx);
/* If neither context have a parent context; they cannot be clones. */ /* If neither context have a parent context; they cannot be clones. */
if (!parent && !next_parent) if (!parent || !next_parent)
goto unlock; goto unlock;
if (next_parent == ctx || next_ctx == parent || next_parent == parent) { if (next_parent == ctx || next_ctx == parent || next_parent == parent) {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "../util.h" #include "../util.h"
#include "../ui.h" #include "../ui.h"
#include "map.h" #include "map.h"
#include "annotate.h"
struct hist_browser { struct hist_browser {
struct ui_browser b; struct ui_browser b;
...@@ -1593,13 +1594,18 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, ...@@ -1593,13 +1594,18 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
bi->to.sym->name) > 0) bi->to.sym->name) > 0)
annotate_t = nr_options++; annotate_t = nr_options++;
} else { } else {
if (browser->selection != NULL && if (browser->selection != NULL &&
browser->selection->sym != NULL && browser->selection->sym != NULL &&
!browser->selection->map->dso->annotate_warned && !browser->selection->map->dso->annotate_warned) {
asprintf(&options[nr_options], "Annotate %s", struct annotation *notes;
browser->selection->sym->name) > 0)
annotate = nr_options++; notes = symbol__annotation(browser->selection->sym);
if (notes->src &&
asprintf(&options[nr_options], "Annotate %s",
browser->selection->sym->name) > 0)
annotate = nr_options++;
}
} }
if (thread != NULL && if (thread != NULL &&
...@@ -1656,6 +1662,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, ...@@ -1656,6 +1662,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (choice == annotate || choice == annotate_t || choice == annotate_f) { if (choice == annotate || choice == annotate_t || choice == annotate_f) {
struct hist_entry *he; struct hist_entry *he;
struct annotation *notes;
int err; int err;
do_annotate: do_annotate:
if (!objdump_path && perf_session_env__lookup_objdump(env)) if (!objdump_path && perf_session_env__lookup_objdump(env))
...@@ -1679,6 +1686,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, ...@@ -1679,6 +1686,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
he->ms.map = he->branch_info->to.map; he->ms.map = he->branch_info->to.map;
} }
notes = symbol__annotation(he->ms.sym);
if (!notes->src)
continue;
/* /*
* Don't let this be freed, say, by hists__decay_entry. * Don't let this be freed, say, by hists__decay_entry.
*/ */
......
...@@ -496,18 +496,6 @@ struct process_args { ...@@ -496,18 +496,6 @@ struct process_args {
u64 start; u64 start;
}; };
static int symbol__in_kernel(void *arg, const char *name,
char type __maybe_unused, u64 start)
{
struct process_args *args = arg;
if (strchr(name, '['))
return 0;
args->start = start;
return 1;
}
static void machine__get_kallsyms_filename(struct machine *machine, char *buf, static void machine__get_kallsyms_filename(struct machine *machine, char *buf,
size_t bufsz) size_t bufsz)
{ {
...@@ -517,27 +505,41 @@ static void machine__get_kallsyms_filename(struct machine *machine, char *buf, ...@@ -517,27 +505,41 @@ static void machine__get_kallsyms_filename(struct machine *machine, char *buf,
scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir); scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir);
} }
/* Figure out the start address of kernel map from /proc/kallsyms */ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
static u64 machine__get_kernel_start_addr(struct machine *machine)
/* Figure out the start address of kernel map from /proc/kallsyms.
* Returns the name of the start symbol in *symbol_name. Pass in NULL as
* symbol_name if it's not that important.
*/
static u64 machine__get_kernel_start_addr(struct machine *machine,
const char **symbol_name)
{ {
char filename[PATH_MAX]; char filename[PATH_MAX];
struct process_args args; int i;
const char *name;
u64 addr = 0;
machine__get_kallsyms_filename(machine, filename, PATH_MAX); machine__get_kallsyms_filename(machine, filename, PATH_MAX);
if (symbol__restricted_filename(filename, "/proc/kallsyms")) if (symbol__restricted_filename(filename, "/proc/kallsyms"))
return 0; return 0;
if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0) for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
return 0; addr = kallsyms__get_function_start(filename, name);
if (addr)
break;
}
if (symbol_name)
*symbol_name = name;
return args.start; return addr;
} }
int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
{ {
enum map_type type; enum map_type type;
u64 start = machine__get_kernel_start_addr(machine); u64 start = machine__get_kernel_start_addr(machine, NULL);
for (type = 0; type < MAP__NR_TYPES; ++type) { for (type = 0; type < MAP__NR_TYPES; ++type) {
struct kmap *kmap; struct kmap *kmap;
...@@ -852,23 +854,11 @@ static int machine__create_modules(struct machine *machine) ...@@ -852,23 +854,11 @@ static int machine__create_modules(struct machine *machine)
return 0; return 0;
} }
const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
int machine__create_kernel_maps(struct machine *machine) int machine__create_kernel_maps(struct machine *machine)
{ {
struct dso *kernel = machine__get_kernel(machine); struct dso *kernel = machine__get_kernel(machine);
char filename[PATH_MAX];
const char *name; const char *name;
u64 addr = 0; u64 addr = machine__get_kernel_start_addr(machine, &name);
int i;
machine__get_kallsyms_filename(machine, filename, PATH_MAX);
for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
addr = kallsyms__get_function_start(filename, name);
if (addr)
break;
}
if (!addr) if (!addr)
return -1; return -1;
......
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