Hi Josh, On Sat, 15 Aug 2026, at 07:45, Josh Poimboeuf wrote: > On a kernel whose text exceeds the +/128MB direct branch range, the > linker inserts veneers. With BTI enabled, the veneers' indirect branch > targets need a BTI landing pad, which not all functions have starting > with Clang 21 (and for all versions of GCC). > > In such cases the linker can emit a second veneer close to the target > which has the landing pad along with a direct branch to the target. But > a long branch to .idmap.text never gets one because it's missing the > executable section flag. > > With the LLVM linker, it's a silent failure, presumably only discovered > by a BTI exception at runtime. With the GNU linker it's even worse, as > it dereferences the missing stub/veneer group entry and seg faults (this > was how I discovered it). > > Make sure the section is executable by adding the "x" flag to all the > creators of the input section. > > Also manually add "bti c" to primary_entry() and enter_vhe(), otherwise > the linker-generated veneer page pushes the .idmap.text past its > asserted 4KB size: > > ld.bfd: ID map text too big or misaligned > > Link: https://sourceware.org/bugzilla/show_bug.cgi?id=34525 > Signed-off-by: Josh Poimboeuf <[email protected]> > --- > arch/arm64/kernel/cpu-reset.S | 2 +- > arch/arm64/kernel/head.S | 7 ++++--- > arch/arm64/kernel/hyp-stub.S | 1 + > arch/arm64/kernel/sleep.S | 2 +- > arch/arm64/mm/proc.S | 8 ++++---- > 5 files changed, 11 insertions(+), 9 deletions(-) > > diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S > index c87445dde6745..9943a7c70f6b0 100644 > --- a/arch/arm64/kernel/cpu-reset.S > +++ b/arch/arm64/kernel/cpu-reset.S > @@ -14,7 +14,7 @@ > #include <asm/virt.h> > > .text > -.pushsection .idmap.text, "a" > +.pushsection .idmap.text, "ax" >
We've had issues in the past with this change. The problem is that the ID map is restricted to a single page, and [some versions of] the GNU linker concatenate generated veneers onto whichever executable input section came last in the input, which was this one at that point. That resulted in the ID map start/end boundaries being placed further apart than the linker asserts would tolerate, even though the generated code in question would never be called via the 1:1 mapping. Not sure whether that problem has simply disappeared by now, or older versions of the linker may still trigger it. But it is something to be aware of.

