perf tools: Add hw_idx in struct branch_stack
The low level index of raw branch records for the most recent branch can be recorded in a sample with PERF_SAMPLE_BRANCH_HW_INDEX branch_sample_type. Extend struct branch_stack to support it. However, if the PERF_SAMPLE_BRANCH_HW_INDEX is not applied, only nr and entries[] will be output by kernel. The pointer of entries[] could be wrong, since the output format is different with new struct branch_stack. Add a variable no_hw_idx in struct perf_sample to indicate whether the hw_idx is output. Add get_branch_entry() to return corresponding pointer of entries[0]. To make dummy branch sample consistent as new branch sample, add hw_idx in struct dummy_branch_stack for cs-etm and intel-pt. Apply the new struct branch_stack for synthetic events as well. Extend test case sample-parsing to support new struct branch_stack. Committer notes: Renamed get_branch_entries() to perf_sample__branch_entries() to have proper namespacing and pave the way for this to be moved to libperf, eventually. Add 'static' to that inline as it is in a header. Add 'hw_idx' to 'struct dummy_branch_stack' in cs-etm.c to fix the build on arm64. Signed-off-by: Kan Liang <kan.liang@linux.intel.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexey Budankov <alexey.budankov@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Pavel Gerasimov <pavel.gerasimov@intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@linux.ibm.com> Cc: Stephane Eranian <eranian@google.com> Cc: Vitaly Slobodskoy <vitaly.slobodskoy@intel.com> Link: http://lore.kernel.org/lkml/20200228163011.19358-2-kan.liang@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:

committed by
Arnaldo Carvalho de Melo

parent
6339998d22
commit
42bbabed09
@@ -2081,15 +2081,16 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
|
||||
{
|
||||
unsigned int i;
|
||||
const struct branch_stack *bs = sample->branch_stack;
|
||||
struct branch_entry *entries = perf_sample__branch_entries(sample);
|
||||
struct branch_info *bi = calloc(bs->nr, sizeof(struct branch_info));
|
||||
|
||||
if (!bi)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < bs->nr; i++) {
|
||||
ip__resolve_ams(al->thread, &bi[i].to, bs->entries[i].to);
|
||||
ip__resolve_ams(al->thread, &bi[i].from, bs->entries[i].from);
|
||||
bi[i].flags = bs->entries[i].flags;
|
||||
ip__resolve_ams(al->thread, &bi[i].to, entries[i].to);
|
||||
ip__resolve_ams(al->thread, &bi[i].from, entries[i].from);
|
||||
bi[i].flags = entries[i].flags;
|
||||
}
|
||||
return bi;
|
||||
}
|
||||
@@ -2185,6 +2186,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
|
||||
/* LBR only affects the user callchain */
|
||||
if (i != chain_nr) {
|
||||
struct branch_stack *lbr_stack = sample->branch_stack;
|
||||
struct branch_entry *entries = perf_sample__branch_entries(sample);
|
||||
int lbr_nr = lbr_stack->nr, j, k;
|
||||
bool branch;
|
||||
struct branch_flags *flags;
|
||||
@@ -2210,31 +2212,29 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
|
||||
ip = chain->ips[j];
|
||||
else if (j > i + 1) {
|
||||
k = j - i - 2;
|
||||
ip = lbr_stack->entries[k].from;
|
||||
ip = entries[k].from;
|
||||
branch = true;
|
||||
flags = &lbr_stack->entries[k].flags;
|
||||
flags = &entries[k].flags;
|
||||
} else {
|
||||
ip = lbr_stack->entries[0].to;
|
||||
ip = entries[0].to;
|
||||
branch = true;
|
||||
flags = &lbr_stack->entries[0].flags;
|
||||
branch_from =
|
||||
lbr_stack->entries[0].from;
|
||||
flags = &entries[0].flags;
|
||||
branch_from = entries[0].from;
|
||||
}
|
||||
} else {
|
||||
if (j < lbr_nr) {
|
||||
k = lbr_nr - j - 1;
|
||||
ip = lbr_stack->entries[k].from;
|
||||
ip = entries[k].from;
|
||||
branch = true;
|
||||
flags = &lbr_stack->entries[k].flags;
|
||||
flags = &entries[k].flags;
|
||||
}
|
||||
else if (j > lbr_nr)
|
||||
ip = chain->ips[i + 1 - (j - lbr_nr)];
|
||||
else {
|
||||
ip = lbr_stack->entries[0].to;
|
||||
ip = entries[0].to;
|
||||
branch = true;
|
||||
flags = &lbr_stack->entries[0].flags;
|
||||
branch_from =
|
||||
lbr_stack->entries[0].from;
|
||||
flags = &entries[0].flags;
|
||||
branch_from = entries[0].from;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2281,6 +2281,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
|
||||
int max_stack)
|
||||
{
|
||||
struct branch_stack *branch = sample->branch_stack;
|
||||
struct branch_entry *entries = perf_sample__branch_entries(sample);
|
||||
struct ip_callchain *chain = sample->callchain;
|
||||
int chain_nr = 0;
|
||||
u8 cpumode = PERF_RECORD_MISC_USER;
|
||||
@@ -2328,7 +2329,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (callchain_param.order == ORDER_CALLEE) {
|
||||
be[i] = branch->entries[i];
|
||||
be[i] = entries[i];
|
||||
|
||||
if (chain == NULL)
|
||||
continue;
|
||||
@@ -2347,7 +2348,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
|
||||
be[i].from >= chain->ips[first_call] - 8)
|
||||
first_call++;
|
||||
} else
|
||||
be[i] = branch->entries[branch->nr - i - 1];
|
||||
be[i] = entries[branch->nr - i - 1];
|
||||
}
|
||||
|
||||
memset(iter, 0, sizeof(struct iterations) * nr);
|
||||
|
Reference in New Issue
Block a user