All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jens Remus <jremus@linux.ibm.com>
To: Dylan Hatch <dylanbhatch@google.com>,
	Roman Gushchin <roman.gushchin@linux.dev>,
	Weinan Liu <wnliu@google.com>, Will Deacon <will@kernel.org>,
	Josh Poimboeuf <jpoimboe@kernel.org>,
	Indu Bhagat <indu.bhagat@oracle.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Jiri Kosina <jikos@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>,
	Prasanna Kumar T S M <ptsm@linux.microsoft.com>,
	Puranjay Mohan <puranjay@kernel.org>, Song Liu <song@kernel.org>,
	joe.lawrence@redhat.com, linux-toolchains@vger.kernel.org,
	linux-kernel@vger.kernel.org, live-patching@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	Heiko Carstens <hca@linux.ibm.com>
Subject: Re: [PATCH v3 8/8] unwind: arm64: Use sframe to unwind interrupt frames.
Date: Fri, 17 Apr 2026 17:45:10 +0200	[thread overview]
Message-ID: <95f9d11a-dd92-433e-a8db-cbebe94e1611@linux.ibm.com> (raw)
In-Reply-To: <20260406185000.1378082-9-dylanbhatch@google.com>

Hello Dylan and Weinan!

On 4/6/2026 8:50 PM, Dylan Hatch wrote:
> Add unwind_next_frame_sframe() function to unwind by sframe info if
> present. Use this method at exception boundaries, falling back to
> frame-pointer unwind only on failure. In such failure cases, the
> stacktrace is considered unreliable.
> 
> During normal unwind, prefer frame pointer unwind (for better
> performance) with sframe as a backup.
> 
> This change restores the LR behavior originally introduced in commit
> c2c6b27b5aa14fa2 ("arm64: stacktrace: unwind exception boundaries"),
> But later removed in commit 32ed1205682e ("arm64: stacktrace: Skip
> reporting LR at exception boundaries")
> 
> This can be done because the sframe data can be used to determine
> whether the LR is current for the PC value recovered from pt_regs at the
> exception boundary.
> 
> Signed-off-by: Weinan Liu <wnliu@google.com>
> Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
> Reviewed-by: Prasanna Kumar T S M <ptsm@linux.microsoft.com>

> diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c

> +/*
> + * Unwind to the next frame according to sframe.
> + */
> +static __always_inline int
> +unwind_next_frame_sframe(struct kunwind_state *state)
> +{
> +	struct unwind_frame frame;
> +	unsigned long cfa, fp, ra;
> +	enum kunwind_source source = KUNWIND_SOURCE_FRAME;
> +	struct pt_regs *regs = state->regs;
> +
> +	int err;
> +
> +	/* FP/SP alignment 8 bytes */
> +	if (state->common.fp & 0x7 || state->common.sp & 0x7)
> +		return -EINVAL;
> +
> +	/*
> +	 * Most/all outermost functions are not visible to sframe. So, check for
> +	 * a meta frame record if the sframe lookup fails.
> +	 */
> +	err = sframe_find_kernel(state->common.pc, &frame);
> +	if (err)
> +		return kunwind_next_frame_record_meta(state);
> +
> +	if (frame.outermost)
> +		return -ENOENT;
> +
> +	/* Get the Canonical Frame Address (CFA) */
> +	switch (frame.cfa.rule) {
> +	case UNWIND_CFA_RULE_SP_OFFSET:
> +		cfa = state->common.sp;
> +		break;
> +	case UNWIND_CFA_RULE_FP_OFFSET:
> +		if (state->common.fp < state->common.sp)
> +			return -EINVAL;

I wonder whether that check is valid in kernel?  Looking at
call_on_irq_stack() saving SP in FP and then loading SP with the IRQ SP.
Is that condition always true then?

> +		cfa = state->common.fp;
> +		break;
> +	case UNWIND_CFA_RULE_REG_OFFSET:
> +	case UNWIND_CFA_RULE_REG_OFFSET_DEREF:
> +		if (!regs)

		if (!regs || frame.cfa.regnum > 30)

> +			return -EINVAL;
> +		cfa = regs->regs[frame.cfa.regnum];

In unwind user this is guarded by a topmost frame check, as arbitrary
registers are otherwise not available.  Isn't this necessary in the
kernel case?

> +		break;
> +	default:
> +		WARN_ON_ONCE(1);
> +		return -EINVAL;
> +	}
> +	cfa += frame.cfa.offset;
> +
> +	/*
> +	 * CFA typically points to a higher address than RA or FP, so don't
> +	 * consume from the stack when we read it.
> +	 */
> +	if (frame.cfa.rule & UNWIND_RULE_DEREF &&
> +	    !get_word(&state->common, &cfa))
> +		return -EINVAL;
> +
> +	/* CFA alignment 8 bytes */
> +	if (cfa & 0x7)
> +		return -EINVAL;
> +
> +	/* Get the Return Address (RA) */
> +	switch (frame.ra.rule) {
> +	case UNWIND_RULE_RETAIN:
> +		if (!regs)
> +			return -EINVAL;
> +		ra = regs->regs[30];

Likewise: Topmost frame check not required to access arbitrary registers
(including RA/LR)?  Furthermore, provided don't have a thinko, LR may
only be in LR in the topmost frame.  In any other frame it must have
been saved.  Otherwise there would be an endless return loop.

> +		source = KUNWIND_SOURCE_REGS_LR;
> +		break;
> +	/* UNWIND_USER_RULE_CFA_OFFSET not implemented on purpose */
> +	case UNWIND_RULE_CFA_OFFSET_DEREF:
> +		ra = cfa + frame.ra.offset;
> +		break;
> +	case UNWIND_RULE_REG_OFFSET:
> +	case UNWIND_RULE_REG_OFFSET_DEREF:
> +		if (!regs)

		if (!regs || frame.cfa.regnum > 30)

> +			return -EINVAL;
> +		ra = regs->regs[frame.cfa.regnum];

Likewise: Topmost frame check not required to access arbitrary registers?

> +		ra += frame.ra.offset;
> +		break;
> +	default:
> +		WARN_ON_ONCE(1);
> +		return -EINVAL;
> +	}
> +
> +	/* Get the Frame Pointer (FP) */
> +	switch (frame.fp.rule) {
> +	case UNWIND_RULE_RETAIN:
> +		fp = state->common.fp;
> +		break;
> +	/* UNWIND_USER_RULE_CFA_OFFSET not implemented on purpose */
> +	case UNWIND_RULE_CFA_OFFSET_DEREF:
> +		fp = cfa + frame.fp.offset;
> +		break;
> +	case UNWIND_RULE_REG_OFFSET:
> +	case UNWIND_RULE_REG_OFFSET_DEREF:
> +		if (!regs)

		if (!regs || frame.cfa.regnum > 30)

> +			return -EINVAL;
> +		fp = regs->regs[frame.fp.regnum];

Likewise: Topmost frame check not required to access arbitrary registers?

> +		fp += frame.fp.offset;
> +		break;
> +	default:
> +		WARN_ON_ONCE(1);
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Consume RA and FP from the stack. The frame record puts FP at a lower
> +	 * address than RA, so we always read FP first.
> +	 */
> +	if (frame.fp.rule & UNWIND_RULE_DEREF &&
> +	    !get_word(&state->common, &fp))
> +		return -EINVAL;
> +
> +	if (frame.ra.rule & UNWIND_RULE_DEREF &&
> +	    get_consume_word(&state->common, &ra))
> +		return -EINVAL;
> +
> +	state->common.pc = ra;
> +	state->common.sp = cfa;
> +	state->common.fp = fp;
> +
> +	state->source = source;
> +
> +	return 0;
> +}
Thanks and regards,
Jens
-- 
Jens Remus
Linux on Z Development (D3303)
jremus@de.ibm.com / jremus@linux.ibm.com

IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Ehningen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/



  reply	other threads:[~2026-04-17 15:45 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-06 18:49 [PATCH v3 0/8] unwind, arm64: add sframe unwinder for kernel Dylan Hatch
2026-04-06 18:49 ` [PATCH v3 1/8] sframe: Allow kernelspace sframe sections Dylan Hatch
2026-04-14 12:09   ` Jens Remus
2026-04-06 18:49 ` [PATCH v3 2/8] arm64, unwind: build kernel with sframe V3 info Dylan Hatch
2026-04-06 21:36   ` Randy Dunlap
2026-04-14 12:43   ` Jens Remus
2026-04-18  0:20     ` Dylan Hatch
2026-04-20 12:16       ` Jens Remus
2026-04-20 12:44   ` Jens Remus
2026-04-06 18:49 ` [PATCH v3 3/8] arm64: entry: add unwind info for various kernel entries Dylan Hatch
2026-04-16 14:09   ` Jens Remus
2026-04-16 16:49   ` Jens Remus
2026-04-06 18:49 ` [PATCH v3 4/8] sframe: Provide PC lookup for vmlinux .sframe section Dylan Hatch
2026-04-16 15:10   ` Jens Remus
2026-04-06 18:49 ` [PATCH v3 5/8] sframe: Allow unsorted FDEs Dylan Hatch
2026-04-16 14:57   ` Jens Remus
2026-04-06 18:49 ` [PATCH v3 6/8] arm64/module, sframe: Add sframe support for modules Dylan Hatch
2026-04-17 14:07   ` Jens Remus
2026-04-20  9:54   ` Jens Remus
2026-04-06 18:49 ` [PATCH v3 7/8] sframe: Introduce in-kernel SFRAME_VALIDATION Dylan Hatch
2026-04-16 15:04   ` Jens Remus
2026-04-20  5:02     ` Dylan Hatch
2026-04-20 12:30       ` Jens Remus
2026-04-21  1:29         ` Dylan Hatch
2026-04-21  8:33           ` Jens Remus
2026-04-06 18:50 ` [PATCH v3 8/8] unwind: arm64: Use sframe to unwind interrupt frames Dylan Hatch
2026-04-17 15:45   ` Jens Remus [this message]
2026-04-20  5:56     ` Dylan Hatch
2026-04-20  8:42       ` Jens Remus
2026-04-14 16:10 ` [PATCH v3 0/8] unwind, arm64: add sframe unwinder for kernel Jens Remus

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=95f9d11a-dd92-433e-a8db-cbebe94e1611@linux.ibm.com \
    --to=jremus@linux.ibm.com \
    --cc=catalin.marinas@arm.com \
    --cc=dylanbhatch@google.com \
    --cc=hca@linux.ibm.com \
    --cc=indu.bhagat@oracle.com \
    --cc=jikos@kernel.org \
    --cc=joe.lawrence@redhat.com \
    --cc=jpoimboe@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-toolchains@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=peterz@infradead.org \
    --cc=ptsm@linux.microsoft.com \
    --cc=puranjay@kernel.org \
    --cc=roman.gushchin@linux.dev \
    --cc=rostedt@goodmis.org \
    --cc=song@kernel.org \
    --cc=will@kernel.org \
    --cc=wnliu@google.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.