riscv: alternative: patch alternatives in the vDSO

Make it possible to use alternatives in the vDSO, so that better
implementations can be used if possible.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
Reviewed-by: Guo Ren <guoren@kernel.org>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Link: https://lore.kernel.org/r/20230128172856.3814-11-jszhang@kernel.org
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
Jisheng Zhang 2023-01-29 01:28:53 +08:00 committed by Palmer Dabbelt
parent 8d23e94a44
commit cabfd146b3
No known key found for this signature in database
GPG Key ID: 2E1319F35FBB1889
4 changed files with 40 additions and 5 deletions

View File

@ -28,8 +28,12 @@
#define COMPAT_VDSO_SYMBOL(base, name) \
(void __user *)((unsigned long)(base) + compat__vdso_##name##_offset)
extern char compat_vdso_start[], compat_vdso_end[];
#endif /* CONFIG_COMPAT */
extern char vdso_start[], vdso_end[];
#endif /* !__ASSEMBLY__ */
#endif /* CONFIG_MMU */

View File

@ -11,7 +11,9 @@
#include <linux/cpu.h>
#include <linux/uaccess.h>
#include <asm/alternative.h>
#include <asm/module.h>
#include <asm/sections.h>
#include <asm/vdso.h>
#include <asm/vendorid_list.h>
#include <asm/sbi.h>
#include <asm/csr.h>
@ -160,6 +162,31 @@ static void __init_or_module _apply_alternatives(struct alt_entry *begin,
stage);
}
#ifdef CONFIG_MMU
static void __init apply_vdso_alternatives(void)
{
const Elf_Ehdr *hdr;
const Elf_Shdr *shdr;
const Elf_Shdr *alt;
struct alt_entry *begin, *end;
hdr = (Elf_Ehdr *)vdso_start;
shdr = (void *)hdr + hdr->e_shoff;
alt = find_section(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);
}
#else
static void __init apply_vdso_alternatives(void) { }
#endif
void __init apply_boot_alternatives(void)
{
/* If called on non-boot cpu things could go wrong */
@ -168,6 +195,8 @@ void __init apply_boot_alternatives(void)
_apply_alternatives((struct alt_entry *)__alt_start,
(struct alt_entry *)__alt_end,
RISCV_ALTERNATIVES_BOOT);
apply_vdso_alternatives();
}
/*

View File

@ -22,11 +22,6 @@ struct vdso_data {
};
#endif
extern char vdso_start[], vdso_end[];
#ifdef CONFIG_COMPAT
extern char compat_vdso_start[], compat_vdso_end[];
#endif
enum vvar_pages {
VVAR_DATA_PAGE_OFFSET,
VVAR_TIMENS_PAGE_OFFSET,

View File

@ -40,6 +40,13 @@ SECTIONS
. = 0x800;
.text : { *(.text .text.*) } :text
. = ALIGN(4);
.alternative : {
__alt_start = .;
*(.alternative)
__alt_end = .;
}
.data : {
*(.got.plt) *(.got)
*(.data .data.* .gnu.linkonce.d.*)