diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-vdso.h b/sysdeps/unix/sysv/linux/powerpc/dl-vdso.h
new file mode 100644
index 0000000000..f6858f02b2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/dl-vdso.h
@@ -0,0 +1,69 @@
+/* ELF symbol resolve functions for VDSO objects.  PowerPC version.
+   Copyright (C) 2005-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/>.  */
+
+#ifndef _DL_VDSO_POWERPC_H
+#define _DL_VDSO_POWERPC_H	1
+
+#if (defined(__PPC64__) || defined(__powerpc64__)) && _CALL_ELF != 2
+
+# include <dl-machine.h>
+# define get_vdso_symbol        __get_vdso_symbol
+# define get_vdso_mangle_symbol __get_vdso_mangle_symbol
+# include_next <dl-vdso.h>
+# undef get_vdso_symbol
+# undef get_vdso_mangle_symbol
+
+/* The correct solution is for _dl_vdso_vsym to return the address of the OPD
+   for the kernel VDSO function.  That address would then be stored in the
+   __vdso_* variables and returned as the result of the IFUNC resolver function.
+   Yet, the kernel does not contain any OPD entries for the VDSO functions
+   (incomplete implementation).  However, PLT relocations for IFUNCs still expect
+   the address of an OPD to be returned from the IFUNC resolver function (since
+   PLT entries on PPC64 are just copies of OPDs).  The solution for now is to
+   create an artificial static OPD for each VDSO function returned by a resolver
+   function.  The TOC value is set to a non-zero value to avoid triggering lazy
+   symbol resolution via .glink0/.plt0 for a zero TOC (requires thread-safe PLT
+   sequences) when the dynamic linker isn't prepared for it e.g. RTLD_NOW.  None
+   of the kernel VDSO routines use the TOC or AUX values so any non-zero value
+   will work.  Note that function pointer comparisons will not use this artificial
+   static OPD since those are resolved via ADDR64 relocations and will point at
+   the non-IFUNC default OPD for the symbol.  Lastly, because the IFUNC relocations
+   are processed immediately at startup the resolver functions and this code need
+   not be thread-safe, but if the caller writes to a PLT slot it must do so in a
+   thread-safe manner with all the required barriers.  */
+#define get_vdso_symbol(symbol)                                          \
+  ({                                                                     \
+    static Elf64_FuncDesc vdso_opd_##symbol = { .fd_toc = ~0x0 };        \
+    vdso_opd_##symbol.fd_func = (Elf64_Addr) __get_vdso_symbol (symbol); \
+    (void*)&vdso_opd_##symbol;                                           \
+  })
+
+#define get_vdso_mangle_symbol(symbol)					 \
+  ({                                                                     \
+    static Elf64_FuncDesc vdso_opd_##symbol = { .fd_toc = ~0x0 };        \
+    vdso_opd_##symbol.fd_func = (Elf64_Addr) __get_vdso_symbol (symbol); \
+    void *vdsop = &vdso_opd_##symbol;                                    \
+    PTR_MANGLE (vdsop);                                                  \
+    vdsop;                                                               \
+  })
+
+#else
+# include_next <dl-vdso.h>
+#endif
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c b/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c
index 23e7694d87..b551412356 100644
--- a/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c
+++ b/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c
@@ -23,17 +23,11 @@
 #include <not-cancel.h>
 #include <libc-vdso.h>
 
-uint64_t
-__get_timebase_freq (void)
+static uint64_t
+get_timebase_freq_fallback (void)
 {
   hp_timing_t result = 0L;
 
-#ifdef SHARED
-  /* The vDSO does not return an error (it clear cr0.so on returning).  */
-  INTERNAL_SYSCALL_DECL (err);
-  result =
-    INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, uint64_t, 0);
-#else
   /* We read the information from the /proc filesystem.  /proc/cpuinfo
      contains at least one line like:
      timebase        : 33333333
@@ -99,8 +93,18 @@ __get_timebase_freq (void)
 	    }
 	}
     }
-#endif
 
   return result;
 }
+
+uint64_t
+__get_timebase_freq (void)
+{
+  /* The vDSO does not have a fallback mechanism (such calling a syscall).  */
+  __typeof (VDSO_SYMBOL (get_tbfreq)) vdsop = VDSO_SYMBOL (get_tbfreq);
+  if (vdsop == NULL)
+    return get_timebase_freq_fallback ();
+  PTR_DEMANGLE (vdsop);
+  return vdsop ();
+}
 weak_alias (__get_timebase_freq, __ppc_get_timebase_freq)
diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
index 6b92e2807b..7a4e3cca0c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -58,13 +58,13 @@ __gettimeofday_syscall (struct timeval *tv, struct timezone *tz)
 }
 
 # define INIT_ARCH()						\
-  void *vdso_gettimeofday = get_vdso_symbol ("__kernel_gettimeofday")
+  void *vdso_gettimeofday = get_vdso_symbol (HAVE_GETTIMEOFDAY_VSYSCALL)
   
 
 /* If the vDSO is not available we fall back syscall.  */
 libc_ifunc_hidden (__redirect___gettimeofday, __gettimeofday,
 		   vdso_gettimeofday
-		   ? VDSO_IFUNC_RET (vdso_gettimeofday)
+		   ? vdso_gettimeofday
 		   : (void *) __gettimeofday_syscall);
 libc_hidden_def (__gettimeofday)
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h
index 47e925493b..c2da7bd7f1 100644
--- a/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h
@@ -32,34 +32,4 @@ extern void *VDSO_SYMBOL(sigtramp32);
 extern void *VDSO_SYMBOL(sigtramp_rt32);
 #endif
 
-#if (defined(__PPC64__) || defined(__powerpc64__)) && _CALL_ELF != 2
-/* The correct solution is for _dl_vdso_vsym to return the address of the OPD
-   for the kernel VDSO function.  That address would then be stored in the
-   __vdso_* variables and returned as the result of the IFUNC resolver function.
-   Yet, the kernel does not contain any OPD entries for the VDSO functions
-   (incomplete implementation).  However, PLT relocations for IFUNCs still expect
-   the address of an OPD to be returned from the IFUNC resolver function (since
-   PLT entries on PPC64 are just copies of OPDs).  The solution for now is to
-   create an artificial static OPD for each VDSO function returned by a resolver
-   function.  The TOC value is set to a non-zero value to avoid triggering lazy
-   symbol resolution via .glink0/.plt0 for a zero TOC (requires thread-safe PLT
-   sequences) when the dynamic linker isn't prepared for it e.g. RTLD_NOW.  None
-   of the kernel VDSO routines use the TOC or AUX values so any non-zero value
-   will work.  Note that function pointer comparisons will not use this artificial
-   static OPD since those are resolved via ADDR64 relocations and will point at
-   the non-IFUNC default OPD for the symbol.  Lastly, because the IFUNC relocations
-   are processed immediately at startup the resolver functions and this code need
-   not be thread-safe, but if the caller writes to a PLT slot it must do so in a
-   thread-safe manner with all the required barriers.  */
-#define VDSO_IFUNC_RET(value)                            \
-  ({                                                     \
-    static Elf64_FuncDesc vdso_opd = { .fd_toc = ~0x0 }; \
-    vdso_opd.fd_func = (Elf64_Addr)value;                \
-    &vdso_opd;                                           \
-  })
-
-#else
-#define VDSO_IFUNC_RET(value)  ((void *) (value))
-#endif
-
 #endif /* _LIBC_VDSO_H */
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
index f459543fcd..889c6ac117 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
@@ -34,43 +34,6 @@
 
 # include <errno.h>
 
-/* Define a macro which expands inline into the wrapper code for a VDSO
-   call. This use is for internal calls that do not need to handle errors
-   normally. It will never touch errno.
-   On powerpc a system call basically clobbers the same registers like a
-   function call, with the exception of LR (which is needed for the
-   "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
-   an error return status).  */
-# define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, nr, type, args...)	      \
-  ({									      \
-    register void *r0  __asm__ ("r0");					      \
-    register long int r3  __asm__ ("r3");				      \
-    register long int r4  __asm__ ("r4");				      \
-    register long int r5  __asm__ ("r5");				      \
-    register long int r6  __asm__ ("r6");				      \
-    register long int r7  __asm__ ("r7");				      \
-    register long int r8  __asm__ ("r8");				      \
-    register long int r9  __asm__ ("r9");				      \
-    register long int r10 __asm__ ("r10");				      \
-    register long int r11 __asm__ ("r11");				      \
-    register long int r12 __asm__ ("r12");				      \
-    register type rval  __asm__ ("r3");					      \
-    LOADARGS_##nr (funcptr, args);					      \
-    __asm__ __volatile__						      \
-      ("mtctr %0\n\t"							      \
-       "bctrl\n\t"							      \
-       "mfcr %0"							      \
-       : "+r" (r0), "+r" (r3), "+r" (r4), "+r" (r5),  "+r" (r6),  "+r" (r7),  \
-	 "+r" (r8), "+r" (r9), "+r" (r10), "+r" (r11), "+r" (r12)	      \
-       : : "cr0", "ctr", "lr", "memory");				      \
-    err = (long int) r0;						      \
-    __asm__ __volatile__ ("" : "=r" (rval) : "r" (r3), "r" (r4));	      \
-    rval;								      \
-  })
-
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
-  INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, nr, long int, args)
-
 # undef INLINE_SYSCALL
 # define INLINE_SYSCALL(name, nr, args...)				\
   ({									\
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
index 06222f52e6..4e507db00d 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
@@ -45,59 +45,9 @@
 
 #endif /* __ASSEMBLER__ */
 
-/* This version is for internal uses when there is no desire
-   to set errno */
-#define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, type, nr, args...)   \
-  ({									      \
-    type sc_ret = ENOSYS;						      \
-									      \
-    __typeof (__vdso_##name) vdsop = __vdso_##name;			      \
-    PTR_DEMANGLE (vdsop);						      \
-    if (vdsop != NULL)							      \
-      sc_ret =								      \
-        INTERNAL_VSYSCALL_CALL_TYPE (vdsop, err, type, nr, ##args);	      \
-    else								      \
-      err = 1 << 28;							      \
-    sc_ret;								      \
-  })
-
-/* 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
-   normally. It will never touch errno. This returns just what the kernel
-   gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
-   the negation of the return value in the kernel gets reverted.  */
-
-#define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, type, nr, args...)    \
-  ({									\
-    register void *r0  __asm__ ("r0");					\
-    register long int r3  __asm__ ("r3");				\
-    register long int r4  __asm__ ("r4");				\
-    register long int r5  __asm__ ("r5");				\
-    register long int r6  __asm__ ("r6");				\
-    register long int r7  __asm__ ("r7");				\
-    register long int r8  __asm__ ("r8");				\
-    register type rval  __asm__ ("r3");				        \
-    LOADARGS_##nr (funcptr, args);					\
-    __asm__ __volatile__						\
-      ("mtctr %0\n\t"							\
-       "bctrl\n\t"							\
-       "mfcr  %0\n\t"							\
-       "0:"								\
-       : "+r" (r0), "+r" (r3), "+r" (r4), "+r" (r5),  "+r" (r6),        \
-         "+r" (r7), "+r" (r8)						\
-       : : "r9", "r10", "r11", "r12", "cr0", "ctr", "lr", "memory");	\
-    err = (long int) r0;						\
-    __asm__ __volatile__ ("" : "=r" (rval) : "r" (r3));		        \
-    rval;								\
-  })
-
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...)		\
-  INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, long int, nr, args)
-
-#undef INLINE_SYSCALL
-
 /* This version is for kernels that implement system calls that
    behave like function calls as far as register saving.  */
+#undef INLINE_SYSCALL
 #define INLINE_SYSCALL(name, nr, args...)				\
   ({									\
     INTERNAL_SYSCALL_DECL (sc_err);					\
diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/sysdep.h
index 20167615c8..cf967a8c33 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 HAVE_GETTIMEOFDAY_VSYSCALL	"__kernel_gettimeofday"
 #define HAVE_GET_TBFREQ                 "__kernel_get_tbfreq"
 
 #if defined(__PPC64__) || defined(__powerpc64__)
@@ -32,3 +33,12 @@
 # define HAVE_SIGTRAMP_32		"__kernel_sigtramp32"
 # define HAVE_SIGTRAMP_RT32		"__kernel_sigtramp_rt32"
 #endif
+
+#ifndef __ASSEMBLER__
+
+/* PowerPC vDSO symbols always succeed, so there is no need to emulate a
+   function call and check for CR0.SO value.  */
+#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...)		\
+  ({ err = 0; funcptr (args); })
+
+#endif /* __ASSEMBLER__  */
diff --git a/sysdeps/unix/sysv/linux/powerpc/time.c b/sysdeps/unix/sysv/linux/powerpc/time.c
index 53fd119b00..ca6721cf95 100644
--- a/sysdeps/unix/sysv/linux/powerpc/time.c
+++ b/sysdeps/unix/sysv/linux/powerpc/time.c
@@ -67,12 +67,12 @@ time_syscall (time_t *t)
 }
 
 # define INIT_ARCH()							\
-  void *vdso_time = get_vdso_symbol ("__kernel_time");
+  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_IFUNC_RET (vdso_time)
+		   ? vdso_time
 		   : (void *) time_syscall);
 libc_hidden_def (time)
 
