summaryrefslogtreecommitdiff
path: root/tools/perf/util/annotate.c
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2015-10-02 11:15:13 -0700
committerStephen Boyd <sboyd@codeaurora.org>2015-10-02 11:22:23 -0700
commit9f30a04d768f64280dc0c40b730746e82f298d88 (patch)
treee112853eb73627ed7b9a2ef8e4feab6685a0200e /tools/perf/util/annotate.c
parent9e294bf88a583825a413df408b9fe9e658fb93ac (diff)
parent7aba4f5201d1b7b3ddb0b03883d9edf69851ddad (diff)
Merge branch 'for-4.3-rc/ti-clk-fixes' of https://github.com/t-kristo/linux-pm into clk-fixes
Pull fixes from Tero Kristo: "A few TI clock driver fixes to pull against 4.3-rc" * 'for-4.3-rc/ti-clk-fixes' of https://github.com/t-kristo/linux-pm: (3 commits) clk: ti: dflt: fix enable_reg validity check clk: ti: fix dual-registration of uart4_ick clk: ti: clk-7xx: Remove hardwired ABE clock configuration
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r--tools/perf/util/annotate.c128
1 files changed, 125 insertions, 3 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 03b7bc70eb660..d1eece70b84d6 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -473,17 +473,73 @@ int symbol__alloc_hist(struct symbol *sym)
return 0;
}
+/* The cycles histogram is lazily allocated. */
+static int symbol__alloc_hist_cycles(struct symbol *sym)
+{
+ struct annotation *notes = symbol__annotation(sym);
+ const size_t size = symbol__size(sym);
+
+ notes->src->cycles_hist = calloc(size, sizeof(struct cyc_hist));
+ if (notes->src->cycles_hist == NULL)
+ return -1;
+ return 0;
+}
+
void symbol__annotate_zero_histograms(struct symbol *sym)
{
struct annotation *notes = symbol__annotation(sym);
pthread_mutex_lock(&notes->lock);
- if (notes->src != NULL)
+ if (notes->src != NULL) {
memset(notes->src->histograms, 0,
notes->src->nr_histograms * notes->src->sizeof_sym_hist);
+ if (notes->src->cycles_hist)
+ memset(notes->src->cycles_hist, 0,
+ symbol__size(sym) * sizeof(struct cyc_hist));
+ }
pthread_mutex_unlock(&notes->lock);
}
+static int __symbol__account_cycles(struct annotation *notes,
+ u64 start,
+ unsigned offset, unsigned cycles,
+ unsigned have_start)
+{
+ struct cyc_hist *ch;
+
+ ch = notes->src->cycles_hist;
+ /*
+ * For now we can only account one basic block per
+ * final jump. But multiple could be overlapping.
+ * Always account the longest one. So when
+ * a shorter one has been already seen throw it away.
+ *
+ * We separately always account the full cycles.
+ */
+ ch[offset].num_aggr++;
+ ch[offset].cycles_aggr += cycles;
+
+ if (!have_start && ch[offset].have_start)
+ return 0;
+ if (ch[offset].num) {
+ if (have_start && (!ch[offset].have_start ||
+ ch[offset].start > start)) {
+ ch[offset].have_start = 0;
+ ch[offset].cycles = 0;
+ ch[offset].num = 0;
+ if (ch[offset].reset < 0xffff)
+ ch[offset].reset++;
+ } else if (have_start &&
+ ch[offset].start < start)
+ return 0;
+ }
+ ch[offset].have_start = have_start;
+ ch[offset].start = start;
+ ch[offset].cycles += cycles;
+ ch[offset].num++;
+ return 0;
+}
+
static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
struct annotation *notes, int evidx, u64 addr)
{
@@ -506,7 +562,7 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
return 0;
}
-static struct annotation *symbol__get_annotation(struct symbol *sym)
+static struct annotation *symbol__get_annotation(struct symbol *sym, bool cycles)
{
struct annotation *notes = symbol__annotation(sym);
@@ -514,6 +570,10 @@ static struct annotation *symbol__get_annotation(struct symbol *sym)
if (symbol__alloc_hist(sym) < 0)
return NULL;
}
+ if (!notes->src->cycles_hist && cycles) {
+ if (symbol__alloc_hist_cycles(sym) < 0)
+ return NULL;
+ }
return notes;
}
@@ -524,12 +584,73 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
if (sym == NULL)
return 0;
- notes = symbol__get_annotation(sym);
+ notes = symbol__get_annotation(sym, false);
if (notes == NULL)
return -ENOMEM;
return __symbol__inc_addr_samples(sym, map, notes, evidx, addr);
}
+static int symbol__account_cycles(u64 addr, u64 start,
+ struct symbol *sym, unsigned cycles)
+{
+ struct annotation *notes;
+ unsigned offset;
+
+ if (sym == NULL)
+ return 0;
+ notes = symbol__get_annotation(sym, true);
+ if (notes == NULL)
+ return -ENOMEM;
+ if (addr < sym->start || addr >= sym->end)
+ return -ERANGE;
+
+ if (start) {
+ if (start < sym->start || start >= sym->end)
+ return -ERANGE;
+ if (start >= addr)
+ start = 0;
+ }
+ offset = addr - sym->start;
+ return __symbol__account_cycles(notes,
+ start ? start - sym->start : 0,
+ offset, cycles,
+ !!start);
+}
+
+int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
+ struct addr_map_symbol *start,
+ unsigned cycles)
+{
+ u64 saddr = 0;
+ int err;
+
+ if (!cycles)
+ return 0;
+
+ /*
+ * Only set start when IPC can be computed. We can only
+ * compute it when the basic block is completely in a single
+ * function.
+ * Special case the case when the jump is elsewhere, but
+ * it starts on the function start.
+ */
+ if (start &&
+ (start->sym == ams->sym ||
+ (ams->sym &&
+ start->addr == ams->sym->start + ams->map->start)))
+ saddr = start->al_addr;
+ if (saddr == 0)
+ pr_debug2("BB with bad start: addr %"PRIx64" start %"PRIx64" sym %"PRIx64" saddr %"PRIx64"\n",
+ ams->addr,
+ start ? start->addr : 0,
+ ams->sym ? ams->sym->start + ams->map->start : 0,
+ saddr);
+ err = symbol__account_cycles(ams->al_addr, saddr, ams->sym, cycles);
+ if (err)
+ pr_debug2("account_cycles failed %d\n", err);
+ return err;
+}
+
int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx)
{
return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr);
@@ -1005,6 +1126,7 @@ fallback:
dso->annotate_warned = 1;
pr_err("Can't annotate %s:\n\n"
"No vmlinux file%s\nwas found in the path.\n\n"
+ "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
"Please use:\n\n"
" perf buildid-cache -vu vmlinux\n\n"
"or:\n\n"