Skip to content

Commit

Permalink
perf tools: Add mem access sampling core support
Browse files Browse the repository at this point in the history
This patch adds the sorting and histogram support
functions to enable profiling of memory accesses.

The following sorting orders are added:
 - symbol_daddr: data address symbol (or raw address)
 - dso_daddr: data address shared object
 - locked: access uses locked transaction
 - tlb : TLB access
 - mem : memory level of the access (L1, L2, L3, RAM, ...)
 - snoop: access snoop mode

Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1359040242-8269-12-git-send-email-eranian@google.com
[ committer note: changed to cope with fc5871e, the move of methods to
  machine.[ch], and the rename of dsrc to data_src, to match the change
  made in the PERF_SAMPLE_DSRC in a previous patch. ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Stephane Eranian authored and Arnaldo Carvalho de Melo committed Apr 1, 2013
1 parent 0548429 commit 98a3b32
Show file tree
Hide file tree
Showing 10 changed files with 525 additions and 10 deletions.
8 changes: 8 additions & 0 deletions tools/perf/util/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,21 @@ struct perf_sample {
u64 weight;
u32 cpu;
u32 raw_size;
u64 data_src;
void *raw_data;
struct ip_callchain *callchain;
struct branch_stack *branch_stack;
struct regs_dump user_regs;
struct stack_dump user_stack;
};

#define PERF_MEM_DATA_SRC_NONE \
(PERF_MEM_S(OP, NA) |\
PERF_MEM_S(LVL, NA) |\
PERF_MEM_S(SNOOP, NA) |\
PERF_MEM_S(LOCK, NA) |\
PERF_MEM_S(TLB, NA))

struct build_id_event {
struct perf_event_header header;
pid_t pid;
Expand Down
6 changes: 6 additions & 0 deletions tools/perf/util/evsel.c
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
array++;
}

data->data_src = PERF_MEM_DATA_SRC_NONE;
if (type & PERF_SAMPLE_DATA_SRC) {
data->data_src = *array;
array++;
}

return 0;
}

Expand Down
86 changes: 83 additions & 3 deletions tools/perf/util/hist.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,16 @@ static void hists__set_unres_dso_col_len(struct hists *hists, int dso)
void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
{
const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
int symlen;
u16 len;

if (h->ms.sym)
hists__new_col_len(hists, HISTC_SYMBOL, h->ms.sym->namelen + 4);
else
else {
symlen = unresolved_col_width + 4 + 2;
hists__new_col_len(hists, HISTC_SYMBOL, symlen);
hists__set_unres_dso_col_len(hists, HISTC_DSO);
}

len = thread__comm_len(h->thread);
if (hists__new_col_len(hists, HISTC_COMM, len))
Expand All @@ -87,7 +91,6 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen);

if (h->branch_info) {
int symlen;
/*
* +4 accounts for '[x] ' priv level info
* +2 account of 0x prefix on raw addresses
Expand Down Expand Up @@ -116,6 +119,42 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
hists__set_unres_dso_col_len(hists, HISTC_DSO_TO);
}
}

if (h->mem_info) {
/*
* +4 accounts for '[x] ' priv level info
* +2 account of 0x prefix on raw addresses
*/
if (h->mem_info->daddr.sym) {
symlen = (int)h->mem_info->daddr.sym->namelen + 4
+ unresolved_col_width + 2;
hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
symlen);
} else {
symlen = unresolved_col_width + 4 + 2;
hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
symlen);
}
if (h->mem_info->daddr.map) {
symlen = dso__name_len(h->mem_info->daddr.map->dso);
hists__new_col_len(hists, HISTC_MEM_DADDR_DSO,
symlen);
} else {
symlen = unresolved_col_width + 4 + 2;
hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
}
} else {
symlen = unresolved_col_width + 4 + 2;
hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
}

hists__new_col_len(hists, HISTC_MEM_LOCKED, 6);
hists__new_col_len(hists, HISTC_MEM_TLB, 22);
hists__new_col_len(hists, HISTC_MEM_SNOOP, 12);
hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3);
hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
}

void hists__output_recalc_col_len(struct hists *hists, int max_rows)
Expand Down Expand Up @@ -158,6 +197,7 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he,
static void he_stat__add_period(struct he_stat *he_stat, u64 period,
u64 weight)
{

he_stat->period += period;
he_stat->weight += weight;
he_stat->nr_events += 1;
Expand Down Expand Up @@ -243,7 +283,7 @@ void hists__decay_entries_threaded(struct hists *hists,
static struct hist_entry *hist_entry__new(struct hist_entry *template)
{
size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
struct hist_entry *he = malloc(sizeof(*he) + callchain_size);
struct hist_entry *he = zalloc(sizeof(*he) + callchain_size);

if (he != NULL) {
*he = *template;
Expand All @@ -258,6 +298,13 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
he->branch_info->to.map->referenced = true;
}

if (he->mem_info) {
if (he->mem_info->iaddr.map)
he->mem_info->iaddr.map->referenced = true;
if (he->mem_info->daddr.map)
he->mem_info->daddr.map->referenced = true;
}

if (symbol_conf.use_callchain)
callchain_init(he->callchain);

Expand Down Expand Up @@ -346,6 +393,36 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
return he;
}

struct hist_entry *__hists__add_mem_entry(struct hists *self,
struct addr_location *al,
struct symbol *sym_parent,
struct mem_info *mi,
u64 period,
u64 weight)
{
struct hist_entry entry = {
.thread = al->thread,
.ms = {
.map = al->map,
.sym = al->sym,
},
.stat = {
.period = period,
.weight = weight,
.nr_events = 1,
},
.cpu = al->cpu,
.ip = al->addr,
.level = al->level,
.parent = sym_parent,
.filtered = symbol__parent_filter(sym_parent),
.hists = self,
.mem_info = mi,
.branch_info = NULL,
};
return add_hist_entry(self, &entry, al, period, weight);
}

struct hist_entry *__hists__add_branch_entry(struct hists *self,
struct addr_location *al,
struct symbol *sym_parent,
Expand All @@ -371,6 +448,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
.filtered = symbol__parent_filter(sym_parent),
.branch_info = bi,
.hists = self,
.mem_info = NULL,
};

return add_hist_entry(self, &entry, al, period, weight);
Expand Down Expand Up @@ -398,6 +476,8 @@ struct hist_entry *__hists__add_entry(struct hists *self,
.parent = sym_parent,
.filtered = symbol__parent_filter(sym_parent),
.hists = self,
.branch_info = NULL,
.mem_info = NULL,
};

return add_hist_entry(self, &entry, al, period, weight);
Expand Down
13 changes: 13 additions & 0 deletions tools/perf/util/hist.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ enum hist_column {
HISTC_SRCLINE,
HISTC_LOCAL_WEIGHT,
HISTC_GLOBAL_WEIGHT,
HISTC_MEM_DADDR_SYMBOL,
HISTC_MEM_DADDR_DSO,
HISTC_MEM_LOCKED,
HISTC_MEM_TLB,
HISTC_MEM_LVL,
HISTC_MEM_SNOOP,
HISTC_NR_COLS, /* Last entry */
};

Expand Down Expand Up @@ -90,6 +96,13 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
u64 period,
u64 weight);

struct hist_entry *__hists__add_mem_entry(struct hists *self,
struct addr_location *al,
struct symbol *sym_parent,
struct mem_info *mi,
u64 period,
u64 weight);

void hists__output_resort(struct hists *self);
void hists__output_resort_threaded(struct hists *hists);
void hists__collapse_resort(struct hists *self);
Expand Down
32 changes: 32 additions & 0 deletions tools/perf/util/machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,38 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
ams->map = al.map;
}

static void ip__resolve_data(struct machine *machine, struct thread *thread,
u8 m, struct addr_map_symbol *ams, u64 addr)
{
struct addr_location al;

memset(&al, 0, sizeof(al));

thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, &al,
NULL);
ams->addr = addr;
ams->al_addr = al.addr;
ams->sym = al.sym;
ams->map = al.map;
}

struct mem_info *machine__resolve_mem(struct machine *machine,
struct thread *thr,
struct perf_sample *sample,
u8 cpumode)
{
struct mem_info *mi = zalloc(sizeof(*mi));

if (!mi)
return NULL;

ip__resolve_ams(machine, thr, &mi->iaddr, sample->ip);
ip__resolve_data(machine, thr, cpumode, &mi->daddr, sample->addr);
mi->data_src.val = sample->data_src;

return mi;
}

struct branch_info *machine__resolve_bstack(struct machine *machine,
struct thread *thr,
struct branch_stack *bs)
Expand Down
3 changes: 3 additions & 0 deletions tools/perf/util/machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ void machine__delete(struct machine *machine);
struct branch_info *machine__resolve_bstack(struct machine *machine,
struct thread *thread,
struct branch_stack *bs);
struct mem_info *machine__resolve_mem(struct machine *machine,
struct thread *thread,
struct perf_sample *sample, u8 cpumode);
int machine__resolve_callchain(struct machine *machine,
struct perf_evsel *evsel,
struct thread *thread,
Expand Down
3 changes: 3 additions & 0 deletions tools/perf/util/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,

if (sample_type & PERF_SAMPLE_WEIGHT)
printf("... weight: %" PRIu64 "\n", sample->weight);

if (sample_type & PERF_SAMPLE_DATA_SRC)
printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
}

static struct machine *
Expand Down
Loading

0 comments on commit 98a3b32

Please sign in to comment.