lib/vdso: Move fallback invocation to the callers
authorThomas Gleixner <tglx@linutronix.de>
Sun, 28 Jul 2019 13:12:53 +0000 (15:12 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 30 Jul 2019 22:09:09 +0000 (00:09 +0200)
To allow syscall fallbacks using the legacy 32bit syscall for 32bit VDSO
builds, move the fallback invocation out into the callers.

Split the common code out of __cvdso_clock_gettime/getres() and invoke the
syscall fallback in the 64bit and 32bit variants.

Preparatory work for using legacy syscalls in 32bit VDSO. No functional
change.

Fixes: 00b26474c2f1 ("lib/vdso: Provide generic VDSO implementation")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Link: https://lkml.kernel.org/r/20190728131648.695579736@linutronix.de
lib/vdso/gettimeofday.c

index e28f5a607a5fa810b1de4bf8d67f298fa8936547..a9e7fd029593ac60e4c28ebf4ff94f300e2090c1 100644 (file)
@@ -51,7 +51,7 @@ static int do_hres(const struct vdso_data *vd, clockid_t clk,
                ns = vdso_ts->nsec;
                last = vd->cycle_last;
                if (unlikely((s64)cycles < 0))
-                       return clock_gettime_fallback(clk, ts);
+                       return -1;
 
                ns += vdso_calc_delta(cycles, last, vd->mask, vd->mult);
                ns >>= vd->shift;
@@ -82,14 +82,14 @@ static void do_coarse(const struct vdso_data *vd, clockid_t clk,
 }
 
 static __maybe_unused int
-__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
+__cvdso_clock_gettime_common(clockid_t clock, struct __kernel_timespec *ts)
 {
        const struct vdso_data *vd = __arch_get_vdso_data();
        u32 msk;
 
        /* Check for negative values or invalid clocks */
        if (unlikely((u32) clock >= MAX_CLOCKS))
-               goto fallback;
+               return -1;
 
        /*
         * Convert the clockid to a bitmask and use it to check which
@@ -104,9 +104,17 @@ __cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
        } else if (msk & VDSO_RAW) {
                return do_hres(&vd[CS_RAW], clock, ts);
        }
+       return -1;
+}
 
-fallback:
-       return clock_gettime_fallback(clock, ts);
+static __maybe_unused int
+__cvdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
+{
+       int ret = __cvdso_clock_gettime_common(clock, ts);
+
+       if (unlikely(ret))
+               return clock_gettime_fallback(clock, ts);
+       return 0;
 }
 
 static __maybe_unused int
@@ -115,9 +123,12 @@ __cvdso_clock_gettime32(clockid_t clock, struct old_timespec32 *res)
        struct __kernel_timespec ts;
        int ret;
 
-       ret = __cvdso_clock_gettime(clock, &ts);
+       ret = __cvdso_clock_gettime_common(clock, &ts);
 
-       if (ret == 0) {
+       if (unlikely(ret))
+               ret = clock_gettime_fallback(clock, &ts);
+
+       if (likely(!ret)) {
                res->tv_sec = ts.tv_sec;
                res->tv_nsec = ts.tv_nsec;
        }
@@ -163,17 +174,18 @@ static __maybe_unused time_t __cvdso_time(time_t *time)
 
 #ifdef VDSO_HAS_CLOCK_GETRES
 static __maybe_unused
-int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
+int __cvdso_clock_getres_common(clockid_t clock, struct __kernel_timespec *res)
 {
        const struct vdso_data *vd = __arch_get_vdso_data();
-       u64 ns;
+       u64 hrtimer_res;
        u32 msk;
-       u64 hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
+       u64 ns;
 
        /* Check for negative values or invalid clocks */
        if (unlikely((u32) clock >= MAX_CLOCKS))
-               goto fallback;
+               return -1;
 
+       hrtimer_res = READ_ONCE(vd[CS_HRES_COARSE].hrtimer_res);
        /*
         * Convert the clockid to a bitmask and use it to check which
         * clocks are handled in the VDSO directly.
@@ -195,16 +207,22 @@ int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
                 */
                ns = hrtimer_res;
        } else {
-               goto fallback;
+               return -1;
        }
 
        res->tv_sec = 0;
        res->tv_nsec = ns;
 
        return 0;
+}
+
+int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
+{
+       int ret = __cvdso_clock_getres_common(clock, res);
 
-fallback:
-       return clock_getres_fallback(clock, res);
+       if (unlikely(ret))
+               return clock_getres_fallback(clock, res);
+       return 0;
 }
 
 static __maybe_unused int
@@ -213,13 +231,14 @@ __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
        struct __kernel_timespec ts;
        int ret;
 
-       ret = __cvdso_clock_getres(clock, &ts);
+       ret = __cvdso_clock_getres_common(clock, &ts);
+       if (unlikely(ret))
+               ret = clock_getres_fallback(clock, &ts);
 
-       if (ret == 0) {
+       if (likely(!ret)) {
                res->tv_sec = ts.tv_sec;
                res->tv_nsec = ts.tv_nsec;
        }
-
        return ret;
 }
 #endif /* VDSO_HAS_CLOCK_GETRES */