2014-01-20  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>

	[BZ#16431]
	* sysdeps/unix/sysv/linux/powerpc/gettimeofday.c (__gettimeofday):
	Adjust the vDSO correctly for internal calls.

2014-01-16  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>

	[BZ#16430]
        * sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
	(__GI___gettimeofday): Alias for a different internal symbol to avoid
	local calls issues by not having a PLT stub required for IFUNC calls.

2013-11-08  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>

	* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h (VDSO_IFUNC_RET):
	Add artificial ODP entry for vDSO symbol for PPC64.
	* sysdeps/unix/sysv/linux/powerpc/gettimeofday.c: Adjust includes.

2013-03-15  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>

	* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h (VDSO_IFUNC_RET): Add
	macro to return vdso values correctly in IFUNC implementations.
	* sysdeps/unix/sysv/linux/powerpc/gettimeofday.c (__gettimeofday):
	Optimization by using IFUNC.

Index: glibc-2.11.3/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
===================================================================
--- glibc-2.11.3.orig/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+++ glibc-2.11.3/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
@@ -33,6 +33,36 @@ extern void *__vdso_get_tbfreq;
 
 extern void *__vdso_getcpu;
 
+#if defined(__PPC64__) || defined(__powerpc64__)
+/* 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
 
 #endif /* _LIBC_VDSO_H */
Index: glibc-2.11.3/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
===================================================================
--- glibc-2.11.3.orig/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ glibc-2.11.3/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -16,27 +16,69 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <sysdep.h>
-#include <bp-checks.h>
-#include <stddef.h>
-#include <sys/time.h>
-#include <time.h>
-#include <hp-timing.h>
 
+#include <sys/time.h>
 #undef __gettimeofday
-#include <bits/libc-vdso.h>
 
-/* Get the current time of day and timezone information,
-   putting it into *TV and *TZ.  If TZ is NULL, *TZ is not filled.
-   Returns 0 on success, -1 on errors.  */
+#ifdef SHARED
+
+# include <dl-vdso.h>
+# include <bits/libc-vdso.h>
+# include <dl-machine.h>
+
+void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday");
+
+static int
+__gettimeofday_syscall (struct timeval *tv, struct timezone *tz)
+{
+  return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
+}
+
+void *
+gettimeofday_ifunc (void)
+{
+  PREPARE_VERSION (linux2615, "LINUX_2.6.15", 123718565);
+
+  /* If the vDSO is not available we fall back syscall.  */
+  void *vdso_gettimeofday = _dl_vdso_vsym ("__kernel_gettimeofday", &linux2615);
+  return (vdso_gettimeofday ? VDSO_IFUNC_RET (vdso_gettimeofday)
+	  : (void*)__gettimeofday_syscall);
+}
+asm (".type __gettimeofday, %gnu_indirect_function");
+
+/* This is doing "INTDEF (__gettimeofday)" but the compiler won't
+   let us do it in C because it doesn't know we're defining __gettimeofday
+   here in this file.  */
+asm (".globl __gettimeofday_internal");
+
+/* __gettimeofday_internal 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.  */
+#ifdef __powerpc64__
+asm ("__gettimeofday_internal = __gettimeofday");
+#else
+int
+__gettimeofday_vsyscall (struct timeval *tv, struct timezone *tz)
+{
+  return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+}
+asm ("__gettimeofday_internal = __gettimeofday_vsyscall");
+#endif
+
+#else
+
+# include <sysdep.h>
+# include <errno.h>
 
 int
-__gettimeofday (tv, tz)
-     struct timeval *tv;
-     struct timezone *tz;
+__gettimeofday (struct timeval *tv, struct timezone *tz)
 {
-  return INLINE_VSYSCALL (gettimeofday, 2, CHECK_1 (tv), CHECK_1 (tz));
+  return INLINE_SYSCALL (gettimeofday, 2, tv, tz);
 }
 
 INTDEF (__gettimeofday)
+#endif
 weak_alias (__gettimeofday, gettimeofday)
