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