Re: [PATCH v2 2/2] LoongArch: Skip address pairing for non-exec sections

From: Huacai Chen

Date: Fri Jul 31 2026 - 03:40:42 EST


Hi, Tiezhu,

On Fri, Jul 24, 2026 at 2:07 PM Tiezhu Yang <yangtiezhu@xxxxxxxxxxx> wrote:
>
> On 2026/7/21 下午5:06, Tiezhu Yang wrote:
> > The module loader currently runs expensive address pairing logic for all
> > sections blindly during relocation. For massive modules like amdgpu, this
> > causes the loader to waste lots of CPU cycles analyzing non-exec sections.
> >
> > Furthermore, there is an inconsistency since module_frob_arch_sections()
> > already ignores non-exec sections during the counting phase.
> >
> > Check the SHF_EXECINSTR flag in apply_relocate_add(). If the section is
> > non-exec, skip address pairing and then jump to normal relocation. This
> > eliminates redundant search loops to improve module loading efficiency.
> >
> > Signed-off-by: Tiezhu Yang <yangtiezhu@xxxxxxxxxxx>
> > ---
> > arch/loongarch/kernel/module.c | 6 ++++++
> > 1 file changed, 6 insertions(+)
> >
> > diff --git a/arch/loongarch/kernel/module.c b/arch/loongarch/kernel/module.c
> > index 7d4d571ee55e..c84ac1546dc6 100644
> > --- a/arch/loongarch/kernel/module.c
> > +++ b/arch/loongarch/kernel/module.c
> > @@ -484,6 +484,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
> > Elf_Addr v;
> > Elf_Sym *sym;
> > Elf_Rela *rel = (void *) sechdrs[relsec].sh_addr;
> > + Elf_Shdr *dst_sec = sechdrs + sechdrs[relsec].sh_info;
> >
> > pr_debug("%s: Applying relocate section %u to %u\n", __func__, relsec,
> > sechdrs[relsec].sh_info);
> > @@ -522,6 +523,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
> >
> > v = sym->st_value + rel[i].r_addend;
> >
> > + /* Skip address pairing for non-exec sections */
> > + if (!(dst_sec->sh_flags & SHF_EXECINSTR))
> > + goto apply_normal;
> > +
> > if (type == R_LARCH_PCADD_LO12 || type == R_LARCH_GOT_PCADD_LO12) {
> > bool found = false;
> > unsigned int j = idx;
> > @@ -562,6 +567,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
> > idx = j; /* Record the previous j-loop end index */
> > }
> >
> > +apply_normal:
> > switch (type) {
> > case R_LARCH_B26:
> > err = apply_r_larch_b26(mod, sechdrs, location,
> >
>
> According to the LoongArch ABI specification, the following relocation
> types exist exclusively in executable code sections:
>
> R_LARCH_PCADD_LO12
> R_LARCH_GOT_PCADD_LO12
> R_LARCH_B26
> R_LARCH_GOT_PC_HI20...R_LARCH_GOT_PC_LO12
> R_LARCH_GOT_PCADD_HI20...R_LARCH_GOT_PCADD_LO12
> R_LARCH_SOP_PUSH_PLT_PCREL
>
> https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc
>
> Thus, here is a better way:
>
> ```
> diff --git a/arch/loongarch/kernel/module.c b/arch/loongarch/kernel/module.c
> index 7d4d571ee55e..b1452b8adc63 100644
> --- a/arch/loongarch/kernel/module.c
> +++ b/arch/loongarch/kernel/module.c
> @@ -484,6 +484,8 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char
> *strtab,
> Elf_Addr v;
> Elf_Sym *sym;
> Elf_Rela *rel = (void *) sechdrs[relsec].sh_addr;
> + Elf_Shdr *dst_sec = sechdrs + sechdrs[relsec].sh_info;
> + bool is_exec = !!(dst_sec->sh_flags & SHF_EXECINSTR);
>
> pr_debug("%s: Applying relocate section %u to %u\n", __func__,
> relsec,
> sechdrs[relsec].sh_info);
> @@ -522,6 +524,14 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const
> char *strtab,
>
> v = sym->st_value + rel[i].r_addend;
>
> + /* Skip relocation types that exist exclusively in
> executable sections */
> + if (!is_exec) {
> + err = handler(mod, location, v, rela_stack,
> &rela_stack_top, type);
> + if (err)
> + return err;
> + continue;
> + }
> +
> if (type == R_LARCH_PCADD_LO12 || type ==
> R_LARCH_GOT_PCADD_LO12) {
> bool found = false;
> unsigned int j = idx;
> ```
>
> For the non-exec sections such as .orc_unwind_ip:
>
> fedora@linux:~/7.2-rc3.git$ objdump -h
> drivers/gpu/drm/amd/amdgpu/amdgpu.ko | grep -A 1 .orc_unwind_ip
> 32 .orc_unwind_ip 000ac104 0000000000000000 0000000000000000
> 18592470 2**0
> CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
>
> there are 176193 relocation entries:
>
> fedora@linux:~/7.2-rc3.git$ readelf -rW
> drivers/gpu/drm/amd/amdgpu/amdgpu.o | grep .rela.orc_unwind_ip
> Relocation section '.rela.orc_unwind_ip' at offset 0x3a5321e8 contains
> 176193 entries:
>
> Using the section flag check reduces the operation to a single check for
> massive data sections; otherwise, the loader would have to perform six
> redundant type comparisons across the if-statement and switch-case for
> every single relocation entry.
Please just drop this patch and make the first one better.

Now the first patch has a risk that the distance between .init.text
and .text of the same module exceeds 128MB. I solved it and you can
verify:
https://github.com/chenhuacai/linux/commit/f87f9d82869ebc71dca4c02bdff1cd203913a98f

Huacai
>
> Thanks,
> Tiezhu
>