From: Dylan Hatch <dylanbhatch@google.com>
To: Roman Gushchin <roman.gushchin@linux.dev>,
Weinan Liu <wnliu@google.com>, Will Deacon <will@kernel.org>,
Josh Poimboeuf <jpoimboe@kernel.org>,
Indu Bhagat <ibhagatgnu@gmail.com>,
Peter Zijlstra <peterz@infradead.org>,
Steven Rostedt <rostedt@goodmis.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Jiri Kosina <jikos@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Jens Remus <jremus@linux.ibm.com>
Cc: Dylan Hatch <dylanbhatch@google.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,
Randy Dunlap <rdunlap@infradead.org>,
Mostafa Saleh <smostafa@google.com>,
Herbert Xu <herbert@gondor.apana.org.au>,
"David S. Miller" <davem@davemloft.net>
Subject: [PATCH v7 04/11] sframe: Separate reading of FRE from reading of FRE data words
Date: Fri, 18 Sep 2026 22:41:50 +0000 [thread overview]
Message-ID: <20260918224157.1471085-5-dylanbhatch@google.com> (raw)
In-Reply-To: <20260918224157.1471085-1-dylanbhatch@google.com>
From: Jens Remus <jremus@linux.ibm.com>
__find_fre() performs linear search for a matching SFrame FRE for a
given IP. For that purpose it uses __read_fre(), which reads the whole
FRE. That is the variable-size FRE structure as well as the trailing
variable-length array of variable-size data words. For the search logic
to skip over the FRE it would be sufficient to read the variable-size
FRE structure only, which includes the count and size of data words.
Add fields to struct sframe_fre_internal to store the FRE data word's
address, count, and size. Change __read_fre() to read the variable-
size FRE structure only and populate those new fields. Change
__read_fre_datawords() to use those new fields. Change __find_fre()
to use __read_fre_datawords() to read the FRE data words only after a
matching FRE has been found.
[ Dylan Hatch: Adapt for in-kernel unwinding without flexible FDEs. ]
Reviewed-by: Indu Bhagat <ibhagatgnu@gmail.com>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
This patch is adapted from commit 745489faa10c ("unwind_user/sframe:
Separate reading of FRE from reading of FRE data words") and squashes
changes from:
- fdaf91d4fc0d ("unwind_user/sframe: Add support for SFrame V3
flexible FDEs")
- 79313210e44e ("unwind_user/sframe: Add support for outermost frame
indication")
all of which are from Steven's sframe/core branch.
Changes include:
- Drop support for flexible FDEs (SFRAME_FDE_TYPE_FLEX).
- Sqaush in creation of __read_default_fre_datawords() and
__read_fre_datawords().
- Squash in outermost frame handling logic.
- Deferred sframe_validate_section() changes to a later patch.
---
kernel/unwind/sframe.c | 97 +++++++++++++++++++++++++++++++-----------
1 file changed, 73 insertions(+), 24 deletions(-)
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index f3975c7e89493..9aac703f7ce6e 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -36,6 +36,9 @@ struct sframe_fre_internal {
s32 ra_off;
s32 fp_off;
u8 info;
+ unsigned long dw_addr;
+ unsigned char dw_count;
+ unsigned char dw_size;
};
static __always_inline unsigned char fre_type_to_size(unsigned char fre_type)
@@ -179,6 +182,67 @@ static __always_inline int __find_fde(struct sframe_section *sec,
s32 : GET_SIGNED_AND_INC(to, from, size), \
s64 : GET_SIGNED_AND_INC(to, from, size))
+static __always_inline int
+__read_default_fre_datawords(struct sframe_section *sec,
+ struct sframe_fde_internal *fde,
+ struct sframe_fre_internal *fre)
+{
+ unsigned char dataword_count = fre->dw_count;
+ unsigned char dataword_size = fre->dw_size;
+ unsigned long cur = fre->dw_addr;
+ s32 cfa_off, ra_off, fp_off;
+
+ GET_AND_INC(cfa_off, cur, dataword_size);
+ dataword_count--;
+
+ ra_off = sec->ra_off;
+ if (!ra_off && dataword_count) {
+ dataword_count--;
+ GET_AND_INC(ra_off, cur, dataword_size);
+ }
+
+ fp_off = sec->fp_off;
+ if (!fp_off && dataword_count) {
+ dataword_count--;
+ GET_AND_INC(fp_off, cur, dataword_size);
+ }
+
+ if (dataword_count)
+ return -EFAULT;
+
+ fre->cfa_off = cfa_off;
+ fre->ra_off = ra_off;
+ fre->fp_off = fp_off;
+
+ return 0;
+}
+
+static __always_inline int
+__read_fre_datawords(struct sframe_section *sec,
+ struct sframe_fde_internal *fde,
+ struct sframe_fre_internal *fre)
+{
+ unsigned char fde_type = SFRAME_V3_FDE_TYPE(fde->info2);
+ unsigned char dataword_count = fre->dw_count;
+
+ if (!dataword_count) {
+ /* A FRE without data words indicates an outermost frame. */
+ fre->cfa_off = 0;
+ fre->ra_off = 0;
+ fre->fp_off = 0;
+
+ return 0;
+ }
+
+ switch (fde_type) {
+ case SFRAME_FDE_TYPE_DEFAULT:
+ return __read_default_fre_datawords(sec, fde, fre);
+ /* Flexible FDEs not supported */
+ default:
+ return -EFAULT;
+ }
+}
+
static __always_inline int __read_fre(struct sframe_section *sec,
struct sframe_fde_internal *fde,
unsigned long fre_addr,
@@ -188,7 +252,6 @@ static __always_inline int __read_fre(struct sframe_section *sec,
unsigned char fde_pctype = SFRAME_V3_FDE_PCTYPE(fde->info);
unsigned char fre_type = SFRAME_V3_FDE_FRE_TYPE(fde->info);
unsigned char dataword_count, dataword_size;
- s32 cfa_off, ra_off, fp_off;
unsigned long cur = fre_addr;
unsigned char addr_size;
u32 ip_off;
@@ -208,7 +271,7 @@ static __always_inline int __read_fre(struct sframe_section *sec,
GET_AND_INC(info, cur, 1);
dataword_count = SFRAME_V3_FRE_DATAWORD_COUNT(info);
dataword_size = dataword_size_enum_to_size(SFRAME_V3_FRE_DATAWORD_SIZE(info));
- if (!dataword_size || !dataword_count)
+ if (!dataword_size)
return -EFAULT;
if (cur + (dataword_count * dataword_size) > sec->fres_end)
@@ -219,30 +282,11 @@ static __always_inline int __read_fre(struct sframe_section *sec,
return -EFAULT;
fre->size = addr_size + 1 + (dataword_count * dataword_size);
-
- GET_AND_INC(cfa_off, cur, dataword_size);
- dataword_count--;
-
- ra_off = sec->ra_off;
- if (!ra_off && dataword_count) {
- dataword_count--;
- GET_AND_INC(ra_off, cur, dataword_size);
- }
-
- fp_off = sec->fp_off;
- if (!fp_off && dataword_count) {
- dataword_count--;
- GET_AND_INC(fp_off, cur, dataword_size);
- }
-
- if (dataword_count)
- return -EFAULT;
-
fre->ip_off = ip_off;
- fre->cfa_off = cfa_off;
- fre->ra_off = ra_off;
- fre->fp_off = fp_off;
fre->info = info;
+ fre->dw_addr = cur;
+ fre->dw_count = dataword_count;
+ fre->dw_size = dataword_size;
return 0;
}
@@ -292,6 +336,7 @@ static __always_inline int __find_fre(struct sframe_section *sec,
bool which = false;
unsigned int i;
u32 ip_off;
+ int ret;
ip_off = ip - fde->func_addr;
@@ -332,6 +377,10 @@ static __always_inline int __find_fre(struct sframe_section *sec,
return -EINVAL;
fre = prev_fre;
+ ret = __read_fre_datawords(sec, fde, fre);
+ if (ret)
+ return ret;
+
if (sframe_init_cfa_rule_data(&frame->cfa, fre->info, fre->cfa_off))
return -EINVAL;
--
2.55.0.1082.g2b9226bbc0-goog
next prev parent reply other threads:[~2026-09-18 22:42 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 22:41 [PATCH v7 00/11] unwind, arm64: add sframe unwinder for kernel Dylan Hatch
2026-09-18 22:41 ` [PATCH v7 01/11] arm64, unwind: build kernel with sframe V3 info Dylan Hatch
2026-09-18 22:41 ` [PATCH v7 02/11] arm64/sframe: Read vmlinux .sframe header Dylan Hatch
2026-09-18 22:41 ` [PATCH v7 03/11] sframe: Add support for reading vmlinux .sframe contents Dylan Hatch
2026-09-18 22:41 ` Dylan Hatch [this message]
2026-09-18 22:41 ` [PATCH v7 05/11] arm64/module, sframe: Add sframe support for modules Dylan Hatch
2026-09-18 22:54 ` sashiko-bot
2026-09-18 22:41 ` [PATCH v7 06/11] arm64/sframe: Validate IP addresses Dylan Hatch
2026-09-18 22:41 ` [PATCH v7 07/11] sframe: Add debug helpers with object name Dylan Hatch
2026-09-18 22:41 ` [PATCH v7 08/11] sframe: Add .sframe validation option Dylan Hatch
2026-09-18 22:41 ` [PATCH v7 09/11] arm64: entry: add unwind info for call_on_irq_stack() Dylan Hatch
2026-09-18 22:41 ` [PATCH v7 10/11] arm64, crypto/lib: Annotate leaf functions with CFI info Dylan Hatch
2026-09-18 22:58 ` sashiko-bot
2026-09-18 22:41 ` [PATCH v7 11/11] unwind: arm64: Use sframe to unwind interrupt frames Dylan Hatch
2026-09-18 23:00 ` sashiko-bot
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=20260918224157.1471085-5-dylanbhatch@google.com \
--to=dylanbhatch@google.com \
--cc=catalin.marinas@arm.com \
--cc=davem@davemloft.net \
--cc=herbert@gondor.apana.org.au \
--cc=ibhagatgnu@gmail.com \
--cc=jikos@kernel.org \
--cc=joe.lawrence@redhat.com \
--cc=jpoimboe@kernel.org \
--cc=jremus@linux.ibm.com \
--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=rdunlap@infradead.org \
--cc=roman.gushchin@linux.dev \
--cc=rostedt@goodmis.org \
--cc=smostafa@google.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®