xref: /openbmc/linux/drivers/hv/hv_util.c (revision 6dfcd296)
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 #include "hyperv_vmbus.h"
32 
33 #define SD_MAJOR	3
34 #define SD_MINOR	0
35 #define SD_VERSION	(SD_MAJOR << 16 | SD_MINOR)
36 
37 #define SD_MAJOR_1	1
38 #define SD_VERSION_1	(SD_MAJOR_1 << 16 | SD_MINOR)
39 
40 #define TS_MAJOR	4
41 #define TS_MINOR	0
42 #define TS_VERSION	(TS_MAJOR << 16 | TS_MINOR)
43 
44 #define TS_MAJOR_1	1
45 #define TS_VERSION_1	(TS_MAJOR_1 << 16 | TS_MINOR)
46 
47 #define TS_MAJOR_3	3
48 #define TS_VERSION_3	(TS_MAJOR_3 << 16 | TS_MINOR)
49 
50 #define HB_MAJOR	3
51 #define HB_MINOR	0
52 #define HB_VERSION	(HB_MAJOR << 16 | HB_MINOR)
53 
54 #define HB_MAJOR_1	1
55 #define HB_VERSION_1	(HB_MAJOR_1 << 16 | HB_MINOR)
56 
57 static int sd_srv_version;
58 static int ts_srv_version;
59 static int hb_srv_version;
60 static int util_fw_version;
61 
62 static void shutdown_onchannelcallback(void *context);
63 static struct hv_util_service util_shutdown = {
64 	.util_cb = shutdown_onchannelcallback,
65 };
66 
67 static int hv_timesync_init(struct hv_util_service *srv);
68 static void hv_timesync_deinit(void);
69 
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,
75 };
76 
77 static void heartbeat_onchannelcallback(void *context);
78 static struct hv_util_service util_heartbeat = {
79 	.util_cb = heartbeat_onchannelcallback,
80 };
81 
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,
86 };
87 
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,
92 };
93 
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,
98 };
99 
100 static void perform_shutdown(struct work_struct *dummy)
101 {
102 	orderly_poweroff(true);
103 }
104 
105 /*
106  * Perform the shutdown operation in a thread context.
107  */
108 static DECLARE_WORK(shutdown_work, perform_shutdown);
109 
110 static void shutdown_onchannelcallback(void *context)
111 {
112 	struct vmbus_channel *channel = context;
113 	u32 recvlen;
114 	u64 requestid;
115 	bool execute_shutdown = false;
116 	u8  *shut_txf_buf = util_shutdown.recv_buffer;
117 
118 	struct shutdown_msg_data *shutdown_msg;
119 
120 	struct icmsg_hdr *icmsghdrp;
121 	struct icmsg_negotiate *negop = NULL;
122 
123 	vmbus_recvpacket(channel, shut_txf_buf,
124 			 PAGE_SIZE, &recvlen, &requestid);
125 
126 	if (recvlen > 0) {
127 		icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
128 			sizeof(struct vmbuspipe_hdr)];
129 
130 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
131 			vmbus_prep_negotiate_resp(icmsghdrp, negop,
132 					shut_txf_buf, util_fw_version,
133 					sd_srv_version);
134 		} else {
135 			shutdown_msg =
136 				(struct shutdown_msg_data *)&shut_txf_buf[
137 					sizeof(struct vmbuspipe_hdr) +
138 					sizeof(struct icmsg_hdr)];
139 
140 			switch (shutdown_msg->flags) {
141 			case 0:
142 			case 1:
143 				icmsghdrp->status = HV_S_OK;
144 				execute_shutdown = true;
145 
146 				pr_info("Shutdown request received -"
147 					    " graceful shutdown initiated\n");
148 				break;
149 			default:
150 				icmsghdrp->status = HV_E_FAIL;
151 				execute_shutdown = false;
152 
153 				pr_info("Shutdown request received -"
154 					    " Invalid request\n");
155 				break;
156 			}
157 		}
158 
159 		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
160 			| ICMSGHDRFLAG_RESPONSE;
161 
162 		vmbus_sendpacket(channel, shut_txf_buf,
163 				       recvlen, requestid,
164 				       VM_PKT_DATA_INBAND, 0);
165 	}
166 
167 	if (execute_shutdown == true)
168 		schedule_work(&shutdown_work);
169 }
170 
171 /*
172  * Set the host time in a process context.
173  */
174 
175 struct adj_time_work {
176 	struct work_struct work;
177 	u64	host_time;
178 	u64	ref_time;
179 	u8	flags;
180 };
181 
182 static void hv_set_host_time(struct work_struct *work)
183 {
184 	struct adj_time_work	*wrk;
185 	s64 host_tns;
186 	u64 newtime;
187 	struct timespec host_ts;
188 
189 	wrk = container_of(work, struct adj_time_work, work);
190 
191 	newtime = wrk->host_time;
192 	if (ts_srv_version > TS_VERSION_3) {
193 		/*
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.
197 		 *
198 		 * This sample is given by TimeSync v4 and above hosts.
199 		 */
200 		u64 current_tick;
201 
202 		rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
203 		newtime += (current_tick - wrk->ref_time);
204 	}
205 	host_tns = (newtime - WLTIMEDELTA) * 100;
206 	host_ts = ns_to_timespec(host_tns);
207 
208 	do_settimeofday(&host_ts);
209 }
210 
211 /*
212  * Synchronize time with host after reboot, restore, etc.
213  *
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.
219  *
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.
223  */
224 static struct adj_time_work  wrk;
225 static inline void adj_guesttime(u64 hosttime, u64 reftime, u8 flags)
226 {
227 
228 	/*
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.
232 	 */
233 	if (work_pending(&wrk.work))
234 		return;
235 
236 	wrk.host_time = hosttime;
237 	wrk.ref_time = reftime;
238 	wrk.flags = flags;
239 	if ((flags & (ICTIMESYNCFLAG_SYNC | ICTIMESYNCFLAG_SAMPLE)) != 0) {
240 		schedule_work(&wrk.work);
241 	}
242 }
243 
244 /*
245  * Time Sync Channel message handler.
246  */
247 static void timesync_onchannelcallback(void *context)
248 {
249 	struct vmbus_channel *channel = context;
250 	u32 recvlen;
251 	u64 requestid;
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;
257 
258 	vmbus_recvpacket(channel, time_txf_buf,
259 			 PAGE_SIZE, &recvlen, &requestid);
260 
261 	if (recvlen > 0) {
262 		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
263 				sizeof(struct vmbuspipe_hdr)];
264 
265 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
266 			vmbus_prep_negotiate_resp(icmsghdrp, negop,
267 						time_txf_buf,
268 						util_fw_version,
269 						ts_srv_version);
270 			pr_info("Using TimeSync version %d.%d\n",
271 				ts_srv_version >> 16, ts_srv_version & 0xFFFF);
272 		} else {
273 			if (ts_srv_version > TS_VERSION_3) {
274 				refdata = (struct ictimesync_ref_data *)
275 					&time_txf_buf[
276 					sizeof(struct vmbuspipe_hdr) +
277 					sizeof(struct icmsg_hdr)];
278 
279 				adj_guesttime(refdata->parenttime,
280 						refdata->vmreferencetime,
281 						refdata->flags);
282 			} else {
283 				timedatap = (struct ictimesync_data *)
284 					&time_txf_buf[
285 					sizeof(struct vmbuspipe_hdr) +
286 					sizeof(struct icmsg_hdr)];
287 				adj_guesttime(timedatap->parenttime,
288 						0,
289 						timedatap->flags);
290 			}
291 		}
292 
293 		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
294 			| ICMSGHDRFLAG_RESPONSE;
295 
296 		vmbus_sendpacket(channel, time_txf_buf,
297 				recvlen, requestid,
298 				VM_PKT_DATA_INBAND, 0);
299 	}
300 }
301 
302 /*
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.
306  */
307 static void heartbeat_onchannelcallback(void *context)
308 {
309 	struct vmbus_channel *channel = context;
310 	u32 recvlen;
311 	u64 requestid;
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;
316 
317 	vmbus_recvpacket(channel, hbeat_txf_buf,
318 			 PAGE_SIZE, &recvlen, &requestid);
319 
320 	if (recvlen > 0) {
321 		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
322 				sizeof(struct vmbuspipe_hdr)];
323 
324 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
325 			vmbus_prep_negotiate_resp(icmsghdrp, negop,
326 				hbeat_txf_buf, util_fw_version,
327 				hb_srv_version);
328 		} else {
329 			heartbeat_msg =
330 				(struct heartbeat_msg_data *)&hbeat_txf_buf[
331 					sizeof(struct vmbuspipe_hdr) +
332 					sizeof(struct icmsg_hdr)];
333 
334 			heartbeat_msg->seq_num += 1;
335 		}
336 
337 		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
338 			| ICMSGHDRFLAG_RESPONSE;
339 
340 		vmbus_sendpacket(channel, hbeat_txf_buf,
341 				       recvlen, requestid,
342 				       VM_PKT_DATA_INBAND, 0);
343 	}
344 }
345 
346 static int util_probe(struct hv_device *dev,
347 			const struct hv_vmbus_device_id *dev_id)
348 {
349 	struct hv_util_service *srv =
350 		(struct hv_util_service *)dev_id->driver_data;
351 	int ret;
352 
353 	srv->recv_buffer = kmalloc(PAGE_SIZE * 4, GFP_KERNEL);
354 	if (!srv->recv_buffer)
355 		return -ENOMEM;
356 	srv->channel = dev->channel;
357 	if (srv->util_init) {
358 		ret = srv->util_init(srv);
359 		if (ret) {
360 			ret = -ENODEV;
361 			goto error1;
362 		}
363 	}
364 
365 	/*
366 	 * The set of services managed by the util driver are not performance
367 	 * critical and do not need batched reading. Furthermore, some services
368 	 * such as KVP can only handle one message from the host at a time.
369 	 * Turn off batched reading for all util drivers before we open the
370 	 * channel.
371 	 */
372 
373 	set_channel_read_state(dev->channel, false);
374 
375 	hv_set_drvdata(dev, srv);
376 
377 	/*
378 	 * Based on the host; initialize the framework and
379 	 * service version numbers we will negotiate.
380 	 */
381 	switch (vmbus_proto_version) {
382 	case (VERSION_WS2008):
383 		util_fw_version = UTIL_WS2K8_FW_VERSION;
384 		sd_srv_version = SD_VERSION_1;
385 		ts_srv_version = TS_VERSION_1;
386 		hb_srv_version = HB_VERSION_1;
387 		break;
388 	case(VERSION_WIN10):
389 		util_fw_version = UTIL_FW_VERSION;
390 		sd_srv_version = SD_VERSION;
391 		ts_srv_version = TS_VERSION;
392 		hb_srv_version = HB_VERSION;
393 		break;
394 	default:
395 		util_fw_version = UTIL_FW_VERSION;
396 		sd_srv_version = SD_VERSION;
397 		ts_srv_version = TS_VERSION_3;
398 		hb_srv_version = HB_VERSION;
399 	}
400 
401 	ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
402 			srv->util_cb, dev->channel);
403 	if (ret)
404 		goto error;
405 
406 	return 0;
407 
408 error:
409 	if (srv->util_deinit)
410 		srv->util_deinit();
411 error1:
412 	kfree(srv->recv_buffer);
413 	return ret;
414 }
415 
416 static int util_remove(struct hv_device *dev)
417 {
418 	struct hv_util_service *srv = hv_get_drvdata(dev);
419 
420 	if (srv->util_deinit)
421 		srv->util_deinit();
422 	vmbus_close(dev->channel);
423 	kfree(srv->recv_buffer);
424 
425 	return 0;
426 }
427 
428 static const struct hv_vmbus_device_id id_table[] = {
429 	/* Shutdown guid */
430 	{ HV_SHUTDOWN_GUID,
431 	  .driver_data = (unsigned long)&util_shutdown
432 	},
433 	/* Time synch guid */
434 	{ HV_TS_GUID,
435 	  .driver_data = (unsigned long)&util_timesynch
436 	},
437 	/* Heartbeat guid */
438 	{ HV_HEART_BEAT_GUID,
439 	  .driver_data = (unsigned long)&util_heartbeat
440 	},
441 	/* KVP guid */
442 	{ HV_KVP_GUID,
443 	  .driver_data = (unsigned long)&util_kvp
444 	},
445 	/* VSS GUID */
446 	{ HV_VSS_GUID,
447 	  .driver_data = (unsigned long)&util_vss
448 	},
449 	/* File copy GUID */
450 	{ HV_FCOPY_GUID,
451 	  .driver_data = (unsigned long)&util_fcopy
452 	},
453 	{ },
454 };
455 
456 MODULE_DEVICE_TABLE(vmbus, id_table);
457 
458 /* The one and only one */
459 static  struct hv_driver util_drv = {
460 	.name = "hv_util",
461 	.id_table = id_table,
462 	.probe =  util_probe,
463 	.remove =  util_remove,
464 };
465 
466 static int hv_timesync_init(struct hv_util_service *srv)
467 {
468 	INIT_WORK(&wrk.work, hv_set_host_time);
469 	return 0;
470 }
471 
472 static void hv_timesync_deinit(void)
473 {
474 	cancel_work_sync(&wrk.work);
475 }
476 
477 static int __init init_hyperv_utils(void)
478 {
479 	pr_info("Registering HyperV Utility Driver\n");
480 
481 	return vmbus_driver_register(&util_drv);
482 }
483 
484 static void exit_hyperv_utils(void)
485 {
486 	pr_info("De-Registered HyperV Utility Driver\n");
487 
488 	vmbus_driver_unregister(&util_drv);
489 }
490 
491 module_init(init_hyperv_utils);
492 module_exit(exit_hyperv_utils);
493 
494 MODULE_DESCRIPTION("Hyper-V Utilities");
495 MODULE_LICENSE("GPL");
496