All of lore.kernel.org
 help / color / mirror / Atom feed
From: Leo Yan <leo.yan@linaro.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>,
	Mathieu Poirier <mathieu.poirier@linaro.org>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Mark Rutland <mark.rutland@arm.com>,
	Mike Leach <mike.leach@linaro.org>,
	Robert Walker <robert.walker@arm.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@redhat.com>, Namhyung Kim <namhyung@kernel.org>,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org,
	Coresight ML <coresight@lists.linaro.org>
Cc: Leo Yan <leo.yan@linaro.org>
Subject: [PATCH v5 9/9] perf cs-etm: Fixup exception exit for thread stack
Date: Thu, 20 Feb 2020 13:27:01 +0800	[thread overview]
Message-ID: <20200220052701.7754-10-leo.yan@linaro.org> (raw)
In-Reply-To: <20200220052701.7754-1-leo.yan@linaro.org>

For instruction emulation or other cases (like ptrace), the program will
be trapped into kernel and the kernel executes the instruction with
single step, so the exception return address will be one instruction
ahead than the recorded address 'ret_addr' in the thread stack.
Finally, it's impossible to pop up the thread stack due to the mismatch
between the return address and 'ret_addr'.

To fix this issue, this patch reads out the 'ret_addr' from the top of
thread stack, and if detects the exception return address is one
instruction ahead than 'ret_addr', it implies the kernel has executed
single step.  For this case, calibrate 'to_ip' to 'ret_addr' so can
allow the thread stack to pop up.

Before:

  main  3258        100      instructions:
          ffff800010095f48 do_emulate_mrs+0x48 ([kernel.kallsyms])
          ffff800010096060 emulate_mrs+0x48 ([kernel.kallsyms])
          ffff8000100904ec do_undefinstr+0x1f4 ([kernel.kallsyms])
          ffff80001008788c el0_sync_handler+0x124 ([kernel.kallsyms])
          ffff800010082d00 el0_sync+0x140 ([kernel.kallsyms])
              ffffad8137d8 _dl_sysdep_start+0x2f8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

  main  3258        100      instructions:
          ffff8000100835fc finish_ret_to_user+0xbc ([kernel.kallsyms])
              ffffad8137d8 _dl_sysdep_start+0x2f8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

  main  3258        100      instructions:
              ffffad801138 dl_main+0x70 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad81384c _dl_sysdep_start+0x36c (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad8137d8 _dl_sysdep_start+0x2f8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

Note: after return back from instruction emulation with emulate_mrs(),
_dl_sysdep_start+0x2f8 cannot be popped up.

After:

  main  3258        100      instructions:
          ffff800010095f48 do_emulate_mrs+0x48 ([kernel.kallsyms])
          ffff800010096060 emulate_mrs+0x48 ([kernel.kallsyms])
          ffff8000100904ec do_undefinstr+0x1f4 ([kernel.kallsyms])
          ffff80001008788c el0_sync_handler+0x124 ([kernel.kallsyms])
          ffff800010082d00 el0_sync+0x140 ([kernel.kallsyms])
              ffffad8137d8 _dl_sysdep_start+0x2f8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

  main  3258        100      instructions:
          ffff8000100835fc finish_ret_to_user+0xbc ([kernel.kallsyms])
              ffffad8137d8 _dl_sysdep_start+0x2f8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

  main  3258        100      instructions:
              ffffad801138 dl_main+0x70 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad81384c _dl_sysdep_start+0x36c (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/util/cs-etm.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 4800daf0dc3d..7ff55704de5c 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -1190,6 +1190,34 @@ static void cs_etm__add_stack_event(struct cs_etm_queue *etmq,
 		    tidq->prev_packet->end_addr)
 			insn_len = 0;
 
+		/*
+		 * Fixup the exception exit.
+		 *
+		 * For instruction emulation or single step cases, when return
+		 * from exception, since an extra instruction has been executed
+		 * in kernel, the exception return address 'top_ip' is an
+		 * instruction ahead than the expected address 'ret_addr' in
+		 * thread stack.
+		 *
+		 * When detects this case, calibrate 'to_ip' to 'ret_addr' so
+		 * can pop up thread stack.
+		 */
+		flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN |
+			PERF_IP_FLAG_INTERRUPT;
+		if (tidq->prev_packet->flags == flags) {
+			u64 ret_addr;
+			int ret_insn_len;
+
+			ret_addr = thread_stack__get_top_ret_addr(tidq->thread,
+						tidq->prev_packet->cpu);
+			ret_insn_len = cs_etm__instr_size(etmq,
+							  trace_chan_id,
+							  tidq->packet->isa,
+							  ret_addr);
+			if (to_ip == ret_addr + ret_insn_len)
+				to_ip = ret_addr;
+		}
+
 		/*
 		 * Create thread stacks by keeping track of calls and returns;
 		 * any call pushes thread stack, return pops the stack, and
-- 
2.17.1


WARNING: multiple messages have this Message-ID (diff)
From: Leo Yan <leo.yan@linaro.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>,
	Mathieu Poirier <mathieu.poirier@linaro.org>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Mark Rutland <mark.rutland@arm.com>,
	Mike Leach <mike.leach@linaro.org>,
	Robert Walker <robert.walker@arm.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@redhat.com>, Namhyung Kim <namhyung@kernel.org>,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org,
	Coresight ML <coresight@lists.linaro.org>
Cc: Leo Yan <leo.yan@linaro.org>
Subject: [PATCH v5 9/9] perf cs-etm: Fixup exception exit for thread stack
Date: Thu, 20 Feb 2020 13:27:01 +0800	[thread overview]
Message-ID: <20200220052701.7754-10-leo.yan@linaro.org> (raw)
In-Reply-To: <20200220052701.7754-1-leo.yan@linaro.org>

For instruction emulation or other cases (like ptrace), the program will
be trapped into kernel and the kernel executes the instruction with
single step, so the exception return address will be one instruction
ahead than the recorded address 'ret_addr' in the thread stack.
Finally, it's impossible to pop up the thread stack due to the mismatch
between the return address and 'ret_addr'.

To fix this issue, this patch reads out the 'ret_addr' from the top of
thread stack, and if detects the exception return address is one
instruction ahead than 'ret_addr', it implies the kernel has executed
single step.  For this case, calibrate 'to_ip' to 'ret_addr' so can
allow the thread stack to pop up.

Before:

  main  3258        100      instructions:
          ffff800010095f48 do_emulate_mrs+0x48 ([kernel.kallsyms])
          ffff800010096060 emulate_mrs+0x48 ([kernel.kallsyms])
          ffff8000100904ec do_undefinstr+0x1f4 ([kernel.kallsyms])
          ffff80001008788c el0_sync_handler+0x124 ([kernel.kallsyms])
          ffff800010082d00 el0_sync+0x140 ([kernel.kallsyms])
              ffffad8137d8 _dl_sysdep_start+0x2f8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

  main  3258        100      instructions:
          ffff8000100835fc finish_ret_to_user+0xbc ([kernel.kallsyms])
              ffffad8137d8 _dl_sysdep_start+0x2f8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

  main  3258        100      instructions:
              ffffad801138 dl_main+0x70 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad81384c _dl_sysdep_start+0x36c (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad8137d8 _dl_sysdep_start+0x2f8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

Note: after return back from instruction emulation with emulate_mrs(),
_dl_sysdep_start+0x2f8 cannot be popped up.

After:

  main  3258        100      instructions:
          ffff800010095f48 do_emulate_mrs+0x48 ([kernel.kallsyms])
          ffff800010096060 emulate_mrs+0x48 ([kernel.kallsyms])
          ffff8000100904ec do_undefinstr+0x1f4 ([kernel.kallsyms])
          ffff80001008788c el0_sync_handler+0x124 ([kernel.kallsyms])
          ffff800010082d00 el0_sync+0x140 ([kernel.kallsyms])
              ffffad8137d8 _dl_sysdep_start+0x2f8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

  main  3258        100      instructions:
          ffff8000100835fc finish_ret_to_user+0xbc ([kernel.kallsyms])
              ffffad8137d8 _dl_sysdep_start+0x2f8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

  main  3258        100      instructions:
              ffffad801138 dl_main+0x70 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad81384c _dl_sysdep_start+0x36c (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800884 _dl_start_final+0xac (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800b00 _dl_start+0x200 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)
              ffffad800048 _start+0x8 (/usr/lib/aarch64-linux-gnu/ld-2.28.so)

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/util/cs-etm.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 4800daf0dc3d..7ff55704de5c 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -1190,6 +1190,34 @@ static void cs_etm__add_stack_event(struct cs_etm_queue *etmq,
 		    tidq->prev_packet->end_addr)
 			insn_len = 0;
 
+		/*
+		 * Fixup the exception exit.
+		 *
+		 * For instruction emulation or single step cases, when return
+		 * from exception, since an extra instruction has been executed
+		 * in kernel, the exception return address 'top_ip' is an
+		 * instruction ahead than the expected address 'ret_addr' in
+		 * thread stack.
+		 *
+		 * When detects this case, calibrate 'to_ip' to 'ret_addr' so
+		 * can pop up thread stack.
+		 */
+		flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN |
+			PERF_IP_FLAG_INTERRUPT;
+		if (tidq->prev_packet->flags == flags) {
+			u64 ret_addr;
+			int ret_insn_len;
+
+			ret_addr = thread_stack__get_top_ret_addr(tidq->thread,
+						tidq->prev_packet->cpu);
+			ret_insn_len = cs_etm__instr_size(etmq,
+							  trace_chan_id,
+							  tidq->packet->isa,
+							  ret_addr);
+			if (to_ip == ret_addr + ret_insn_len)
+				to_ip = ret_addr;
+		}
+
 		/*
 		 * Create thread stacks by keeping track of calls and returns;
 		 * any call pushes thread stack, return pops the stack, and
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2020-02-20  5:29 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-20  5:26 [PATCH v5 0/9] perf cs-etm: Support thread stack and callchain Leo Yan
2020-02-20  5:26 ` Leo Yan
2020-02-20  5:26 ` [PATCH v5 1/9] perf cs-etm: Defer to assign exception sample flag Leo Yan
2020-02-20  5:26   ` Leo Yan
2020-02-20  5:26 ` [PATCH v5 2/9] perf cs-etm: Reflect branch prior to exception Leo Yan
2020-02-20  5:26   ` Leo Yan
2020-02-20  5:26 ` [PATCH v5 3/9] perf cs-etm: Refactor instruction size handling Leo Yan
2020-02-20  5:26   ` Leo Yan
2020-02-20  5:26 ` [PATCH v5 4/9] perf cs-etm: Support thread stack Leo Yan
2020-02-20  5:26   ` Leo Yan
2020-02-20  5:26 ` [PATCH v5 5/9] perf cs-etm: Support branch filter Leo Yan
2020-02-20  5:26   ` Leo Yan
2020-02-20  5:26 ` [PATCH v5 6/9] perf cs-etm: Support callchain for instruction sample Leo Yan
2020-02-20  5:26   ` Leo Yan
2020-02-20  5:26 ` [PATCH v5 7/9] perf cs-etm: Fixup exception entry for thread stack Leo Yan
2020-02-20  5:26   ` Leo Yan
2020-02-20  5:27 ` [PATCH v5 8/9] perf thread: Add helper to get top return address Leo Yan
2020-02-20  5:27   ` Leo Yan
2020-02-20  5:27 ` Leo Yan [this message]
2020-02-20  5:27   ` [PATCH v5 9/9] perf cs-etm: Fixup exception exit for thread stack Leo Yan
2020-11-05 22:50 ` [PATCH v5 0/9] perf cs-etm: Support thread stack and callchain Stephen Boyd
2020-11-05 22:50   ` Stephen Boyd
2020-11-06  2:09   ` Leo Yan
2020-11-06  2:09     ` Leo Yan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200220052701.7754-10-leo.yan@linaro.org \
    --to=leo.yan@linaro.org \
    --cc=acme@kernel.org \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=coresight@lists.linaro.org \
    --cc=jolsa@redhat.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mathieu.poirier@linaro.org \
    --cc=mike.leach@linaro.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=robert.walker@arm.com \
    --cc=suzuki.poulose@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.