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

guoren at kernel.org guoren at kernel.org
Sat Nov 11 22:14:44 PST 2023


From: Guo Ren <guoren at linux.alibaba.com>

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 at linux.alibaba.com>
Signed-off-by: Guo Ren <guoren at kernel.org>
---
 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




More information about the linux-riscv mailing list