Unverified Commit cabfd146 authored by Jisheng Zhang's avatar Jisheng Zhang Committed by Palmer Dabbelt
Browse files

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: default avatarJisheng Zhang <jszhang@kernel.org>
Reviewed-by: default avatarGuo Ren <guoren@kernel.org>
Reviewed-by: default avatarAndrew Jones <ajones@ventanamicro.com>
Link: https://lore.kernel.org/r/20230128172856.3814-11-jszhang@kernel.org


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 8d23e94a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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 */
+29 −0
Original line number Diff line number Diff line
@@ -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();
}

/*
+0 −5
Original line number Diff line number Diff line
@@ -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,
+7 −0
Original line number Diff line number Diff line
@@ -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.*)