All of lore.kernel.org
 help / color / mirror / Atom feed
From: Miroslav Benes <mbenes@suse.cz>
To: Mark Brown <broonie@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>, Heiko Carstens <hca@linux.ibm.com>,
	Vasily Gorbik <gor@linux.ibm.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Borislav Petkov <bp@alien8.de>, "H. Peter Anvin" <hpa@zytor.com>,
	Christian Borntraeger <borntraeger@de.ibm.com>,
	Ingo Molnar <mingo@kernel.org>, Jiri Slaby <jirislaby@kernel.org>,
	x86@kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-s390@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 3/3] arm64: stacktrace: Convert to ARCH_STACKWALK
Date: Thu, 16 Jul 2020 13:56:13 +0200 (CEST)	[thread overview]
Message-ID: <alpine.LSU.2.21.2007161342290.3958@pobox.suse.cz> (raw)
In-Reply-To: <20200715202821.12220-4-broonie@kernel.org>

Hi,

On Wed, 15 Jul 2020, Mark Brown wrote:

> Historically architectures have had duplicated code in their stack trace
> implementations for filtering what gets traced. In order to avoid this
> duplication some generic code has been provided using a new interface
> arch_stack_walk(), enabled by selecting ARCH_STACKWALK in Kconfig, which
> factors all this out into the generic stack trace code. Convert arm64
> to use this common infrastructure.
> 
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
>  arch/arm64/Kconfig             |  1 +
>  arch/arm64/kernel/stacktrace.c | 79 ++++------------------------------
>  2 files changed, 9 insertions(+), 71 deletions(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 5d4f02b3dfe9..6ed4b6c6df95 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -29,6 +29,7 @@ config ARM64
>  	select ARCH_HAS_SETUP_DMA_OPS
>  	select ARCH_HAS_SET_DIRECT_MAP
>  	select ARCH_HAS_SET_MEMORY
> +	select ARCH_STACKWALK
>  	select ARCH_HAS_STRICT_KERNEL_RWX
>  	select ARCH_HAS_STRICT_MODULE_RWX
>  	select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
> index 743cf11fbfca..a33fba048954 100644
> --- a/arch/arm64/kernel/stacktrace.c
> +++ b/arch/arm64/kernel/stacktrace.c
> @@ -133,82 +133,19 @@ void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
>  NOKPROBE_SYMBOL(walk_stackframe);
>  
>  #ifdef CONFIG_STACKTRACE
> -struct stack_trace_data {
> -	struct stack_trace *trace;
> -	unsigned int no_sched_functions;
> -	unsigned int skip;
> -};
>  
> -static bool save_trace(void *d, unsigned long addr)
> +void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
> +		     struct task_struct *task, struct pt_regs *regs)
>  {
> -	struct stack_trace_data *data = d;
> -	struct stack_trace *trace = data->trace;
> -
> -	if (data->no_sched_functions && in_sched_functions(addr))
> -		return false;
> -	if (data->skip) {
> -		data->skip--;
> -		return false;
> -	}
> -
> -	trace->entries[trace->nr_entries++] = addr;
> -
> -	return trace->nr_entries >= trace->max_entries;
> -}
> -
> -void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
> -{
> -	struct stack_trace_data data;
> -	struct stackframe frame;
> -
> -	data.trace = trace;
> -	data.skip = trace->skip;
> -	data.no_sched_functions = 0;
> -
> -	start_backtrace(&frame, regs->regs[29], regs->pc);
> -	walk_stackframe(current, &frame, save_trace, &data);
> -}
> -EXPORT_SYMBOL_GPL(save_stack_trace_regs);
> -
> -static noinline void __save_stack_trace(struct task_struct *tsk,
> -	struct stack_trace *trace, unsigned int nosched)
> -{
> -	struct stack_trace_data data;
>  	struct stackframe frame;
>  
> -	if (!try_get_task_stack(tsk))
> -		return;
> +	if (regs)
> +		start_backtrace(&frame, regs->regs[29], regs->pc);
> +	else
> +		start_backtrace(&frame, thread_saved_fp(task),
> +				thread_saved_pc(task));
>  
> -	data.trace = trace;
> -	data.skip = trace->skip;
> -	data.no_sched_functions = nosched;
> -
> -	if (tsk != current) {
> -		start_backtrace(&frame, thread_saved_fp(tsk),
> -				thread_saved_pc(tsk));
> -	} else {
> -		/* We don't want this function nor the caller */
> -		data.skip += 2;
> -		start_backtrace(&frame,
> -				(unsigned long)__builtin_frame_address(0),
> -				(unsigned long)__save_stack_trace);
> -	}
> -
> -	walk_stackframe(tsk, &frame, save_trace, &data);
> -
> -	put_task_stack(tsk);
> -}
> -
> -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
> -{
> -	__save_stack_trace(tsk, trace, 1);
> -}
> -EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
> -
> -void save_stack_trace(struct stack_trace *trace)
> -{
> -	__save_stack_trace(current, trace, 0);
> +	walk_stackframe(task, &frame, consume_entry, cookie);
>  }

just an idea for further improvement (and it might be a matter of taste). 
Wouldn't it be slightly better to do one more step and define "struct 
unwind_state" instead of "struct stackframe" and also some iterator for 
the unwinding and use that right in new arch_stack_walk() instead of 
walk_stackframe()? I mean, take the unbounded loop, "inline" it to 
arch_stack_walk() and replace the loop with the iterator. The body of the 
iterator would call to unwind_frame() and consume_entry() and that's it. 
It would make arm64 implementation very similar to x86 and s390 and thus 
easier to follow when one switches between architectures all the time.

Tangential to this patch, but another idea for improvement is in 
unwind_frame(). If I am not missing something, everything in 
CONFIG_FUNCTION_GRAPH_TRACER could be replaced by a simple call to 
ftrace_graph_ret_addr(). Again see for example unwind_next_frame() in
arch/s390/kernel/unwind_bc.c (x86 has it too).

Regards
Miroslav

WARNING: multiple messages have this Message-ID (diff)
From: Miroslav Benes <mbenes@suse.cz>
To: Mark Brown <broonie@kernel.org>
Cc: linux-s390@vger.kernel.org, Vasily Gorbik <gor@linux.ibm.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Heiko Carstens <hca@linux.ibm.com>,
	x86@kernel.org, linux-kernel@vger.kernel.org,
	Christian Borntraeger <borntraeger@de.ibm.com>,
	Borislav Petkov <bp@alien8.de>, "H. Peter Anvin" <hpa@zytor.com>,
	Jiri Slaby <jirislaby@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Will Deacon <will@kernel.org>, Ingo Molnar <mingo@kernel.org>,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 3/3] arm64: stacktrace: Convert to ARCH_STACKWALK
Date: Thu, 16 Jul 2020 13:56:13 +0200 (CEST)	[thread overview]
Message-ID: <alpine.LSU.2.21.2007161342290.3958@pobox.suse.cz> (raw)
In-Reply-To: <20200715202821.12220-4-broonie@kernel.org>

Hi,

On Wed, 15 Jul 2020, Mark Brown wrote:

> Historically architectures have had duplicated code in their stack trace
> implementations for filtering what gets traced. In order to avoid this
> duplication some generic code has been provided using a new interface
> arch_stack_walk(), enabled by selecting ARCH_STACKWALK in Kconfig, which
> factors all this out into the generic stack trace code. Convert arm64
> to use this common infrastructure.
> 
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
>  arch/arm64/Kconfig             |  1 +
>  arch/arm64/kernel/stacktrace.c | 79 ++++------------------------------
>  2 files changed, 9 insertions(+), 71 deletions(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 5d4f02b3dfe9..6ed4b6c6df95 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -29,6 +29,7 @@ config ARM64
>  	select ARCH_HAS_SETUP_DMA_OPS
>  	select ARCH_HAS_SET_DIRECT_MAP
>  	select ARCH_HAS_SET_MEMORY
> +	select ARCH_STACKWALK
>  	select ARCH_HAS_STRICT_KERNEL_RWX
>  	select ARCH_HAS_STRICT_MODULE_RWX
>  	select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
> index 743cf11fbfca..a33fba048954 100644
> --- a/arch/arm64/kernel/stacktrace.c
> +++ b/arch/arm64/kernel/stacktrace.c
> @@ -133,82 +133,19 @@ void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame,
>  NOKPROBE_SYMBOL(walk_stackframe);
>  
>  #ifdef CONFIG_STACKTRACE
> -struct stack_trace_data {
> -	struct stack_trace *trace;
> -	unsigned int no_sched_functions;
> -	unsigned int skip;
> -};
>  
> -static bool save_trace(void *d, unsigned long addr)
> +void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
> +		     struct task_struct *task, struct pt_regs *regs)
>  {
> -	struct stack_trace_data *data = d;
> -	struct stack_trace *trace = data->trace;
> -
> -	if (data->no_sched_functions && in_sched_functions(addr))
> -		return false;
> -	if (data->skip) {
> -		data->skip--;
> -		return false;
> -	}
> -
> -	trace->entries[trace->nr_entries++] = addr;
> -
> -	return trace->nr_entries >= trace->max_entries;
> -}
> -
> -void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
> -{
> -	struct stack_trace_data data;
> -	struct stackframe frame;
> -
> -	data.trace = trace;
> -	data.skip = trace->skip;
> -	data.no_sched_functions = 0;
> -
> -	start_backtrace(&frame, regs->regs[29], regs->pc);
> -	walk_stackframe(current, &frame, save_trace, &data);
> -}
> -EXPORT_SYMBOL_GPL(save_stack_trace_regs);
> -
> -static noinline void __save_stack_trace(struct task_struct *tsk,
> -	struct stack_trace *trace, unsigned int nosched)
> -{
> -	struct stack_trace_data data;
>  	struct stackframe frame;
>  
> -	if (!try_get_task_stack(tsk))
> -		return;
> +	if (regs)
> +		start_backtrace(&frame, regs->regs[29], regs->pc);
> +	else
> +		start_backtrace(&frame, thread_saved_fp(task),
> +				thread_saved_pc(task));
>  
> -	data.trace = trace;
> -	data.skip = trace->skip;
> -	data.no_sched_functions = nosched;
> -
> -	if (tsk != current) {
> -		start_backtrace(&frame, thread_saved_fp(tsk),
> -				thread_saved_pc(tsk));
> -	} else {
> -		/* We don't want this function nor the caller */
> -		data.skip += 2;
> -		start_backtrace(&frame,
> -				(unsigned long)__builtin_frame_address(0),
> -				(unsigned long)__save_stack_trace);
> -	}
> -
> -	walk_stackframe(tsk, &frame, save_trace, &data);
> -
> -	put_task_stack(tsk);
> -}
> -
> -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
> -{
> -	__save_stack_trace(tsk, trace, 1);
> -}
> -EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
> -
> -void save_stack_trace(struct stack_trace *trace)
> -{
> -	__save_stack_trace(current, trace, 0);
> +	walk_stackframe(task, &frame, consume_entry, cookie);
>  }

just an idea for further improvement (and it might be a matter of taste). 
Wouldn't it be slightly better to do one more step and define "struct 
unwind_state" instead of "struct stackframe" and also some iterator for 
the unwinding and use that right in new arch_stack_walk() instead of 
walk_stackframe()? I mean, take the unbounded loop, "inline" it to 
arch_stack_walk() and replace the loop with the iterator. The body of the 
iterator would call to unwind_frame() and consume_entry() and that's it. 
It would make arm64 implementation very similar to x86 and s390 and thus 
easier to follow when one switches between architectures all the time.

Tangential to this patch, but another idea for improvement is in 
unwind_frame(). If I am not missing something, everything in 
CONFIG_FUNCTION_GRAPH_TRACER could be replaced by a simple call to 
ftrace_graph_ret_addr(). Again see for example unwind_next_frame() in
arch/s390/kernel/unwind_bc.c (x86 has it too).

Regards
Miroslav

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

  reply	other threads:[~2020-07-16 11:57 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-15 20:28 [PATCH 0/3] arm64: Convert to ARCH_STACKWALK Mark Brown
2020-07-15 20:28 ` Mark Brown
2020-07-15 20:28 ` [PATCH 1/3] stacktrace: Remove reliable argument from arch_stack_walk() callback Mark Brown
2020-07-15 20:28   ` Mark Brown
2020-07-17  9:04   ` Miroslav Benes
2020-07-17  9:04     ` Miroslav Benes
2020-07-15 20:28 ` [PATCH 2/3] arm64: stacktrace: Make stack walk callback consistent with generic code Mark Brown
2020-07-15 20:28   ` Mark Brown
2020-07-15 20:28 ` [PATCH 3/3] arm64: stacktrace: Convert to ARCH_STACKWALK Mark Brown
2020-07-15 20:28   ` Mark Brown
2020-07-16 11:56   ` Miroslav Benes [this message]
2020-07-16 11:56     ` Miroslav Benes
2020-07-16 16:20     ` Mark Brown
2020-07-16 16:20       ` Mark Brown
2020-07-17  9:06       ` Miroslav Benes
2020-07-17  9:06         ` Miroslav Benes

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=alpine.LSU.2.21.2007161342290.3958@pobox.suse.cz \
    --to=mbenes@suse.cz \
    --cc=borntraeger@de.ibm.com \
    --cc=bp@alien8.de \
    --cc=broonie@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=gor@linux.ibm.com \
    --cc=hca@linux.ibm.com \
    --cc=hpa@zytor.com \
    --cc=jirislaby@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /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.