2 * Copyright (c) 2010, Microsoft Corporation.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 * Haiyang Zhang <haiyangz@microsoft.com>
19 * Hank Janssen <hjanssen@microsoft.com>
21 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23 #include <linux/kernel.h>
24 #include <linux/init.h>
25 #include <linux/module.h>
26 #include <linux/slab.h>
27 #include <linux/sysctl.h>
28 #include <linux/reboot.h>
29 #include <linux/hyperv.h>
31 #include "hyperv_vmbus.h"
35 #define SD_VERSION (SD_MAJOR << 16 | SD_MINOR)
38 #define SD_VERSION_1 (SD_MAJOR_1 << 16 | SD_MINOR)
42 #define TS_VERSION (TS_MAJOR << 16 | TS_MINOR)
45 #define TS_VERSION_1 (TS_MAJOR_1 << 16 | TS_MINOR)
48 #define TS_VERSION_3 (TS_MAJOR_3 << 16 | TS_MINOR)
52 #define HB_VERSION (HB_MAJOR << 16 | HB_MINOR)
55 #define HB_VERSION_1 (HB_MAJOR_1 << 16 | HB_MINOR)
57 static int sd_srv_version
;
58 static int ts_srv_version
;
59 static int hb_srv_version
;
60 static int util_fw_version
;
62 static void shutdown_onchannelcallback(void *context
);
63 static struct hv_util_service util_shutdown
= {
64 .util_cb
= shutdown_onchannelcallback
,
67 static int hv_timesync_init(struct hv_util_service
*srv
);
68 static void hv_timesync_deinit(void);
70 static void timesync_onchannelcallback(void *context
);
71 static struct hv_util_service util_timesynch
= {
72 .util_cb
= timesync_onchannelcallback
,
73 .util_init
= hv_timesync_init
,
74 .util_deinit
= hv_timesync_deinit
,
77 static void heartbeat_onchannelcallback(void *context
);
78 static struct hv_util_service util_heartbeat
= {
79 .util_cb
= heartbeat_onchannelcallback
,
82 static struct hv_util_service util_kvp
= {
83 .util_cb
= hv_kvp_onchannelcallback
,
84 .util_init
= hv_kvp_init
,
85 .util_deinit
= hv_kvp_deinit
,
88 static struct hv_util_service util_vss
= {
89 .util_cb
= hv_vss_onchannelcallback
,
90 .util_init
= hv_vss_init
,
91 .util_deinit
= hv_vss_deinit
,
94 static struct hv_util_service util_fcopy
= {
95 .util_cb
= hv_fcopy_onchannelcallback
,
96 .util_init
= hv_fcopy_init
,
97 .util_deinit
= hv_fcopy_deinit
,
100 static void perform_shutdown(struct work_struct
*dummy
)
102 orderly_poweroff(true);
106 * Perform the shutdown operation in a thread context.
108 static DECLARE_WORK(shutdown_work
, perform_shutdown
);
110 static void shutdown_onchannelcallback(void *context
)
112 struct vmbus_channel
*channel
= context
;
115 bool execute_shutdown
= false;
116 u8
*shut_txf_buf
= util_shutdown
.recv_buffer
;
118 struct shutdown_msg_data
*shutdown_msg
;
120 struct icmsg_hdr
*icmsghdrp
;
121 struct icmsg_negotiate
*negop
= NULL
;
123 vmbus_recvpacket(channel
, shut_txf_buf
,
124 PAGE_SIZE
, &recvlen
, &requestid
);
127 icmsghdrp
= (struct icmsg_hdr
*)&shut_txf_buf
[
128 sizeof(struct vmbuspipe_hdr
)];
130 if (icmsghdrp
->icmsgtype
== ICMSGTYPE_NEGOTIATE
) {
131 vmbus_prep_negotiate_resp(icmsghdrp
, negop
,
132 shut_txf_buf
, util_fw_version
,
136 (struct shutdown_msg_data
*)&shut_txf_buf
[
137 sizeof(struct vmbuspipe_hdr
) +
138 sizeof(struct icmsg_hdr
)];
140 switch (shutdown_msg
->flags
) {
143 icmsghdrp
->status
= HV_S_OK
;
144 execute_shutdown
= true;
146 pr_info("Shutdown request received -"
147 " graceful shutdown initiated\n");
150 icmsghdrp
->status
= HV_E_FAIL
;
151 execute_shutdown
= false;
153 pr_info("Shutdown request received -"
154 " Invalid request\n");
159 icmsghdrp
->icflags
= ICMSGHDRFLAG_TRANSACTION
160 | ICMSGHDRFLAG_RESPONSE
;
162 vmbus_sendpacket(channel
, shut_txf_buf
,
164 VM_PKT_DATA_INBAND
, 0);
167 if (execute_shutdown
== true)
168 schedule_work(&shutdown_work
);
172 * Set the host time in a process context.
175 struct adj_time_work
{
176 struct work_struct work
;
182 static void hv_set_host_time(struct work_struct
*work
)
184 struct adj_time_work
*wrk
;
187 struct timespec host_ts
;
189 wrk
= container_of(work
, struct adj_time_work
, work
);
191 newtime
= wrk
->host_time
;
192 if (ts_srv_version
> TS_VERSION_3
) {
194 * Some latency has been introduced since Hyper-V generated
195 * its time sample. Take that latency into account before
196 * using TSC reference time sample from Hyper-V.
198 * This sample is given by TimeSync v4 and above hosts.
202 rdmsrl(HV_X64_MSR_TIME_REF_COUNT
, current_tick
);
203 newtime
+= (current_tick
- wrk
->ref_time
);
205 host_tns
= (newtime
- WLTIMEDELTA
) * 100;
206 host_ts
= ns_to_timespec(host_tns
);
208 do_settimeofday(&host_ts
);
212 * Synchronize time with host after reboot, restore, etc.
214 * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
215 * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
216 * message after the timesync channel is opened. Since the hv_utils module is
217 * loaded after hv_vmbus, the first message is usually missed. This bit is
218 * considered a hard request to discipline the clock.
220 * ICTIMESYNCFLAG_SAMPLE bit indicates a time sample from host. This is
221 * typically used as a hint to the guest. The guest is under no obligation
222 * to discipline the clock.
224 static struct adj_time_work wrk
;
225 static inline void adj_guesttime(u64 hosttime
, u64 reftime
, u8 flags
)
229 * This check is safe since we are executing in the
230 * interrupt context and time synch messages arre always
231 * delivered on the same CPU.
233 if (work_pending(&wrk
.work
))
236 wrk
.host_time
= hosttime
;
237 wrk
.ref_time
= reftime
;
239 if ((flags
& (ICTIMESYNCFLAG_SYNC
| ICTIMESYNCFLAG_SAMPLE
)) != 0) {
240 schedule_work(&wrk
.work
);
245 * Time Sync Channel message handler.
247 static void timesync_onchannelcallback(void *context
)
249 struct vmbus_channel
*channel
= context
;
252 struct icmsg_hdr
*icmsghdrp
;
253 struct ictimesync_data
*timedatap
;
254 struct ictimesync_ref_data
*refdata
;
255 u8
*time_txf_buf
= util_timesynch
.recv_buffer
;
256 struct icmsg_negotiate
*negop
= NULL
;
258 vmbus_recvpacket(channel
, time_txf_buf
,
259 PAGE_SIZE
, &recvlen
, &requestid
);
262 icmsghdrp
= (struct icmsg_hdr
*)&time_txf_buf
[
263 sizeof(struct vmbuspipe_hdr
)];
265 if (icmsghdrp
->icmsgtype
== ICMSGTYPE_NEGOTIATE
) {
266 vmbus_prep_negotiate_resp(icmsghdrp
, negop
,
270 pr_info("Using TimeSync version %d.%d\n",
271 ts_srv_version
>> 16, ts_srv_version
& 0xFFFF);
273 if (ts_srv_version
> TS_VERSION_3
) {
274 refdata
= (struct ictimesync_ref_data
*)
276 sizeof(struct vmbuspipe_hdr
) +
277 sizeof(struct icmsg_hdr
)];
279 adj_guesttime(refdata
->parenttime
,
280 refdata
->vmreferencetime
,
283 timedatap
= (struct ictimesync_data
*)
285 sizeof(struct vmbuspipe_hdr
) +
286 sizeof(struct icmsg_hdr
)];
287 adj_guesttime(timedatap
->parenttime
,
293 icmsghdrp
->icflags
= ICMSGHDRFLAG_TRANSACTION
294 | ICMSGHDRFLAG_RESPONSE
;
296 vmbus_sendpacket(channel
, time_txf_buf
,
298 VM_PKT_DATA_INBAND
, 0);
303 * Heartbeat functionality.
304 * Every two seconds, Hyper-V send us a heartbeat request message.
305 * we respond to this message, and Hyper-V knows we are alive.
307 static void heartbeat_onchannelcallback(void *context
)
309 struct vmbus_channel
*channel
= context
;
312 struct icmsg_hdr
*icmsghdrp
;
313 struct heartbeat_msg_data
*heartbeat_msg
;
314 u8
*hbeat_txf_buf
= util_heartbeat
.recv_buffer
;
315 struct icmsg_negotiate
*negop
= NULL
;
319 vmbus_recvpacket(channel
, hbeat_txf_buf
,
320 PAGE_SIZE
, &recvlen
, &requestid
);
325 icmsghdrp
= (struct icmsg_hdr
*)&hbeat_txf_buf
[
326 sizeof(struct vmbuspipe_hdr
)];
328 if (icmsghdrp
->icmsgtype
== ICMSGTYPE_NEGOTIATE
) {
329 vmbus_prep_negotiate_resp(icmsghdrp
, negop
,
330 hbeat_txf_buf
, util_fw_version
,
334 (struct heartbeat_msg_data
*)&hbeat_txf_buf
[
335 sizeof(struct vmbuspipe_hdr
) +
336 sizeof(struct icmsg_hdr
)];
338 heartbeat_msg
->seq_num
+= 1;
341 icmsghdrp
->icflags
= ICMSGHDRFLAG_TRANSACTION
342 | ICMSGHDRFLAG_RESPONSE
;
344 vmbus_sendpacket(channel
, hbeat_txf_buf
,
346 VM_PKT_DATA_INBAND
, 0);
350 static int util_probe(struct hv_device
*dev
,
351 const struct hv_vmbus_device_id
*dev_id
)
353 struct hv_util_service
*srv
=
354 (struct hv_util_service
*)dev_id
->driver_data
;
357 srv
->recv_buffer
= kmalloc(PAGE_SIZE
* 4, GFP_KERNEL
);
358 if (!srv
->recv_buffer
)
360 srv
->channel
= dev
->channel
;
361 if (srv
->util_init
) {
362 ret
= srv
->util_init(srv
);
370 * The set of services managed by the util driver are not performance
371 * critical and do not need batched reading. Furthermore, some services
372 * such as KVP can only handle one message from the host at a time.
373 * Turn off batched reading for all util drivers before we open the
377 set_channel_read_state(dev
->channel
, false);
379 hv_set_drvdata(dev
, srv
);
382 * Based on the host; initialize the framework and
383 * service version numbers we will negotiate.
385 switch (vmbus_proto_version
) {
386 case (VERSION_WS2008
):
387 util_fw_version
= UTIL_WS2K8_FW_VERSION
;
388 sd_srv_version
= SD_VERSION_1
;
389 ts_srv_version
= TS_VERSION_1
;
390 hb_srv_version
= HB_VERSION_1
;
393 util_fw_version
= UTIL_FW_VERSION
;
394 sd_srv_version
= SD_VERSION
;
395 ts_srv_version
= TS_VERSION
;
396 hb_srv_version
= HB_VERSION
;
399 util_fw_version
= UTIL_FW_VERSION
;
400 sd_srv_version
= SD_VERSION
;
401 ts_srv_version
= TS_VERSION_3
;
402 hb_srv_version
= HB_VERSION
;
405 ret
= vmbus_open(dev
->channel
, 4 * PAGE_SIZE
, 4 * PAGE_SIZE
, NULL
, 0,
406 srv
->util_cb
, dev
->channel
);
413 if (srv
->util_deinit
)
416 kfree(srv
->recv_buffer
);
420 static int util_remove(struct hv_device
*dev
)
422 struct hv_util_service
*srv
= hv_get_drvdata(dev
);
424 if (srv
->util_deinit
)
426 vmbus_close(dev
->channel
);
427 kfree(srv
->recv_buffer
);
432 static const struct hv_vmbus_device_id id_table
[] = {
435 .driver_data
= (unsigned long)&util_shutdown
437 /* Time synch guid */
439 .driver_data
= (unsigned long)&util_timesynch
442 { HV_HEART_BEAT_GUID
,
443 .driver_data
= (unsigned long)&util_heartbeat
447 .driver_data
= (unsigned long)&util_kvp
451 .driver_data
= (unsigned long)&util_vss
455 .driver_data
= (unsigned long)&util_fcopy
460 MODULE_DEVICE_TABLE(vmbus
, id_table
);
462 /* The one and only one */
463 static struct hv_driver util_drv
= {
465 .id_table
= id_table
,
467 .remove
= util_remove
,
470 static int hv_timesync_init(struct hv_util_service
*srv
)
472 INIT_WORK(&wrk
.work
, hv_set_host_time
);
476 static void hv_timesync_deinit(void)
478 cancel_work_sync(&wrk
.work
);
481 static int __init
init_hyperv_utils(void)
483 pr_info("Registering HyperV Utility Driver\n");
485 return vmbus_driver_register(&util_drv
);
488 static void exit_hyperv_utils(void)
490 pr_info("De-Registered HyperV Utility Driver\n");
492 vmbus_driver_unregister(&util_drv
);
495 module_init(init_hyperv_utils
);
496 module_exit(exit_hyperv_utils
);
498 MODULE_DESCRIPTION("Hyper-V Utilities");
499 MODULE_LICENSE("GPL");