[issue report] ARM: compile error of frame size

Arnd Bergmann arnd at arndb.de
Tue Jul 29 00:27:08 PDT 2025


On Tue, Jul 29, 2025, at 09:15, Geert Uytterhoeven wrote:
> On Tue, 29 Jul 2025 at 02:12, Kuninori Morimoto
> <kuninori.morimoto.gx at renesas.com> wrote:
>> > >         > grep CONFIG_FRAME_WARN .config
>> > >         CONFIG_FRAME_WARN=2040
>> > >
>> > >         > git diff
>> > >         diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
>> > >         index d61369b1eabe..c5173bd82380 100644
>> > >         --- a/arch/arm/boot/compressed/Makefile
>> > >         +++ b/arch/arm/boot/compressed/Makefile
>> > >         @@ -80,7 +80,7 @@ libfdt_objs := fdt_rw.o fdt_ro.o fdt_wip.o fdt.o
>> > >
>> > >          ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
>> > >          CFLAGS_REMOVE_atags_to_fdt.o += -Wframe-larger-than=${CONFIG_FRAME_WARN}
>> > > -        CFLAGS_atags_to_fdt.o += -Wframe-larger-than=1280
>> > > +        CFLAGS_atags_to_fdt.o += -Wframe-larger-than=2040
>> > >          OBJS   += $(libfdt_objs) atags_to_fdt.o
>> > >          endif
>> > >          ifeq ($(CONFIG_USE_OF),y)
>> (snip)
>> > Yes it is.  And it is hard to fix, according to the maple_tree maintainer:
>>
>> Hmm...
>> Actually I have tried to same solution (= remove or fix the big node), but
>> noticed there are many such code. My suggested was very simple solution
>> I guess, but I'm not sure detail of ARM limitation, and/or it can solve all
>> cases, etc...
>>
>> But other CPU (like ARM64) doesn't have this issue, so we can follow same
>> way (= allow large frame) I guess.
>
> I do see it in one my arm64 builds, it depends on your kernel config:
>
>     lib/maple_tree.c: In function ‘mas_wr_spanning_store’:
>     lib/maple_tree.c:3812:1: warning: the frame size of 1040 bytes is
> larger than 1024 bytes [-Wframe-larger-than=] 3812 | }
>
> I guess Arnd has seen it in his randconfig builds, too...
>
>> Does ARM has some reason which can't use large frame ? If not, do you think
>> we can allow to use it on ARM ?
>
> (stacked) Large frames may cause kernel stack overflow.

The version below works around the warning for arm, arm64 and x86
on both gcc and clang.

IIRC there are still warnings on riscv and powerpc with this, at
least with clang.

To some degree, adding 'noinline' ends up just hiding the actual
stack usage, as it just gets split between more functions. On the
other hand there are cases where the inlining also lets the compiler
run into some corner case where it ends up spilling extra variables
to the stack, especially with sanitizers enabled.

    Arnd

diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index b4ee2d29d7a9..622300b49afc 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -3569,7 +3569,7 @@ static bool mas_wr_walk(struct ma_wr_state *wr_mas)
 	return true;
 }
 
-static void mas_wr_walk_index(struct ma_wr_state *wr_mas)
+static noinline void mas_wr_walk_index(struct ma_wr_state *wr_mas)
 {
 	struct ma_state *mas = wr_mas->mas;
 
@@ -3730,10 +3730,9 @@ static inline void mas_new_root(struct ma_state *mas, void *entry)
  * span.
  * @wr_mas: The maple write state
  */
-static noinline void mas_wr_spanning_store(struct ma_wr_state *wr_mas)
+static noinline_for_kasan void _mas_wr_spanning_store(struct ma_wr_state *wr_mas, struct maple_big_node *b_node)
 {
 	struct maple_subtree_state mast;
-	struct maple_big_node b_node;
 	struct ma_state *mas;
 	unsigned char height;
 
@@ -3771,7 +3770,7 @@ static noinline void mas_wr_spanning_store(struct ma_wr_state *wr_mas)
 	 * store to ensure it's not NULL and to combine both the next node and
 	 * the node with the start together.
 	 */
-	r_mas = *mas;
+	memcpy(&r_mas, mas, sizeof(r_mas));
 	/* Avoid overflow, walk to next slot in the tree. */
 	if (r_mas.last + 1)
 		r_mas.last++;
@@ -3781,7 +3780,7 @@ static noinline void mas_wr_spanning_store(struct ma_wr_state *wr_mas)
 	r_mas.last = r_mas.index = mas->last;
 
 	/* Set up left side. */
-	l_mas = *mas;
+	memcpy(&l_mas, mas, sizeof(l_mas));
 	mas_wr_walk_index(&l_wr_mas);
 
 	if (!wr_mas->entry) {
@@ -3797,26 +3796,34 @@ static noinline void mas_wr_spanning_store(struct ma_wr_state *wr_mas)
 		return mas_new_root(mas, wr_mas->entry);
 	}
 
-	memset(&b_node, 0, sizeof(struct maple_big_node));
+	memset(b_node, 0, sizeof(struct maple_big_node));
 	/* Copy l_mas and store the value in b_node. */
-	mas_store_b_node(&l_wr_mas, &b_node, l_mas.end);
+	mas_store_b_node(&l_wr_mas, b_node, l_mas.end);
+
 	/* Copy r_mas into b_node if there is anything to copy. */
 	if (r_mas.max > r_mas.last)
 		mas_mab_cp(&r_mas, r_mas.offset, r_mas.end,
-			   &b_node, b_node.b_end + 1);
+			   b_node, b_node->b_end + 1);
 	else
-		b_node.b_end++;
+		b_node->b_end++;
 
 	/* Stop spanning searches by searching for just index. */
 	l_mas.index = l_mas.last = mas->index;
 
-	mast.bn = &b_node;
+	mast.bn = b_node;
 	mast.orig_l = &l_mas;
 	mast.orig_r = &r_mas;
+
 	/* Combine l_mas and r_mas and split them up evenly again. */
 	return mas_spanning_rebalance(mas, &mast, height + 1);
 }
 
+static noinline void mas_wr_spanning_store(struct ma_wr_state *wr_mas)
+{
+	struct maple_big_node b_node;
+
+	_mas_wr_spanning_store(wr_mas, &b_node);
+}
 /*
  * mas_wr_node_store() - Attempt to store the value in a node
  * @wr_mas: The maple write state
@@ -4069,7 +4076,7 @@ static inline void mas_wr_append(struct ma_wr_state *wr_mas,
  *
  * This is where split, rebalance end up.
  */
-static void mas_wr_bnode(struct ma_wr_state *wr_mas)
+static noinline void mas_wr_bnode(struct ma_wr_state *wr_mas)
 {
 	struct maple_big_node b_node;
 



More information about the linux-arm-kernel mailing list