[RFC PATCH 1/1] riscv: add Kconfig.vdso

Palmer Dabbelt palmer at rivosinc.com
Mon Sep 25 08:08:00 PDT 2023


On Thu, 18 May 2023 10:48:52 PDT (-0700), falcon at tinylab.org wrote:
> Allow users to disable the vdso and compat vdso in Kconfig.
>
> Copied and adapted some code from arm and arm64.
>
> Size measured with a small rv64 config of v6.4-rc2:
>
>             Config | Size      | Shrink
>     ---------------|-----------|--------
>            default | 1588 KB   |
>     no compat vdso | 1584 KB   | -4 KB
>      (and) no vdso | 1576 KB   | -12 KB

Do the resulting kernels actually work?  As far as I can tell this 
disables some syscalls that would break userspace (that time-related 
stuff that would be turned off) and the lack of rt_sigreturn would need 
an executable stack (which probably cancels out any benefits from the 
smaller text size).

> Signed-off-by: Zhangjin Wu <falcon at tinylab.org>
> ---
>  arch/riscv/Kconfig                |  6 +-----
>  arch/riscv/Kconfig.vdso           | 28 ++++++++++++++++++++++++++++
>  arch/riscv/Makefile               |  8 +++++---
>  arch/riscv/include/asm/elf.h      |  6 ++++--
>  arch/riscv/include/asm/mmu.h      |  2 ++
>  arch/riscv/include/asm/vdso.h     |  8 ++++----
>  arch/riscv/kernel/Makefile        |  4 ++--
>  arch/riscv/kernel/alternative.c   |  2 +-
>  arch/riscv/kernel/compat_signal.c |  2 ++
>  arch/riscv/kernel/entry.S         |  2 +-
>  arch/riscv/kernel/signal.c        |  4 ++--
>  arch/riscv/kernel/sys_riscv.c     |  2 +-
>  arch/riscv/kernel/vdso.c          | 10 +++++-----
>  13 files changed, 58 insertions(+), 26 deletions(-)
>  create mode 100644 arch/riscv/Kconfig.vdso
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index 348c0fa1fc8c..79a6b3f1e697 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -34,7 +34,6 @@ config RISCV
>  	select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL
>  	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
>  	select ARCH_HAS_UBSAN_SANITIZE_ALL
> -	select ARCH_HAS_VDSO_DATA
>  	select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
>  	select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
>  	select ARCH_STACKWALK
> @@ -63,7 +62,6 @@ config RISCV
>  	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
>  	select GENERIC_EARLY_IOREMAP
>  	select GENERIC_ENTRY
> -	select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
>  	select GENERIC_IDLE_POLL_SETUP
>  	select GENERIC_IOREMAP if MMU
>  	select GENERIC_IRQ_IPI if SMP
> @@ -76,8 +74,6 @@ config RISCV
>  	select GENERIC_PTDUMP if MMU
>  	select GENERIC_SCHED_CLOCK
>  	select GENERIC_SMP_IDLE_THREAD
> -	select GENERIC_TIME_VSYSCALL if MMU && 64BIT
> -	select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO
>  	select HARDIRQS_SW_RESEND
>  	select HAS_IOPORT if MMU
>  	select HAVE_ARCH_AUDITSYSCALL
> @@ -105,7 +101,6 @@ config RISCV
>  	select HAVE_FUNCTION_ARG_ACCESS_API
>  	select HAVE_FUNCTION_ERROR_INJECTION
>  	select HAVE_GCC_PLUGINS
> -	select HAVE_GENERIC_VDSO if MMU && 64BIT
>  	select HAVE_IRQ_TIME_ACCOUNTING
>  	select HAVE_KPROBES if !XIP_KERNEL
>  	select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL
> @@ -262,6 +257,7 @@ config RISCV_DMA_NONCOHERENT
>  config AS_HAS_INSN
>  	def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)
>
> +source "arch/riscv/Kconfig.vdso"
>  source "arch/riscv/Kconfig.socs"
>  source "arch/riscv/Kconfig.errata"
>
> diff --git a/arch/riscv/Kconfig.vdso b/arch/riscv/Kconfig.vdso
> new file mode 100644
> index 000000000000..3c7ec638361d
> --- /dev/null
> +++ b/arch/riscv/Kconfig.vdso
> @@ -0,0 +1,28 @@
> +menu "VDSO selection"
> +	depends on MMU
> +
> +config VDSO
> +	bool "Enable VDSO for acceleration of some system calls" if EXPERT
> +	default y
> +	select HAVE_GENERIC_VDSO if 64BIT
> +	select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO
> +	select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
> +	select GENERIC_TIME_VSYSCALL if 64BIT
> +	select ARCH_HAS_VDSO_DATA
> +	help
> +	  Place in the process address space an ELF shared object
> +	  providing fast implementations of gettimeofday and
> +	  clock_gettime.
> +
> +config COMPAT_VDSO
> +	bool "Enable vDSO for 32-bit applications" if EXPERT
> +	default y
> +	depends on VDSO
> +	depends on COMPAT
> +	select GENERIC_COMPAT_VDSO
> +	help
> +	  Place in the process address space of 32-bit applications an
> +	  ELF shared object providing fast implementations of gettimeofday
> +	  and clock_gettime.
> +
> +endmenu # "VDSO selection"
> diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> index 0fb256bf8270..6aa32e83f812 100644
> --- a/arch/riscv/Makefile
> +++ b/arch/riscv/Makefile
> @@ -130,18 +130,20 @@ endif
>  libs-y += arch/riscv/lib/
>  libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
>
> +ifeq ($(CONFIG_VDSO),y)
>  PHONY += vdso_install
>  vdso_install:
>  	$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
> -	$(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
> +	$(if $(CONFIG_COMPAT_VDSO),$(Q)$(MAKE) \
>  		$(build)=arch/riscv/kernel/compat_vdso compat_$@)
> +endif
>
>  ifeq ($(KBUILD_EXTMOD),)
> -ifeq ($(CONFIG_MMU),y)
> +ifeq ($(CONFIG_VDSO),y)
>  prepare: vdso_prepare
>  vdso_prepare: prepare0
>  	$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h
> -	$(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
> +	$(if $(CONFIG_COMPAT_VDSO),$(Q)$(MAKE) \
>  		$(build)=arch/riscv/kernel/compat_vdso include/generated/compat_vdso-offsets.h)
>
>  endif
> diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
> index 30e7d2455960..e67ed2696f23 100644
> --- a/arch/riscv/include/asm/elf.h
> +++ b/arch/riscv/include/asm/elf.h
> @@ -78,7 +78,7 @@ extern unsigned long elf_hwcap;
>
>  #define COMPAT_ELF_PLATFORM	(NULL)
>
> -#ifdef CONFIG_MMU
> +#ifdef CONFIG_VDSO
>  #define ARCH_DLINFO						\
>  do {								\
>  	/*							\
> @@ -110,7 +110,7 @@ do {								\
>  struct linux_binprm;
>  extern int arch_setup_additional_pages(struct linux_binprm *bprm,
>  	int uses_interp);
> -#endif /* CONFIG_MMU */
> +#endif /* CONFIG_VDSO */
>
>  #define ELF_CORE_COPY_REGS(dest, regs)			\
>  do {							\
> @@ -136,10 +136,12 @@ do {    if ((ex).e_ident[EI_CLASS] == ELFCLASS32)		\
>  typedef compat_ulong_t			compat_elf_greg_t;
>  typedef compat_elf_greg_t		compat_elf_gregset_t[ELF_NGREG];
>
> +#ifdef CONFIG_COMPAT_VDSO
>  extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
>  					      int uses_interp);
>  #define compat_arch_setup_additional_pages \
>  				compat_arch_setup_additional_pages
> +#endif
>
>  #endif /* CONFIG_COMPAT */
>  #endif /* _ASM_RISCV_ELF_H */
> diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h
> index 0099dc116168..8e88e81fcc32 100644
> --- a/arch/riscv/include/asm/mmu.h
> +++ b/arch/riscv/include/asm/mmu.h
> @@ -15,7 +15,9 @@ typedef struct {
>  #else
>  	atomic_long_t id;
>  #endif
> +#ifdef CONFIG_VDSO
>  	void *vdso;
> +#endif
>  #ifdef CONFIG_SMP
>  	/* A local icache flush is needed before user execution can resume. */
>  	cpumask_t icache_stale_mask;
> diff --git a/arch/riscv/include/asm/vdso.h b/arch/riscv/include/asm/vdso.h
> index f891478829a5..a4cedac5bdc9 100644
> --- a/arch/riscv/include/asm/vdso.h
> +++ b/arch/riscv/include/asm/vdso.h
> @@ -12,7 +12,7 @@
>   * All systems with an MMU have a VDSO, but systems without an MMU don't
>   * support shared libraries and therefore don't have one.
>   */
> -#ifdef CONFIG_MMU
> +#ifdef CONFIG_VDSO
>
>  #define __VVAR_PAGES    2
>
> @@ -22,7 +22,7 @@
>  #define VDSO_SYMBOL(base, name)							\
>  	(void __user *)((unsigned long)(base) + __vdso_##name##_offset)
>
> -#ifdef CONFIG_COMPAT
> +#ifdef CONFIG_COMPAT_VDSO
>  #include <generated/compat_vdso-offsets.h>
>
>  #define COMPAT_VDSO_SYMBOL(base, name)						\
> @@ -30,12 +30,12 @@
>
>  extern char compat_vdso_start[], compat_vdso_end[];
>
> -#endif /* CONFIG_COMPAT */
> +#endif /* CONFIG_COMPAT_VDSO */
>
>  extern char vdso_start[], vdso_end[];
>
>  #endif /* !__ASSEMBLY__ */
>
> -#endif /* CONFIG_MMU */
> +#endif /* CONFIG_VDSO */
>
>  #endif /* _ASM_RISCV_VDSO_H */
> diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
> index fbdccc21418a..0bc4eb093e47 100644
> --- a/arch/riscv/kernel/Makefile
> +++ b/arch/riscv/kernel/Makefile
> @@ -52,7 +52,7 @@ obj-y	+= stacktrace.o
>  obj-y	+= cacheinfo.o
>  obj-y	+= patch.o
>  obj-y	+= probes/
> -obj-$(CONFIG_MMU) += vdso.o vdso/
> +obj-$(CONFIG_VDSO) += vdso.o vdso/
>
>  obj-$(CONFIG_RISCV_M_MODE)	+= traps_misaligned.o
>  obj-$(CONFIG_FPU)		+= fpu.o
> @@ -89,6 +89,6 @@ obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o
>  obj-$(CONFIG_EFI)		+= efi.o
>  obj-$(CONFIG_COMPAT)		+= compat_syscall_table.o
>  obj-$(CONFIG_COMPAT)		+= compat_signal.o
> -obj-$(CONFIG_COMPAT)		+= compat_vdso/
> +obj-$(CONFIG_COMPAT_VDSO)	+= compat_vdso/
>
>  obj-$(CONFIG_64BIT)		+= pi/
> diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
> index 6b75788c18e6..16e9a10e24b4 100644
> --- a/arch/riscv/kernel/alternative.c
> +++ b/arch/riscv/kernel/alternative.c
> @@ -181,7 +181,7 @@ static void __init_or_module _apply_alternatives(struct alt_entry *begin,
>  				stage);
>  }
>
> -#ifdef CONFIG_MMU
> +#ifdef CONFIG_VDSO
>  static void __init apply_vdso_alternatives(void)
>  {
>  	const Elf_Ehdr *hdr;
> diff --git a/arch/riscv/kernel/compat_signal.c b/arch/riscv/kernel/compat_signal.c
> index 6ec4e34255a9..9405880b1df6 100644
> --- a/arch/riscv/kernel/compat_signal.c
> +++ b/arch/riscv/kernel/compat_signal.c
> @@ -217,8 +217,10 @@ int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
>  	if (err)
>  		return -EFAULT;
>
> +#ifdef CONFIG_COMPAT_VDSO
>  	regs->ra = (unsigned long)COMPAT_VDSO_SYMBOL(
>  			current->mm->context.vdso, rt_sigreturn);
> +#endif
>
>  	/*
>  	 * Set up registers for signal handler.
> diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
> index 3fbb100bc9e4..11c5e6edae3c 100644
> --- a/arch/riscv/kernel/entry.S
> +++ b/arch/riscv/kernel/entry.S
> @@ -345,7 +345,7 @@ SYM_CODE_START(excp_vect_table)
>  excp_vect_table_end:
>  SYM_CODE_END(excp_vect_table)
>
> -#ifndef CONFIG_MMU
> +#ifndef CONFIG_VDSO
>  SYM_CODE_START(__user_rt_sigreturn)
>  	li a7, __NR_rt_sigreturn
>  	scall
> diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
> index 9aff9d720590..bb8ee87ae28f 100644
> --- a/arch/riscv/kernel/signal.c
> +++ b/arch/riscv/kernel/signal.c
> @@ -29,7 +29,7 @@ extern u32 __user_rt_sigreturn[2];
>  struct rt_sigframe {
>  	struct siginfo info;
>  	struct ucontext uc;
> -#ifndef CONFIG_MMU
> +#ifndef CONFIG_VDSO
>  	u32 sigreturn_code[2];
>  #endif
>  };
> @@ -201,7 +201,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
>  		return -EFAULT;
>
>  	/* Set up to return from userspace. */
> -#ifdef CONFIG_MMU
> +#ifdef CONFIG_VDSO
>  	regs->ra = (unsigned long)VDSO_SYMBOL(
>  		current->mm->context.vdso, rt_sigreturn);
>  #else
> diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c
> index 5db29683ebee..8691bc8d247b 100644
> --- a/arch/riscv/kernel/sys_riscv.c
> +++ b/arch/riscv/kernel/sys_riscv.c
> @@ -246,7 +246,7 @@ static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs,
>  	return 0;
>  }
>
> -#ifdef CONFIG_MMU
> +#ifdef CONFIG_VDSO
>
>  static int __init init_hwprobe_vdso_data(void)
>  {
> diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c
> index 9a68e7eaae4d..8a4cb4e4bd8b 100644
> --- a/arch/riscv/kernel/vdso.c
> +++ b/arch/riscv/kernel/vdso.c
> @@ -50,7 +50,7 @@ struct __vdso_info {
>  };
>
>  static struct __vdso_info vdso_info;
> -#ifdef CONFIG_COMPAT
> +#ifdef CONFIG_COMPAT_VDSO
>  static struct __vdso_info compat_vdso_info;
>  #endif
>
> @@ -115,7 +115,7 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
>  	for_each_vma(vmi, vma) {
>  		if (vma_is_special_mapping(vma, vdso_info.dm))
>  			zap_vma_pages(vma);
> -#ifdef CONFIG_COMPAT
> +#ifdef CONFIG_COMPAT_VDSO
>  		if (vma_is_special_mapping(vma, compat_vdso_info.dm))
>  			zap_vma_pages(vma);
>  #endif
> @@ -179,7 +179,7 @@ static struct __vdso_info vdso_info __ro_after_init = {
>  	.cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO],
>  };
>
> -#ifdef CONFIG_COMPAT
> +#ifdef CONFIG_COMPAT_VDSO
>  static struct vm_special_mapping rv_compat_vdso_maps[] __ro_after_init = {
>  	[RV_VDSO_MAP_VVAR] = {
>  		.name   = "[vvar]",
> @@ -203,7 +203,7 @@ static struct __vdso_info compat_vdso_info __ro_after_init = {
>  static int __init vdso_init(void)
>  {
>  	__vdso_init(&vdso_info);
> -#ifdef CONFIG_COMPAT
> +#ifdef CONFIG_COMPAT_VDSO
>  	__vdso_init(&compat_vdso_info);
>  #endif
>
> @@ -254,7 +254,7 @@ static int __setup_additional_pages(struct mm_struct *mm,
>  	return PTR_ERR(ret);
>  }
>
> -#ifdef CONFIG_COMPAT
> +#ifdef CONFIG_COMPAT_VDSO
>  int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
>  				       int uses_interp)
>  {



More information about the linux-riscv mailing list