diff options
author | Stefani Seibold <stefani@seibold.net> | 2014-03-17 23:22:09 +0100 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-03-18 12:52:37 -0700 |
commit | 7a59ed415f5b57469e22e41fc4188d5399e0b194 (patch) | |
tree | fb57bae076853fbcbd44af62fb07d77d3c44125b /arch/x86/vdso/vclock_gettime.c | |
parent | b4b541a610c4db8643b36030ee5012203ca65778 (diff) | |
download | linux-7a59ed415f5b57469e22e41fc4188d5399e0b194.tar.bz2 |
x86, vdso: Add 32 bit VDSO time support for 32 bit kernel
This patch add the time support for 32 bit a VDSO to a 32 bit kernel.
For 32 bit programs running on a 32 bit kernel, the same mechanism is
used as for 64 bit programs running on a 64 bit kernel.
Reviewed-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Link: http://lkml.kernel.org/r/1395094933-14252-10-git-send-email-stefani@seibold.net
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/vdso/vclock_gettime.c')
-rw-r--r-- | arch/x86/vdso/vclock_gettime.c | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c index 09dae4a1c6dc..90bb5e8027ac 100644 --- a/arch/x86/vdso/vclock_gettime.c +++ b/arch/x86/vdso/vclock_gettime.c @@ -4,6 +4,9 @@ * * Fast user context implementation of clock_gettime, gettimeofday, and time. * + * 32 Bit compat layer by Stefani Seibold <stefani@seibold.net> + * sponsored by Rohde & Schwarz GmbH & Co. KG Munich/Germany + * * The code should have no internal unresolved relocations. * Check with readelf after changing. */ @@ -12,13 +15,11 @@ #define DISABLE_BRANCH_PROFILING #include <linux/kernel.h> -#include <linux/posix-timers.h> -#include <linux/time.h> +#include <uapi/linux/time.h> #include <linux/string.h> #include <asm/vsyscall.h> #include <asm/fixmap.h> #include <asm/vgtod.h> -#include <asm/timex.h> #include <asm/hpet.h> #include <asm/unistd.h> #include <asm/io.h> @@ -26,6 +27,12 @@ #define gtod (&VVAR(vsyscall_gtod_data)) +extern int __vdso_clock_gettime(clockid_t clock, struct timespec *ts); +extern int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz); +extern time_t __vdso_time(time_t *t); + +#ifndef BUILD_VDSO32 + static notrace cycle_t vread_hpet(void) { return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + HPET_COUNTER); @@ -118,6 +125,59 @@ static notrace cycle_t vread_pvclock(int *mode) } #endif +#else + +extern u8 hpet_page + __attribute__((visibility("hidden"))); + +#ifdef CONFIG_HPET_TIMER +static notrace cycle_t vread_hpet(void) +{ + return readl((const void __iomem *)(&hpet_page + HPET_COUNTER)); +} +#endif + +notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) +{ + long ret; + + asm( + "mov %%ebx, %%edx \n" + "mov %2, %%ebx \n" + "call VDSO32_vsyscall \n" + "mov %%edx, %%ebx \n" + : "=a" (ret) + : "0" (__NR_clock_gettime), "g" (clock), "c" (ts) + : "memory", "edx"); + return ret; +} + +notrace static long vdso_fallback_gtod(struct timeval *tv, struct timezone *tz) +{ + long ret; + + asm( + "mov %%ebx, %%edx \n" + "mov %2, %%ebx \n" + "call VDSO32_vsyscall \n" + "mov %%edx, %%ebx \n" + : "=a" (ret) + : "0" (__NR_gettimeofday), "g" (tv), "c" (tz) + : "memory", "edx"); + return ret; +} + +#ifdef CONFIG_PARAVIRT_CLOCK + +static notrace cycle_t vread_pvclock(int *mode) +{ + *mode = VCLOCK_NONE; + return 0; +} +#endif + +#endif + notrace static cycle_t vread_tsc(void) { cycle_t ret; @@ -131,7 +191,7 @@ notrace static cycle_t vread_tsc(void) * but no one has ever seen it happen. */ rdtsc_barrier(); - ret = (cycle_t)vget_cycles(); + ret = (cycle_t)__native_read_tsc(); last = gtod->clock.cycle_last; @@ -152,12 +212,14 @@ notrace static cycle_t vread_tsc(void) notrace static inline u64 vgetsns(int *mode) { - long v; + u64 v; cycles_t cycles; if (gtod->clock.vclock_mode == VCLOCK_TSC) cycles = vread_tsc(); +#ifdef CONFIG_HPET_TIMER else if (gtod->clock.vclock_mode == VCLOCK_HPET) cycles = vread_hpet(); +#endif #ifdef CONFIG_PARAVIRT_CLOCK else if (gtod->clock.vclock_mode == VCLOCK_PVCLOCK) cycles = vread_pvclock(mode); @@ -189,7 +251,7 @@ notrace static int __always_inline do_realtime(struct timespec *ts) return mode; } -notrace static int do_monotonic(struct timespec *ts) +notrace static int __always_inline do_monotonic(struct timespec *ts) { unsigned long seq; u64 ns; @@ -284,7 +346,7 @@ int gettimeofday(struct timeval *, struct timezone *) */ notrace time_t __vdso_time(time_t *t) { - /* This is atomic on x86_64 so we don't need any locks. */ + /* This is atomic on x86 so we don't need any locks. */ time_t result = ACCESS_ONCE(gtod->wall_time_sec); if (t) |