1 /* 2 * Copyright (c) 2010, Microsoft Corporation. 3 * 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. 7 * 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 11 * more details. 12 * 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. 16 * 17 * Authors: 18 * Haiyang Zhang <haiyangz@microsoft.com> 19 * Hank Janssen <hjanssen@microsoft.com> 20 */ 21 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 22 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> 30 31 32 #define SD_MAJOR 3 33 #define SD_MINOR 0 34 #define SD_VERSION (SD_MAJOR << 16 | SD_MINOR) 35 36 #define SD_WS2008_MAJOR 1 37 #define SD_WS2008_VERSION (SD_WS2008_MAJOR << 16 | SD_MINOR) 38 39 #define TS_MAJOR 3 40 #define TS_MINOR 0 41 #define TS_VERSION (TS_MAJOR << 16 | TS_MINOR) 42 43 #define TS_WS2008_MAJOR 1 44 #define TS_WS2008_VERSION (TS_WS2008_MAJOR << 16 | TS_MINOR) 45 46 #define HB_MAJOR 3 47 #define HB_MINOR 0 48 #define HB_VERSION (HB_MAJOR << 16 | HB_MINOR) 49 50 #define HB_WS2008_MAJOR 1 51 #define HB_WS2008_VERSION (HB_WS2008_MAJOR << 16 | HB_MINOR) 52 53 static int sd_srv_version; 54 static int ts_srv_version; 55 static int hb_srv_version; 56 static int util_fw_version; 57 58 static void shutdown_onchannelcallback(void *context); 59 static struct hv_util_service util_shutdown = { 60 .util_cb = shutdown_onchannelcallback, 61 }; 62 63 static void timesync_onchannelcallback(void *context); 64 static struct hv_util_service util_timesynch = { 65 .util_cb = timesync_onchannelcallback, 66 }; 67 68 static void heartbeat_onchannelcallback(void *context); 69 static struct hv_util_service util_heartbeat = { 70 .util_cb = heartbeat_onchannelcallback, 71 }; 72 73 static struct hv_util_service util_kvp = { 74 .util_cb = hv_kvp_onchannelcallback, 75 .util_init = hv_kvp_init, 76 .util_deinit = hv_kvp_deinit, 77 }; 78 79 static struct hv_util_service util_vss = { 80 .util_cb = hv_vss_onchannelcallback, 81 .util_init = hv_vss_init, 82 .util_deinit = hv_vss_deinit, 83 }; 84 85 static void perform_shutdown(struct work_struct *dummy) 86 { 87 orderly_poweroff(true); 88 } 89 90 /* 91 * Perform the shutdown operation in a thread context. 92 */ 93 static DECLARE_WORK(shutdown_work, perform_shutdown); 94 95 static void shutdown_onchannelcallback(void *context) 96 { 97 struct vmbus_channel *channel = context; 98 u32 recvlen; 99 u64 requestid; 100 bool execute_shutdown = false; 101 u8 *shut_txf_buf = util_shutdown.recv_buffer; 102 103 struct shutdown_msg_data *shutdown_msg; 104 105 struct icmsg_hdr *icmsghdrp; 106 struct icmsg_negotiate *negop = NULL; 107 108 vmbus_recvpacket(channel, shut_txf_buf, 109 PAGE_SIZE, &recvlen, &requestid); 110 111 if (recvlen > 0) { 112 icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[ 113 sizeof(struct vmbuspipe_hdr)]; 114 115 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 116 vmbus_prep_negotiate_resp(icmsghdrp, negop, 117 shut_txf_buf, util_fw_version, 118 sd_srv_version); 119 } else { 120 shutdown_msg = 121 (struct shutdown_msg_data *)&shut_txf_buf[ 122 sizeof(struct vmbuspipe_hdr) + 123 sizeof(struct icmsg_hdr)]; 124 125 switch (shutdown_msg->flags) { 126 case 0: 127 case 1: 128 icmsghdrp->status = HV_S_OK; 129 execute_shutdown = true; 130 131 pr_info("Shutdown request received -" 132 " graceful shutdown initiated\n"); 133 break; 134 default: 135 icmsghdrp->status = HV_E_FAIL; 136 execute_shutdown = false; 137 138 pr_info("Shutdown request received -" 139 " Invalid request\n"); 140 break; 141 } 142 } 143 144 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION 145 | ICMSGHDRFLAG_RESPONSE; 146 147 vmbus_sendpacket(channel, shut_txf_buf, 148 recvlen, requestid, 149 VM_PKT_DATA_INBAND, 0); 150 } 151 152 if (execute_shutdown == true) 153 schedule_work(&shutdown_work); 154 } 155 156 /* 157 * Set guest time to host UTC time. 158 */ 159 static inline void do_adj_guesttime(u64 hosttime) 160 { 161 s64 host_tns; 162 struct timespec host_ts; 163 164 host_tns = (hosttime - WLTIMEDELTA) * 100; 165 host_ts = ns_to_timespec(host_tns); 166 167 do_settimeofday(&host_ts); 168 } 169 170 /* 171 * Set the host time in a process context. 172 */ 173 174 struct adj_time_work { 175 struct work_struct work; 176 u64 host_time; 177 }; 178 179 static void hv_set_host_time(struct work_struct *work) 180 { 181 struct adj_time_work *wrk; 182 183 wrk = container_of(work, struct adj_time_work, work); 184 do_adj_guesttime(wrk->host_time); 185 kfree(wrk); 186 } 187 188 /* 189 * Synchronize time with host after reboot, restore, etc. 190 * 191 * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM. 192 * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time 193 * message after the timesync channel is opened. Since the hv_utils module is 194 * loaded after hv_vmbus, the first message is usually missed. The other 195 * thing is, systime is automatically set to emulated hardware clock which may 196 * not be UTC time or in the same time zone. So, to override these effects, we 197 * use the first 50 time samples for initial system time setting. 198 */ 199 static inline void adj_guesttime(u64 hosttime, u8 flags) 200 { 201 struct adj_time_work *wrk; 202 static s32 scnt = 50; 203 204 wrk = kmalloc(sizeof(struct adj_time_work), GFP_ATOMIC); 205 if (wrk == NULL) 206 return; 207 208 wrk->host_time = hosttime; 209 if ((flags & ICTIMESYNCFLAG_SYNC) != 0) { 210 INIT_WORK(&wrk->work, hv_set_host_time); 211 schedule_work(&wrk->work); 212 return; 213 } 214 215 if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) { 216 scnt--; 217 INIT_WORK(&wrk->work, hv_set_host_time); 218 schedule_work(&wrk->work); 219 } else 220 kfree(wrk); 221 } 222 223 /* 224 * Time Sync Channel message handler. 225 */ 226 static void timesync_onchannelcallback(void *context) 227 { 228 struct vmbus_channel *channel = context; 229 u32 recvlen; 230 u64 requestid; 231 struct icmsg_hdr *icmsghdrp; 232 struct ictimesync_data *timedatap; 233 u8 *time_txf_buf = util_timesynch.recv_buffer; 234 struct icmsg_negotiate *negop = NULL; 235 236 vmbus_recvpacket(channel, time_txf_buf, 237 PAGE_SIZE, &recvlen, &requestid); 238 239 if (recvlen > 0) { 240 icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[ 241 sizeof(struct vmbuspipe_hdr)]; 242 243 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 244 vmbus_prep_negotiate_resp(icmsghdrp, negop, 245 time_txf_buf, 246 util_fw_version, 247 ts_srv_version); 248 } else { 249 timedatap = (struct ictimesync_data *)&time_txf_buf[ 250 sizeof(struct vmbuspipe_hdr) + 251 sizeof(struct icmsg_hdr)]; 252 adj_guesttime(timedatap->parenttime, timedatap->flags); 253 } 254 255 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION 256 | ICMSGHDRFLAG_RESPONSE; 257 258 vmbus_sendpacket(channel, time_txf_buf, 259 recvlen, requestid, 260 VM_PKT_DATA_INBAND, 0); 261 } 262 } 263 264 /* 265 * Heartbeat functionality. 266 * Every two seconds, Hyper-V send us a heartbeat request message. 267 * we respond to this message, and Hyper-V knows we are alive. 268 */ 269 static void heartbeat_onchannelcallback(void *context) 270 { 271 struct vmbus_channel *channel = context; 272 u32 recvlen; 273 u64 requestid; 274 struct icmsg_hdr *icmsghdrp; 275 struct heartbeat_msg_data *heartbeat_msg; 276 u8 *hbeat_txf_buf = util_heartbeat.recv_buffer; 277 struct icmsg_negotiate *negop = NULL; 278 279 vmbus_recvpacket(channel, hbeat_txf_buf, 280 PAGE_SIZE, &recvlen, &requestid); 281 282 if (recvlen > 0) { 283 icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[ 284 sizeof(struct vmbuspipe_hdr)]; 285 286 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 287 vmbus_prep_negotiate_resp(icmsghdrp, negop, 288 hbeat_txf_buf, util_fw_version, 289 hb_srv_version); 290 } else { 291 heartbeat_msg = 292 (struct heartbeat_msg_data *)&hbeat_txf_buf[ 293 sizeof(struct vmbuspipe_hdr) + 294 sizeof(struct icmsg_hdr)]; 295 296 heartbeat_msg->seq_num += 1; 297 } 298 299 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION 300 | ICMSGHDRFLAG_RESPONSE; 301 302 vmbus_sendpacket(channel, hbeat_txf_buf, 303 recvlen, requestid, 304 VM_PKT_DATA_INBAND, 0); 305 } 306 } 307 308 static int util_probe(struct hv_device *dev, 309 const struct hv_vmbus_device_id *dev_id) 310 { 311 struct hv_util_service *srv = 312 (struct hv_util_service *)dev_id->driver_data; 313 int ret; 314 315 srv->recv_buffer = kmalloc(PAGE_SIZE * 2, GFP_KERNEL); 316 if (!srv->recv_buffer) 317 return -ENOMEM; 318 if (srv->util_init) { 319 ret = srv->util_init(srv); 320 if (ret) { 321 ret = -ENODEV; 322 goto error1; 323 } 324 } 325 326 /* 327 * The set of services managed by the util driver are not performance 328 * critical and do not need batched reading. Furthermore, some services 329 * such as KVP can only handle one message from the host at a time. 330 * Turn off batched reading for all util drivers before we open the 331 * channel. 332 */ 333 334 set_channel_read_state(dev->channel, false); 335 336 ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0, 337 srv->util_cb, dev->channel); 338 if (ret) 339 goto error; 340 341 hv_set_drvdata(dev, srv); 342 /* 343 * Based on the host; initialize the framework and 344 * service version numbers we will negotiate. 345 */ 346 switch (vmbus_proto_version) { 347 case (VERSION_WS2008): 348 util_fw_version = UTIL_WS2K8_FW_VERSION; 349 sd_srv_version = SD_WS2008_VERSION; 350 ts_srv_version = TS_WS2008_VERSION; 351 hb_srv_version = HB_WS2008_VERSION; 352 break; 353 354 default: 355 util_fw_version = UTIL_FW_VERSION; 356 sd_srv_version = SD_VERSION; 357 ts_srv_version = TS_VERSION; 358 hb_srv_version = HB_VERSION; 359 } 360 361 return 0; 362 363 error: 364 if (srv->util_deinit) 365 srv->util_deinit(); 366 error1: 367 kfree(srv->recv_buffer); 368 return ret; 369 } 370 371 static int util_remove(struct hv_device *dev) 372 { 373 struct hv_util_service *srv = hv_get_drvdata(dev); 374 375 vmbus_close(dev->channel); 376 if (srv->util_deinit) 377 srv->util_deinit(); 378 kfree(srv->recv_buffer); 379 380 return 0; 381 } 382 383 static const struct hv_vmbus_device_id id_table[] = { 384 /* Shutdown guid */ 385 { HV_SHUTDOWN_GUID, 386 .driver_data = (unsigned long)&util_shutdown 387 }, 388 /* Time synch guid */ 389 { HV_TS_GUID, 390 .driver_data = (unsigned long)&util_timesynch 391 }, 392 /* Heartbeat guid */ 393 { HV_HEART_BEAT_GUID, 394 .driver_data = (unsigned long)&util_heartbeat 395 }, 396 /* KVP guid */ 397 { HV_KVP_GUID, 398 .driver_data = (unsigned long)&util_kvp 399 }, 400 /* VSS GUID */ 401 { HV_VSS_GUID, 402 .driver_data = (unsigned long)&util_vss 403 }, 404 { }, 405 }; 406 407 MODULE_DEVICE_TABLE(vmbus, id_table); 408 409 /* The one and only one */ 410 static struct hv_driver util_drv = { 411 .name = "hv_util", 412 .id_table = id_table, 413 .probe = util_probe, 414 .remove = util_remove, 415 }; 416 417 static int __init init_hyperv_utils(void) 418 { 419 pr_info("Registering HyperV Utility Driver\n"); 420 421 return vmbus_driver_register(&util_drv); 422 } 423 424 static void exit_hyperv_utils(void) 425 { 426 pr_info("De-Registered HyperV Utility Driver\n"); 427 428 vmbus_driver_unregister(&util_drv); 429 } 430 431 module_init(init_hyperv_utils); 432 module_exit(exit_hyperv_utils); 433 434 MODULE_DESCRIPTION("Hyper-V Utilities"); 435 MODULE_LICENSE("GPL"); 436