* [PATCH 1/1] staging: hv: Add Time Sync feature to hv_utils module
@ 2010-05-05 19:23 Haiyang Zhang
2010-05-06 0:58 ` Joe Perches
0 siblings, 1 reply; 4+ messages in thread
From: Haiyang Zhang @ 2010-05-05 19:23 UTC (permalink / raw)
To: linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org,
virtualization@lists.osdl.org
Cc: Hank Janssen
[-- Attachment #1: Type: text/plain, Size: 6013 bytes --]
From: Haiyang Zhang <haiyangz@microsoft.com>
Subject: Add Time Sync feature to hv_utils module.
The Time Sync feature synchronizes guest time to host UTC time after reboot,
and restore from saved/paused state.
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/staging/hv/ChannelMgmt.c | 24 ++++++++++-
drivers/staging/hv/hyperv_utils.c | 84 +++++++++++++++++++++++++++++++++++++
drivers/staging/hv/utils.h | 25 ++++++++++-
3 files changed, 130 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c
index 445506d..71fe8dd 100644
--- a/drivers/staging/hv/ChannelMgmt.c
+++ b/drivers/staging/hv/ChannelMgmt.c
@@ -33,8 +33,8 @@ struct vmbus_channel_message_table_entry {
void (*messageHandler)(struct vmbus_channel_message_header *msg);
};
-#define MAX_MSG_TYPES 1
-#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 5
+#define MAX_MSG_TYPES 2
+#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 6
static const struct hv_guid
gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
@@ -81,6 +81,14 @@ static const struct hv_guid
0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
}
},
+ /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
+ /* TimeSync */
+ {
+ .data = {
+ 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+ 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
+ }
+ },
};
@@ -191,6 +199,18 @@ struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = {
.callback = chn_cb_negotiate,
.log_msg = "Shutdown channel functionality initialized"
},
+
+ /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
+ /* TimeSync */
+ {
+ .msg_type = HV_TIMESYNC_MSG,
+ .data = {
+ 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+ 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
+ },
+ .callback = chn_cb_negotiate,
+ .log_msg = "Timesync channel functionality initialized"
+ },
};
EXPORT_SYMBOL(hv_cb_utils);
diff --git a/drivers/staging/hv/hyperv_utils.c b/drivers/staging/hv/hyperv_utils.c
index cbebad3..9174f79 100644
--- a/drivers/staging/hv/hyperv_utils.c
+++ b/drivers/staging/hv/hyperv_utils.c
@@ -106,6 +106,82 @@ static void shutdown_onchannelcallback(void *context)
orderly_poweroff(false);
}
+
+/*
+ * Synchronize time with host after reboot, restore, etc.
+ */
+static void adj_guesttime(winfiletime_t hosttime, u8 flags)
+{
+ s64 host_tns;
+ struct timespec host_ts;
+ static s32 scnt = 50;
+
+ host_tns = (hosttime - WLTIMEDELTA) * 100;
+ host_ts = ns_to_timespec(host_tns);
+
+ if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
+ do_settimeofday(&host_ts);
+ return;
+ }
+
+ if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 &&
+ scnt > 0) {
+ scnt--;
+ do_settimeofday(&host_ts);
+ }
+
+ return;
+}
+
+/*
+ * Time Sync Channel message handler.
+ */
+static void timesync_onchannelcallback(void *context)
+{
+ struct vmbus_channel *channel = context;
+ u8 *buf;
+ u32 buflen, recvlen;
+ u64 requestid;
+ struct icmsg_hdr *icmsghdrp;
+ struct ictimesync_data *timedatap;
+
+ DPRINT_ENTER(VMBUS);
+
+ buflen = PAGE_SIZE;
+ buf = kmalloc(buflen, GFP_ATOMIC);
+
+ VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid);
+
+ if (recvlen > 0) {
+ DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld",
+ recvlen, requestid);
+
+ icmsghdrp = (struct icmsg_hdr *)&buf[
+ sizeof(struct vmbuspipe_hdr)];
+
+ if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+ prep_negotiate_resp(icmsghdrp, NULL, buf);
+ } else {
+ timedatap = (struct ictimesync_data *)&buf[
+ sizeof(struct vmbuspipe_hdr) +
+ sizeof(struct icmsg_hdr)];
+ adj_guesttime(timedatap->parenttime, timedatap->flags);
+ }
+
+ icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+ | ICMSGHDRFLAG_RESPONSE;
+
+ VmbusChannelSendPacket(channel, buf,
+ recvlen, requestid,
+ VmbusPacketTypeDataInBand, 0);
+ }
+
+ kfree(buf);
+
+ DPRINT_EXIT(VMBUS);
+}
+
+
static int __init init_hyperv_utils(void)
{
printk(KERN_INFO "Registering HyperV Utility Driver\n");
@@ -114,6 +190,10 @@ static int __init init_hyperv_utils(void)
&shutdown_onchannelcallback;
hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
+ hv_cb_utils[HV_TIMESYNC_MSG].channel->OnChannelCallback =
+ ×ync_onchannelcallback;
+ hv_cb_utils[HV_TIMESYNC_MSG].callback = ×ync_onchannelcallback;
+
return 0;
}
@@ -124,6 +204,10 @@ static void exit_hyperv_utils(void)
hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback =
&chn_cb_negotiate;
hv_cb_utils[HV_SHUTDOWN_MSG].callback = &chn_cb_negotiate;
+
+ hv_cb_utils[HV_TIMESYNC_MSG].channel->OnChannelCallback =
+ &chn_cb_negotiate;
+ hv_cb_utils[HV_TIMESYNC_MSG].callback = &chn_cb_negotiate;
}
module_init(init_hyperv_utils);
diff --git a/drivers/staging/hv/utils.h b/drivers/staging/hv/utils.h
index e404b21..d1d2f28 100644
--- a/drivers/staging/hv/utils.h
+++ b/drivers/staging/hv/utils.h
@@ -75,7 +75,30 @@ struct shutdown_msg_data {
u8 display_message[2048];
} __attribute__((packed));
-#define HV_SHUTDOWN_MSG 0
+
+/* Time Sync IC defs */
+#define ICTIMESYNCFLAG_PROBE 0
+#define ICTIMESYNCFLAG_SYNC 1
+#define ICTIMESYNCFLAG_SAMPLE 2
+
+#ifdef __x86_64__
+#define WLTIMEDELTA 116444736000000000L /* in 100ns unit */
+#else
+#define WLTIMEDELTA 116444736000000000LL
+#endif
+
+typedef u64 winfiletime_t; /* Windows FILETIME type */
+
+struct ictimesync_data{
+ winfiletime_t parenttime;
+ winfiletime_t childtime;
+ winfiletime_t roundtriptime;
+ u8 flags;
+} __attribute__((packed));
+
+/* Index for each IC struct in array hv_cb_utils[] */
+#define HV_SHUTDOWN_MSG 0
+#define HV_TIMESYNC_MSG 1
struct hyperv_service_callback {
u8 msg_type;
--
1.6.3.2
[-- Attachment #2: 0505-timesync-ic.patch --]
[-- Type: application/octet-stream, Size: 5800 bytes --]
From: Haiyang Zhang <haiyangz@microsoft.com>
Subject: Add Time Sync feature to hv_utils module.
The Time Sync feature synchronizes guest time to host UTC time after reboot,
and restore from saved/paused state.
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/staging/hv/ChannelMgmt.c | 24 ++++++++++-
drivers/staging/hv/hyperv_utils.c | 84 +++++++++++++++++++++++++++++++++++++
drivers/staging/hv/utils.h | 25 ++++++++++-
3 files changed, 130 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/hv/ChannelMgmt.c b/drivers/staging/hv/ChannelMgmt.c
index 445506d..71fe8dd 100644
--- a/drivers/staging/hv/ChannelMgmt.c
+++ b/drivers/staging/hv/ChannelMgmt.c
@@ -33,8 +33,8 @@ struct vmbus_channel_message_table_entry {
void (*messageHandler)(struct vmbus_channel_message_header *msg);
};
-#define MAX_MSG_TYPES 1
-#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 5
+#define MAX_MSG_TYPES 2
+#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 6
static const struct hv_guid
gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
@@ -81,6 +81,14 @@ static const struct hv_guid
0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
}
},
+ /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
+ /* TimeSync */
+ {
+ .data = {
+ 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+ 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
+ }
+ },
};
@@ -191,6 +199,18 @@ struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = {
.callback = chn_cb_negotiate,
.log_msg = "Shutdown channel functionality initialized"
},
+
+ /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
+ /* TimeSync */
+ {
+ .msg_type = HV_TIMESYNC_MSG,
+ .data = {
+ 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
+ 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
+ },
+ .callback = chn_cb_negotiate,
+ .log_msg = "Timesync channel functionality initialized"
+ },
};
EXPORT_SYMBOL(hv_cb_utils);
diff --git a/drivers/staging/hv/hyperv_utils.c b/drivers/staging/hv/hyperv_utils.c
index cbebad3..9174f79 100644
--- a/drivers/staging/hv/hyperv_utils.c
+++ b/drivers/staging/hv/hyperv_utils.c
@@ -106,6 +106,82 @@ static void shutdown_onchannelcallback(void *context)
orderly_poweroff(false);
}
+
+/*
+ * Synchronize time with host after reboot, restore, etc.
+ */
+static void adj_guesttime(winfiletime_t hosttime, u8 flags)
+{
+ s64 host_tns;
+ struct timespec host_ts;
+ static s32 scnt = 50;
+
+ host_tns = (hosttime - WLTIMEDELTA) * 100;
+ host_ts = ns_to_timespec(host_tns);
+
+ if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
+ do_settimeofday(&host_ts);
+ return;
+ }
+
+ if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 &&
+ scnt > 0) {
+ scnt--;
+ do_settimeofday(&host_ts);
+ }
+
+ return;
+}
+
+/*
+ * Time Sync Channel message handler.
+ */
+static void timesync_onchannelcallback(void *context)
+{
+ struct vmbus_channel *channel = context;
+ u8 *buf;
+ u32 buflen, recvlen;
+ u64 requestid;
+ struct icmsg_hdr *icmsghdrp;
+ struct ictimesync_data *timedatap;
+
+ DPRINT_ENTER(VMBUS);
+
+ buflen = PAGE_SIZE;
+ buf = kmalloc(buflen, GFP_ATOMIC);
+
+ VmbusChannelRecvPacket(channel, buf, buflen, &recvlen, &requestid);
+
+ if (recvlen > 0) {
+ DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld",
+ recvlen, requestid);
+
+ icmsghdrp = (struct icmsg_hdr *)&buf[
+ sizeof(struct vmbuspipe_hdr)];
+
+ if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+ prep_negotiate_resp(icmsghdrp, NULL, buf);
+ } else {
+ timedatap = (struct ictimesync_data *)&buf[
+ sizeof(struct vmbuspipe_hdr) +
+ sizeof(struct icmsg_hdr)];
+ adj_guesttime(timedatap->parenttime, timedatap->flags);
+ }
+
+ icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+ | ICMSGHDRFLAG_RESPONSE;
+
+ VmbusChannelSendPacket(channel, buf,
+ recvlen, requestid,
+ VmbusPacketTypeDataInBand, 0);
+ }
+
+ kfree(buf);
+
+ DPRINT_EXIT(VMBUS);
+}
+
+
static int __init init_hyperv_utils(void)
{
printk(KERN_INFO "Registering HyperV Utility Driver\n");
@@ -114,6 +190,10 @@ static int __init init_hyperv_utils(void)
&shutdown_onchannelcallback;
hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
+ hv_cb_utils[HV_TIMESYNC_MSG].channel->OnChannelCallback =
+ ×ync_onchannelcallback;
+ hv_cb_utils[HV_TIMESYNC_MSG].callback = ×ync_onchannelcallback;
+
return 0;
}
@@ -124,6 +204,10 @@ static void exit_hyperv_utils(void)
hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback =
&chn_cb_negotiate;
hv_cb_utils[HV_SHUTDOWN_MSG].callback = &chn_cb_negotiate;
+
+ hv_cb_utils[HV_TIMESYNC_MSG].channel->OnChannelCallback =
+ &chn_cb_negotiate;
+ hv_cb_utils[HV_TIMESYNC_MSG].callback = &chn_cb_negotiate;
}
module_init(init_hyperv_utils);
diff --git a/drivers/staging/hv/utils.h b/drivers/staging/hv/utils.h
index e404b21..d1d2f28 100644
--- a/drivers/staging/hv/utils.h
+++ b/drivers/staging/hv/utils.h
@@ -75,7 +75,30 @@ struct shutdown_msg_data {
u8 display_message[2048];
} __attribute__((packed));
-#define HV_SHUTDOWN_MSG 0
+
+/* Time Sync IC defs */
+#define ICTIMESYNCFLAG_PROBE 0
+#define ICTIMESYNCFLAG_SYNC 1
+#define ICTIMESYNCFLAG_SAMPLE 2
+
+#ifdef __x86_64__
+#define WLTIMEDELTA 116444736000000000L /* in 100ns unit */
+#else
+#define WLTIMEDELTA 116444736000000000LL
+#endif
+
+typedef u64 winfiletime_t; /* Windows FILETIME type */
+
+struct ictimesync_data{
+ winfiletime_t parenttime;
+ winfiletime_t childtime;
+ winfiletime_t roundtriptime;
+ u8 flags;
+} __attribute__((packed));
+
+/* Index for each IC struct in array hv_cb_utils[] */
+#define HV_SHUTDOWN_MSG 0
+#define HV_TIMESYNC_MSG 1
struct hyperv_service_callback {
u8 msg_type;
--
1.6.3.2
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 1/1] staging: hv: Add Time Sync feature to hv_utils module
2010-05-05 19:23 [PATCH 1/1] staging: hv: Add Time Sync feature to hv_utils module Haiyang Zhang
@ 2010-05-06 0:58 ` Joe Perches
2010-05-06 1:42 ` Haiyang Zhang
0 siblings, 1 reply; 4+ messages in thread
From: Joe Perches @ 2010-05-06 0:58 UTC (permalink / raw)
To: Haiyang Zhang
Cc: linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org,
virtualization@lists.osdl.org, gregkh@suse.de, Hank Janssen
On Wed, 2010-05-05 at 19:23 +0000, Haiyang Zhang wrote:
> From: Haiyang Zhang <haiyangz@microsoft.com>
>
> Subject: Add Time Sync feature to hv_utils module.
> The Time Sync feature synchronizes guest time to host UTC time after reboot,
> and restore from saved/paused state.
> +static void adj_guesttime(winfiletime_t hosttime, u8 flags)
> +{
> + s64 host_tns;
> + struct timespec host_ts;
> + static s32 scnt = 50;
Why a maximum of 50 samples?
> + host_tns = (hosttime - WLTIMEDELTA) * 100;
> + host_ts = ns_to_timespec(host_tns);
> +
> + if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
> + do_settimeofday(&host_ts);
> + return;
> + }
> +
> + if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 &&
> + scnt > 0) {
> + scnt--;
> + do_settimeofday(&host_ts);
> + }
It might be better to do something like this
so the ns_to_timespec isn't performe when unnecessary.
static void settimeofday(winfiletime_t hosttime)
{
s64 host_tns = (hosttime - WLTIMEDELTA) * 100;
struct timespec host_ts = ns_to_timespec(host_tns);
do_settimeofday(&host_ts);
}
static void adj_guesttime(winfiletime_t hosttime, u8 flags)
{
static s32 scnt = 50;
if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
settimeofday(hosttime);
return;
}
if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) {
scnt--;
settimeofday(hosttime);
}
}
^ permalink raw reply [flat|nested] 4+ messages in thread* RE: [PATCH 1/1] staging: hv: Add Time Sync feature to hv_utils module
2010-05-06 0:58 ` Joe Perches
@ 2010-05-06 1:42 ` Haiyang Zhang
2010-05-06 1:59 ` Joe Perches
0 siblings, 1 reply; 4+ messages in thread
From: Haiyang Zhang @ 2010-05-06 1:42 UTC (permalink / raw)
To: Joe Perches
Cc: linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org,
virtualization@lists.osdl.org, gregkh@suse.de, Hank Janssen
> Why a maximum of 50 samples?
After reboot the flag ICTIMESYNCFLAG_SYNC is included in the
first time message after the timesync channel is opened. Since the
hv_utils module is loaded after hv_vmbus, the first message is usually
missed. The other thing is, systime is automatically set to emulated
hardware clock which may not be UTC time or the same time
zone. So, to override these effects, we use the first 50 time samples
for initial system time setting.
> It might be better to do something like this
> so the ns_to_timespec isn't performe when unnecessary.
Thanks for the optimization, I will put it into the code.
- Haiyang
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH 1/1] staging: hv: Add Time Sync feature to hv_utils module
2010-05-06 1:42 ` Haiyang Zhang
@ 2010-05-06 1:59 ` Joe Perches
0 siblings, 0 replies; 4+ messages in thread
From: Joe Perches @ 2010-05-06 1:59 UTC (permalink / raw)
To: Haiyang Zhang
Cc: linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org,
virtualization@lists.osdl.org, gregkh@suse.de, Hank Janssen
On Thu, 2010-05-06 at 01:42 +0000, Haiyang Zhang wrote:
> > Why a maximum of 50 samples?
> After reboot the flag ICTIMESYNCFLAG_SYNC is included in the
> first time message after the timesync channel is opened. Since the
> hv_utils module is loaded after hv_vmbus, the first message is usually
> missed. The other thing is, systime is automatically set to emulated
> hardware clock which may not be UTC time or the same time
> zone. So, to override these effects, we use the first 50 time samples
> for initial system time setting.
I suggest putting that in a commit message or a code comment.
cheers, Joe
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-05-06 1:59 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-05 19:23 [PATCH 1/1] staging: hv: Add Time Sync feature to hv_utils module Haiyang Zhang
2010-05-06 0:58 ` Joe Perches
2010-05-06 1:42 ` Haiyang Zhang
2010-05-06 1:59 ` Joe Perches
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox