On Thu, Oct 22, 2026 at 1:37 PM Jani Nikula <[email protected]> wrote: > > On Mon, 19 Oct 2026, "Arnd Bergmann" <[email protected]> wrote: > > On Mon, Oct 19, 2026, at 15:28, Jani Nikula wrote: > >> On Tue, 13 Oct 2026, Arnd Bergmann <[email protected]> wrote: > >>> From: Arnd Bergmann <[email protected]> > >>> > >>> The drm_parse_cea_ext() calls into nine individual parser functions > >>> based on the data format. If all of those get inlined and KASAN_STACK > >>> is enabled, this can explode the combined stack usage beyond a > >>> reasonable amount: > >>> > >>> drivers/gpu/drm/drm_edid.c: In function 'update_display_info': > >>> drivers/gpu/drm/drm_edid.c:7040:1: error: the frame size of 1888 bytes is > >>> larger than 1536 bytes [-Werror=frame-larger-than=] > >>> 7040 | } > >>> | ^ > >>> > >>> Mark all of the individual parser functions as noinline_for_stack > >>> to avoid this and keep their stack frames separate. This reduces > >>> the stack usage for update_display_info/drm_parse_cea_ext to > >>> a more manageable 744 bytes, while each parser only adds at most > >>> 200 bytes on top. > >> > >> Is there really no way to tell the compiler to not do silly things in a > >> more generic way? > > > > The problem is really the sanitizers here, which turn off the > > optimizations that gcc relies on for its normal behavior and > > which cause additional register pressure for the inserted function > > calls. > > Cc: a bunch of KASAN folks. > > I think it's really silly and ugly to have to sprinkle > noinline_for_stack all over the place in pretty normal code [1]. The > stack usage for each individual function is fairly small. >
Together with my LLM friend, I did some digging to see whether this can be handled on the compiler side instead. Summary of what we found (x86_64 defconfig + KASAN_STACK, GCC 15.2 and Clang 21, -fstack-usage on every object): 1. The immediate cause here is that GCC's inliner has no idea what the frame will cost under KASAN. Its stack estimate for a callee only sums the raw sizes of address-taken locals, so it never includes the ASan redzones and never sees the register spills that instrumentation causes. For all nine parsers in drm_parse_cea_ext() the estimate is literally 0 bytes, which short-circuits the -fconserve-stack limits, and since each parser has a single caller, -finline-functions-called-once inlines them regardless of size. 2. A generic knob therefore exists: passing -fno-inline-functions-called-once under CONFIG_KASAN_STACK with GCC brings update_display_info() from 704 to 344 bytes here without touching the source (drm_parse_cea_ext stays a separate 368-byte frame). Kernel-wide on that config it removes 22 of the 103 frames above 1024 bytes and introduces 6 new ones, for +1.2% text. 3. The GCC estimate itself is also fixable (make account_stack_vars() add the redzones it is going to allocate anyway, ~30 lines in cfgexpand.cc). That reduces total KASAN stack usage by ~7% for +0.35% text and fixes this particular case on its own (704 -> 368), so it is probably worth upstreaming. But it is a correctness fix, not a cure: it doesn't change the number of frames above 1024/2048 at all. 4. The reason is that the big frames under KASAN are overwhelmingly functions that already have 0.5-1.5KB of genuine locals without KASAN (97 of the 103 above 1024 bytes); KASAN then multiplies them by 1.5x (median) to 2.3x (p90) through redzones and spills. No inlining heuristic can undo that, and this is inherent in how the stack instrumentation works. So for KASAN_STACK builds we think FRAME_WARN simply has to be higher than for regular builds. For what it's worth, Clang does worse on the same config (149 frames above 1024 vs. 103 for GCC, 1176 bytes for update_display_info), which is why KASAN_STACK is already off by default there. Arnd, one thing I could not do is reproduce the 1888 bytes: with linux-next's drm_edid.c the worst we get is 704 on x86_64, 752 on arm64 and 1264 on arm64 with PROFILE_ALL_BRANCHES. Could you share the .config and GCC version?
