• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2010, Microsoft Corporation.
4  *
5  * Authors:
6  *   Haiyang Zhang <haiyangz@microsoft.com>
7  *   Hank Janssen  <hjanssen@microsoft.com>
8  */
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/sysctl.h>
16 #include <linux/reboot.h>
17 #include <linux/hyperv.h>
18 #include <linux/clockchips.h>
19 #include <linux/ptp_clock_kernel.h>
20 #include <clocksource/hyperv_timer.h>
21 #include <asm/mshyperv.h>
22 
23 #include "hyperv_vmbus.h"
24 
25 #define SD_MAJOR	3
26 #define SD_MINOR	0
27 #define SD_VERSION	(SD_MAJOR << 16 | SD_MINOR)
28 
29 #define SD_MAJOR_1	1
30 #define SD_VERSION_1	(SD_MAJOR_1 << 16 | SD_MINOR)
31 
32 #define TS_MAJOR	4
33 #define TS_MINOR	0
34 #define TS_VERSION	(TS_MAJOR << 16 | TS_MINOR)
35 
36 #define TS_MAJOR_1	1
37 #define TS_VERSION_1	(TS_MAJOR_1 << 16 | TS_MINOR)
38 
39 #define TS_MAJOR_3	3
40 #define TS_VERSION_3	(TS_MAJOR_3 << 16 | TS_MINOR)
41 
42 #define HB_MAJOR	3
43 #define HB_MINOR	0
44 #define HB_VERSION	(HB_MAJOR << 16 | HB_MINOR)
45 
46 #define HB_MAJOR_1	1
47 #define HB_VERSION_1	(HB_MAJOR_1 << 16 | HB_MINOR)
48 
49 static int sd_srv_version;
50 static int ts_srv_version;
51 static int hb_srv_version;
52 
53 #define SD_VER_COUNT 2
54 static const int sd_versions[] = {
55 	SD_VERSION,
56 	SD_VERSION_1
57 };
58 
59 #define TS_VER_COUNT 3
60 static const int ts_versions[] = {
61 	TS_VERSION,
62 	TS_VERSION_3,
63 	TS_VERSION_1
64 };
65 
66 #define HB_VER_COUNT 2
67 static const int hb_versions[] = {
68 	HB_VERSION,
69 	HB_VERSION_1
70 };
71 
72 #define FW_VER_COUNT 2
73 static const int fw_versions[] = {
74 	UTIL_FW_VERSION,
75 	UTIL_WS2K8_FW_VERSION
76 };
77 
78 static void shutdown_onchannelcallback(void *context);
79 static struct hv_util_service util_shutdown = {
80 	.util_cb = shutdown_onchannelcallback,
81 };
82 
83 static int hv_timesync_init(struct hv_util_service *srv);
84 static void hv_timesync_deinit(void);
85 
86 static void timesync_onchannelcallback(void *context);
87 static struct hv_util_service util_timesynch = {
88 	.util_cb = timesync_onchannelcallback,
89 	.util_init = hv_timesync_init,
90 	.util_deinit = hv_timesync_deinit,
91 };
92 
93 static void heartbeat_onchannelcallback(void *context);
94 static struct hv_util_service util_heartbeat = {
95 	.util_cb = heartbeat_onchannelcallback,
96 };
97 
98 static struct hv_util_service util_kvp = {
99 	.util_cb = hv_kvp_onchannelcallback,
100 	.util_init = hv_kvp_init,
101 	.util_deinit = hv_kvp_deinit,
102 };
103 
104 static struct hv_util_service util_vss = {
105 	.util_cb = hv_vss_onchannelcallback,
106 	.util_init = hv_vss_init,
107 	.util_deinit = hv_vss_deinit,
108 };
109 
110 static struct hv_util_service util_fcopy = {
111 	.util_cb = hv_fcopy_onchannelcallback,
112 	.util_init = hv_fcopy_init,
113 	.util_deinit = hv_fcopy_deinit,
114 };
115 
perform_shutdown(struct work_struct * dummy)116 static void perform_shutdown(struct work_struct *dummy)
117 {
118 	orderly_poweroff(true);
119 }
120 
121 /*
122  * Perform the shutdown operation in a thread context.
123  */
124 static DECLARE_WORK(shutdown_work, perform_shutdown);
125 
shutdown_onchannelcallback(void * context)126 static void shutdown_onchannelcallback(void *context)
127 {
128 	struct vmbus_channel *channel = context;
129 	u32 recvlen;
130 	u64 requestid;
131 	bool execute_shutdown = false;
132 	u8  *shut_txf_buf = util_shutdown.recv_buffer;
133 
134 	struct shutdown_msg_data *shutdown_msg;
135 
136 	struct icmsg_hdr *icmsghdrp;
137 
138 	vmbus_recvpacket(channel, shut_txf_buf,
139 			 PAGE_SIZE, &recvlen, &requestid);
140 
141 	if (recvlen > 0) {
142 		icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
143 			sizeof(struct vmbuspipe_hdr)];
144 
145 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
146 			if (vmbus_prep_negotiate_resp(icmsghdrp, shut_txf_buf,
147 					fw_versions, FW_VER_COUNT,
148 					sd_versions, SD_VER_COUNT,
149 					NULL, &sd_srv_version)) {
150 				pr_info("Shutdown IC version %d.%d\n",
151 					sd_srv_version >> 16,
152 					sd_srv_version & 0xFFFF);
153 			}
154 		} else {
155 			shutdown_msg =
156 				(struct shutdown_msg_data *)&shut_txf_buf[
157 					sizeof(struct vmbuspipe_hdr) +
158 					sizeof(struct icmsg_hdr)];
159 
160 			switch (shutdown_msg->flags) {
161 			case 0:
162 			case 1:
163 				icmsghdrp->status = HV_S_OK;
164 				execute_shutdown = true;
165 
166 				pr_info("Shutdown request received -"
167 					    " graceful shutdown initiated\n");
168 				break;
169 			default:
170 				icmsghdrp->status = HV_E_FAIL;
171 				execute_shutdown = false;
172 
173 				pr_info("Shutdown request received -"
174 					    " Invalid request\n");
175 				break;
176 			}
177 		}
178 
179 		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
180 			| ICMSGHDRFLAG_RESPONSE;
181 
182 		vmbus_sendpacket(channel, shut_txf_buf,
183 				       recvlen, requestid,
184 				       VM_PKT_DATA_INBAND, 0);
185 	}
186 
187 	if (execute_shutdown == true)
188 		schedule_work(&shutdown_work);
189 }
190 
191 /*
192  * Set the host time in a process context.
193  */
194 static struct work_struct adj_time_work;
195 
196 /*
197  * The last time sample, received from the host. PTP device responds to
198  * requests by using this data and the current partition-wide time reference
199  * count.
200  */
201 static struct {
202 	u64				host_time;
203 	u64				ref_time;
204 	spinlock_t			lock;
205 } host_ts;
206 
hv_get_adj_host_time(void)207 static struct timespec64 hv_get_adj_host_time(void)
208 {
209 	struct timespec64 ts;
210 	u64 newtime, reftime;
211 	unsigned long flags;
212 
213 	spin_lock_irqsave(&host_ts.lock, flags);
214 	reftime = hyperv_cs->read(hyperv_cs);
215 	newtime = host_ts.host_time + (reftime - host_ts.ref_time);
216 	ts = ns_to_timespec64((newtime - WLTIMEDELTA) * 100);
217 	spin_unlock_irqrestore(&host_ts.lock, flags);
218 
219 	return ts;
220 }
221 
hv_set_host_time(struct work_struct * work)222 static void hv_set_host_time(struct work_struct *work)
223 {
224 	struct timespec64 ts = hv_get_adj_host_time();
225 
226 	do_settimeofday64(&ts);
227 }
228 
229 /*
230  * Synchronize time with host after reboot, restore, etc.
231  *
232  * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
233  * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
234  * message after the timesync channel is opened. Since the hv_utils module is
235  * loaded after hv_vmbus, the first message is usually missed. This bit is
236  * considered a hard request to discipline the clock.
237  *
238  * ICTIMESYNCFLAG_SAMPLE bit indicates a time sample from host. This is
239  * typically used as a hint to the guest. The guest is under no obligation
240  * to discipline the clock.
241  */
adj_guesttime(u64 hosttime,u64 reftime,u8 adj_flags)242 static inline void adj_guesttime(u64 hosttime, u64 reftime, u8 adj_flags)
243 {
244 	unsigned long flags;
245 	u64 cur_reftime;
246 
247 	/*
248 	 * Save the adjusted time sample from the host and the snapshot
249 	 * of the current system time.
250 	 */
251 	spin_lock_irqsave(&host_ts.lock, flags);
252 
253 	cur_reftime = hyperv_cs->read(hyperv_cs);
254 	host_ts.host_time = hosttime;
255 	host_ts.ref_time = cur_reftime;
256 
257 	/*
258 	 * TimeSync v4 messages contain reference time (guest's Hyper-V
259 	 * clocksource read when the time sample was generated), we can
260 	 * improve the precision by adding the delta between now and the
261 	 * time of generation. For older protocols we set
262 	 * reftime == cur_reftime on call.
263 	 */
264 	host_ts.host_time += (cur_reftime - reftime);
265 
266 	spin_unlock_irqrestore(&host_ts.lock, flags);
267 
268 	/* Schedule work to do do_settimeofday64() */
269 	if (adj_flags & ICTIMESYNCFLAG_SYNC)
270 		schedule_work(&adj_time_work);
271 }
272 
273 /*
274  * Time Sync Channel message handler.
275  */
timesync_onchannelcallback(void * context)276 static void timesync_onchannelcallback(void *context)
277 {
278 	struct vmbus_channel *channel = context;
279 	u32 recvlen;
280 	u64 requestid;
281 	struct icmsg_hdr *icmsghdrp;
282 	struct ictimesync_data *timedatap;
283 	struct ictimesync_ref_data *refdata;
284 	u8 *time_txf_buf = util_timesynch.recv_buffer;
285 
286 	vmbus_recvpacket(channel, time_txf_buf,
287 			 PAGE_SIZE, &recvlen, &requestid);
288 
289 	if (recvlen > 0) {
290 		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
291 				sizeof(struct vmbuspipe_hdr)];
292 
293 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
294 			if (vmbus_prep_negotiate_resp(icmsghdrp, time_txf_buf,
295 						fw_versions, FW_VER_COUNT,
296 						ts_versions, TS_VER_COUNT,
297 						NULL, &ts_srv_version)) {
298 				pr_info("TimeSync IC version %d.%d\n",
299 					ts_srv_version >> 16,
300 					ts_srv_version & 0xFFFF);
301 			}
302 		} else {
303 			if (ts_srv_version > TS_VERSION_3) {
304 				refdata = (struct ictimesync_ref_data *)
305 					&time_txf_buf[
306 					sizeof(struct vmbuspipe_hdr) +
307 					sizeof(struct icmsg_hdr)];
308 
309 				adj_guesttime(refdata->parenttime,
310 						refdata->vmreferencetime,
311 						refdata->flags);
312 			} else {
313 				timedatap = (struct ictimesync_data *)
314 					&time_txf_buf[
315 					sizeof(struct vmbuspipe_hdr) +
316 					sizeof(struct icmsg_hdr)];
317 				adj_guesttime(timedatap->parenttime,
318 					      hyperv_cs->read(hyperv_cs),
319 					      timedatap->flags);
320 			}
321 		}
322 
323 		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
324 			| ICMSGHDRFLAG_RESPONSE;
325 
326 		vmbus_sendpacket(channel, time_txf_buf,
327 				recvlen, requestid,
328 				VM_PKT_DATA_INBAND, 0);
329 	}
330 }
331 
332 /*
333  * Heartbeat functionality.
334  * Every two seconds, Hyper-V send us a heartbeat request message.
335  * we respond to this message, and Hyper-V knows we are alive.
336  */
heartbeat_onchannelcallback(void * context)337 static void heartbeat_onchannelcallback(void *context)
338 {
339 	struct vmbus_channel *channel = context;
340 	u32 recvlen;
341 	u64 requestid;
342 	struct icmsg_hdr *icmsghdrp;
343 	struct heartbeat_msg_data *heartbeat_msg;
344 	u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
345 
346 	while (1) {
347 
348 		vmbus_recvpacket(channel, hbeat_txf_buf,
349 				 PAGE_SIZE, &recvlen, &requestid);
350 
351 		if (!recvlen)
352 			break;
353 
354 		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
355 				sizeof(struct vmbuspipe_hdr)];
356 
357 		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
358 			if (vmbus_prep_negotiate_resp(icmsghdrp,
359 					hbeat_txf_buf,
360 					fw_versions, FW_VER_COUNT,
361 					hb_versions, HB_VER_COUNT,
362 					NULL, &hb_srv_version)) {
363 
364 				pr_info("Heartbeat IC version %d.%d\n",
365 					hb_srv_version >> 16,
366 					hb_srv_version & 0xFFFF);
367 			}
368 		} else {
369 			heartbeat_msg =
370 				(struct heartbeat_msg_data *)&hbeat_txf_buf[
371 					sizeof(struct vmbuspipe_hdr) +
372 					sizeof(struct icmsg_hdr)];
373 
374 			heartbeat_msg->seq_num += 1;
375 		}
376 
377 		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
378 			| ICMSGHDRFLAG_RESPONSE;
379 
380 		vmbus_sendpacket(channel, hbeat_txf_buf,
381 				       recvlen, requestid,
382 				       VM_PKT_DATA_INBAND, 0);
383 	}
384 }
385 
util_probe(struct hv_device * dev,const struct hv_vmbus_device_id * dev_id)386 static int util_probe(struct hv_device *dev,
387 			const struct hv_vmbus_device_id *dev_id)
388 {
389 	struct hv_util_service *srv =
390 		(struct hv_util_service *)dev_id->driver_data;
391 	int ret;
392 
393 	srv->recv_buffer = kmalloc(PAGE_SIZE * 4, GFP_KERNEL);
394 	if (!srv->recv_buffer)
395 		return -ENOMEM;
396 	srv->channel = dev->channel;
397 	if (srv->util_init) {
398 		ret = srv->util_init(srv);
399 		if (ret) {
400 			ret = -ENODEV;
401 			goto error1;
402 		}
403 	}
404 
405 	/*
406 	 * The set of services managed by the util driver are not performance
407 	 * critical and do not need batched reading. Furthermore, some services
408 	 * such as KVP can only handle one message from the host at a time.
409 	 * Turn off batched reading for all util drivers before we open the
410 	 * channel.
411 	 */
412 	set_channel_read_mode(dev->channel, HV_CALL_DIRECT);
413 
414 	hv_set_drvdata(dev, srv);
415 
416 	ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
417 			srv->util_cb, dev->channel);
418 	if (ret)
419 		goto error;
420 
421 	return 0;
422 
423 error:
424 	if (srv->util_deinit)
425 		srv->util_deinit();
426 error1:
427 	kfree(srv->recv_buffer);
428 	return ret;
429 }
430 
util_remove(struct hv_device * dev)431 static int util_remove(struct hv_device *dev)
432 {
433 	struct hv_util_service *srv = hv_get_drvdata(dev);
434 
435 	if (srv->util_deinit)
436 		srv->util_deinit();
437 	vmbus_close(dev->channel);
438 	kfree(srv->recv_buffer);
439 
440 	return 0;
441 }
442 
443 static const struct hv_vmbus_device_id id_table[] = {
444 	/* Shutdown guid */
445 	{ HV_SHUTDOWN_GUID,
446 	  .driver_data = (unsigned long)&util_shutdown
447 	},
448 	/* Time synch guid */
449 	{ HV_TS_GUID,
450 	  .driver_data = (unsigned long)&util_timesynch
451 	},
452 	/* Heartbeat guid */
453 	{ HV_HEART_BEAT_GUID,
454 	  .driver_data = (unsigned long)&util_heartbeat
455 	},
456 	/* KVP guid */
457 	{ HV_KVP_GUID,
458 	  .driver_data = (unsigned long)&util_kvp
459 	},
460 	/* VSS GUID */
461 	{ HV_VSS_GUID,
462 	  .driver_data = (unsigned long)&util_vss
463 	},
464 	/* File copy GUID */
465 	{ HV_FCOPY_GUID,
466 	  .driver_data = (unsigned long)&util_fcopy
467 	},
468 	{ },
469 };
470 
471 MODULE_DEVICE_TABLE(vmbus, id_table);
472 
473 /* The one and only one */
474 static  struct hv_driver util_drv = {
475 	.name = "hv_utils",
476 	.id_table = id_table,
477 	.probe =  util_probe,
478 	.remove =  util_remove,
479 	.driver = {
480 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
481 	},
482 };
483 
hv_ptp_enable(struct ptp_clock_info * info,struct ptp_clock_request * request,int on)484 static int hv_ptp_enable(struct ptp_clock_info *info,
485 			 struct ptp_clock_request *request, int on)
486 {
487 	return -EOPNOTSUPP;
488 }
489 
hv_ptp_settime(struct ptp_clock_info * p,const struct timespec64 * ts)490 static int hv_ptp_settime(struct ptp_clock_info *p, const struct timespec64 *ts)
491 {
492 	return -EOPNOTSUPP;
493 }
494 
hv_ptp_adjfreq(struct ptp_clock_info * ptp,s32 delta)495 static int hv_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
496 {
497 	return -EOPNOTSUPP;
498 }
hv_ptp_adjtime(struct ptp_clock_info * ptp,s64 delta)499 static int hv_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
500 {
501 	return -EOPNOTSUPP;
502 }
503 
hv_ptp_gettime(struct ptp_clock_info * info,struct timespec64 * ts)504 static int hv_ptp_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
505 {
506 	*ts = hv_get_adj_host_time();
507 
508 	return 0;
509 }
510 
511 static struct ptp_clock_info ptp_hyperv_info = {
512 	.name		= "hyperv",
513 	.enable         = hv_ptp_enable,
514 	.adjtime        = hv_ptp_adjtime,
515 	.adjfreq        = hv_ptp_adjfreq,
516 	.gettime64      = hv_ptp_gettime,
517 	.settime64      = hv_ptp_settime,
518 	.owner		= THIS_MODULE,
519 };
520 
521 static struct ptp_clock *hv_ptp_clock;
522 
hv_timesync_init(struct hv_util_service * srv)523 static int hv_timesync_init(struct hv_util_service *srv)
524 {
525 	/* TimeSync requires Hyper-V clocksource. */
526 	if (!hyperv_cs)
527 		return -ENODEV;
528 
529 	spin_lock_init(&host_ts.lock);
530 
531 	INIT_WORK(&adj_time_work, hv_set_host_time);
532 
533 	/*
534 	 * ptp_clock_register() returns NULL when CONFIG_PTP_1588_CLOCK is
535 	 * disabled but the driver is still useful without the PTP device
536 	 * as it still handles the ICTIMESYNCFLAG_SYNC case.
537 	 */
538 	hv_ptp_clock = ptp_clock_register(&ptp_hyperv_info, NULL);
539 	if (IS_ERR_OR_NULL(hv_ptp_clock)) {
540 		pr_err("cannot register PTP clock: %ld\n",
541 		       PTR_ERR(hv_ptp_clock));
542 		hv_ptp_clock = NULL;
543 	}
544 
545 	return 0;
546 }
547 
hv_timesync_deinit(void)548 static void hv_timesync_deinit(void)
549 {
550 	if (hv_ptp_clock)
551 		ptp_clock_unregister(hv_ptp_clock);
552 	cancel_work_sync(&adj_time_work);
553 }
554 
init_hyperv_utils(void)555 static int __init init_hyperv_utils(void)
556 {
557 	pr_info("Registering HyperV Utility Driver\n");
558 
559 	return vmbus_driver_register(&util_drv);
560 }
561 
exit_hyperv_utils(void)562 static void exit_hyperv_utils(void)
563 {
564 	pr_info("De-Registered HyperV Utility Driver\n");
565 
566 	vmbus_driver_unregister(&util_drv);
567 }
568 
569 module_init(init_hyperv_utils);
570 module_exit(exit_hyperv_utils);
571 
572 MODULE_DESCRIPTION("Hyper-V Utilities");
573 MODULE_LICENSE("GPL");
574