diff mbox series

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

Message ID 95c2e86acbcaf8966251a471997b3f0cd3c64fbd.1684430522.git.falcon@tinylab.org (mailing list archive)
State New, archived
Headers show
Series riscv: Allow disable vdso support | expand

Commit Message

Zhangjin Wu May 18, 2023, 5:48 p.m. UTC
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

Signed-off-by: Zhangjin Wu <falcon@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

Comments

Palmer Dabbelt Sept. 25, 2023, 3:08 p.m. UTC | #1
On Thu, 18 May 2023 10:48:52 PDT (-0700), falcon@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@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)
>  {
Zhangjin Wu Oct. 3, 2023, 6:39 a.m. UTC | #2
Hi, Palmer

Thanks very much for your review.

> On Thu, 18 May 2023 10:48:52 PDT (-0700), falcon@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).
>

Yes, its working is limited in extremely small embedded systems (who
don't require such syscalls or their vdso speedup variants), the libc we
currently tested is NoLibc.

This is part of our work on kernel tinification for RISC-V, exactly, it
is derived from the in-progress DCE/DSE work [1].

The simple background logic here is if the target system don't require a target
syscall, no need to provide both the syscall and/or its vdso variants from
kernel side.  seems this logic is not specific to RISC-V, perhaps we should
rethink it under the whole DSE work (Arnd has given some suggestions), for
example, let the DSE 'framework' (based on user-space profiling) tell us which
vdso variants should be reserved and which one is not required, manual
selection is really not that friendly although ARM also currently provide the
same config option.

Thanks,
Zhangjin Wu
---
[1]: https://lore.kernel.org/lkml/cover.1695679700.git.falcon@tinylab.org/
diff mbox series

Patch

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)
 {