[RFC PATCH V2 08/38] riscv: u64ilp32: Adjust vDSO alternative for 64ilp32 abi

From: guoren
Date: Sun Nov 12 2023 - 01:16:43 EST


From: Guo Ren <guoren@xxxxxxxxxxxxxxxxx>

The 64ilp32 uses the same ELF32 as 32ilp32 and the 64lp64 uses ELF64, so
separate apply_vdso_alternatives into 64 and 32 versions and serve for
three kinds of vDSO - vdso32, vdso64, vdso64ilp32.

Signed-off-by: Guo Ren <guoren@xxxxxxxxxxxxxxxxx>
Signed-off-by: Guo Ren <guoren@xxxxxxxxxx>
---
arch/riscv/include/asm/module.h | 30 ++++++++++++++++++++++
arch/riscv/kernel/alternative.c | 45 ++++++++++++++++++++++++---------
2 files changed, 63 insertions(+), 12 deletions(-)

diff --git a/arch/riscv/include/asm/module.h b/arch/riscv/include/asm/module.h
index 0f3baaa6a9a8..9f556435a1a4 100644
--- a/arch/riscv/include/asm/module.h
+++ b/arch/riscv/include/asm/module.h
@@ -127,4 +127,34 @@ static inline const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
return NULL;
}

+static inline const Elf64_Shdr *find_section64(const Elf64_Ehdr *hdr,
+ const Elf64_Shdr *sechdrs,
+ const char *name)
+{
+ const Elf64_Shdr *s, *se;
+ const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) {
+ if (strcmp(name, secstrs + s->sh_name) == 0)
+ return s;
+ }
+
+ return NULL;
+}
+
+static inline const Elf32_Shdr *find_section32(const Elf32_Ehdr *hdr,
+ const Elf32_Shdr *sechdrs,
+ const char *name)
+{
+ const Elf32_Shdr *s, *se;
+ const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) {
+ if (strcmp(name, secstrs + s->sh_name) == 0)
+ return s;
+ }
+
+ return NULL;
+}
+
#endif /* _ASM_RISCV_MODULE_H */
diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
index 73a2d7533806..ab9eb42a5502 100644
--- a/arch/riscv/kernel/alternative.c
+++ b/arch/riscv/kernel/alternative.c
@@ -181,17 +181,40 @@ static void __init_or_module _apply_alternatives(struct alt_entry *begin,
stage);
}

-#ifdef CONFIG_MMU
-static void __init apply_vdso_alternatives(void *vdso_start)
+#ifdef CONFIG_VDSO64
+static void __init apply_vdso_alternatives64(void *vdso_start)
{
- const Elf_Ehdr *hdr;
- const Elf_Shdr *shdr;
- const Elf_Shdr *alt;
+ const Elf64_Ehdr *hdr;
+ const Elf64_Shdr *shdr;
+ const Elf64_Shdr *alt;
struct alt_entry *begin, *end;

- hdr = (Elf_Ehdr *)vdso_start;
+ hdr = (Elf64_Ehdr *)vdso_start;
shdr = (void *)hdr + hdr->e_shoff;
- alt = find_section(hdr, shdr, ".alternative");
+ alt = find_section64(hdr, shdr, ".alternative");
+ if (!alt)
+ return;
+
+ begin = (void *)hdr + alt->sh_offset,
+ end = (void *)hdr + alt->sh_offset + alt->sh_size,
+
+ _apply_alternatives((struct alt_entry *)begin,
+ (struct alt_entry *)end,
+ RISCV_ALTERNATIVES_BOOT);
+}
+#endif
+
+#if IS_ENABLED(CONFIG_VDSO32) || IS_ENABLED(CONFIG_VDSO64ILP32)
+static void __init apply_vdso_alternatives32(void *vdso_start)
+{
+ const Elf32_Ehdr *hdr;
+ const Elf32_Shdr *shdr;
+ const Elf32_Shdr *alt;
+ struct alt_entry *begin, *end;
+
+ hdr = (Elf32_Ehdr *)vdso_start;
+ shdr = (void *)hdr + hdr->e_shoff;
+ alt = find_section32(hdr, shdr, ".alternative");
if (!alt)
return;

@@ -202,8 +225,6 @@ static void __init apply_vdso_alternatives(void *vdso_start)
(struct alt_entry *)end,
RISCV_ALTERNATIVES_BOOT);
}
-#else
-static void __init apply_vdso_alternatives(void *vdso_start) { }
#endif

void __init apply_boot_alternatives(void)
@@ -217,13 +238,13 @@ void __init apply_boot_alternatives(void)
RISCV_ALTERNATIVES_BOOT);

#ifdef CONFIG_VDSO64
- apply_vdso_alternatives(vdso64_start);
+ apply_vdso_alternatives64(vdso64_start);
#endif
#ifdef CONFIG_VDSO32
- apply_vdso_alternatives(vdso32_start);
+ apply_vdso_alternatives32(vdso32_start);
#endif
#ifdef CONFIG_VDSO64ILP32
- apply_vdso_alternatives(vdso64ilp32_start);
+ apply_vdso_alternatives32(vdso64ilp32_start);
#endif

}
--
2.36.1