aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorLeo Yan <leo.yan@linaro.org>2018-10-30 03:18:28 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2018-10-31 08:57:50 -0400
commitd6c9c05fe1eb4b213b183d8a1e79416256dc833a (patch)
treee2ea7f1378aad8245525b082fa52fa74772f60b9 /tools/perf
parent1fe627da30331024f453faef04d500079b901107 (diff)
perf cs-etm: Correct CPU mode for samples
Since commit edeb0c90df35 ("perf tools: Stop fallbacking to kallsyms for vdso symbols lookup"), the kernel address cannot be properly parsed to kernel symbol with command 'perf script -k vmlinux'. The reason is CoreSight samples is always to set CPU mode as PERF_RECORD_MISC_USER, thus it fails to find corresponding map/dso in below flows: process_sample_event() `-> machine__resolve() `-> thread__find_map(thread, sample->cpumode, sample->ip, al); In this flow it needs to pass argument 'sample->cpumode' to tell what's the CPU mode, before it always passed PERF_RECORD_MISC_USER but without any failure until the commit edeb0c90df35 ("perf tools: Stop fallbacking to kallsyms for vdso symbols lookup") has been merged. The reason is even with the wrong CPU mode the function thread__find_map() firstly fails to find map but it will rollback to find kernel map for vdso symbols lookup. In the latest code it has removed the fallback code, thus if CPU mode is PERF_RECORD_MISC_USER then it cannot find map anymore with kernel address. This patch is to correct samples CPU mode setting, it creates a new helper function cs_etm__cpu_mode() to tell what's the CPU mode based on the address with the info from machine structure; this patch has a bit extension to check not only kernel and user mode, but also check for host/guest and hypervisor mode. Finally this patch uses the function in instruction and branch samples and also apply in cs_etm__mem_access() for a minor polishing. Signed-off-by: Leo Yan <leo.yan@linaro.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: David Miller <davem@davemloft.net> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Cc: stable@kernel.org # v4.19 Link: http://lkml.kernel.org/r/1540883908-17018-1-git-send-email-leo.yan@linaro.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/cs-etm.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 3b37d66dc533..73430b73570d 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -244,6 +244,27 @@ static void cs_etm__free(struct perf_session *session)
244 zfree(&aux); 244 zfree(&aux);
245} 245}
246 246
247static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
248{
249 struct machine *machine;
250
251 machine = etmq->etm->machine;
252
253 if (address >= etmq->etm->kernel_start) {
254 if (machine__is_host(machine))
255 return PERF_RECORD_MISC_KERNEL;
256 else
257 return PERF_RECORD_MISC_GUEST_KERNEL;
258 } else {
259 if (machine__is_host(machine))
260 return PERF_RECORD_MISC_USER;
261 else if (perf_guest)
262 return PERF_RECORD_MISC_GUEST_USER;
263 else
264 return PERF_RECORD_MISC_HYPERVISOR;
265 }
266}
267
247static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address, 268static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
248 size_t size, u8 *buffer) 269 size_t size, u8 *buffer)
249{ 270{
@@ -258,10 +279,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
258 return -1; 279 return -1;
259 280
260 machine = etmq->etm->machine; 281 machine = etmq->etm->machine;
261 if (address >= etmq->etm->kernel_start) 282 cpumode = cs_etm__cpu_mode(etmq, address);
262 cpumode = PERF_RECORD_MISC_KERNEL;
263 else
264 cpumode = PERF_RECORD_MISC_USER;
265 283
266 thread = etmq->thread; 284 thread = etmq->thread;
267 if (!thread) { 285 if (!thread) {
@@ -653,7 +671,7 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
653 struct perf_sample sample = {.ip = 0,}; 671 struct perf_sample sample = {.ip = 0,};
654 672
655 event->sample.header.type = PERF_RECORD_SAMPLE; 673 event->sample.header.type = PERF_RECORD_SAMPLE;
656 event->sample.header.misc = PERF_RECORD_MISC_USER; 674 event->sample.header.misc = cs_etm__cpu_mode(etmq, addr);
657 event->sample.header.size = sizeof(struct perf_event_header); 675 event->sample.header.size = sizeof(struct perf_event_header);
658 676
659 sample.ip = addr; 677 sample.ip = addr;
@@ -665,7 +683,7 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
665 sample.cpu = etmq->packet->cpu; 683 sample.cpu = etmq->packet->cpu;
666 sample.flags = 0; 684 sample.flags = 0;
667 sample.insn_len = 1; 685 sample.insn_len = 1;
668 sample.cpumode = event->header.misc; 686 sample.cpumode = event->sample.header.misc;
669 687
670 if (etm->synth_opts.last_branch) { 688 if (etm->synth_opts.last_branch) {
671 cs_etm__copy_last_branch_rb(etmq); 689 cs_etm__copy_last_branch_rb(etmq);
@@ -706,12 +724,15 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
706 u64 nr; 724 u64 nr;
707 struct branch_entry entries; 725 struct branch_entry entries;
708 } dummy_bs; 726 } dummy_bs;
727 u64 ip;
728
729 ip = cs_etm__last_executed_instr(etmq->prev_packet);
709 730
710 event->sample.header.type = PERF_RECORD_SAMPLE; 731 event->sample.header.type = PERF_RECORD_SAMPLE;
711 event->sample.header.misc = PERF_RECORD_MISC_USER; 732 event->sample.header.misc = cs_etm__cpu_mode(etmq, ip);
712 event->sample.header.size = sizeof(struct perf_event_header); 733 event->sample.header.size = sizeof(struct perf_event_header);
713 734
714 sample.ip = cs_etm__last_executed_instr(etmq->prev_packet); 735 sample.ip = ip;
715 sample.pid = etmq->pid; 736 sample.pid = etmq->pid;
716 sample.tid = etmq->tid; 737 sample.tid = etmq->tid;
717 sample.addr = cs_etm__first_executed_instr(etmq->packet); 738 sample.addr = cs_etm__first_executed_instr(etmq->packet);
@@ -720,7 +741,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
720 sample.period = 1; 741 sample.period = 1;
721 sample.cpu = etmq->packet->cpu; 742 sample.cpu = etmq->packet->cpu;
722 sample.flags = 0; 743 sample.flags = 0;
723 sample.cpumode = PERF_RECORD_MISC_USER; 744 sample.cpumode = event->sample.header.misc;
724 745
725 /* 746 /*
726 * perf report cannot handle events without a branch stack 747 * perf report cannot handle events without a branch stack