[PATCH] hyperv: Implement Time Synchronization using host time sample

2014-10-14 Thread Thomas Shao
In current hyper-v time sync service,it only gets the initial clock time
from the host. It didn't process the following time samples. This change
introduced a module parameter called host_time_sync. If it is set to true,
the guest will periodically sychronize it's time with the host clock using
host time sample. By default it is disabled, because we still recommend
user to configure NTP for time synchronization.

Signed-off-by: Thomas Shao huis...@microsoft.com
Reviewed-by: K. Y. Srinivasan k...@microsoft.com
---
 drivers/hv/hv_util.c  |  114 +---
 kernel/time/timekeeping.c |1 +
 2 files changed, 107 insertions(+), 8 deletions(-)

diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 3b9c9ef..1d8390c 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -51,11 +51,30 @@
 #define HB_WS2008_MAJOR1
 #define HB_WS2008_VERSION  (HB_WS2008_MAJOR  16 | HB_MINOR)
 
+#define  TIMESAMPLE_INTERVAL 50L  /* 5s in nanosecond */
+
+/*host sends time sample for every 5s.So the max polling interval
+ *is 128*5 = 640s.
+*/
+#define  TIME_ADJ_MAX_INTERVAL 128 /*Max polling interval */
+
 static int sd_srv_version;
 static int ts_srv_version;
 static int hb_srv_version;
 static int util_fw_version;
 
+/*host sends time sample for every 5s.So the initial polling interval
+ *is 5s.
+*/
+static s32 adj_interval = 1;
+
+/*The host_time_sync module parameter is used to control the time
+  sync between host and guest.
+*/
+static bool host_time_sync;
+module_param(host_time_sync, bool, (S_IRUGO | S_IWUSR));
+MODULE_PARM_DESC(host_time_sync, If the guest sync time with host);
+
 static void shutdown_onchannelcallback(void *context);
 static struct hv_util_service util_shutdown = {
.util_cb = shutdown_onchannelcallback,
@@ -163,15 +182,61 @@ static void shutdown_onchannelcallback(void *context)
 /*
  * Set guest time to host UTC time.
  */
-static inline void do_adj_guesttime(u64 hosttime)
+static inline void do_adj_guesttime(u64 hosttime, bool forceSync)
 {
-   s64 host_tns;
-   struct timespec host_ts;
+   s64 host_tns, guest_tns, diff;
+   struct timespec host_ts, guest_ts;
+   struct timex txc;
+   s64 tickchg;
+   int diff_sign;
 
host_tns = (hosttime - WLTIMEDELTA) * 100;
host_ts = ns_to_timespec(host_tns);
 
-   do_settimeofday(host_ts);
+   if (forceSync) {
+   do_settimeofday(host_ts);
+   } else {
+   guest_ts = CURRENT_TIME;
+   guest_tns = timespec_to_ns(guest_ts);
+   diff = host_tns - guest_tns;
+   if (diff = 0) {
+   diff_sign = 1;
+   } else {
+   diff_sign = -1;
+   diff = -diff;
+   }
+
+   /*1s in nanosecond */
+   if (diff  10 || diff  -10) {
+   do_settimeofday(host_ts);
+   return;
+   }
+
+   /*1ms in nanosecond */
+   if (diff  100 || diff  -100) {
+   /* get the current tick value */
+   txc.modes = 0;
+   do_adjtimex(txc);
+
+   tickchg = diff * TICK_USEC /
+   (TIMESAMPLE_INTERVAL * adj_interval);
+
+   if (tickchg  TICK_USEC/10)
+   tickchg = TICK_USEC/10;
+
+   if (txc.tick == TICK_USEC + diff_sign * tickchg)
+   return;
+
+   txc.modes = ADJ_TICK;
+   txc.tick = TICK_USEC + diff_sign * tickchg;
+
+   do_adjtimex(txc);
+   } else {
+   /* double the polling interval*/
+   if (adj_interval  TIME_ADJ_MAX_INTERVAL)
+   adj_interval = adj_interval * 2;
+   }
+   }
 }
 
 /*
@@ -179,8 +244,9 @@ static inline void do_adj_guesttime(u64 hosttime)
  */
 
 struct adj_time_work {
-   struct work_struct work;
+   struct  work_struct work;
u64 host_time;
+   boolforceSync;
 };
 
 static void hv_set_host_time(struct work_struct *work)
@@ -188,7 +254,7 @@ static void hv_set_host_time(struct work_struct *work)
struct adj_time_work*wrk;
 
wrk = container_of(work, struct adj_time_work, work);
-   do_adj_guesttime(wrk-host_time);
+   do_adj_guesttime(wrk-host_time, wrk-forceSync);
kfree(wrk);
 }
 
@@ -202,11 +268,14 @@ static void hv_set_host_time(struct work_struct *work)
  * thing is, systime is automatically set to emulated hardware clock which may
  * not be UTC time or in the same time zone. So, to override these effects, we
  * use the first 50 time samples for initial system time setting.
+ * If the host_time_sync module parameter is set, we will use the host time
+ * samples to 

Re: [PATCH] hyperv: Implement Time Synchronization using host time sample

2014-10-14 Thread Greg KH
On Tue, Oct 14, 2014 at 01:23:46AM -0700, Thomas Shao wrote:
 --- a/kernel/time/timekeeping.c
 +++ b/kernel/time/timekeeping.c
 @@ -1786,6 +1786,7 @@ int do_adjtimex(struct timex *txc)
  
   return ret;
  }
 +EXPORT_SYMBOL(do_adjtimex);

EXPORT_SYMBOL_GPL()?
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


RE: [PATCH] hyperv: Implement Time Synchronization using host time sample

2014-10-14 Thread Thomas Shao

 -Original Message-
 From: Greg KH [mailto:gre...@linuxfoundation.org]
 Sent: Tuesday, October 14, 2014 3:35 PM
 To: Thomas Shao
 Cc: t...@linutronix.de; linux-ker...@vger.kernel.org;
 de...@linuxdriverproject.org; o...@aepfle.de; a...@canonical.com;
 jasow...@redhat.com; KY Srinivasan
 Subject: Re: [PATCH] hyperv: Implement Time Synchronization using host
 time sample
 
 On Tue, Oct 14, 2014 at 01:23:46AM -0700, Thomas Shao wrote:
  --- a/kernel/time/timekeeping.c
  +++ b/kernel/time/timekeeping.c
  @@ -1786,6 +1786,7 @@ int do_adjtimex(struct timex *txc)
 
  return ret;
   }
  +EXPORT_SYMBOL(do_adjtimex);
 
 EXPORT_SYMBOL_GPL()?

Oh, yes,  I should use EXPORT_SYMBOL_GPL. I'll send a new patch. Thanks Greg.
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


RE: [PATCH] hyperv: Implement Time Synchronization using host time sample

2014-10-14 Thread Thomas Gleixner
On Tue, 14 Oct 2014, Thomas Shao wrote:
  -Original Message-
  From: Greg KH [mailto:gre...@linuxfoundation.org]
  Sent: Tuesday, October 14, 2014 3:35 PM
  To: Thomas Shao
  Cc: t...@linutronix.de; linux-ker...@vger.kernel.org;
  de...@linuxdriverproject.org; o...@aepfle.de; a...@canonical.com;
  jasow...@redhat.com; KY Srinivasan
  Subject: Re: [PATCH] hyperv: Implement Time Synchronization using host
  time sample
  
  On Tue, Oct 14, 2014 at 01:23:46AM -0700, Thomas Shao wrote:
   --- a/kernel/time/timekeeping.c
   +++ b/kernel/time/timekeeping.c
   @@ -1786,6 +1786,7 @@ int do_adjtimex(struct timex *txc)
  
 return ret;
}
   +EXPORT_SYMBOL(do_adjtimex);
  
  EXPORT_SYMBOL_GPL()?
 
 Oh, yes,  I should use EXPORT_SYMBOL_GPL. I'll send a new patch. Thanks Greg.

And please make that export a separate patch. 

Thanks,

tglx
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


RE: [PATCH] hyperv: Implement Time Synchronization using host time sample

2014-10-14 Thread Thomas Shao

 -Original Message-
 From: Thomas Gleixner [mailto:t...@linutronix.de]
 Sent: Tuesday, October 14, 2014 5:14 PM
 To: Thomas Shao
 Cc: Greg KH; linux-ker...@vger.kernel.org; de...@linuxdriverproject.org;
 o...@aepfle.de; a...@canonical.com; jasow...@redhat.com; KY Srinivasan
 Subject: RE: [PATCH] hyperv: Implement Time Synchronization using host
 time sample
 
 On Tue, 14 Oct 2014, Thomas Shao wrote:
   -Original Message-
   From: Greg KH [mailto:gre...@linuxfoundation.org]
   Sent: Tuesday, October 14, 2014 3:35 PM
   To: Thomas Shao
   Cc: t...@linutronix.de; linux-ker...@vger.kernel.org;
   de...@linuxdriverproject.org; o...@aepfle.de; a...@canonical.com;
   jasow...@redhat.com; KY Srinivasan
   Subject: Re: [PATCH] hyperv: Implement Time Synchronization using
   host time sample
  
   On Tue, Oct 14, 2014 at 01:23:46AM -0700, Thomas Shao wrote:
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1786,6 +1786,7 @@ int do_adjtimex(struct timex *txc)
   
return ret;
 }
+EXPORT_SYMBOL(do_adjtimex);
  
   EXPORT_SYMBOL_GPL()?
 
  Oh, yes,  I should use EXPORT_SYMBOL_GPL. I'll send a new patch. Thanks
 Greg.
 
 And please make that export a separate patch.
 
OK. I'll send the separate patch. For my original patch, do I need to wait? 
Since it depends on the 
Export patch to build.

 Thanks,
 
   tglx
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


RE: [PATCH] hyperv: Implement Time Synchronization using host time sample

2014-10-14 Thread Thomas Shao
These old duplicated patches are accidentally send by the mail server...  Sorry 
for that. 

 -Original Message-
 From: Thomas Shao [mailto:huis...@microsoft.com]
 Sent: Tuesday, October 14, 2014 1:49 PM
 To: t...@linutronix.de; gre...@linuxfoundation.org; linux-
 ker...@vger.kernel.org; de...@linuxdriverproject.org; o...@aepfle.de;
 a...@canonical.com; jasow...@redhat.com; KY Srinivasan
 Cc: Thomas Shao
 Subject: [PATCH] hyperv: Implement Time Synchronization using host time
 sample
 
 In current hyper-v time sync service,it only gets the initial clock time from 
 the
 host. It didn't process the following time samples. This change introduced a
 module parameter called host_time_sync. If it is set to true, the guest will
 periodically sychronize it's time with the host clock using host time sample. 
 By
 default it is disabled, because we still recommend user to configure NTP for
 time synchronization.
 
 Signed-off-by: Thomas Shao huis...@microsoft.com
 Reviewed-by: K. Y. Srinivasan k...@microsoft.com
 ---
  drivers/hv/hv_util.c  |  114
 +---
  kernel/time/timekeeping.c |1 +
  2 files changed, 107 insertions(+), 8 deletions(-)
 
 diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 
 3b9c9ef..1d8390c
 100644
 --- a/drivers/hv/hv_util.c
 +++ b/drivers/hv/hv_util.c
 @@ -51,11 +51,30 @@
  #define HB_WS2008_MAJOR  1
  #define HB_WS2008_VERSION(HB_WS2008_MAJOR  16 | HB_MINOR)
 
 +#define  TIMESAMPLE_INTERVAL 50L  /* 5s in nanosecond */
 +
 +/*host sends time sample for every 5s.So the max polling interval  *is
 +128*5 = 640s.
 +*/
 +#define  TIME_ADJ_MAX_INTERVAL 128 /*Max polling interval */
 +
  static int sd_srv_version;
  static int ts_srv_version;
  static int hb_srv_version;
  static int util_fw_version;
 
 +/*host sends time sample for every 5s.So the initial polling interval
 +*is 5s.
 +*/
 +static s32 adj_interval = 1;
 +
 +/*The host_time_sync module parameter is used to control the time
 +  sync between host and guest.
 +*/
 +static bool host_time_sync;
 +module_param(host_time_sync, bool, (S_IRUGO | S_IWUSR));
 +MODULE_PARM_DESC(host_time_sync, If the guest sync time with host);
 +
  static void shutdown_onchannelcallback(void *context);  static struct
 hv_util_service util_shutdown = {
   .util_cb = shutdown_onchannelcallback, @@ -163,15 +182,61 @@
 static void shutdown_onchannelcallback(void *context)
  /*
   * Set guest time to host UTC time.
   */
 -static inline void do_adj_guesttime(u64 hosttime)
 +static inline void do_adj_guesttime(u64 hosttime, bool forceSync)
  {
 - s64 host_tns;
 - struct timespec host_ts;
 + s64 host_tns, guest_tns, diff;
 + struct timespec host_ts, guest_ts;
 + struct timex txc;
 + s64 tickchg;
 + int diff_sign;
 
   host_tns = (hosttime - WLTIMEDELTA) * 100;
   host_ts = ns_to_timespec(host_tns);
 
 - do_settimeofday(host_ts);
 + if (forceSync) {
 + do_settimeofday(host_ts);
 + } else {
 + guest_ts = CURRENT_TIME;
 + guest_tns = timespec_to_ns(guest_ts);
 + diff = host_tns - guest_tns;
 + if (diff = 0) {
 + diff_sign = 1;
 + } else {
 + diff_sign = -1;
 + diff = -diff;
 + }
 +
 + /*1s in nanosecond */
 + if (diff  10 || diff  -10) {
 + do_settimeofday(host_ts);
 + return;
 + }
 +
 + /*1ms in nanosecond */
 + if (diff  100 || diff  -100) {
 + /* get the current tick value */
 + txc.modes = 0;
 + do_adjtimex(txc);
 +
 + tickchg = diff * TICK_USEC /
 + (TIMESAMPLE_INTERVAL *
 adj_interval);
 +
 + if (tickchg  TICK_USEC/10)
 + tickchg = TICK_USEC/10;
 +
 + if (txc.tick == TICK_USEC + diff_sign * tickchg)
 + return;
 +
 + txc.modes = ADJ_TICK;
 + txc.tick = TICK_USEC + diff_sign * tickchg;
 +
 + do_adjtimex(txc);
 + } else {
 + /* double the polling interval*/
 + if (adj_interval  TIME_ADJ_MAX_INTERVAL)
 + adj_interval = adj_interval * 2;
 + }
 + }
  }
 
  /*
 @@ -179,8 +244,9 @@ static inline void do_adj_guesttime(u64 hosttime)
   */
 
  struct adj_time_work {
 - struct work_struct work;
 + struct  work_struct work;
   u64 host_time;
 + boolforceSync;
  };
 
  static void hv_set_host_time(struct work_struct *work) @@ -188,7 +254,7
 @@ static void hv_set_host_time(struct work_struct *work)
   struct adj_time_work*wrk;
 
   wrk = container_of(work, struct adj_time_work, work