diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index b68ec4b7f5..dc6f2e31e2 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -548,6 +548,7 @@ for linking")
 #  define hidden_ver(local, name)	__hidden_ver1(local, __GI_##name, name);
 #  define hidden_data_ver(local, name)	hidden_ver(local, name)
 #  define hidden_def(name)		__hidden_ver1(__GI_##name, name, name);
+#  define hidden_def_redir(redir, name)	__hidden_ver1(redir, __GI_##name, redir);
 #  define hidden_data_def(name)		hidden_def(name)
 #  define hidden_tls_def(name)				\
   __hidden_ver2 (__thread, __GI_##name, name, name);
@@ -575,6 +576,7 @@ for linking")
    hidden_proto doesn't make sense for assembly but the equivalent
    is to call via the HIDDEN_JUMPTARGET macro instead of JUMPTARGET.  */
 #  define hidden_def(name)	strong_alias (name, __GI_##name)
+#  define hidden_def_redir(redir, name)	strong_alias(redir, __GI_##name);
 #  define hidden_weak(name)	hidden_def (name)
 #  define hidden_ver(local, name) strong_alias (local, __GI_##name)
 #  define hidden_data_def(name)	strong_data_alias (name, __GI_##name)
@@ -605,6 +607,7 @@ for linking")
 # endif /* Not  __ASSEMBLER__ */
 # define hidden_weak(name)
 # define hidden_def(name)
+# define hidden_def_redir(redir, name)
 # define hidden_ver(local, name)
 # define hidden_data_weak(name)
 # define hidden_data_def(name)
@@ -617,6 +620,7 @@ for linking")
 # define libc_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
 # define libc_hidden_tls_proto(name, attrs...) hidden_tls_proto (name, ##attrs)
 # define libc_hidden_def(name) hidden_def (name)
+# define libc_hidden_def_redir(redir, name) hidden_def_redir (redir, name)
 # define libc_hidden_weak(name) hidden_weak (name)
 # ifdef LINK_OBSOLETE_RPC
    /* libc_hidden_nolink_sunrpc should only get used in sunrpc code.  */
@@ -633,6 +637,7 @@ for linking")
 # define libc_hidden_proto(name, attrs...)
 # define libc_hidden_tls_proto(name, attrs...)
 # define libc_hidden_def(name)
+# define libc_hidden_def_redir(redir, name)
 # define libc_hidden_weak(name)
 # define libc_hidden_ver(local, name)
 # define libc_hidden_data_def(name)
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index e793fdc936..4f79f25989 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -315,6 +315,8 @@ struct libc_do_syscall_args
 /* List of system calls which are supported as vsyscalls.  */
 # define HAVE_CLOCK_GETTIME_VSYSCALL    "__vdso_clock_gettime"
 # define HAVE_GETTIMEOFDAY_VSYSCALL     "__vdso_gettimeofday"
+# define HAVE_TIME_VSYSCALL             "__vdso_time"
+# define USE_TIME_VSYSCALL_IFUNC	1
 
 /* Define a macro which expands inline into the wrapper code for a system
    call.  This use is for internal calls that do not need to handle errors
diff --git a/sysdeps/unix/sysv/linux/i386/time.c b/sysdeps/unix/sysv/linux/i386/time.c
deleted file mode 100644
index 440e3e6ab4..0000000000
--- a/sysdeps/unix/sysv/linux/i386/time.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* time -- Get number of seconds since Epoch.  Linux/i386 version.
-   Copyright (C) 2015-2019 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#ifdef SHARED
-# define time __redirect_time
-#endif
-
-#include <time.h>
-
-#ifdef SHARED
-# undef time
-# define time_type __redirect_time
-
-# undef libc_hidden_def
-# define libc_hidden_def(name)  \
-  __hidden_ver1 (__time_syscall, __GI_time, __time_syscall);
-#endif
-
-#include <sysdeps/unix/sysv/linux/x86/time.c>
diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/sysdep.h
index cf967a8c33..44bfa3f1b6 100644
--- a/sysdeps/unix/sysv/linux/powerpc/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/sysdep.h
@@ -24,6 +24,7 @@
 #define HAVE_CLOCK_GETTIME_VSYSCALL	"__kernel_clock_gettime"
 #define HAVE_GETCPU_VSYSCALL		"__kernel_getcpu"
 #define HAVE_TIME_VSYSCALL		"__kernel_time"
+#define USE_TIME_VSYSCALL_IFUNC		1
 #define HAVE_GETTIMEOFDAY_VSYSCALL	"__kernel_gettimeofday"
 #define HAVE_GET_TBFREQ                 "__kernel_get_tbfreq"
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/time.c b/sysdeps/unix/sysv/linux/powerpc/time.c
deleted file mode 100644
index ca6721cf95..0000000000
--- a/sysdeps/unix/sysv/linux/powerpc/time.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* time system call for Linux/PowerPC.
-   Copyright (C) 2013-2019 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#ifdef SHARED
-# ifndef __powerpc64__
-#  define time __redirect_time
-# else
-#  define __redirect_time time
-# endif
-
-# include <time.h>
-# include <sysdep.h>
-# include <dl-vdso.h>
-# include <libc-vdso.h>
-# include <dl-machine.h>
-
-# ifndef __powerpc64__
-#  undef time
-
-time_t
-__time_vsyscall (time_t *t)
-{
-  return INLINE_VSYSCALL (time, 1, t);
-}
-
-/* __GI_time is defined as hidden and for ppc32 it enables the
-   compiler make a local call (symbol@local) for internal GLIBC usage. It
-   means the PLT won't be used and the ifunc resolver will be called directly.
-   For ppc64 a call to a function in another translation unit might use a
-   different toc pointer thus disallowing direct branchess and making internal
-   ifuncs calls safe.  */
-#  undef libc_hidden_def
-#  define libc_hidden_def(name)					\
-  __hidden_ver1 (__time_vsyscall, __GI_time, __time_vsyscall);
-
-# endif /* !__powerpc64__  */
-
-static time_t
-time_syscall (time_t *t)
-{
-  struct timeval tv;
-  time_t result;
-
-  if (INLINE_VSYSCALL (gettimeofday, 2, &tv, NULL) < 0)
-    result = (time_t) -1;
-  else
-    result = (time_t) tv.tv_sec;
-
-  if (t != NULL)
-    *t = result;
-  return result;
-}
-
-# define INIT_ARCH()							\
-  void *vdso_time = get_vdso_symbol (HAVE_TIME_VSYSCALL);
-
-/* If the vDSO is not available we fall back to the syscall.  */
-libc_ifunc_hidden (__redirect_time, time,
-		   vdso_time
-		   ? vdso_time
-		   : (void *) time_syscall);
-libc_hidden_def (time)
-
-#else
-
-#include <sysdeps/posix/time.c>
-
-#endif /* !SHARED */
diff --git a/sysdeps/unix/sysv/linux/time.c b/sysdeps/unix/sysv/linux/time.c
index 1978f6d817..93e036fe16 100644
--- a/sysdeps/unix/sysv/linux/time.c
+++ b/sysdeps/unix/sysv/linux/time.c
@@ -15,27 +15,64 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <stddef.h>
+/* Currently we have 3 possible time implementations, which is also selected
+   in the order:
+
+   1. Wire-up __NR_time with a vDSO implementation (currently only x86 and
+      powerpc).
+   2. Only wire-up __NR_time (usually old kABIs).
+   3. Using internal gettimeofday (which may call a vDSO as well).  */
+
+#define time __redirect_time
 #include <time.h>
+#undef time
+#include <sys/time.h>
 
 #include <sysdep.h>
+#ifdef HAVE_TIME_VSYSCALL
+# define HAVE_VSYSCALL
+#endif
+#include <sysdep-vdso.h>
+#include <libc-vdso.h>
 
-#ifdef __NR_time
-
-time_t
-time (time_t *t)
+static time_t
+time_syscall (time_t *t)
 {
+  time_t res;
+#ifdef __NR_time
   INTERNAL_SYSCALL_DECL (err);
-  time_t res = INTERNAL_SYSCALL (time, err, 1, NULL);
+  res = INTERNAL_VSYSCALL (time, err, 1, NULL);
   /* There cannot be any error.  */
+#else
+  struct timeval tv;
+  /* gettimeofday does not fail with valid 'tv' and null timezone.  */
+  __gettimeofday (&tv, NULL);
+  res = tv.tv_sec;
+#endif
   if (t != NULL)
     *t = res;
   return res;
 }
-libc_hidden_def (time)
 
+#if HAVE_IFUNC && defined USE_TIME_VSYSCALL_IFUNC
+/* Route externals calls direct to vDSO and static and internal calls to
+   fallback implementation (which also might call the vDSO).  */
+# ifdef SHARED
+#  define INIT_ARCH()
+libc_ifunc_redirected (__redirect_time, time,
+		       get_vdso_symbol (HAVE_TIME_VSYSCALL)
+		       ?: time_syscall);
+libc_hidden_def_redir (time_syscall, time)
+#  else
+strong_alias (time_syscall, time)
+#  endif /* SHARED  */
 #else
 
-# include <sysdeps/posix/time.c>
+time_t
+time (time_t *t)
+{
+  return time_syscall (t);
+}
+libc_hidden_def_redir (time, time)
 
 #endif
diff --git a/sysdeps/unix/sysv/linux/x86/time.c b/sysdeps/unix/sysv/linux/x86/time.c
deleted file mode 100644
index 60e6d1b7c0..0000000000
--- a/sysdeps/unix/sysv/linux/x86/time.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* time -- Get number of seconds since Epoch.  Linux/x86 version.
-   Copyright (C) 2015-2019 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <time.h>
-
-#ifdef SHARED
-
-#include <dl-vdso.h>
-#include <errno.h>
-#include <sysdep-vdso.h>
-
-static time_t
-__time_syscall (time_t *t)
-{
-  INTERNAL_SYSCALL_DECL (err);
-  return INTERNAL_SYSCALL (time, err, 1, t);
-}
-
-# ifndef time_type
-/* The i386 time.c includes this file with a defined time_type macro.
-   For x86_64 we have to define it to time as the internal symbol is the
-   ifunc'ed one.  */
-#  define time_type time
-# endif
-
-#undef INIT_ARCH
-#define INIT_ARCH()
-
-/* If the vDSO is not available we fall back on the syscall.  */
-libc_ifunc_hidden (time_type, time,
-		   (get_vdso_symbol ("__vdso_time") ?: __time_syscall))
-libc_hidden_def (time)
-
-#else
-
-# include <sysdep.h>
-
-time_t
-time (time_t *t)
-{
-  INTERNAL_SYSCALL_DECL (err);
-  return INTERNAL_SYSCALL (time, err, 1, t);
-}
-
-#endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
index 4541c0d492..c64fbd1e26 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
@@ -376,6 +376,8 @@
 /* List of system calls which are supported as vsyscalls.  */
 # define HAVE_CLOCK_GETTIME_VSYSCALL    "__vdso_clock_gettime"
 # define HAVE_GETTIMEOFDAY_VSYSCALL     "__vdso_gettimeofday"
+# define HAVE_TIME_VSYSCALL		"__vdso_time"
+# define USE_TIME_VSYSCALL_IFUNC	1
 # define HAVE_GETCPU_VSYSCALL		"__vdso_getcpu"
 
 # define SINGLE_THREAD_BY_GLOBAL		1
