Fix powerpc32 __get_clockfreq for non-power4 (bug 17263)

Message ID Pine.LNX.4.64.1408122344440.5394@digraph.polyomino.org.uk
State Committed
Headers

Commit Message

Joseph Myers Aug. 12, 2014, 11:45 p.m. UTC
  In my powerpc32 testing I've observed misc/test-gettimebasefreq
failing.

This is a glibc build (soft-float, though that's not relevant here)
without any --with-cpu and without any special configuration of the
default CPU for GCC either.  In particular, it's one not using
sysdeps/powerpc/powerpc32/power4/hp-timing.h (although in fact the
processor I'm using for testing is POWER4-based), so hp_timing_t is
32-bit not 64-bit.  But the VDSO call being used by
INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK is generating a 64-bit result
(high part in r3, low part in r4).  The code extracting that result,
however, expects a result of the type hp_timing_t as passed to
INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK, meaning that only r3 (= 0) is
used and the value in r4 is ignored.  This patch fixes this by always
using uint64_t as the type in INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK -
reflecting the actual ABI (unconditional in the kernel) of that VDSO
call.  This is the minimal change for this issue - no check for
overflow, no change of the type of the timebase_freq variable or the
return type of __get_clockfreq to something other than hp_timing_t
(such a change would simply move the implicit conversions to the over
callers of that function), no change to hp_timing_t itself.

Tested for powerpc32 soft float.

2014-08-12  Joseph Myers  <joseph@codesourcery.com>

	[BZ #17263]
	* sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c: Include
	<stdint.h>.
	(__get_clockfreq): Use uint64_t instead of hp_timing_t in
	INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK call.
  

Comments

Adhemerval Zanella Netto Aug. 13, 2014, 12:32 p.m. UTC | #1
That's ok, thanks for catching this.

On 12-08-2014 20:45, Joseph S. Myers wrote:
> In my powerpc32 testing I've observed misc/test-gettimebasefreq
> failing.
>
> This is a glibc build (soft-float, though that's not relevant here)
> without any --with-cpu and without any special configuration of the
> default CPU for GCC either.  In particular, it's one not using
> sysdeps/powerpc/powerpc32/power4/hp-timing.h (although in fact the
> processor I'm using for testing is POWER4-based), so hp_timing_t is
> 32-bit not 64-bit.  But the VDSO call being used by
> INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK is generating a 64-bit result
> (high part in r3, low part in r4).  The code extracting that result,
> however, expects a result of the type hp_timing_t as passed to
> INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK, meaning that only r3 (= 0) is
> used and the value in r4 is ignored.  This patch fixes this by always
> using uint64_t as the type in INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK -
> reflecting the actual ABI (unconditional in the kernel) of that VDSO
> call.  This is the minimal change for this issue - no check for
> overflow, no change of the type of the timebase_freq variable or the
> return type of __get_clockfreq to something other than hp_timing_t
> (such a change would simply move the implicit conversions to the over
> callers of that function), no change to hp_timing_t itself.
>
> Tested for powerpc32 soft float.
>
> 2014-08-12  Joseph Myers  <joseph@codesourcery.com>
>
> 	[BZ #17263]
> 	* sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c: Include
> 	<stdint.h>.
> 	(__get_clockfreq): Use uint64_t instead of hp_timing_t in
> 	INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK call.
>
> diff --git a/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c b/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
> index 8b37943..62217b1 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
> +++ b/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
> @@ -18,6 +18,7 @@
>
>  #include <ctype.h>
>  #include <fcntl.h>
> +#include <stdint.h>
>  #include <string.h>
>  #include <unistd.h>
>  #include <libc-internal.h>
> @@ -42,7 +43,7 @@ __get_clockfreq (void)
>  #ifdef SHARED
>    INTERNAL_SYSCALL_DECL (err);
>    timebase_freq =
> -    INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, hp_timing_t, 0);
> +    INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, uint64_t, 0);
>    if (INTERNAL_SYSCALL_ERROR_P (timebase_freq, err)
>        && INTERNAL_SYSCALL_ERRNO (timebase_freq, err) == ENOSYS)
>  #endif
>
  

Patch

diff --git a/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c b/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
index 8b37943..62217b1 100644
--- a/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
+++ b/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c
@@ -18,6 +18,7 @@ 
 
 #include <ctype.h>
 #include <fcntl.h>
+#include <stdint.h>
 #include <string.h>
 #include <unistd.h>
 #include <libc-internal.h>
@@ -42,7 +43,7 @@  __get_clockfreq (void)
 #ifdef SHARED
   INTERNAL_SYSCALL_DECL (err);
   timebase_freq =
-    INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, hp_timing_t, 0);
+    INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, uint64_t, 0);
   if (INTERNAL_SYSCALL_ERROR_P (timebase_freq, err)
       && INTERNAL_SYSCALL_ERRNO (timebase_freq, err) == ENOSYS)
 #endif