arch/arm64/Kconfig | 1 + arch/arm64/include/asm/module.h | 2 - arch/arm64/include/asm/module.lds.h | 3 - arch/arm64/kernel/ftrace.c | 13 +--- arch/arm64/kernel/module-plts.c | 63 +++++--------------- arch/arm64/kernel/module.c | 20 +------ arch/arm64/mm/init.c | 19 +++++- arch/arm64/mm/pageattr.c | 13 +++- include/linux/execmem.h | 11 ++++ include/linux/module.h | 4 +- kernel/module/main.c | 22 +++++-- mm/execmem.c | 47 ++++++++++++++- 12 files changed, 124 insertions(+), 94 deletions(-)
From: Ard Biesheuvel <ardb@kernel.org> The arm64 module loader has to deal with a couple of corner cases that may occur when .init.text is placed out of direct branch range of .text: - ordinary direct branches from .init.text into .text may require the use of a PLT entry (i.e., a trampoline aka veneer), which means not only that additional PLT entries need to be allocated for cross-section calls, but also that .init.text needs its own PLT reservation, as the one in .text will be out of range as well; - dynamic patching of the ftrace handler into .init.text code needs its own dedicated trampoline as the one in .text may be too far away. - recent compilers may omit BTI veneers for static functions that never have their address taken, and so additional veneers will need to be added to .text in case cross-section direct branches from .init.text require a PLT entry (and therefore a landing pad at the target end). This is unfortunate, because it is actually somewhat unusual for .text and .init.text to be so far away from each other: only when allocating either of them (but not both) exhausts the 'near' (PLT-less) module region, the other will be allocated from the spillover region, which is not in direct branching range, and therefore requires PLT entries for cross-section calls. This series addresses this wart by allocating both of them as a single chunk, and freeing the .init.text part along with the other init sections at the appropriate time. This ensures that the two regions will never require veneers for cross-section calls, allowing the arm64 module loader to be simplified. Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Mike Rapoport <rppt@kernel.org> Cc: Luis Chamberlain <mcgrof@kernel.org> Cc: Petr Pavlu <petr.pavlu@suse.com> Cc: Daniel Gomez <da.gomez@kernel.org> Cc: Sami Tolvanen <samitolvanen@google.com> Cc: Aaron Tomlin <atomlin@atomlin.com> Cc: "Adrian Barnaś" <abarnas@google.com> Cc: Ryan Roberts <ryan.roberts@arm.com> Cc: Kevin Brodsky <kevin.brodsky@arm.com> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-trace-kernel@vger.kernel.org Cc: linux-mm@kvack.org Cc: linux-modules@vger.kernel.org Ard Biesheuvel (9): mm: execmem: Add API to split an existing execmem cache allocation mm: execmem: Allow huge vmappings to be avoided for execmem caches module: Place MOD_TEXT before MOD_INIT_TEXT in enumeration module: Allocate MOD_INIT_TEXT from the MOD_TEXT ROX allocation arm64: mm: Permit permissions changes on huge vmappings arm64: Enable the execmem ROX cache for module text arm64: ftrace: Revert "fix unreachable PLT for ftrace_caller ..." arm64: module: Combine init and core PLT entries again arm64: ftrace: Simplify PLT handling arch/arm64/Kconfig | 1 + arch/arm64/include/asm/module.h | 2 - arch/arm64/include/asm/module.lds.h | 3 - arch/arm64/kernel/ftrace.c | 13 +--- arch/arm64/kernel/module-plts.c | 63 +++++--------------- arch/arm64/kernel/module.c | 20 +------ arch/arm64/mm/init.c | 19 +++++- arch/arm64/mm/pageattr.c | 13 +++- include/linux/execmem.h | 11 ++++ include/linux/module.h | 4 +- kernel/module/main.c | 22 +++++-- mm/execmem.c | 47 ++++++++++++++- 12 files changed, 124 insertions(+), 94 deletions(-) -- 2.55.0.860.g4b6b3295ed-goog
Hi Ard, On Sat, Aug 22, 2026 at 03:53:22PM +0200, Ard Biesheuvel wrote: > From: Ard Biesheuvel <ardb@kernel.org> > > The arm64 module loader has to deal with a couple of corner cases that > may occur when .init.text is placed out of direct branch range of .text: > > - ordinary direct branches from .init.text into .text may require the > use of a PLT entry (i.e., a trampoline aka veneer), which means not > only that additional PLT entries need to be allocated for > cross-section calls, but also that .init.text needs its own PLT > reservation, as the one in .text will be out of range as well; > > - dynamic patching of the ftrace handler into .init.text code needs its > own dedicated trampoline as the one in .text may be too far away. > > - recent compilers may omit BTI veneers for static functions that never > have their address taken, and so additional veneers will need to be > added to .text in case cross-section direct branches from .init.text > require a PLT entry (and therefore a landing pad at the target end). > > This is unfortunate, because it is actually somewhat unusual for .text > and .init.text to be so far away from each other: only when allocating > either of them (but not both) exhausts the 'near' (PLT-less) module > region, the other will be allocated from the spillover region, which is > not in direct branching range, and therefore requires PLT entries for > cross-section calls. > > This series addresses this wart by allocating both of them as a single > chunk, and freeing the .init.text part along with the other init > sections at the appropriate time. This ensures that the two regions will > never require veneers for cross-section calls, allowing the arm64 module > loader to be simplified. > > Ard Biesheuvel (9): > mm: execmem: Add API to split an existing execmem cache allocation > mm: execmem: Allow huge vmappings to be avoided for execmem caches > module: Place MOD_TEXT before MOD_INIT_TEXT in enumeration > module: Allocate MOD_INIT_TEXT from the MOD_TEXT ROX allocation > arm64: mm: Permit permissions changes on huge vmappings > arm64: Enable the execmem ROX cache for module text > arm64: ftrace: Revert "fix unreachable PLT for ftrace_caller ..." > arm64: module: Combine init and core PLT entries again > arm64: ftrace: Simplify PLT handling I can't say I like the idea of tying the single chunk allocation of modules .text and .init.text to the ROX cache. The goal of the cache is to have executable code mapped at higher page table levels. Letting it use base-page mappings completely dismisses it. I'm not against having execmem_split() or something along these lines, but it should work without the ROX cache as well. Another question I had is did you consider splitting the area on free rather than on alloc? In this case it could be execmem_shrink() that immediately frees the .init.text part. > arch/arm64/Kconfig | 1 + > arch/arm64/include/asm/module.h | 2 - > arch/arm64/include/asm/module.lds.h | 3 - > arch/arm64/kernel/ftrace.c | 13 +--- > arch/arm64/kernel/module-plts.c | 63 +++++--------------- > arch/arm64/kernel/module.c | 20 +------ > arch/arm64/mm/init.c | 19 +++++- > arch/arm64/mm/pageattr.c | 13 +++- > include/linux/execmem.h | 11 ++++ > include/linux/module.h | 4 +- > kernel/module/main.c | 22 +++++-- > mm/execmem.c | 47 ++++++++++++++- > 12 files changed, 124 insertions(+), 94 deletions(-) > > -- > 2.55.0.860.g4b6b3295ed-goog > -- Sincerely yours, Mike.
On 8/22/26 3:53 PM, Ard Biesheuvel wrote: > From: Ard Biesheuvel <ardb@kernel.org> > > The arm64 module loader has to deal with a couple of corner cases that > may occur when .init.text is placed out of direct branch range of .text: > > - ordinary direct branches from .init.text into .text may require the > use of a PLT entry (i.e., a trampoline aka veneer), which means not > only that additional PLT entries need to be allocated for > cross-section calls, but also that .init.text needs its own PLT > reservation, as the one in .text will be out of range as well; > > - dynamic patching of the ftrace handler into .init.text code needs its > own dedicated trampoline as the one in .text may be too far away. > > - recent compilers may omit BTI veneers for static functions that never > have their address taken, and so additional veneers will need to be > added to .text in case cross-section direct branches from .init.text > require a PLT entry (and therefore a landing pad at the target end). > > This is unfortunate, because it is actually somewhat unusual for .text > and .init.text to be so far away from each other: only when allocating > either of them (but not both) exhausts the 'near' (PLT-less) module > region, the other will be allocated from the spillover region, which is > not in direct branching range, and therefore requires PLT entries for > cross-section calls. > > This series addresses this wart by allocating both of them as a single > chunk, and freeing the .init.text part along with the other init > sections at the appropriate time. This ensures that the two regions will > never require veneers for cross-section calls, allowing the arm64 module > loader to be simplified. It looks like this should also be useful for ppc64, which currently merges .init.text and .text because keeping them separate would require stubs between the two, and consequently .init.text is never released in modules on this architecture. -- Thanks, Petr
On Fri, 28 Aug 2026, at 15:07, Petr Pavlu wrote: > On 8/22/26 3:53 PM, Ard Biesheuvel wrote: >> From: Ard Biesheuvel <ardb@kernel.org> >> >> The arm64 module loader has to deal with a couple of corner cases that >> may occur when .init.text is placed out of direct branch range of .text: >> >> - ordinary direct branches from .init.text into .text may require the >> use of a PLT entry (i.e., a trampoline aka veneer), which means not >> only that additional PLT entries need to be allocated for >> cross-section calls, but also that .init.text needs its own PLT >> reservation, as the one in .text will be out of range as well; >> >> - dynamic patching of the ftrace handler into .init.text code needs its >> own dedicated trampoline as the one in .text may be too far away. >> >> - recent compilers may omit BTI veneers for static functions that never >> have their address taken, and so additional veneers will need to be >> added to .text in case cross-section direct branches from .init.text >> require a PLT entry (and therefore a landing pad at the target end). >> >> This is unfortunate, because it is actually somewhat unusual for .text >> and .init.text to be so far away from each other: only when allocating >> either of them (but not both) exhausts the 'near' (PLT-less) module >> region, the other will be allocated from the spillover region, which is >> not in direct branching range, and therefore requires PLT entries for >> cross-section calls. >> >> This series addresses this wart by allocating both of them as a single >> chunk, and freeing the .init.text part along with the other init >> sections at the appropriate time. This ensures that the two regions will >> never require veneers for cross-section calls, allowing the arm64 module >> loader to be simplified. > > It looks like this should also be useful for ppc64, which currently > merges .init.text and .text because keeping them separate would require > stubs between the two, and consequently .init.text is never released in > modules on this architecture. > Thanks for the data point - are those stubs needed when there is some distance between the placements of .text and .init.text?
On 8/28/26 3:45 PM, Ard Biesheuvel wrote: > On Fri, 28 Aug 2026, at 15:07, Petr Pavlu wrote: >> On 8/22/26 3:53 PM, Ard Biesheuvel wrote: >>> From: Ard Biesheuvel <ardb@kernel.org> >>> >>> The arm64 module loader has to deal with a couple of corner cases that >>> may occur when .init.text is placed out of direct branch range of .text: >>> >>> - ordinary direct branches from .init.text into .text may require the >>> use of a PLT entry (i.e., a trampoline aka veneer), which means not >>> only that additional PLT entries need to be allocated for >>> cross-section calls, but also that .init.text needs its own PLT >>> reservation, as the one in .text will be out of range as well; >>> >>> - dynamic patching of the ftrace handler into .init.text code needs its >>> own dedicated trampoline as the one in .text may be too far away. >>> >>> - recent compilers may omit BTI veneers for static functions that never >>> have their address taken, and so additional veneers will need to be >>> added to .text in case cross-section direct branches from .init.text >>> require a PLT entry (and therefore a landing pad at the target end). >>> >>> This is unfortunate, because it is actually somewhat unusual for .text >>> and .init.text to be so far away from each other: only when allocating >>> either of them (but not both) exhausts the 'near' (PLT-less) module >>> region, the other will be allocated from the spillover region, which is >>> not in direct branching range, and therefore requires PLT entries for >>> cross-section calls. >>> >>> This series addresses this wart by allocating both of them as a single >>> chunk, and freeing the .init.text part along with the other init >>> sections at the appropriate time. This ensures that the two regions will >>> never require veneers for cross-section calls, allowing the arm64 module >>> loader to be simplified. >> >> It looks like this should also be useful for ppc64, which currently >> merges .init.text and .text because keeping them separate would require >> stubs between the two, and consequently .init.text is never released in >> modules on this architecture. >> > > Thanks for the data point - are those stubs needed when there is some > distance between the placements of .text and .init.text? Yes, my understanding is that these stubs are primarily needed because the BL instruction on ppc64 can only reach a range of +-32 MB. Another aspect on ppc64 is the use of the Table of Contents (TOC). In theory, when splitting .text and .init.text, one would also want separate TOCs, along with stubs to support switching between them. However, I don't think this is particularly feasible. As far as I can see, the ABI and GCC don't allow separate TOCs within a single relocatable object file. In practice, it shouldn't be a large problem to keep a single TOC, even if some data related only to .init.text remains present after the module is loaded. Being able to free .init.text is the important part. On newer Power10 with PCREL, the TOC is not used, so this issue goes away. -- Cheers, Petr
© 2016 - 2026 Red Hat, Inc.