xen/x86: support XENPF_settime64
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>
Mon, 23 Nov 2015 10:42:12 +0000 (10:42 +0000)
committerDavid Vrabel <david.vrabel@citrix.com>
Mon, 21 Dec 2015 14:40:59 +0000 (14:40 +0000)
Try XENPF_settime64 first, if it is not available fall back to
XENPF_settime32.

No need to call __current_kernel_time() when all the info needed are
already passed via the struct timekeeper * argument.

Return NOTIFY_BAD in case of errors.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
arch/x86/xen/time.c

index 3bbd377e1657040fad9526495a1a7ca6c04a5f2a..4b8af45b211a121f102f3ec836d7dc1094450680 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/gfp.h>
 #include <linux/slab.h>
 #include <linux/pvclock_gtod.h>
+#include <linux/timekeeper_internal.h>
 
 #include <asm/pvclock.h>
 #include <asm/xen/hypervisor.h>
@@ -123,9 +124,13 @@ static int xen_pvclock_gtod_notify(struct notifier_block *nb,
        static struct timespec next_sync;
 
        struct xen_platform_op op;
-       struct timespec now;
+       struct timespec64 now;
+       struct timekeeper *tk = priv;
+       static bool settime64_supported = true;
+       int ret;
 
-       now = __current_kernel_time();
+       now.tv_sec = tk->xtime_sec;
+       now.tv_nsec = (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift);
 
        /*
         * We only take the expensive HV call when the clock was set
@@ -134,12 +139,28 @@ static int xen_pvclock_gtod_notify(struct notifier_block *nb,
        if (!was_set && timespec_compare(&now, &next_sync) < 0)
                return NOTIFY_OK;
 
-       op.cmd = XENPF_settime32;
-       op.u.settime32.secs = now.tv_sec;
-       op.u.settime32.nsecs = now.tv_nsec;
-       op.u.settime32.system_time = xen_clocksource_read();
+again:
+       if (settime64_supported) {
+               op.cmd = XENPF_settime64;
+               op.u.settime64.mbz = 0;
+               op.u.settime64.secs = now.tv_sec;
+               op.u.settime64.nsecs = now.tv_nsec;
+               op.u.settime64.system_time = xen_clocksource_read();
+       } else {
+               op.cmd = XENPF_settime32;
+               op.u.settime32.secs = now.tv_sec;
+               op.u.settime32.nsecs = now.tv_nsec;
+               op.u.settime32.system_time = xen_clocksource_read();
+       }
+
+       ret = HYPERVISOR_platform_op(&op);
 
-       (void)HYPERVISOR_platform_op(&op);
+       if (ret == -ENOSYS && settime64_supported) {
+               settime64_supported = false;
+               goto again;
+       }
+       if (ret < 0)
+               return NOTIFY_BAD;
 
        /*
         * Move the next drift compensation time 11 minutes
This page took 0.025882 seconds and 5 git commands to generate.